js.ide.index.jsx Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of DevCenter Show documentation
Show all versions of DevCenter Show documentation
Prompto Development Center POM
const catalog = new Catalog();
let project = null;
let currentContent = null;
function getParam(name) {
// return new URL(window.location.href).searchParams.get(name);
return new RegExp('[\?&]' + name + '=([^]*)').exec(window.location.href)[1];
}
function makeTreeId(content) {
return content.type==="Prompto" ?
content.subType + "_" + makeValidId(content.name) :
content.value.mimeType.replace("/", "_") + "_" + makeValidId(content.value.name);
}
function saveBlob() {
const blob = new Blob(["Hello, world!"], {type: "text/plain;charset=utf-8"});
saveAs(blob,'test.txt');
}
function getEditorWindow() {
const frame = document.getElementById("editor");
return frame.contentWindow;
}
function editorReady() {
setEditorDefaults();
loadProject(true);
}
function setEditorDefaults() {
const window = getEditorWindow();
window.setDialect("E");
}
function loadProject(loadDependencies) {
const dbId = getParam("dbId");
loadCodeInWorker(dbId, loadDependencies);
loadDescription(dbId);
loadResources(dbId);
}
function loadDescription(dbId) {
var params = [{name: "dbId", value: dbId.toString()}, {name: "register", type: "Boolean", value: false}];
var url = '/ws/run/getModuleDescription?params=' + JSON.stringify(params);
loadJSON(url, function (response) {
if (response.error)
alert(response.error);
else
project = response.data;
});
}
function loadResources(dbId) {
const params = [ {name:"dbId", value:dbId} ];
const url = '/ws/run/getModuleResources?params=' + JSON.stringify(params);
loadJSON(url, function(response) {
if (response.error)
alert(response.error);
else {
const resources = response.data.value;
const delta = { added: { resources: resources}};
catalogUpdated(delta, () => {});
catalog.markResources(resources, "CLEAN");
}
});
}
function loadJSON(url, success) {
loadText(url, function (text) {
const json = JSON.parse(text);
success(json);
});
}
function loadText(url, success) {
const xhr = new XMLHttpRequest();
xhr.onerror = function(e) {
self.console.log("Error " + e.target.status + " occurred while receiving the document.");
return null;
};
xhr.onload = function(e) {
if(success)
success(xhr.responseText);
};
xhr.open('GET', url);
//noinspection EqualityComparisonWithCoercionJS
if(url[0]!="/" && url[0]!=".")
xhr.setRequestHeader("Access-Control-Allow-Origin", "*");
xhr.send(null);
}
function loadCodeInWorker(dbId, loadDependencies) {
const window = getEditorWindow();
window.setProject(dbId, loadDependencies);
}
class GroupTree extends React.Component {
constructor(props) {
super(props);
this.renderItem = this.renderItem.bind(this);
this.toggleTreeNode = this.toggleTreeNode.bind(this);
this.itemClicked = this.itemClicked.bind(this);
}
render() {
let items = this.props.items;
if(!this.props.showLibraries)
items = items.filter(item => !item.core);
return
{
items.map(item => { return this.renderItem(item); }, this)
}
}
renderItem(item) {
const key = this.props.type + "_" + makeValidId(item.name);
const className = 'list-group-item' + (item.core ? ' core' : '');
return
{item.name}
{item.core && }
;
}
toggleTreeNode(e) {
$(e.target).parent().children('ul').toggle(300);
}
itemClicked(e) {
e.stopPropagation();
const a = $(e.target);
let content = { type: "Prompto", subType: this.props.type, name: a.text() };
content.core = a.attr("core") ? eval(a.attr("core")) : false;
setEditorContent(content);
}
}
class MethodTree extends GroupTree {
constructor(props) {
super(props);
this.renderItem = this.renderItem.bind(this);
this.renderProto = this.renderProto.bind(this);
}
renderItem(method) {
const key = this.props.type + "_" + makeValidId(method.name);
const className = 'list-group-item' + (method.core ? ' core' : '');
if(method.protos.length>1) {
return
{
method.protos.map(proto => {
return this.renderProto(method, proto);
}, this)
}
;
} else {
const proto = method.protos[0];
return
{method.name}
{method.core && }
;
}
}
renderProto(method, proto) {
const key = this.props.type + "_" + makeValidId(proto.proto);
const className = 'list-group-item' + (method.core ? ' core' : '');
return
{proto.proto}
{ method.core && }
;
}
itemClicked(e) {
e.stopPropagation();
const a = $(e.target);
const name = a.attr("name");
const proto = a.attr("proto");
const core = a.attr("core") ? eval(a.attr("core")) : false;
const main = a.attr("main") ? eval(a.attr("main")) : false;
const content = { type: "Prompto", subType: this.props.type, name: name, proto: proto, core: core, main: main };
setEditorContent(content);
}
}
class TextResourceTree extends GroupTree {
constructor(props) {
super(props);
this.renderItem = this.renderItem.bind(this);
this.itemClicked = this.itemClicked.bind(this);
}
renderItem(item) {
const key = item.value.mimeType.replace("/", "_") + "_" + makeValidId(item.value.name);
return
{item.value.name}
;
}
itemClicked(e) {
e.stopPropagation();
const a = $(e.target);
let content = { type: this.props.type, name: a.text() };
content.body = catalog.getResourceBody(content);
setEditorContent(content);
}
}
class BinaryResourceTree extends GroupTree {
constructor(props) {
super(props);
this.renderItem = this.renderItem.bind(this);
this.itemClicked = this.itemClicked.bind(this);
}
renderItem(item) {
const key = item.value.mimeType.replace("/", "_") + "_" + makeValidId(item.value.name);
return
{item.value.name}
;
}
itemClicked(e) {
e.stopPropagation();
const a = $(e.target);
let content = { type: this.props.type, name: a.text() };
let resource = catalog.resourceFromContent(content);
if(resource.value.data)
content.data = resource.value.data;
else if(resource.value.file)
content.file = resource.value.file;
setEditorContent(content);
}
}
class ProjectTree extends React.Component {
render() {
const catalog = this.props.catalog;
return
-
-
;
}
toggleShowLibraries(e) {
showLibraries(e.target.checked);
}
toggleTreeNode(e) {
$(e.target).parent().children('div').toggle(300);
}
}
function showLibraries(show) {
catalog.showLibraries = show;
ReactDOM.render(, document.getElementById('project-tree'));
}
function catalogUpdated(delta, callback) {
catalog.applyDelta(delta);
ReactDOM.render(, document.getElementById('project-tree'), callback);
}
function installDialectDropdownHandler() {
$('#nav-dialect').click(function (e) {
if(e.target.id.indexOf('dialect-')===0) {
$('li').removeClass('active');
$(e.target).parent().addClass('active');
const dialect = e.target.id.substring('dialect-'.length, 'dialect-'.length + 1);
const window = getEditorWindow();
window.setDialect(dialect);
}
});
}
function installNewDropdownHandler() {
$('#nav-new').click(function (e) {
if(e.target.id.indexOf('new-')===0) {
const label = $(e.target).text();
const type = e.target.id.substring('new-'.length);
if(type==='Prompto')
setEditorContent({ type: "Prompto" });
else if(type==='Image' || type==='Audio' || type==='Video' || type==='Other')
newFileResource(type, label);
else
newTextResource(type, label);
}
});
}
function renderNavbar() {
const projectName = getParam("name");
ReactDOM.render(Prompto Code Editor for: {projectName}, document.getElementById('project-name'));
}
$(document).ready(function () {
renderNavbar();
installDialectDropdownHandler();
installNewDropdownHandler();
});
function selectContentInProjectTree(content) {
const id = makeTreeId(content);
const leaf = $("#" + id);
leaf.parentsUntil("#project-tree").show(50);
leaf.trigger("click");
}
function isTextResourceContent() {
return currentContent &&
currentContent.type !== "Prompto" &&
currentContent.type !== "Image" &&
currentContent.type !== "Audio" &&
currentContent.type !== "Video" &&
currentContent.type !== "Other";
}
function setEditorContent(content) {
if(content && content===currentContent)
return;
const window = getEditorWindow();
if(isTextResourceContent()) {
currentContent.body = window.getResourceBody();
catalog.setResourceBody(currentContent);
}
currentContent = content;
window.setContent(content);
}
class NewTextResourceDialog extends React.Component {
constructor(props) {
super(props);
this.state = {folder: getParam("name"), name: '', extension: this.props.type.toLowerCase().replace(" ", "-")};
this.handleFolder = this.handleFolder.bind(this);
this.handleName = this.handleName.bind(this);
this.handleExtension = this.handleExtension.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
}
render() {
const placeholder = this.props.label;
return
New {this.props.label}
;
}
handleFolder(event) {
this.state.folder = event.target.value;
}
handleName(event) {
this.state.name = event.target.value;
}
handleExtension(event) {
this.state.extension = event.target.value;
}
handleSubmit(event) {
const path = this.state.folder + "/" + this.state.name + "." + this.state.extension;
this.props.submit(this.props.type, path);
}
}
function newTextResource(type, label) {
ReactDOM.render(, document.getElementById('new-resource'));
const dialog = $("#new-resource");
dialog.on('shown.bs.modal', () => $("#nameInput").focus());
dialog.modal();
}
function createTextResource(type, path) {
const id = createTextResourceInCatalog(type, path, () => selectContentInProjectTree(id));
$('#new-resource').modal('toggle');
}
function createTextResourceInCatalog(type, path, callback) {
const methodName = "createResource" + type;
if(!window[methodName])
alert("No such method:" + methodName);
const content = window[methodName](path);
content.value.module = { type: "Module", value: { dbId: getParam("dbId") } };
const delta = { added: { resources: [content]}};
catalogUpdated(delta, callback);
return content;
}
function createResourceHtml(path) {
return {
type: "TextResource",
value: {
name: path,
mimeType: "text/html",
body: "\n" +
"\n" +
"\t\n" +
"\t\n" +
"\t\n" +
"\t\tHello!\n" +
"\t\n" +
""
}
};
}
function createResourceJs(path) {
return {
type: "TextResource",
value: {
name: path,
mimeType: "text/javascript",
body: "function hello() {\n" +
"\talert('Hello');\n" +
"}"
}
};
}
function createResourceJsx(path) {
return {
type: "TextResource",
value: {
name: path,
mimeType: "text/babel",
body: "function hello() {\n" +
"\talert('Hello');\n" +
"}"
}
};
}
function createResourceCss(path) {
return {
type: "TextResource",
value: {
name: path,
mimeType: "text/css",
body: "body {\n" +
"\tbackground-color: white;\n" +
"}"
}
};
}
function createResourceJson(path) {
return {
type: "TextResource",
value: {
name: path,
mimeType: "text/json",
body: '{ "field": 123 }'
}
};
}
function createResourceXml(path) {
return {
type: "TextResource",
value: {
name: path,
mimeType: "text/xml",
body: '\n' +
'\n' +
'\tdata\n' +
' \n'
}
};
}
function createResourceYaml(path) {
return {
type: "TextResource",
value: {
name: path,
mimeType: "text/yaml",
body: 'invoice: 34843\n' +
'date : 2001-01-23\n' +
'bill-to: &id001\n' +
'\tgiven : Chris\n' +
'\tfamily : Dumars\n' +
'\taddress:\n' +
'\t\tlines: |\n' +
'\t\t\t458 Walkman Dr.\n' +
'\t\t\tSuite #292\n' +
'\t\tcity : Royal Oak\n' +
'\t\tstate : MI\n' +
'\t\tpostal : 48046\n'
}
};
}
function createResourceTxt(path) {
return {
type: "TextResource",
value: {
name: path,
mimeType: "text/plain",
body: 'Hello there!'
}
};
}
const DroppedFileWidget = widgets.DroppedFileWidget.default;
const DroppedWidgetStyle = {
display: 'inline-flex',
border: '1px solid lightgray',
height: '300px',
width: '650px',
padding: '20px',
alignItems: 'center',
justifyContent: 'center'
};
class NewFileResourceDialog extends React.Component {
constructor(props) {
super(props);
this.state = {folder: getParam("name"), file: null};
this.handleFolder = this.handleFolder.bind(this);
this.handleName = this.handleName.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
this.handleDrop = this.handleDrop.bind(this);
}
render() {
return
New {this.props.label}
;
}
handleDrop(file) {
this.setState({ file: file, name: file.name });
}
handleFolder(event) {
this.setState({ folder: event.target.value });
}
handleName(event) {
this.setState({ name: event.target.value });
}
handleSubmit(event) {
const path = this.state.folder + "/" + this.state.name;
this.props.submit(this.props.type, path, this.state.file);
}
}
function newFileResource(type, label) {
ReactDOM.render(, document.getElementById('new-resource'));
const dialog = $("#new-resource");
dialog.on('shown.bs.modal', () => $("#nameInput").focus());
dialog.modal();
}
function createFileResource(type, path, file) {
const id = createFileResourceInCatalog(type, path, file, () => selectContentInProjectTree(id));
$('#new-resource').modal('toggle');
}
function createFileResourceInCatalog(type, path, file, callback) {
const content = {
type: "BinaryResource",
value: {
name: path,
mimeType: file.type,
file: file
}
};
content.value.module = { type: "Module", value: { dbId: getParam("dbId") } };
const delta = { added: { resources: [content]}};
catalogUpdated(delta, callback);
return content;
}
class ImageDisplayer extends React.Component {
constructor(props) {
super(props);
this.loadPreview = this.loadPreview.bind(this);
this.state = { preview: null};
this.loadPreview(this.props.file);
}
componentWillReceiveProps(nextProps) {
if(this.props.file !== nextProps.file) {
this.setState({preview: null});
this.loadPreview(nextProps.file);
}
}
loadPreview(file) {
if(file && file.type.startsWith("image/")) {
const reader = new FileReader();
reader.onload = (e) => {
this.setState({ preview: e.target.result });
};
reader.readAsDataURL(file);
}
}
render() {
const source = this.props.source || this.state.preview;
const state = source ? "PREVIEW" : "LOADING";
return
{ state==="PREVIEW" && }
{ state==="LOADING" && 'Loading...' }
}
}
function setContentImage(element, content) {
ReactDOM.render( , element);
}
function destroy() {
if(currentContent===null)
window.alert("Nothing to destroy!");
else {
const id = currentContent;
currentContent = null;
const window = getEditorWindow();
window.destroy(id);
}
}
function revert() {
// TODO confirm
setEditorContent({ type: "Prompto" });
loadProject(false);
}
function commit() {
// TODO confirm
setEditorContent({ type: "Prompto" });
const window = getEditorWindow();
window.prepareCommit();
}
function commitPrepared(declarations) {
let resources = catalog.prepareCommit();
if((declarations && declarations.length) || (resources && resources.length)) {
const form = new FormData();
if(resources && resources.length)
resources = prepareResourceFiles(form, resources);
const stuff = (declarations || []).concat(resources || []);
const params = JSON.stringify([{name: "edited", type: "EditedStuff[]", value: stuff}]);
form.append("params", params);
const xhr = new XMLHttpRequest();
xhr.upload.addEventListener('load', function(success) { commitSuccessful(success); });
xhr.addEventListener('error', function(failure) { commitFailed(failure); });
xhr.open('POST', '/ws/run/storeEdited', true);
xhr.send(form);
}
}
function prepareResourceFiles(formData, resources) {
return resources.map(res => {
let stuff = res.value.stuff;
if(stuff.type==="BinaryResource" && stuff.value.file) {
stuff = Object.assign({}, stuff);
stuff.value.data = { mimeType: stuff.value.file.type, partName: "@" + stuff.value.file.name };
formData.append(stuff.value.data.partName, stuff.value.file);
delete stuff.value.file;
res.value.stuff = stuff;
}
return res;
});
}
function commitFailed(failure) {
alert("Commit failed!"); // TODO send to UI
}
function commitSuccessful(success) {
alert("Commit ok!");
const window = getEditorWindow();
window.commitSuccessful();
}
function setRunMode(label) {
$("#run-mode").html(" " + label + " " + "");
}
function getRunMode() {
const text = $("#run-mode").text();
const mode = text.indexOf("compiled")>=0 ? "EXECUTE/" : "INTERPRET/";
return mode + (text.indexOf("Server")>=0 ? "REMOTE" : "LOCAL");
}
function run() {
const msg = getRunnableAlert(currentContent);
if (msg)
alert(msg);
else if (currentContent.type === "Html")
openWebPage(currentContent);
else
runPromptoCode();
}
function stopServer() {
fetchModuleURL((url)=>{
var fullUrl = url + "ws/control/exit";
loadText(fullUrl);
});
}
function resetServer() {
fetchModuleURL((url)=>{
var fullUrl = url + "ws/control/clear-context";
loadText(fullUrl);
});
}
function openWebPage(id) {
const tab = window.open(window.location.href, '_blank', '');
fetchModuleURL((url)=>{
tab.location = url + id.name;
tab.focus();
});
}
function fetchModuleURL(success) {
const dbId = getParam("dbId");
const params = [ {name:"dbId", value:dbId.toString()}];
const url = '/ws/run/getModulePort?params=' + JSON.stringify(params);
loadJSON(url, function(response) {
if (response.error)
; // TODO something
else {
const href = self.location.protocol +
"//" + self.location.hostname +
":" + response.data + "/";
success(href);
}
});
}
function runPromptoCode() {
switchUIToRunMode();
print("Running " + currentContent.name + "...");
const runMode = getRunMode();
const window = getEditorWindow();
window.runMethod(currentContent, runMode);
}
function done(data) {
const button = document.getElementById("run-button");
button.innerHTML = "Done";
}
function getRunnableAlert(id) {
if (!id)
return "Nothing to run!";
else if(id.subType==="test")
return null;
else if(id.subType==="method" && id.main)
return null;
else if(id.type=="Html" && project.type==="WebSite")
return null;
else
return "Can only run tests methods, main methods or web pages!";
}
function stop() {
edit();
}
function edit() {
switchUIToEditMode();
}
function switchUIToRunMode() {
const doc = document.getElementById("output");
doc.innerHTML = "";
$(".edit-mode").hide();
$(".run-mode").show();
const button = document.getElementById("run-button");
button.onclick = function() { stop(); };
button.innerHTML = "Stop";
}
function switchUIToEditMode() {
$(".run-mode").hide();
$(".edit-mode").show();
const button = document.getElementById("run-button");
button.onclick = function() { run(); };
button.innerHTML = "Run";
}
function print(msg) {
const doc = document.getElementById("output");
doc.innerHTML += msg + "
";
}
// a utility method to inspect worker data in Firefox/Safari
function inspect(name) {
const window = getEditorWindow();
window.inspect(name);
}
// a utility method to inspect worker data in Firefox/Safari
function inspected(data) {
console.log(data);
}