/** * Main setupPage application */ define([ 'jquery', 'app/init', 'app/util', 'app/render', 'app/map/worker', 'peityInlineChart', ], ($, Init, Util, Render, MapWorker) => { 'use strict'; let config = { splashOverlayClass: 'pf-splash', // class for "splash" overlay // navigation navigationElementId: 'pf-navbar', // id for navbar element // sticky panel stickyPanelClass: 'pf-landing-sticky-panel', // class for sticky panels hiddenByAttributeClass: 'pf-hidden-by-attr', // class for elements that are hidden/shown by [data-attr] value shownByAttributeClass: 'pf-shown-by-attr', // class for elements that are hidden/shown by [data-attr] value webSocketStatsId: 'pf-setup-webSocket-stats', // id for webSocket "stats" panel webSocketRefreshStatsId: 'pf-setup-webSocket-stats-refresh', // class for "reload stats" button cronRowActiveClass: 'pf-cron-row-active', // class for "active" (e.g. "inProgress") table row jsonPopoverClass: 'pf-json-popover', // class for "json" popover elements barChartClass: 'pf-bar-chart', // class for "bar" chart elements lineChartClass: 'pf-line-chart' // class for "line" chart elements }; /** * send ajax request for index build * @param url * @param requestData * @param context * @param callback */ let sendRequest = (url, requestData, context, callback) => { if(requestData.count === 0){ // first iteration context.target.button('loading'); } $.ajax({ url: url, type: 'POST', dataType: 'json', data: requestData, context: context }).done(function(data){ callback(this, data); }).fail(function(jqXHR, status, error){ let reason = status + ' ' + error; Util.showNotify({title: jqXHR.status + ': Failed. Please retry', text: reason, type: 'warning'}); this.target.button('reset'); }); }; /** * * @param container * @param selector */ let setCollapseObserver = (container, selector) => { container.find(selector).css({cursor: 'pointer'}); container.on('click', selector, function(){ $(this).find('.pf-animate-rotate').toggleClass('right'); }); }; /** * set page observer */ let setPageObserver = () => { let body = $('body'); // navigation (scroll) ---------------------------------------------------------------------------------------- Util.initScrollSpy(document.getElementById(config.navigationElementId), window, { offset: 300 }); // collapse --------------------------------------------------------------------------------------------------- setCollapseObserver(body, '[data-toggle="collapse"]'); // panel actions ---------------------------------------------------------------------------------------------- let collapsedState = false; $('.' + config.stickyPanelClass + ' a[data-panel-action="collapse-all"]').on('click', function(e){ e.preventDefault(); $('.row.collapse').collapse(collapsedState ? 'show' : 'hide'); collapsedState = !collapsedState; }); // buttons ---------------------------------------------------------------------------------------------------- // exclude "download" && "navigation" buttons body.find('.btn') .not('[data-action]') .not('[href^="?export"]') .on('click', function(){ $('.' + config.splashOverlayClass).showSplashOverlay(); }); // build/clear index buttons ---------------------------------------------------------------------------------- // clear index buttons ---------------------------------------------------------------------------------------- body.on('click', '.btn[data-action]', function(e){ e.preventDefault(); e.stopPropagation(); let element = $(this); let url = '/api/setup/' + element.attr('data-action'); let payload = element.attr('data-payload'); let callStartName = element.attr('data-callstart'); let callBackName = element.attr('data-callback'); let callBack = config[callBackName] instanceof Function ? config[callBackName] : () => { console.warn('Invalid callback function name: %s', callBackName); }; let requestData = {}; try{ requestData = Object.assign({}, requestData, JSON.parse(payload)); }catch(error){ console.error('Failed to parse button payload: %s ', payload); } let context = { target: element, url: url }; if(config[callStartName] instanceof Function){ config[callStartName](context); } sendRequest(url, requestData, context, callBack); }); // bar charts (e.g. cronjob table) ---------------------------------------------------------------------------- initBarCharts($('.' + config.barChartClass)); // Json popovers ---------------------------------------------------------------------------------------------- body.on('mouseenter', '.' + config.jsonPopoverClass, function(e){ let element = $(this); if(!element.data('bs.popover')){ let json = element.data('json'); let jsonHighlighted = Render.highlightJson(json); let content = '
' + jsonHighlighted + '';
element.popover({
placement: 'left',
html: true,
trigger: 'hover',
content: content,
container: 'body',
title: 'Last exec. state',
delay: {
show: 180,
hide: 0
}
});
element.popover('show');
}
});
// tooltips ---------------------------------------------------------------------------------------------------
body.initTooltips({
container: 'body'
});
body.on('show.bs.tooltip', e => {
let element = $(e.target);
let level = element.attr('data-level');
if(level && level.length){
element.data('bs.tooltip').$tip.find('.tooltip-inner').addClass('txt-color txt-color-' + level);
}
});
// change url (remove logout parameter)
if(history.pushState){
history.pushState({}, '', location.protocol + '//' + location.host + location.pathname);
}
};
/**
* init "Peity" charts
* @param elements
* @param options
*/
let initBarCharts = (elements, options = {}) => {
let barDangerColor = '#a52521';
let barWarningColor = '#e28a0d';
let barDefaultColor = '#568a89';
// defaultOptions for bar AND line charts
let defaultOptions = {
fill: function(val, i, all){
if(val <= 0){
return barDangerColor;
}else{
// fade out older bars
let opacity = i / all.length;
// limit opacity to min 0.3
opacity = Math.max(opacity, 0.3);
let alphaHex = Math.round(opacity * 255).toString(16);
// set color based on average difference
let avg = this.$el.data('avg') || 0;
let avgBuffer = this.$el.data('avg-buffer') || 0;
let barColor = (val > avg + avgBuffer ) ? barWarningColor : barDefaultColor;
return barColor + (alphaHex.length === 1 ? '0' : '') + alphaHex;
}
},
height: 18,
min: -1,
//max: 2
//width: '100%'
width: '65px'
};
elements.peity('bar', Object.assign({}, defaultOptions, {
padding: 0.1 // bar chart specific
}, options));
};
/**
* @param container
*/
let updateStatusBar = container => {
let statusConfig = ['information', 'hint', 'warning', 'danger', 'success'].map(
type => ({
type: type,
target: container.find('.' + config.hiddenByAttributeClass + ', .' + config.shownByAttributeClass)
.filter('[data-attr-type="' + type + '"]'),
count: container.find('[data-type="' + type + '"]').length
})
);
// show/hide target elements by CSS by attribute update
let typesCheckForSuccess = ['warning', 'danger'];
let checkCount = 0;
for(let config of statusConfig){
// "success" type depends on empty count for checked types
if(typesCheckForSuccess.includes(config.type)){
checkCount += config.count;
}
let count = config.type === 'success' ? checkCount : config.count;
config.target.attr('data-attr', count || '');
}
};
/**
* update cronJob table row
* @type {updateCronjob}
*/
let updateCronjob = config.updateCronjob = (context, responseData) => {
context.target.button('reset');
let jobsData = Util.getObjVal(responseData, 'jobsData') || {};
let html = Util.getObjVal(responseData, 'html');
let jobsCount = Object.keys(jobsData).length;
if(jobsCount && html){
// replace full table tbody or just a single row
let elPanel = context.target.closest('.panel');
let elOld;
let elNew;
if(jobsCount === 1){
// replace single: