|
|
@@ -0,0 +1,547 @@
|
|
|
+(function (global, p5VendorJs) {
|
|
|
+ if (!p5VendorJs.React) throw "Missing React"
|
|
|
+ if (!p5VendorJs.ReactDOM) throw "Missing ReactDOM"
|
|
|
+ if (!p5VendorJs.createReactClass) throw "Missing createReactClass"
|
|
|
+ var React = p5VendorJs.React
|
|
|
+ var ReactDOM = p5VendorJs.ReactDOM
|
|
|
+ var createReactClass = p5VendorJs.createReactClass
|
|
|
+ var h = React.createElement
|
|
|
+ var DBG = 0
|
|
|
+
|
|
|
+ var P5UI__RawHtml = createReactClass({
|
|
|
+ componentDidMount: function () {
|
|
|
+ if (this.props.rawHtml) {
|
|
|
+ this.rootNode.innerHTML = this.props.rawHtml
|
|
|
+ }
|
|
|
+ },
|
|
|
+ render: function () {
|
|
|
+ return h('div', {
|
|
|
+ ref: function (node) { this.rootNode = node; }.bind(this),
|
|
|
+ })
|
|
|
+ }
|
|
|
+ })
|
|
|
+ global.p5VendorJs['P5UI__RawHtml'] = P5UI__RawHtml
|
|
|
+
|
|
|
+ var P5UI__FeatureEditForm = createReactClass({
|
|
|
+ componentDidMount: function () {
|
|
|
+ if(DBG)console.warn('P5UI__FeatureEditForm::componentDidMount this.rootNode', this.rootNode)
|
|
|
+ jQuery(this.rootNode).find('textarea').autosize();
|
|
|
+ jQuery(this.rootNode).find('.frm-help').popover({trigger:'hover'});
|
|
|
+ jQuery(this.rootNode).find('.show-last-value input').on('input', function(e) {
|
|
|
+ var input, btn, btnIco;
|
|
|
+ input = jQuery(e.target);
|
|
|
+ btn = input.next('.button-appendBack');
|
|
|
+ btnIco = btn.find('.glyphicon');
|
|
|
+ if (btn.attr('title') != input.val()) {
|
|
|
+ btnIco.show();
|
|
|
+ } else {
|
|
|
+ btnIco.hide();
|
|
|
+ }
|
|
|
+ });
|
|
|
+ jQuery(this.rootNode).find('.show-last-value').find('.button-appendBack').on('click', function(e) {
|
|
|
+ var input, btn, btnIco;
|
|
|
+ btn = jQuery(this);
|
|
|
+ btnIco = btn.find('.glyphicon');
|
|
|
+ input = btn.prev();
|
|
|
+ if (input.is('input')) {
|
|
|
+ if (btn.attr('title') != input.val()) {
|
|
|
+ input.val(btn.attr('title'));
|
|
|
+ btnIco.hide();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ });
|
|
|
+ },
|
|
|
+ submit: function (e) {
|
|
|
+ if(DBG)console.warn('P5UI__FeatureEditForm::submit this.rootNode', this.rootNode)
|
|
|
+ e.preventDefault()
|
|
|
+
|
|
|
+ var formData = {};
|
|
|
+ jQuery(this.rootNode).serializeArray().map(function(i) { formData[i.name] = i.value; });// TODO: edit Widget - send only updated fields
|
|
|
+ // TODO: change Edit btn to return to edit record with fields -> show form
|
|
|
+
|
|
|
+ var taskCont = jQuery(this.rootNode).parents('.AjaxTableTaskCnt').parent(); // jQuery('#{$this->_htmlID}_task').parent();
|
|
|
+ //taskCont.empty();
|
|
|
+ taskCont.children().fadeOut('slow');
|
|
|
+ var alertCntWrap = jQuery('<div class="AjaxTableAlert AjaxTable-loading"></div>').prependTo(taskCont)
|
|
|
+ , alertCnt = jQuery('<div class="container"></div>').prependTo(alertCntWrap);
|
|
|
+ jQuery('<div class="alert alert-info"><div style="padding:0 0 0 20px; background:url(./icon/loading.gif) no-repeat left top;"> zapisywanie ... </div></div>').appendTo(alertCnt);
|
|
|
+
|
|
|
+ function notifyAjaxCallback(data) {
|
|
|
+ var notify = {}, outMsg = '';
|
|
|
+ notify.type = (data && data.type)? data.type : '';
|
|
|
+ notify.msg = (data && data.msg)? data.msg : '';
|
|
|
+ switch (notify.type) {
|
|
|
+ case 'success':
|
|
|
+ if (!notify.msg) notify.msg = 'Dane poprawnie zaktualizowane';
|
|
|
+ break;
|
|
|
+ case 'info':
|
|
|
+ if (!notify.msg) notify.msg = 'Nie wprowadzono żadnych zmian';
|
|
|
+ break;
|
|
|
+ case 'error':
|
|
|
+ if (!notify.msg) notify.msg = 'Wystąpiły błędy';
|
|
|
+ break;
|
|
|
+ case 'warning':
|
|
|
+ notify.type = 'warn';
|
|
|
+ if (!notify.msg) notify.msg = 'Wystąpiły błędy';
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ notify.msg = 'Nieznany błąd';
|
|
|
+ if (data && data.errorCode) notify.msg += ' ' + data.errorCode;
|
|
|
+ notify.type = '';
|
|
|
+ }
|
|
|
+ jQuery.notify(notify.msg, notify.type);
|
|
|
+ var alertType = ('error' == data.type) ? 'danger' : data.type;
|
|
|
+ outMsg = '<div class="alert alert-' + alertType + '">' + notify.msg + '</div>';
|
|
|
+ return outMsg;
|
|
|
+ }
|
|
|
+
|
|
|
+ var idRecord = this.props.idRecord
|
|
|
+ var tableLabelHtml = this.props.tableLabelHtml
|
|
|
+ superagent
|
|
|
+ .post(this.props.ajaxSaveUrl)
|
|
|
+ .type('json') // header ĺapplication/x-www-form-urlencoded' requires type('form');
|
|
|
+ .send({
|
|
|
+ namespace: this.props.namespace,
|
|
|
+ primaryKey: this.props.idRecord,
|
|
|
+ form: formData
|
|
|
+ })
|
|
|
+ .set('Accept', 'application/json')
|
|
|
+ .end(function(err, res) {
|
|
|
+ var payload;
|
|
|
+ if (err || !res.ok || 'application/json' !== res.type) {
|
|
|
+ payload = {type: 'warning', msg: res.body.msg || 'Wystąpiły błędy', body: res.body};
|
|
|
+ } else {
|
|
|
+ payload = {type: 'success', msg: res.body.msg || '', body: res.body};
|
|
|
+ }
|
|
|
+ var data = res.body;
|
|
|
+
|
|
|
+ alertCntWrap.removeClass('AjaxTable-loading');
|
|
|
+ alertCnt.empty();
|
|
|
+ if (false === ['success', 'info'].indexOf(payload.type)) {
|
|
|
+ jQuery(errorTxt).appendTo(alertCnt);
|
|
|
+ var errLinks = jQuery('<div class="breadcrumb"></div>').appendTo(alertCnt);
|
|
|
+ jQuery('<a href="#" onclick="return tableAjaxBackToTable();"> <i class="icon-arrow-left"></i> Wróć do tabeli '+tableLabelHtml+'</a>').appendTo(errLinks);
|
|
|
+ var backToEditBtn = jQuery('<a href="#EDIT/'+idRecord+'/' + Math.random(1).toString().substr(2) + '" class="btn btn-link btn-small"> <i class="icon-pencil"></i> Popraw dane '+idRecord+'</a>').appendTo(errLinks);
|
|
|
+ backToEditBtn.on('click', function(){
|
|
|
+ alertCnt.remove();
|
|
|
+ taskCont.children().fadeIn('slow');
|
|
|
+ return false;
|
|
|
+ });
|
|
|
+ } else {
|
|
|
+ var outMsg = notifyAjaxCallback(payload);
|
|
|
+ var out = '';
|
|
|
+ out += outMsg;
|
|
|
+ out += '<div class="breadcrumb">' +
|
|
|
+ ' <a href="#" onclick="return tableAjaxBackToTable();" class="btn btn-link btn-sm"> <i class="glyphicon glyphicon-arrow-left"></i> Wróć do tabeli '+tableLabelHtml+'</a>' +
|
|
|
+ ' <a href="#EDIT/'+idRecord+'/' + Math.random(1).toString().substr(2) + '" class="btn btn-link btn-sm"> <i class="glyphicon glyphicon-pencil"></i> Edytuj rekord '+idRecord+'</a>' +
|
|
|
+ '</div>';
|
|
|
+ jQuery(out).appendTo(alertCnt);
|
|
|
+
|
|
|
+ // add rowFunctions from response
|
|
|
+ if (data && data.rowFunctions && data.primaryKey) {
|
|
|
+ var rowFunWrapNode = $('<div class="container"></div>').insertAfter(alertCnt);
|
|
|
+ var rowFunListNode = $('<ul></ul>').appendTo(rowFunWrapNode);
|
|
|
+ var keys = Object.keys(data.rowFunctions),
|
|
|
+ total = keys.length,
|
|
|
+ moreFuncBtnNode,
|
|
|
+ moreFunctions = [],
|
|
|
+ idx
|
|
|
+ ;
|
|
|
+ moreFunctions = keys.splice(3);
|
|
|
+ keys.forEach(function(key) {
|
|
|
+ var cellNode = $('<li></li>');
|
|
|
+ var funObj = data.rowFunctions[key],
|
|
|
+ funcNode = p5UI_TableAjax_generateFunctionNode(funObj, data.primaryKey, {ico: true, label: true})
|
|
|
+ ;
|
|
|
+ funcNode.appendTo(cellNode);
|
|
|
+ cellNode.appendTo(rowFunListNode);
|
|
|
+ });
|
|
|
+ }
|
|
|
+ }
|
|
|
+ })
|
|
|
+ },
|
|
|
+ render: function () {
|
|
|
+ if(DBG)console.warn('P5UI__FeatureEditForm::render this.props', this.props)
|
|
|
+ var formProps = Object.assign({}, this.props)
|
|
|
+ delete formProps.children
|
|
|
+ return h('form', Object.assign(formProps, {
|
|
|
+ ref: function (node) { this.rootNode = node; }.bind(this),
|
|
|
+ onSubmit: this.submit.bind(this)
|
|
|
+ }), this.props.children)
|
|
|
+ }
|
|
|
+ })
|
|
|
+ global.p5VendorJs['P5UI__FeatureEditForm'] = P5UI__FeatureEditForm
|
|
|
+
|
|
|
+ var P5UI__Typespecial = createReactClass({
|
|
|
+ componentDidMount: function () {
|
|
|
+ if(DBG)console.log('TS::componentDidMount (['+this.props.idField+'] '+this.props.fieldNamespace+') ...')
|
|
|
+ // console.log('TS::componentDidMount (['+this.props.idField+'] '+this.props.fieldNamespace+') this.rootNode', this.rootNode) // OK
|
|
|
+ var fldNode = jQuery(document.getElementById(this.props.fieldName)) // jQuery('#{$fName}')
|
|
|
+ var tsNode = jQuery(this.rootNode) // jQuery('#ts-{$fName}')
|
|
|
+ var ajaxDataUrlBase = this.props.ajaxDataUrlBase
|
|
|
+ if (!fldNode && !tsNode) {
|
|
|
+ console.log("BUG Missing fldNode or tsNode in P5UI__Typespecial")
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ if (!ajaxDataUrlBase) {
|
|
|
+ console.log("BUG Missing ajaxDataUrlBase in P5UI__Typespecial")
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ fldNode.attr('name', '');
|
|
|
+ fldNode.hide();
|
|
|
+ if (fldNode.parent().hasClass('show-last-value')) {
|
|
|
+ fldNode.parent().hide();
|
|
|
+ }
|
|
|
+ tsNode.attr('name', this.props.frmFldName)
|
|
|
+ tsNode.attr('tabindex', fldNode.attr('tabindex'))
|
|
|
+
|
|
|
+ var getFetchCallback = ('TypespecialVariable' === this.props.type)
|
|
|
+ ? function (query, callback) {
|
|
|
+ return function(res) {
|
|
|
+ for (var i in res) {
|
|
|
+ if (!res[i].name || res[i].id != res[i].name) {
|
|
|
+ res[i].name = res[i].id + ': ' + res[i].name;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ callback(res);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ : function (query, callback) {
|
|
|
+ return function(res) {
|
|
|
+ var i, prefix, prefixLen;
|
|
|
+ for (i in res) {
|
|
|
+ prefix = '' + res[i].id;
|
|
|
+ prefixLen = prefix.length;
|
|
|
+ if (prefixLen > 0 && prefix !== res[i].name.substr(0, prefixLen)) {
|
|
|
+ res[i].name = res[i].id + ': ' + res[i].name;
|
|
|
+ }
|
|
|
+ res[i]['\$order'] = 1 + (parseInt(i) || 0); // set order from request
|
|
|
+ }
|
|
|
+ callback(res);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ ;
|
|
|
+ var scoreCallback = ('TypespecialVariable' === this.props.type)
|
|
|
+ ? function(search) {
|
|
|
+ var score = this.getScoreFunction(search);
|
|
|
+ return function(item) {
|
|
|
+ // console.log('score:item:', item, ', score:', score(item));
|
|
|
+ if (search && search == item.id) {
|
|
|
+ return 1;
|
|
|
+ } else {
|
|
|
+ return score(item);// score(item) * (1 + Math.min(item.watchers / 100, 1));
|
|
|
+ }
|
|
|
+ };
|
|
|
+ }
|
|
|
+ : function(query) {
|
|
|
+ // console.log('Typespecial({$fName})::score: q(', query, ')');
|
|
|
+ var score = this.getScoreFunction(query);
|
|
|
+ return function(item) {
|
|
|
+ var retScore = 0, lName = ('' + item.name).toLowerCase(), lQuery = query.toLowerCase();
|
|
|
+ if (query.search(' ') > -1) {
|
|
|
+ retScore = score(item);
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ if (lQuery + ':' == lName.substr(0, lQuery.length + 1)) {
|
|
|
+ retScore = 100;
|
|
|
+ } else if (lName.search(lQuery) > -1) {
|
|
|
+ retScore = 90 - lName.search(lQuery);
|
|
|
+ } else {
|
|
|
+ retScore = 0;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ // console.log('Typespecial({$fName})::score: q(', lQuery, ') , retScore(', retScore, '), score(', score(item), '), item.name(', item.name, ') item.id:', item.id);
|
|
|
+ return retScore;
|
|
|
+ };
|
|
|
+ }
|
|
|
+ ;
|
|
|
+
|
|
|
+ tsNode.selectize({
|
|
|
+ theme: 'typespecial',
|
|
|
+ valueField: 'id',
|
|
|
+ labelField: 'id',
|
|
|
+ searchField: 'name',
|
|
|
+ sortField: ('TypespecialVariable' === this.props.type) ? 'name' : '$order', // TODO: skip in Typespecial - default sort field is '$order'
|
|
|
+ create: this.props.create,
|
|
|
+ delimiter: ';',
|
|
|
+ dataAttr: 'typespecial',
|
|
|
+ preload: this.props.preload || false,
|
|
|
+ options: this.props.options,
|
|
|
+ render: {
|
|
|
+ item: function(item, escape) {
|
|
|
+ return '<div>' +
|
|
|
+ '<span class=\"name\">' + escape(item.name || item.id) + '</span>' +
|
|
|
+ '</div>';
|
|
|
+ },
|
|
|
+ option: function(item, escape) {
|
|
|
+ return '<div>' +
|
|
|
+ '<span class=\"title\">' +
|
|
|
+ escape(item.name || item.id) +
|
|
|
+ '</span>' +
|
|
|
+ '</div>';
|
|
|
+ }
|
|
|
+ },
|
|
|
+ onItemAdd: function(value, item) {// Invoked when an item is selected.
|
|
|
+ var curSel = this.options[value] || null, fieldExport;
|
|
|
+ if (curSel && curSel.exports) {
|
|
|
+ for (var i in curSel.exports) {
|
|
|
+ fieldExport = jQuery('#ts-f' + i);
|
|
|
+ if (fieldExport.length) {
|
|
|
+ //console.log('--- onItemAdd fieldExport.selectize(',fieldExport.selectize,')', fieldExport);
|
|
|
+ if (fieldExport.get(0).selectize) {
|
|
|
+ fieldExport.get(0).selectize.addOption({id:curSel.exports[i], name:curSel.exports[i]});
|
|
|
+ fieldExport.get(0).selectize.setValue(curSel.exports[i]);
|
|
|
+ } else {
|
|
|
+ //jQuery('#f' + i).val(curSel.exports[i]);
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ fieldExport = jQuery('#f' + i);
|
|
|
+ if (fieldExport.is('input')) {
|
|
|
+ jQuery('#f' + i).val(curSel.exports[i]);
|
|
|
+ } else if (fieldExport.is('select')) {
|
|
|
+ //TODO: add option and select //jQuery('#f' + i).val(curSel.exports[i]);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ },
|
|
|
+ score: scoreCallback,
|
|
|
+ load: function(query, callback) {
|
|
|
+ // if (!query.length) return callback(); // empty query at preload action
|
|
|
+ $.ajax({
|
|
|
+ url: ajaxDataUrlBase,
|
|
|
+ data: 'q=' + encodeURIComponent(query),
|
|
|
+ type: 'POST',
|
|
|
+ error: function() {
|
|
|
+ callback();
|
|
|
+ },
|
|
|
+ success: getFetchCallback(query, callback),
|
|
|
+ });
|
|
|
+ }
|
|
|
+ });
|
|
|
+ },
|
|
|
+ render: function () {
|
|
|
+ if(DBG)console.log('TS::render (['+this.props.idField+'] '+this.props.fieldNamespace+') props', this.props)
|
|
|
+ return h('div', {
|
|
|
+ 'className': "typespecial",
|
|
|
+ 'style': { 'max-width': '366px' }
|
|
|
+ }, [
|
|
|
+ h('select', {
|
|
|
+ 'ref': function (node) { this.rootNode = node; }.bind(this),
|
|
|
+ }, this.props.children)
|
|
|
+ ])
|
|
|
+ }
|
|
|
+ })
|
|
|
+ global.p5VendorJs['P5UI__Typespecial'] = P5UI__Typespecial
|
|
|
+
|
|
|
+ var P5UI__FeatureRowFunctions = createReactClass({
|
|
|
+ componentDidMount: function () {
|
|
|
+ if(DBG)console.warn('P5UI__FeatureRowFunctions::componentDidMount this.rootNode', this.rootNode)
|
|
|
+ if (this.props.rawHtml) {
|
|
|
+ if(DBG)console.warn('P5UI__FeatureRowFunctions::componentDidMount this.props.rawHtml', this.props.rawHtml)
|
|
|
+ this.rootNode.innerHTML = this.props.rawHtml
|
|
|
+ }
|
|
|
+ },
|
|
|
+ render: function () {
|
|
|
+ var showLabels = this.props.showLabels || false
|
|
|
+ var functions = this.props.functions || {}
|
|
|
+ if (!this.props.id) return h('div', { 'className': 'alert alert-danger' }, "Missing ID")
|
|
|
+ if(DBG)console.warn('P5UI__FeatureRowFunctions::render this.props', this.props)
|
|
|
+ return h('div', {
|
|
|
+ ref: function (node) { this.rootNode = node; }.bind(this),
|
|
|
+ }, [
|
|
|
+ ('hist' in functions)
|
|
|
+ ? h('a', { className: "btn btn-xs btn-link", href: functions.hist.href.replace("{0}", this.props.id), title: functions.hist.title }, [ h('span', { className: functions.hist.ico }), h('span', { style: {'padding': '0 6px'} }, functions.hist.title) ])
|
|
|
+ : null
|
|
|
+ ,
|
|
|
+ ('files' in functions)
|
|
|
+ ? h('a', { className: "btn btn-xs btn-link", href: functions.files.href.replace("{0}", this.props.id), title: functions.files.title }, [ h('span', { className: functions.files.ico }), h('span', { style: {'padding': '0 6px'} }, functions.files.title) ])
|
|
|
+ : null
|
|
|
+ ,
|
|
|
+ ('msgs' in functions)
|
|
|
+ ? h('a', { className: "btn btn-xs btn-link", href: functions.msgs.href.replace("{0}", this.props.id), title: functions.msgs.title }, [ h('span', { className: functions.msgs.ico }), h('span', { style: {'padding': '0 6px'} }, functions.msgs.title) ])
|
|
|
+ : null
|
|
|
+ ,
|
|
|
+ (this.props.viewMoreDropdown)
|
|
|
+ ? h(P5UI__DropdownAjax, this.props.viewMoreDropdown)
|
|
|
+ : null
|
|
|
+ ,
|
|
|
+ ])
|
|
|
+ }
|
|
|
+ })
|
|
|
+ global.p5VendorJs['P5UI__FeatureRowFunctions'] = P5UI__FeatureRowFunctions
|
|
|
+
|
|
|
+ var P5UI__DropdownAjax = createReactClass({
|
|
|
+ componentDidMount: function () {
|
|
|
+ jQuery(this.rootNode).popover({
|
|
|
+ container: 'body',
|
|
|
+ placement: 'bottom',
|
|
|
+ trigger: 'click',
|
|
|
+ // title: e.data.col + '<a href="#" class="glyphicon glyphicon-remove pull-right" onclick="return hidePopover();"></a>',
|
|
|
+ title: 'Więcej funkcji dla rekordu nr ' + this.props.primaryKey, // '<div style="display:block;position:relative;padding:0 20px 0 0;">' + (this.props.friendly || colName) + ' <button type="button" class="close" onclick="return hidePopover();" style="position:absolute;right:0;top:0;">×</button>' + '</div>',
|
|
|
+ html: true,
|
|
|
+ content: 'TODO: list...', // this.renderListToString.bind(this),
|
|
|
+ template: '' +
|
|
|
+ '<div class="popover" role="tooltip" style="max-width:600px;width:400px;">' +
|
|
|
+ '<div class="arrow"></div>' +
|
|
|
+ '<div style="display:block;position:relative;">' +
|
|
|
+ '<div class="popover-title">' +
|
|
|
+ '</div>' +
|
|
|
+ '</div>' +
|
|
|
+ '<div class="popover-content"></div>' +
|
|
|
+ '</div>'
|
|
|
+ })
|
|
|
+ this.setState({ 'isOpen': false })
|
|
|
+ },
|
|
|
+ componentWillUnmount: function () {
|
|
|
+ jQuery(this.rootNode).popover('desctroy')
|
|
|
+ },
|
|
|
+ componentWillMount: function() {
|
|
|
+ this._closeDropdownIfClickedOutside = function (event) {
|
|
|
+ if (!this.state.isOpen) return;
|
|
|
+
|
|
|
+ var idHtmlPopover = jQuery(this.rootNode).attr('aria-describedby')
|
|
|
+ if(DBG)console.warn("P5UI__DropdownAjax::_closeDropdownIfClickedOutside idHtmlPopover:", idHtmlPopover)
|
|
|
+ if (!idHtmlPopover) return;
|
|
|
+
|
|
|
+ var popoverNode = document.getElementById(idHtmlPopover)
|
|
|
+ if (p5UI__clickedOutsideElement(popoverNode, event)) {
|
|
|
+ this.setState({
|
|
|
+ isOpen: false
|
|
|
+ }, this._unbindCloseDropdownIfClickedOutside);
|
|
|
+ jQuery(this.rootNode).popover('hide')
|
|
|
+ }
|
|
|
+ }.bind(this);
|
|
|
+ this._bindCloseDropdownIfClickedOutside = function () {
|
|
|
+ if (!document.addEventListener && document.attachEvent) {
|
|
|
+ document.attachEvent('onclick', this._closeDropdownIfClickedOutside);
|
|
|
+ } else {
|
|
|
+ document.addEventListener('click', this._closeDropdownIfClickedOutside);
|
|
|
+ }
|
|
|
+ }.bind(this);
|
|
|
+ this._unbindCloseDropdownIfClickedOutside = function () {
|
|
|
+ if (!document.removeEventListener && document.detachEvent) {
|
|
|
+ document.detachEvent('onclick', this._closeDropdownIfClickedOutside);
|
|
|
+ } else {
|
|
|
+ document.removeEventListener('click', this._closeDropdownIfClickedOutside);
|
|
|
+ }
|
|
|
+ }.bind(this);
|
|
|
+ },
|
|
|
+ shouldComponentUpdate: function (nextProps, nextState) {
|
|
|
+ if (!nextState) return false
|
|
|
+ if (!this.state) return false
|
|
|
+ if (this.state.rowFunctions !== nextState.rowFunctions) {
|
|
|
+ var idHtmlPopover = jQuery(this.rootNode).attr('aria-describedby')
|
|
|
+ if(DBG)console.warn("P5UI__DropdownAjax::shouldComponentUpdate idHtmlPopover:", idHtmlPopover, 'nextState.rowFunctions', nextState.rowFunctions)
|
|
|
+ if (idHtmlPopover && nextState.rowFunctions && nextState.rowFunctions.length) {
|
|
|
+ jQuery(document.getElementById(idHtmlPopover)).find('.popover-content').html(this.renderListToString(nextState.rowFunctions))
|
|
|
+ } else {
|
|
|
+ jQuery(document.getElementById(idHtmlPopover)).find('.popover-content').html('<p class="text-muted">Brak dodatkowych funkcji</p>')
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return false
|
|
|
+ },
|
|
|
+ renderListToString: function (list) {
|
|
|
+ if(DBG)console.warn('P5UI__DropdownAjax::renderListToString - this.state:', this.state)
|
|
|
+ var primaryKey = this.props.id
|
|
|
+ var out = '<ul class="list-unstyled">' + list.map(function (fun) {
|
|
|
+ return '<li><a href="'+fun.href.replace('{0}', primaryKey)+'" style="margin:0 2px;" title="'+fun.title+'">' +
|
|
|
+ (fun.ico ? '<span class="'+fun.ico+'"></span> ' : '') +
|
|
|
+ fun.label +
|
|
|
+ '</a></li>'
|
|
|
+ }).join('') + '</ul>'
|
|
|
+ if(DBG)console.warn('P5UI__DropdownAjax::renderListToString - out:', out)
|
|
|
+ return out
|
|
|
+ },
|
|
|
+ onAjaxFetch: function (data) {
|
|
|
+ this.setState({ rowFunctions: data.rowFunctions })
|
|
|
+ },
|
|
|
+ handleClick: function (e) {
|
|
|
+ e.preventDefault()
|
|
|
+ if(DBG)console.warn("P5UI__DropdownAjax::handleClick TODO: dropdown clicked - state:", this.state)
|
|
|
+ if (!this.props.uri) throw "Missing uri in P5UI__DropdownAjax"
|
|
|
+ if (this.state.isOpen) {
|
|
|
+ jQuery(this.rootNode).popover('hide')
|
|
|
+ } else {
|
|
|
+ jQuery(this.rootNode).popover('show')
|
|
|
+ var idHtmlPopover = jQuery(this.rootNode).attr('aria-describedby')
|
|
|
+ if (idHtmlPopover) {
|
|
|
+ jQuery(document.getElementById(idHtmlPopover)).find('.popover-content').html('<p>Loading...</p>')
|
|
|
+ }
|
|
|
+ // global.fetch()
|
|
|
+ // setTimeout(this.onAjaxFetch.bind(this, { msg: "Funkcje", type: "success", rowFunctions: [
|
|
|
+ // { id: "msgs", ico: "glyphicon glyphicon-envelope", href: "index.php?_route=TableMsgs&_task=tableRow&idTable=13051&idRow=83", label: 'Wiadomości <span class="badge">0</badge>', title: "Wiadomości (0)" },
|
|
|
+ // { ico: "glyphicon glyphicon-file", href: "https://biuro.biall-net.pl/dev-pl/se-master/index.php?_route=UrlAction_Ant&typeName=default_db:TEST_PERMS&primaryKey=83", label: 'Druki', title: "Druki" },
|
|
|
+ // ] }), 1000)
|
|
|
+ _popoverCellAjaxXhr = jQuery.ajax({
|
|
|
+ type: 'GET',
|
|
|
+ url: this.props.uri,
|
|
|
+ dataType: 'json',
|
|
|
+ contentType: "application/json; charset=utf-8",
|
|
|
+ })
|
|
|
+ .done(function(data, textStatus, jqXHR){
|
|
|
+ if (data && 'success' === data.type) {
|
|
|
+ var rowFunctions = (data.rowFunctions && data.rowFunctions.length > 0)
|
|
|
+ ? data.rowFunctions
|
|
|
+ : [];
|
|
|
+ this.setState({ rowFunctions: data.rowFunctions })
|
|
|
+ }
|
|
|
+ }.bind(this))
|
|
|
+ if (this.state.isOpen) this.setState({ 'isOpen': false })
|
|
|
+ else this.setState({ 'isOpen': true }, this._bindCloseDropdownIfClickedOutside)
|
|
|
+ }
|
|
|
+ },
|
|
|
+ render: function () {
|
|
|
+ if(DBG)console.warn('P5UI__DropdownAjax::render this.props', this.props)
|
|
|
+ return h('button', {
|
|
|
+ className: 'btn btn-xs btn-link',
|
|
|
+ ref: function (node) { this.rootNode = node; }.bind(this),
|
|
|
+ onClick: this.handleClick.bind(this)
|
|
|
+ }, [
|
|
|
+ h('span', {'className':"glyphicon glyphicon-menu-hamburger"}),
|
|
|
+ " Więcej "
|
|
|
+ ]);
|
|
|
+ }
|
|
|
+ })
|
|
|
+ global.p5VendorJs['P5UI__DropdownAjax'] = P5UI__DropdownAjax
|
|
|
+
|
|
|
+
|
|
|
+ function buildDom(dom, target) {
|
|
|
+ ReactDOM.render(buildReactNodeRec(dom), target)
|
|
|
+ }
|
|
|
+ function buildReactNodeRec(dom) {
|
|
|
+ if (null === dom) return null
|
|
|
+ if ('string' === typeof dom) return dom
|
|
|
+ var nodeReactType = dom[0]
|
|
|
+ if ('P5UI__' === nodeReactType.substr(0, 'P5UI__'.length)) {
|
|
|
+ if (nodeReactType in global.p5VendorJs) nodeReactType = global.p5VendorJs[nodeReactType]
|
|
|
+ }
|
|
|
+ return h(nodeReactType,
|
|
|
+ convertAttrsToReact(dom[0], dom[1]),
|
|
|
+ (dom[2] && 'function' === typeof dom[2].map)
|
|
|
+ ? dom[2].map(buildReactNodeRec)
|
|
|
+ : dom[2]
|
|
|
+ )
|
|
|
+ }
|
|
|
+ function convertAttrsToReact(tagName, attrs) {
|
|
|
+ if (!attrs) return null
|
|
|
+ if(DBG)console.log('todo convertAttrsToReact typeof attrs ('+ typeof attrs +') toString('+ attrs.toString() +')');
|
|
|
+ if (!attrs.toString()) return null
|
|
|
+ if ('class' in attrs) {
|
|
|
+ attrs['className'] = attrs['class']
|
|
|
+ delete attrs['class']
|
|
|
+ }
|
|
|
+ if ('input' === tagName && 'value' in attrs) { // fix input to uncontrolled
|
|
|
+ attrs['defaultValue'] = attrs['value']
|
|
|
+ delete attrs['value']
|
|
|
+ }
|
|
|
+ if ('input' === tagName && 'maxlength' in attrs) { // fix input to uncontrolled
|
|
|
+ attrs['maxLength'] = attrs['maxlength']
|
|
|
+ delete attrs['maxlength']
|
|
|
+ }
|
|
|
+ return attrs
|
|
|
+ }
|
|
|
+
|
|
|
+ global.p5UI__buildDom = buildDom
|
|
|
+})(window, window.p5VendorJs);
|