mavensmate
Version:
Core APIs that drive MavensMate IDEs for Salesforce1/Force.com
471 lines (447 loc) • 20.6 kB
HTML
<html>
<head>
{% if project && project.sfdcClient && title %}
<title>MavensMate | {{project.name}} | {{title}}</title>
{% elif title %}
<title>MavensMate | {{title}}</title>
{% else %}
<title>MavensMate</title>
{% endif %}
<link rel="icon" type="image/png" href="{{ mavensmate.ui.getStaticResourcePath() }}/images/favicon.png">
<link rel="stylesheet" href="{{ mavensmate.ui.getStaticResourcePath() }}/lds/assets/styles/salesforce-lightning-design-system.css"></link>
<link rel="stylesheet" href="{{ mavensmate.ui.getStaticResourcePath() }}/css/mavensmate.css"></link>
<link rel="stylesheet" href="{{ mavensmate.ui.getStaticResourcePath() }}/css/prettify.css"></link>
<script>
var baseLocalServerURL = '{{ mavensmate.ui.getBaseUrl() }}';
</script>
<script src="{{ mavensmate.ui.getStaticResourcePath() }}/js/bluebird.min.js" type="text/javascript"></script>
<script src="{{ mavensmate.ui.getStaticResourcePath() }}/js/lodash.min.js" type="text/javascript"></script>
<script src="{{ mavensmate.ui.getStaticResourcePath() }}/js/jquery.js" type="text/javascript"></script>
<script src="{{ mavensmate.ui.getStaticResourcePath() }}/js/jqueryui.js" type="text/javascript"></script>
<script src="{{ mavensmate.ui.getStaticResourcePath() }}/lds/assets/js/jquery.aljs-init.min.js" type="text/javascript"></script>
<script src="{{ mavensmate.ui.getStaticResourcePath() }}/lds/assets/js/jquery.aljs-tabs.min.js" type="text/javascript"></script>
<script src="{{ mavensmate.ui.getStaticResourcePath() }}/lds/assets/js/jquery.aljs-picklist.min.js" type="text/javascript"></script>
<script src="{{ mavensmate.ui.getStaticResourcePath() }}/lds/assets/js/jquery.aljs-modal.min.js" type="text/javascript"></script>
<script src="{{ mavensmate.ui.getStaticResourcePath() }}/lds/assets/js/jquery.aljs-notification.min.js" type="text/javascript"></script>
<script src="{{ mavensmate.ui.getStaticResourcePath() }}/lds/assets/js/jquery.aljs-multi-select.min.js" type="text/javascript"></script>
<script src="{{ mavensmate.ui.getStaticResourcePath() }}/js/prettify.js" type="text/javascript"></script>
<script>
var mavensmate = {};
mavensmate.request = function(opts) {
var self = this;
if (opts.showPageHeaderLoading)
showPageHeaderLoading();
if (opts.async === undefined)
opts.async = true;
this.async = opts.async; // poll the server
this.ajax = opts.ajax;
this.ajax.dataType = opts.ajax.dataType || 'json';
this.ajax.contentType = this.ajax.contentType || 'application/json; charset=utf-8';
this.message = opts.message;
this._getAsyncResult = function(requestId) {
console.log('polling for async result...', requestId);
return new Promise(function(resolve, reject) {
function _pollForAsyncResult(requestId) {
var req = $.ajax({
type: 'GET',
url: '{{ mavensmate.ui.getBaseUrl() }}/execute/'+requestId
});
req
.success(function(res) {
if (res.status === 'pending') {
console.log('request still pending', res);
setTimeout(function() { _pollForAsyncResult(requestId); }, 1000);
} else {
console.log('async polling done', res);
resolve(res);
}
})
.error(function(err) {
reject(err);
});
}
_pollForAsyncResult(requestId);
});
};
return new Promise(function(resolve, reject) {
hideToast();
var loadingPromise = self.async && self.message ? showLoading(self.message.label, self.message.detail) : Promise.resolve();
loadingPromise
.then(function() {
var req = $.ajax(self.ajax)
console.log(req);
req
.success(function(res) {
console.log('ajax call completed successfully, response is:', res);
if (self.async) {
if (res.status === 'pending' && res.id) {
self._getAsyncResult(res.id)
.then(function(res) {
console.log('polling complete', res);
if (res.error) {
showToast(res.error, 'error');
reject(res);
} else {
resolve(res);
}
})
.catch(function(err) {
reject(err);
});
} else {
console.error(res);
showToast('Could not retrieve asynchronous response from server. Your request may have a synchronous request, in which case your mavensmate.request opts should include an async=false flag', 'error');
reject(new Error('Could not retrieve asynchronous response from server. Your request may have a synchronous request, in which case your mavensmate.request opts should include an async=false flag'))
}
} else {
resolve(res);
}
})
.error(function(err) {
console.error('ajax call returned an error', err);
var res;
try {
var res = JSON.parse(err.responseText);
showToast(res.error, 'error');
} catch(e) {
showToast(err.responseText, 'error');
}
reject(err);
});
})
.catch(function(err) {
reject(err);
});
});
};
mavensmate.openProjectInEditor = function(editor, pid) {
pid = pid || '{{project.settings.id}}';
var opts = {
async: false,
ajax: {
type: 'GET',
url: baseLocalServerURL+'/execute',
data: {
command: 'open-project',
editor: editor,
pid: pid
}
}
};
mavensmate.request(opts)
.then(function(response) {
showToast(response.message, 'success');
})
.catch(function(err) {
console.error('could not open project in editor', err);
})
.finally(function() {
hideLoading();
});
}
mavensmate.executeCommand = function(commandName, msg, async, data) {
data = data || {};
if (async === undefined)
async = false;
data.command = commandName;
var opts = {
async: async,
ajax: {
type: 'GET',
url: baseLocalServerURL+'/execute',
data: data
},
message: {
label: msg
}
};
console.log(opts);
mavensmate.request(opts)
.then(function(response) {
showToast(response.message, 'success');
})
.catch(function(err) {
console.error('could not open execute command', err);
})
.finally(function() {
hideLoading();
});
}
var headers = { 'MavensMate-Editor-Agent': '{{ editor }}' };
{% if project && project.settings && project.settings.id %}
headers['MavensMate-pid'] = '{{ project.settings.id }}';
{% endif %}
$.ajaxSetup({
headers: headers
});
$(function() {
$('[data-aljs="modal"]').modal();
$('body').notification();
//focus first input
$("input[type='text']:first").focus();
});
function showLoading(msg, detail) {
return new Promise(function(resolve, reject) {
try {
msg = msg || 'Loading...';
$('#global-loading-modal h2').html(msg);
if (detail) {
$('#global-loading-modal p').html(detail);
$('#global-loading-modal p').show();
} else {
$('#global-loading-modal p').html('');
$('#global-loading-modal p').hide();
}
$('#global-loading-modal').modal('show');
$('#global-loading-modal').on('shown.aljs.modal', function(evt) {
resolve();
});
} catch(e) {
console.error('Could not show global loading indicator', e);
reject(e);
}
});
}
function hideLoading() {
return new Promise(function(resolve, reject) {
try {
$('#global-loading-modal').modal('dismiss');
$('#global-loading-modal').on('dismissed.aljs.modal', function(evt) {
resolve();
});
} catch(e) {
console.error('Could not hide global loading indicator', e);
reject(e);
}
});
}
function notifySound() {
if ({{ mavensmate.ui.config.get('mm_play_sounds') }}) {
var snd = new Audio('{{ mavensmate.ui.getStaticResourcePath() }}/sounds/ding.mp3'); // buffers automatically when created
snd.play();
}
}
function showToast(msg, severity, detail, delay) {
severity = severity || 'info';
if (severity === 'success' && !delay)
delay = 3000;
$('#toast').removeClass('slds-theme--error');
$('#toast').removeClass('slds-theme--info');
$('#toast').removeClass('slds-theme--success');
$('#toast').addClass('slds-theme--'+severity);
$('#toast h2').html(msg);
$('#toast p').html(detail);
$('#toast').notification('show');
var symbolsHref = $('#toast svg.slds-icon use').attr('xlink:href').split('#')[0];
if (severity === 'error') {
symbolsHref += '#warning';
} else if (severity === 'info') {
symbolsHref += '#info';
} else if (severity === 'success') {
symbolsHref += '#check';
}
$('#toast svg.slds-icon use').attr('xlink:href', symbolsHref);
if (delay) {
setTimeout(function() {
$('#toast').notification('dismiss');
}, delay);
}
}
function hideToast() {
$('#toast').notification('dismiss');
}
function showPageHeaderLoading() {
$('#page-header-buttons .slds-button-group').hide();
$('#page-header-loading-indicator').show();
{% if isDesktop %}
ipc.sendToHost('operation:running');
{% endif %}
}
function hidePageHeaderLoading() {
$('#page-header-loading-indicator').hide();
$('#page-header-buttons .slds-button-group').show();
{% if isDesktop %}
ipc.sendToHost('operation:stopped');
{% endif %}
}
function metadataTypeSort(a, b) {
var an = a.getAttribute('id'),
bn = b.getAttribute('id');
if(an > bn) {
return 1;
}
if(an < bn) {
return -1;
}
return 0;
}
</script>
</head>
<body id="body" class="{{ editor }} {% block body_class %}{% endblock %}">
<div class="slds-grid slds-grid--vertical-stretch slds-grid--frame">
{% include 'views/partials/left_menu.html' %}
<div id="frame-right-column" class="slds-p-bottom--large">
<!-- HEADER -->
<div class="" role="banner" id="page-header">
<div class="slds-grid">
<div class="slds-col slds-has-flexi-truncate">
<div class="slds-media slds-media--center slds-no-space slds-grow">
<div class="slds-media__figure">
{% if project %}
<a href="/app/project/{{project.settings.id}}?pid={{project.settings.id}}">
<img src="{{ mavensmate.ui.getStaticResourcePath() }}/images/logo2.png" id="mmlogo"/>
</a>
{% else %}
<a href="{{ mavensmate.ui.getBaseUrl() }}/">
<img src="{{ mavensmate.ui.getStaticResourcePath() }}/images/logo2.png" id="mmlogo"/>
</a>
{% endif %}
</div>
</div>
</div>
<div class="slds-col slds-no-flex slds-grid slds-align-bottom">
{% if isDesktop %}
<!-- app is embedded in mavensmate-desktop so we use its app launcher feature -->
<script type="text/javascript">
// TODO: add url blacklist for URLs where we DO NOT want them to be opened via window.open
var ipc = require('electron').ipcRenderer;
$(function() {
// when page loads, we send contextual information to mavensmate-desktop
ipc.sendToHost('on-load', {
title: '{{title|addslashes}}',
{% if project %}
pid: '{{project.settings.id}}',
projectName: '{{project.name|addslashes}}',
{% endif %}
{% if sldsIconClassName %}
sldsIconName: '{{sldsIconName}}',
sldsIconClassName: '{{sldsIconClassName}}',
sldsSprite: '{{sldsSprite}}',
{% endif %}
});
ipc.on('close-project', function(evt, pid) {
var opts = {
async: false,
ajax: {
type: 'POST',
url: baseLocalServerURL+'/project/'+pid+'/close',
data: {
pid: '{{project.settings.id}}'
}
}
};
mavensmate.request(opts)
.then(function(res) {
console.log('project closed', res);
})
.catch(function(err) {
console.error('could not close project', err);
});
});
});
</script>
<a class="slds-button slds-button--icon slds-align-middle" onClick="ipc.send('show-view-manager');">
<svg aria-hidden="true" class="slds-button__icon slds-button__icon--large">
<use xlink:href="{{ mavensmate.ui.getStaticResourcePath() }}/lds/assets/icons/utility-sprite/svg/symbols.svg#apps"></use>
</svg>
<span class="slds-assistive-text">Launcher</span>
</a>
{% endif %}
<a class="slds-button slds-button--icon slds-align-middle" href="/app/settings{% if project %}?pid={{project.settings.id}}{% endif %}">
<svg aria-hidden="true" class="slds-button__icon slds-button__icon--large">
<use xlink:href="{{ mavensmate.ui.getStaticResourcePath() }}/lds/assets/icons/utility-sprite/svg/symbols.svg#settings"></use>
</svg>
<span class="slds-assistive-text">Settings</span>
</a>
{% if project && mavensmate.ui.getPhotoUrl(project)%}
<img style="border-radius:4px;height:30px;margin-left: 0.4rem;" src="{{mavensmate.ui.getPhotoUrl(project)}}"/>
{% else %}
<div style="border-radius:4px;height:30px;margin-left: 0.4rem;"></div><!-- spacer -->
{% endif %}
</div>
</div>
</div>
<!-- END HEADER -->
<!-- PAGE HEADER -->
<div class="slds-page-header slds-m-bottom--medium" role="banner" style="padding:0.5rem 1.0rem;margin-top: 53px;">
<div class="slds-grid">
<div class="slds-col slds-has-flexi-truncate">
<div class="slds-media slds-media--center">
{% if sldsIconClassName %}
<div class="slds-media__figure">
<svg aria-hidden="true" class="slds-icon {{sldsIconClassName}}">
<use xlink:href="/app/static/lds/assets/icons/{{sldsSprite}}/svg/symbols.svg#{{sldsIconName}}"></use>
</svg>
</div>
{% endif %}
<div class="slds-media__body">
<p class="slds-page-header__title slds-truncate slds-align-middle" title="{{title}}">{{title}}</p>
{% if project && url.indexOf('/app/settings') !== 0 %}
<p class="slds-text-body--small page-header__info">{{project.name}}</p>
{% endif %}
</div>
</div>
</div>
<div class="slds-col slds-no-flex slds-grid slds-align-bottom" id="page-header-buttons">
<div class="slds-button-group" role="group">
{% block buttons %}{% endblock %}
</div>
<div class="slds-spinner slds-spinner--small" aria-hidden="false" role="alert" id="page-header-loading-indicator">
<div class="slds-spinner__dot-a"></div>
<div class="slds-spinner__dot-b"></div>
</div>
</div>
</div>
</div>
<!-- CONTENT -->
<div class="slds-container--fluid" id="main-wrapper">
<div class="slds-m-left--medium slds-m-right--medium">
{% block yield %}{% endblock %}
</div>
</div>
</div>
</div>
{% block body_js %}{% endblock %}
<!-- GLOBAL TOAST -->
<div class="slds-notify_container">
<div class="slds-notify slds-notify--toast slds-hide" role="alert" id="toast">
<span class="slds-assistive-text">Error</span>
<button class="slds-button slds-button--icon-inverse slds-notify__close" data-aljs-dismiss="notification">
<svg aria-hidden="true" class="slds-button__icon slds-button__icon--large">
<use xlink:href="{{ mavensmate.ui.getStaticResourcePath() }}/lds/assets/icons/utility-sprite/svg/symbols.svg#close"></use>
</svg>
<span class="slds-assistive-text">Close</span>
</button>
<div class="slds-notify__content slds-grid">
<svg aria-hidden="true" class="slds-icon slds-icon--small slds-m-right--small slds-col slds-no-flex">
<use xlink:href="{{ mavensmate.ui.getStaticResourcePath() }}/lds/assets/icons/utility-sprite/svg/symbols.svg#warning"></use>
<use xlink:href="{{ mavensmate.ui.getStaticResourcePath() }}/lds/assets/icons/utility-sprite/svg/symbols.svg#check"></use>
<use xlink:href="{{ mavensmate.ui.getStaticResourcePath() }}/lds/assets/icons/utility-sprite/svg/symbols.svg#info"></use>
</svg>
<div class="slds-col slds-align-middle">
<h2 class="slds-text-heading--small"></h2>
<p></p>
</div>
</div>
</div>
</div>
<!-- LOADING MODAL -->
<div aria-hidden="true" role="dialog" class="slds-modal slds-fade-in-open slds-hide" id="global-loading-modal">
<div class="slds-modal__container">
<div class="slds-modal__header">
<h2 class="slds-text-heading--medium"></h2>
</div>
<div class="slds-modal__content slds-p-around--medium">
<div style="position:relative;min-height:70px;">
<div class="slds-spinner--brand slds-spinner slds-spinner--large" aria-hidden="false" role="alert">
<div class="slds-spinner__dot-a"></div>
<div class="slds-spinner__dot-b"></div>
</div>
</div>
<p class="slds-m-top--medium" style="text-align:center;"></p>
</div>
</div>
</div>
{% include 'views/partials/project_modal.html' %}
</body>
</html>