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 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']; var p5WPSHelper_generateProcessSelectFeatureWithArgs = function (identifier, typeName, listPrimaryKeys) { return { identifier: identifier, // "ows:Identifier" dataInputs: [ // "wps:DataInputs" { // "wps:Input" identifier: "typeName", // "ows:Identifier" // title: "Feature typeName", // "ows:Title" data: { literalData: { value: typeName } }, // "wps:Data" // reference: "???", // "wps:Reference" // boundingBoxData: "???", // "wps:BoundingBoxData" } ].concat( listPrimaryKeys.map(function (pk) { return { // "wps:Input" identifier: "primaryKey", // "ows:Identifier" // title: "Feature typeName", // "ows:Title" data: { literalData: { value: pk } }, // "wps:Data" // reference: "???", // "wps:Reference" // boundingBoxData: "???", // "wps:BoundingBoxData" }; }) ), responseForm: { // "wps:ResponseForm" // rawDataOutput: "???", // "wps:RawDataOutput" // responseDocument: "???", // "wps:ResponseDocument" } } } var p5WPS_executeFeatureProcess = function(identifier) { return function (ns, listPrimaryKeys) { return new Promise(function (resolve, reject) { var process = p5WPSHelper_generateProcessSelectFeatureWithArgs(identifier, ns, listPrimaryKeys); 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) { // console.log('response', response); // }, // failure: function (response) { // console.log('response', response); // } }); }); } }; var p5WPS__selecFeature = p5WPS_executeFeatureProcess('p5:selectFeature'); var p5WPS__unselectFeature = p5WPS_executeFeatureProcess('p5:unselectFeature'); var p5WPS__unselecAllFeatures = p5WPS_executeFeatureProcess('p5:unselectAllFeatures'); // var p5WPS__selecAllFeatures = p5WPS_executeFeatureProcess('p5:selectAllFeatures'); // TODO: send current table ogc filter var p5WPS__getSelectedFeatures = p5WPS_executeFeatureProcess('p5:getSelectedFeatures'); function p5Utils__arrayRemove(array, element) { return array.filter(e => e !== element); } 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: state.selected.filter(function (pk) { return ( 'select-all' !== pk ); }) }); return state; } function selectedStore(state, action) { // TODO: fetch from ajax on init, and on change rows in table 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() { 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 reqPromise = checked ? p5WPS__selecFeature(namespace, [ primaryKey ]) : p5WPS__unselectFeature(namespace, [ primaryKey ]); 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: ' + 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; return p5WPS__getSelectedFeatures(namespace, listPrimaryKeys).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: ' + 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 reqPromise = checked ? p5WPS__selecFeature(namespace, listPrimaryKeys) : p5WPS__unselectFeature(namespace, listPrimaryKeys); 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: ' + 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 reqPromise = p5WPS__unselecAllFeatures(namespace, []); 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: ' + 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([]) ); }); }; } return { setPrimaryKeys: setPrimaryKeys, setChecked: setChecked, setUnchecked: setUnchecked, toggle: toggle, unselectAll: unselectAll, } } 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(); return { // isLoading: state.isLoading || 0, // add ? 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.isLoading !== nextState.isLoading ); }, handleUnselectAll: function (event) { DBG && console.log('DBG::P5UI__TableAjaxSelectedInfo::handleChange (ns:'+this.props.namespace+')', { checked: checked }); this.props.store.dispatch( this.props.actions.unselectAll( this.props.namespace ) ) }, 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 8px' } }, [ 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, ]) } }); 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 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 _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 _filterFields = {}; // array with filter DOM elements 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 = {}; _state.filters = {}; _state.filters.currSortCol = ''; _state.filters.currSortFlip = false; _state.filters.filterCols = {}; { // 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.filterInit) { priv.setStateFilters(priv.options.filterInit); } if (priv.options.exportFields) { $.each(priv.options.exportFields, function(ind, col) { _exportFieldsSelect[col] = true; }); } 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); }); } if (priv.options.checkboxes) { priv.options.selectedStore = createStoreWithThunkMiddleware(selectedStore) priv.options.selectedActions = selectedActions() 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 }), _uiNodeSelectedInfo ); } } }; 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