var PHPCensor = { intervals: {}, init: function () { // Setup the date locale moment.locale(LANGUAGE); $(document).ready(function () { // Format datetimes $('time[datetime]').each(function() { var thisDate = $(this).attr('datetime'); var formattedDate = moment(thisDate).format($(this).data('format') || 'lll'); $(this).text(formattedDate); }); // Update latest builds every 5 seconds: PHPCensor.getBuilds(); PHPCensor.intervals.getBuilds = setInterval(PHPCensor.getBuilds, 5000); // Update latest project builds every 10 seconds: if (typeof PROJECT_ID != 'undefined') { PHPCensor.intervals.getProjectBuilds = setInterval(PHPCensor.getProjectBuilds, 10000); } PHPCensor.uiUpdated(); }); $(window).on('builds-updated', function (e, data) { PHPCensor.updateHeaderBuilds(data); }); }, getBuilds: function () { $.ajax({ url: APP_URL + 'build/latest', success: function (data) { $(window).trigger('builds-updated', [data]); }, error: PHPCensor.handleFailedAjax }); }, getProjectBuilds: function () { $.ajax({ url: APP_URL + 'project/builds/' + PROJECT_ID + '?branch=' + PROJECT_BRANCH, success: function (data) { $('#latest-builds').html(data); }, error: PHPCensor.handleFailedAjax }); }, updateHeaderBuilds: function (data) { $('.app-pending-list').empty(); $('.app-running-list').empty(); if (!data.pending.count) { $('.app-pending').hide(); } else { $('.app-pending').show(); $('.app-pending .header').text(Lang.get('n_builds_pending', data.pending.count)); $.each(data.pending.items, function (idx, build) { $('.app-pending-list').append(build.header_row); }); } if (!data.running.count) { $('.app-running').hide(); } else { $('.app-running').show(); $('.app-running .header').text(Lang.get('n_builds_running', data.running.count)); $.each(data.running.items, function (idx, build) { $('.app-running-list').append(build.header_row); }); } }, get: function (uri, success) { $.ajax({ url: window.APP_URL + uri, success: function (data) { success(); PHPCensor.uiUpdated(); }, error: PHPCensor.handleFailedAjax }); }, handleFailedAjax: function (xhr) { if (xhr.status == 401) { window.location.href = window.APP_URL + 'session/login'; } }, uiUpdated: function () { $('.duration').each(function () { var seconds = $(this).data('duration'); if (seconds == 0) { return; } $(this).text(moment.duration(seconds, 'seconds').humanize()); }); $('.datetime').each(function () { var dateString = $(this).data('date'); if (!dateString) { return; } $(this).text(moment(dateString).format('lll')); }); } }; PHPCensor.init(); function handleFailedAjax(xhr) { PHPCensor.handleFailedAjax(xhr); } /** * See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/bind * for the details of code below */ if (!Function.prototype.bind) { Function.prototype.bind = function (oThis) { if (typeof this !== "function") { // closest thing possible to the ECMAScript 5 internal IsCallable function throw new TypeError("Function.prototype.bind - what is trying to be bound is not callable"); } var aArgs = Array.prototype.slice.call(arguments, 1), fToBind = this, fNOP = function () { }, fBound = function () { return fToBind.apply(this instanceof fNOP && oThis ? this : oThis, aArgs.concat(Array.prototype.slice.call(arguments))); }; fNOP.prototype = this.prototype; fBound.prototype = new fNOP(); return fBound; }; } /** * Used for delete buttons in the system, just to prevent accidental clicks. */ function confirmDelete(url, subject, reloadAfter) { var dialog = new PHPCensorConfirmDialog({ message: subject + ' will be permanently deleted. Are you sure?', confirmBtnCaption: 'Delete', /* confirm-btn click handler */ confirmed: function (e) { var dialog = this; e.preventDefault(); /* Call delete URL */ $.ajax({ url: url, success: function (data) { if (reloadAfter) { dialog.onClose = function () { window.location.reload(); }; } dialog.showStatusMessage('Successfully deleted!', 1000); }, error: function (data) { dialog.showStatusMessage('Deletion failed! Server says "' + data.statusText + '"'); if (data.status == 401) { handleFailedAjax(data); } } }); } }); dialog.show(); return dialog; } /** * PHPCensorConfirmDialog constructor options object * @type {{message: string, title: string, confirmBtnCaption: string, cancelBtnCaption: string, confirmed: Function}} */ var PHPCensorConfirmDialogOptions = { message: 'The action will be performed and cannot be undone. Are you sure?', title: 'Confirmation Dialog', confirmBtnCaption: 'Ok', cancelBtnCaption: 'Cancel', confirmed: function (e) { this.close(); } }; var PHPCensorConfirmDialog = Class.extend({ /** * @private * @var {bool} Determines whether the dialog has been confirmed */ confirmed: false, /** * @param {PHPCensorConfirmDialogOptions} options */ init: function (options) { options = options ? $.extend(PHPCensorConfirmDialogOptions, options) : PHPCensorConfirmDialogOptions; if (!$('#confirm-dialog').length) { /* Add the dialog html to a page on first use. No need to have it there before first use. */ $('body').append( '