mirror of
/repos/Prototyper.git
synced 2025-12-30 06:31:32 +01:00
initial commit
This commit is contained in:
commit
9d81b82dde
9
.gitignore
vendored
Normal file
9
.gitignore
vendored
Normal file
@ -0,0 +1,9 @@
|
||||
.hg
|
||||
.idea
|
||||
*.iml
|
||||
.DS_Store
|
||||
*.orig
|
||||
*.swp
|
||||
fleet.json
|
||||
*.log
|
||||
thing
|
||||
35
index.js
Normal file
35
index.js
Normal file
@ -0,0 +1,35 @@
|
||||
var connect = require('connect');
|
||||
var express = require('express');
|
||||
var instance = require('./server.js');
|
||||
|
||||
process.title = "Prototyper";
|
||||
|
||||
var config = {
|
||||
errors: true,
|
||||
debug: false,
|
||||
port: 8000,
|
||||
mongo: {
|
||||
server: "mongodb://silo01.local:27017/Prototyper",
|
||||
options: {
|
||||
server: {
|
||||
maxPoolSize:10,
|
||||
auto_reconnect:true
|
||||
}
|
||||
}
|
||||
},
|
||||
share: {
|
||||
sockjs: {},
|
||||
db: {type: 'none'}
|
||||
}
|
||||
};
|
||||
|
||||
var server = express.createServer();
|
||||
server.use(connect.logger());
|
||||
server.use(express.static(__dirname + '/public'));
|
||||
|
||||
instance(server, config);
|
||||
|
||||
server.listen(config.port, function (err) {
|
||||
// console.log('routes',server.routes);
|
||||
console.log('Server running at http://127.0.0.1:', config.port);
|
||||
});
|
||||
211
mongodata.js
Normal file
211
mongodata.js
Normal file
@ -0,0 +1,211 @@
|
||||
var MongoClient = require('mongodb').MongoClient;
|
||||
var ObjectID = require('mongodb').ObjectID;
|
||||
|
||||
|
||||
module.exports = function (config) {
|
||||
|
||||
function getMongoContent(options, callback) {
|
||||
config.debug && console.log('getMongoContent options', options);
|
||||
MongoClient.connect(config.mongo.server, config.mongo.options, function (err, db) {
|
||||
if (err) {
|
||||
config.debug && console.log('ERR1 getMongoContent',err);
|
||||
return callback(err);
|
||||
}
|
||||
db.collection(options.collection, function (err, col) {
|
||||
if (err) {
|
||||
config.debug && console.log('ERR2 getMongoContent',err);
|
||||
return callback(err);
|
||||
}
|
||||
if (options.query._id && !(options.query._id instanceof Object)) {
|
||||
options.query._id = new ObjectID.createFromHexString(options.query._id);
|
||||
}
|
||||
col.findOne(options.query, function (err, result) {
|
||||
if (err) {
|
||||
config.debug && console.log('ERR3 getMongoContent',err);
|
||||
return callback(err);
|
||||
}
|
||||
if (!result) {
|
||||
return callback(new Error('Data not found ' + options.collection + '/' + JSON.stringify(options.query)));
|
||||
}
|
||||
return callback(null, result, col);
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function getMongoAttribute(options, callback) {
|
||||
config.debug && console.log('getMongoAttribute options', options);
|
||||
return getMongoContent(options, function (err, result) {
|
||||
if (err) {
|
||||
config.errors && console.log('ERR1 getMongoAttribute',err);
|
||||
return callback(err);
|
||||
}
|
||||
var attribute_options = null;
|
||||
config.debug && console.log('getMongoAttribute result', result);
|
||||
if (result && result.hasOwnProperty(options.attribute)) {
|
||||
attribute_options = {
|
||||
collection: options.collection,
|
||||
query: {_id: result[options.attribute].guid}
|
||||
};
|
||||
config.debug && console.log('getMongoAttribute attribute_options', attribute_options);
|
||||
|
||||
return getMongoContent(attribute_options, function (err, attribute_result) {
|
||||
if (err) {
|
||||
config.errors && console.log('ERR2 getMongoAttribute',err);
|
||||
return callback(err);
|
||||
}
|
||||
config.debug && console.log('getMongoAttribute attribute_result', attribute_result);
|
||||
return callback(err, attribute_result);
|
||||
});
|
||||
} else {
|
||||
config.debug && console.log('getMongoAttribute try direct lookup');
|
||||
attribute_options = {
|
||||
collection: options.collection,
|
||||
query: {
|
||||
parent: result._id,
|
||||
name: result.name+'.'+options.attribute
|
||||
}
|
||||
};
|
||||
config.debug && console.log('getMongoAttribute attribute_options', attribute_options);
|
||||
|
||||
return getMongoContent(attribute_options, function (err, attribute_result) {
|
||||
if (err) {
|
||||
config.errors && console.log('ERR3 getMongoAttribute',err);
|
||||
return callback(err);
|
||||
}
|
||||
if (attribute_result) {
|
||||
config.debug && console.log('getMongoAttribute direct attribute_result', attribute_result);
|
||||
return callback(err, attribute_result);
|
||||
} else {
|
||||
if (options.type) {
|
||||
if (options.type == 'json') {
|
||||
config.errors && console.log('ERR4 getMongoAttribute empty json {}');
|
||||
|
||||
return callback(null, '{}');
|
||||
}
|
||||
if (options.type == 'text') {
|
||||
config.errors && console.log('ERR5 getMongoAttribute empty string');
|
||||
return callback(null, '');
|
||||
}
|
||||
}
|
||||
return callback(new Error('Data not found ' + options.collection + '/' + JSON.stringify(options.query) + '.' + options.attribute));
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
})
|
||||
}
|
||||
function saveData(collection, data, callback) {
|
||||
if (data._id && !(data._id instanceof Object)) {
|
||||
data._id = new ObjectID.createFromHexString(data._id);
|
||||
}
|
||||
config.debug && console.log('saving', data._id);
|
||||
collection.save(data, {safe:true}, callback);
|
||||
}
|
||||
|
||||
function setMongoContent(data, options, callback) {
|
||||
config.debug && console.log('setMongoContent options', options);
|
||||
MongoClient.connect(config.mongo.server, config.mongo.options, function (err, db) {
|
||||
if (err) {
|
||||
config.errors && console.log('ERR1 setMongoContent',err);
|
||||
return callback(err);
|
||||
}
|
||||
db.collection(options.collection, function (err, col) {
|
||||
if (err) {
|
||||
config.errors && console.log('ERR2 setMongoContent',err);
|
||||
return callback(err);
|
||||
}
|
||||
if (options.operation) {
|
||||
data.version = options.operation.v;
|
||||
}
|
||||
if (!data._id) {
|
||||
config.debug && console.log('setMongoContent lookup by query',options.query);
|
||||
col.findOne(options.query, function (err, result) {
|
||||
if (result){
|
||||
data._id=result._id;
|
||||
}
|
||||
return saveData(col, data, callback);
|
||||
})
|
||||
} else {
|
||||
return saveData(col, data, callback);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function setMongoAttribute(data, options, callback) {
|
||||
config.debug && console.log('setMongoAttribute options', options);
|
||||
getMongoContent(options, function (err, result, col) {
|
||||
if (err) {
|
||||
config.errors && console.log('ERR1 setMongoAttribute',err);
|
||||
return callback(err);
|
||||
}
|
||||
var attribute_options = {
|
||||
collection: options.collection
|
||||
};
|
||||
if (result.hasOwnProperty(options.attribute)) {
|
||||
config.debug && console.log('getMongoAttribute parent found, get child and save');
|
||||
attribute_options.query = {_id: result[options.attribute].guid};
|
||||
getMongoContent(attribute_options, function (err, attribute_result, col) {
|
||||
if (err) {
|
||||
config.errors && console.log('ERR2 setMongoAttribute',err);
|
||||
return callback(err);
|
||||
}
|
||||
attribute_result[options.attribute] = data;
|
||||
if (options.operation) {
|
||||
attribute_result.version = options.operation.v;
|
||||
}
|
||||
attribute_result.parent = result._id;
|
||||
return saveData(col, attribute_result, callback);
|
||||
});
|
||||
} else {
|
||||
config.debug && console.log('getMongoAttribute try direct lookup');
|
||||
attribute_options = {
|
||||
collection: options.collection,
|
||||
query: {
|
||||
parent: result._id,
|
||||
name: result.name+'.'+options.attribute
|
||||
}
|
||||
};
|
||||
config.debug && console.log('getMongoAttribute attribute_options', attribute_options);
|
||||
return getMongoContent(attribute_options, function (err, attribute_result) {
|
||||
if (attribute_result) {
|
||||
config.debug && console.log('getMongoAttribute found lost attribute, reconnect');
|
||||
result[options.attribute] = { guid: attribute_result._id };
|
||||
return saveData(col, result, callback);
|
||||
|
||||
} else {
|
||||
config.debug && console.log('getMongoAttribute field does not exist yet. need to create doc first.');
|
||||
var attribute_data = {
|
||||
name: result.name + '.' + options.attribute,
|
||||
parent: result._id
|
||||
};
|
||||
attribute_data[options.attribute] = data;
|
||||
if (options.operation) {
|
||||
attribute_data.version = options.operation.v;
|
||||
}
|
||||
|
||||
return saveData(col, attribute_data, function (err, attribute_result) {
|
||||
if(err){
|
||||
config.errors && console.log('ERR3 setMongoAttribute',err);
|
||||
}
|
||||
result[options.attribute] = { guid: attribute_result._id };
|
||||
return saveData(col, result, callback);
|
||||
})
|
||||
}
|
||||
});
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
return {
|
||||
getMongoAttribute: getMongoAttribute,
|
||||
getMongoContent: getMongoContent,
|
||||
setMongoAttribute: setMongoAttribute,
|
||||
setMongoContent: setMongoContent
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
29
package.json
Normal file
29
package.json
Normal file
@ -0,0 +1,29 @@
|
||||
{
|
||||
"name": "Prototyper",
|
||||
"version": "0.0.0",
|
||||
"main": "index.js",
|
||||
"private": "true",
|
||||
"dependencies": {
|
||||
"share": "~0.6.0",
|
||||
"connect": "~2.7.5",
|
||||
"express": "~2.5.11",
|
||||
"mongodb": "~1.2.14",
|
||||
"handlebars": "~1.0.10",
|
||||
"underscore": "~1.4.4",
|
||||
"less": "~1.3.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
"sockjs": "~0.3.5"
|
||||
},
|
||||
"repository": "",
|
||||
"author": "Aiko Mastboom",
|
||||
"license": "BSD",
|
||||
"readmeFilename": "README.md",
|
||||
"directories": {
|
||||
"test": "test"
|
||||
},
|
||||
"description": "README.md",
|
||||
"scripts": {
|
||||
"test": "echo \"Error: no test specified\" && exit 1"
|
||||
}
|
||||
}
|
||||
106
preview.js
Normal file
106
preview.js
Normal file
@ -0,0 +1,106 @@
|
||||
var Handlebars = require('handlebars');
|
||||
var _ = require('underscore');
|
||||
var less = require('less');
|
||||
|
||||
module.exports = function (config) {
|
||||
|
||||
var sourceHead =
|
||||
'<script src="//cdnjs.cloudflare.com/ajax/libs/modernizr/2.6.2/modernizr.min.js"></script>\n' +
|
||||
'{{#if debug}}' +
|
||||
'<link href="/content/{{collection}}/{{name}}/style.css" media="all" rel="stylesheet/less" type="text/css">\n' +
|
||||
'<script src="//cdnjs.cloudflare.com/ajax/libs/less.js/1.3.3/less.min.js"></script>\n' +
|
||||
'{{else}}' +
|
||||
'<link href="/content/{{collection}}/{{name}}/style.css" media="all" rel="stylesheet" type="text/css">\n' +
|
||||
'{{/if}}';
|
||||
|
||||
var sourceBody =
|
||||
'<script src="//cdnjs.cloudflare.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>\n' +
|
||||
'<script src="//cdnjs.cloudflare.com/ajax/libs/knockout/2.2.1/knockout-min.js"></script>\n' +
|
||||
'<script src="//cdnjs.cloudflare.com/ajax/libs/knockout-validation/1.0.2/knockout.validation.min.js"></script>\n' +
|
||||
'<script src="//cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/2.3.1/js/bootstrap.min.js"></script>\n' +
|
||||
'<script src="/content/{{collection}}/{{name}}/behaviour.js"></script>\n';
|
||||
|
||||
var templateHead = Handlebars.compile(sourceHead);
|
||||
var templateBody = Handlebars.compile(sourceBody);
|
||||
|
||||
|
||||
var getCSS = function (callback) {
|
||||
contentInstance.getAllOrderedObjects('Stylesheet', function (err, dataObjects) {
|
||||
if (err) {
|
||||
return callback(err);
|
||||
}
|
||||
|
||||
var stylesheets = _.map(dataObjects, function(dataObject) {
|
||||
return "\n/* -- " + dataObject.get('title') + ' -- */\n\n' +
|
||||
dataObject.get('body');
|
||||
}).join('\n');
|
||||
|
||||
function lessCompilationError(stylesheets, err, callback){
|
||||
stylesheets = "/*\n -- The following ERROR(s) occurred during less compilation:\n\n" +
|
||||
err.message +
|
||||
"\n\n -- you can add ?debug to the preview url to enable browser side less compilation." +
|
||||
"\n\n0: this is line 0 */\n" +
|
||||
stylesheets;
|
||||
return callback(null, stylesheets);
|
||||
}
|
||||
|
||||
try {
|
||||
less.render(stylesheets, function (err, css) {
|
||||
if (err) {
|
||||
return lessCompilationError(stylesheets, err, callback);
|
||||
}
|
||||
return callback(err, css);
|
||||
});
|
||||
} catch (err){
|
||||
return lessCompilationError(stylesheets, err, callback);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
var getJS = function (callback) {
|
||||
contentInstance.getAllOrderedObjects('Behaviour', function (err, dataObjects) {
|
||||
if (err) {
|
||||
return callback(err);
|
||||
}
|
||||
|
||||
var scripts = _.map(dataObjects, function(dataObject) {
|
||||
return dataObject.get('body');
|
||||
}).join('\n');
|
||||
|
||||
callback(null, scripts);
|
||||
});
|
||||
};
|
||||
|
||||
var getPreviewHTML = function (options, content, callback) {
|
||||
|
||||
var html = replaceMarkers(content, templateHead(options), templateBody(options));
|
||||
|
||||
callback(null, html);
|
||||
};
|
||||
|
||||
var replaceMarkers = function (html, styleMarkerReplacement, jsMarkerReplacement) {
|
||||
|
||||
function replace(marker, replacement) {
|
||||
var regExp = new RegExp('<!--\\s*@@' + marker + '\\s*-->');
|
||||
if (html.match(regExp)){
|
||||
html = html.replace(regExp, replacement);
|
||||
} else {
|
||||
html = html.replace('</head>', '<script>if (typeof window.console !== "undefined"){console.log("WARNING: Missing <!--@@' + marker + '-->");}</script>\n</head>');
|
||||
}
|
||||
}
|
||||
|
||||
replace('ipe_style_marker', styleMarkerReplacement);
|
||||
replace('ipe_js_marker', jsMarkerReplacement);
|
||||
|
||||
return html;
|
||||
};
|
||||
|
||||
|
||||
return {
|
||||
getCSS: getCSS,
|
||||
getJS: getJS,
|
||||
getPreviewHTML: getPreviewHTML,
|
||||
_replaceMarkers: replaceMarkers
|
||||
};
|
||||
};
|
||||
|
||||
79
public/behaviour.html
Normal file
79
public/behaviour.html
Normal file
@ -0,0 +1,79 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<link href="style.css" rel="stylesheet" type="text/css">
|
||||
<title>app/main/behaviour</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div id="header">
|
||||
<div id="htext">
|
||||
Editing <b>behaviour</b>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="editor"></div>
|
||||
|
||||
<script src="//cdnjs.cloudflare.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
|
||||
<script src="//cdnjs.cloudflare.com/ajax/libs/knockout/2.2.1/knockout-min.js"></script>
|
||||
<script src="//cdnjs.cloudflare.com/ajax/libs/knockout-validation/1.0.2/knockout.validation.min.js"></script>
|
||||
<script src="//cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/2.3.1/js/bootstrap.min.js"></script>
|
||||
<script src="lib/ace/ace.js" type="text/javascript" charset="utf-8"></script>
|
||||
<!--<script src="lib/ace/mode-html.js" type="text/javascript" charset="utf-8"></script>-->
|
||||
<script src="lib/ace/mode-javascript.js" type="text/javascript" charset="utf-8"></script>
|
||||
<!--<script src="lib/ace/mode-css.js" type="text/javascript" charset="utf-8"></script>-->
|
||||
<!--<script src="lib/ace/mode-markdown.js" type="text/javascript" charset="utf-8"></script>-->
|
||||
<script src="//cdn.sockjs.org/sockjs-0.3.min.js"></script>
|
||||
<!--<script src="/channel/bcsocket.js"></script>-->
|
||||
<!--<script src="/socket.io/socket.io.js"></script>-->
|
||||
<script src="/share/share.uncompressed.js"></script>
|
||||
<script src="/share/json.js"></script>
|
||||
<script src="/share/ace.js"></script>
|
||||
|
||||
<script>
|
||||
var attribute = 'behaviour';
|
||||
var editor = ace.edit("editor");
|
||||
var aceMode = require("ace/mode/javascript").Mode;
|
||||
var session = editor.getSession();
|
||||
session.setMode(new aceMode());
|
||||
|
||||
sharejs.open('json:app:main','json', function (error, main) {
|
||||
var indexField = null;
|
||||
if (error) {
|
||||
console.log('error opening app:main:json', error, main);
|
||||
} else {
|
||||
console.log('yes!!',main);
|
||||
if (main.snapshot == null) {
|
||||
main.submitOp([
|
||||
{ p: [], oi: {name:'main'}, od: null }
|
||||
]);
|
||||
}
|
||||
function openIndex() {
|
||||
if (main.snapshot._id && !indexField){
|
||||
indexField = 'busy';
|
||||
console.log('main.snapshot._id',main.snapshot._id);
|
||||
sharejs.open('text:app:'+main.snapshot._id+':'+attribute, 'text', function(error, index) {
|
||||
if (error) {
|
||||
console.log('error opening text:app:'+main.snapshot._id+':'+attribute, error, index);
|
||||
indexField=null;
|
||||
} else {
|
||||
console.log('yes index!!',index);
|
||||
indexField=index;
|
||||
index.attach_ace(editor);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
openIndex();
|
||||
main.on('change', function (op) {
|
||||
console.log('main:change',op,main.snapshot);
|
||||
openIndex();
|
||||
});
|
||||
|
||||
|
||||
}
|
||||
})
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
79
public/index.html
Normal file
79
public/index.html
Normal file
@ -0,0 +1,79 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<link href="style.css" rel="stylesheet" type="text/css">
|
||||
<title>app/main/index</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div id="header">
|
||||
<div id="htext">
|
||||
Editing <b>index</b>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="editor"></div>
|
||||
|
||||
<script src="//cdnjs.cloudflare.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
|
||||
<script src="//cdnjs.cloudflare.com/ajax/libs/knockout/2.2.1/knockout-min.js"></script>
|
||||
<script src="//cdnjs.cloudflare.com/ajax/libs/knockout-validation/1.0.2/knockout.validation.min.js"></script>
|
||||
<script src="//cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/2.3.1/js/bootstrap.min.js"></script>
|
||||
<script src="lib/ace/ace.js" type="text/javascript" charset="utf-8"></script>
|
||||
<script src="lib/ace/mode-html.js" type="text/javascript" charset="utf-8"></script>
|
||||
<!--<script src="lib/ace/mode-javascript.js" type="text/javascript" charset="utf-8"></script>-->
|
||||
<!--<script src="lib/ace/mode-css.js" type="text/javascript" charset="utf-8"></script>-->
|
||||
<!--<script src="lib/ace/mode-markdown.js" type="text/javascript" charset="utf-8"></script>-->
|
||||
<script src="//cdn.sockjs.org/sockjs-0.3.min.js"></script>
|
||||
<!--<script src="/channel/bcsocket.js"></script>-->
|
||||
<!--<script src="/socket.io/socket.io.js"></script>-->
|
||||
<script src="/share/share.uncompressed.js"></script>
|
||||
<script src="/share/json.js"></script>
|
||||
<script src="/share/ace.js"></script>
|
||||
|
||||
<script>
|
||||
var attribute = 'index';
|
||||
var editor = ace.edit("editor");
|
||||
var aceMode = require("ace/mode/html").Mode;
|
||||
var session = editor.getSession();
|
||||
session.setMode(new aceMode());
|
||||
|
||||
sharejs.open('json:app:main','json', function (error, main) {
|
||||
var indexField = null;
|
||||
if (error) {
|
||||
console.log('error opening app:main:json', error, main);
|
||||
} else {
|
||||
console.log('yes!!',main);
|
||||
if (main.snapshot == null) {
|
||||
main.submitOp([
|
||||
{ p: [], oi: {name:'main'}, od: null }
|
||||
]);
|
||||
}
|
||||
function openIndex() {
|
||||
if (main.snapshot._id && !indexField){
|
||||
indexField = 'busy';
|
||||
console.log('main.snapshot._id',main.snapshot._id);
|
||||
sharejs.open('text:app:'+main.snapshot._id+':'+attribute, 'text', function(error, index) {
|
||||
if (error) {
|
||||
console.log('error opening text:app:'+main.snapshot._id+':'+attribute, error, index);
|
||||
indexField=null;
|
||||
} else {
|
||||
console.log('yes index!!',index);
|
||||
indexField=index;
|
||||
index.attach_ace(editor);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
openIndex();
|
||||
main.on('change', function (op) {
|
||||
console.log('main:change',op,main.snapshot);
|
||||
openIndex();
|
||||
});
|
||||
|
||||
|
||||
}
|
||||
})
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
44
public/style.css
Normal file
44
public/style.css
Normal file
@ -0,0 +1,44 @@
|
||||
body {
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.ace_bold {
|
||||
font-weight:bold;
|
||||
}
|
||||
|
||||
.ace_italic {
|
||||
font-style:italic;
|
||||
}
|
||||
|
||||
#header {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
right: 0;
|
||||
height: 30px;
|
||||
width: 100%;
|
||||
background-color: black;
|
||||
}
|
||||
|
||||
#htext {
|
||||
line-height: 30px;
|
||||
vertical-align: middle;
|
||||
|
||||
padding-left: 10px;
|
||||
color: white;
|
||||
font-family: baskerville, palatino, 'palatino linotype', georgia,serif;
|
||||
}
|
||||
|
||||
#editor {
|
||||
margin: 0;
|
||||
position: absolute;
|
||||
top: 30px;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
}
|
||||
|
||||
#htext a {
|
||||
color: #aaf;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
79
public/style.html
Normal file
79
public/style.html
Normal file
@ -0,0 +1,79 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<link href="style.css" rel="stylesheet" type="text/css">
|
||||
<title>app/main/style</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div id="header">
|
||||
<div id="htext">
|
||||
Editing <b>style</b>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="editor"></div>
|
||||
|
||||
<script src="//cdnjs.cloudflare.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
|
||||
<script src="//cdnjs.cloudflare.com/ajax/libs/knockout/2.2.1/knockout-min.js"></script>
|
||||
<script src="//cdnjs.cloudflare.com/ajax/libs/knockout-validation/1.0.2/knockout.validation.min.js"></script>
|
||||
<script src="//cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/2.3.1/js/bootstrap.min.js"></script>
|
||||
<script src="lib/ace/ace.js" type="text/javascript" charset="utf-8"></script>
|
||||
<!--<script src="lib/ace/mode-html.js" type="text/javascript" charset="utf-8"></script>-->
|
||||
<!--<script src="lib/ace/mode-javascript.js" type="text/javascript" charset="utf-8"></script>-->
|
||||
<script src="lib/ace/mode-css.js" type="text/javascript" charset="utf-8"></script>
|
||||
<!--<script src="lib/ace/mode-markdown.js" type="text/javascript" charset="utf-8"></script>-->
|
||||
<script src="//cdn.sockjs.org/sockjs-0.3.min.js"></script>
|
||||
<!--<script src="/channel/bcsocket.js"></script>-->
|
||||
<!--<script src="/socket.io/socket.io.js"></script>-->
|
||||
<script src="/share/share.uncompressed.js"></script>
|
||||
<script src="/share/json.js"></script>
|
||||
<script src="/share/ace.js"></script>
|
||||
|
||||
<script>
|
||||
var attribute = 'style';
|
||||
var editor = ace.edit("editor");
|
||||
var aceMode = require("ace/mode/css").Mode;
|
||||
var session = editor.getSession();
|
||||
session.setMode(new aceMode());
|
||||
|
||||
sharejs.open('json:app:main','json', function (error, main) {
|
||||
var indexField = null;
|
||||
if (error) {
|
||||
console.log('error opening app:main:json', error, main);
|
||||
} else {
|
||||
console.log('yes!!',main);
|
||||
if (main.snapshot == null) {
|
||||
main.submitOp([
|
||||
{ p: [], oi: {name:'main'}, od: null }
|
||||
]);
|
||||
}
|
||||
function openIndex() {
|
||||
if (main.snapshot._id && !indexField){
|
||||
indexField = 'busy';
|
||||
console.log('main.snapshot._id',main.snapshot._id);
|
||||
sharejs.open('text:app:'+main.snapshot._id+':'+attribute, 'text', function(error, index) {
|
||||
if (error) {
|
||||
console.log('error opening text:app:'+main.snapshot._id+':'+attribute, error, index);
|
||||
indexField=null;
|
||||
} else {
|
||||
console.log('yes index!!',index);
|
||||
indexField=index;
|
||||
index.attach_ace(editor);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
openIndex();
|
||||
main.on('change', function (op) {
|
||||
console.log('main:change',op,main.snapshot);
|
||||
openIndex();
|
||||
});
|
||||
|
||||
|
||||
}
|
||||
})
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
36
responder.js
Normal file
36
responder.js
Normal file
@ -0,0 +1,36 @@
|
||||
var mimetypes = {
|
||||
'js': 'application/javascript',
|
||||
'html': 'text/html',
|
||||
'text': 'text/plain',
|
||||
'css': 'text/css',
|
||||
'less': 'text/css'
|
||||
};
|
||||
|
||||
var getMimeType = function (ext) {
|
||||
if (mimetypes[ext]) {
|
||||
return mimetypes[ext];
|
||||
}
|
||||
|
||||
return mimetypes.text;
|
||||
};
|
||||
|
||||
module.exports = function (options, res, next) {
|
||||
var responder = function (err, result) {
|
||||
console.log('err',err);
|
||||
if (err) {
|
||||
if (/Data not found*/.test(err.message)) {
|
||||
res.status(404);
|
||||
}
|
||||
return next(err.message);
|
||||
}
|
||||
console.log('responder options',options);
|
||||
var contentType = getMimeType(options.ext);
|
||||
res.setHeader('Content-Type', contentType);
|
||||
var content = result;
|
||||
if (options.attribute) {
|
||||
content = result[options.attribute];
|
||||
}
|
||||
res.send(content);
|
||||
};
|
||||
return responder;
|
||||
};
|
||||
251
server.js
Normal file
251
server.js
Normal file
@ -0,0 +1,251 @@
|
||||
var sharejs = require('share');
|
||||
var mongodata = require('./mongodata.js');
|
||||
var responder = require('./responder.js');
|
||||
var preview = require('./preview.js');
|
||||
|
||||
module.exports = function (server, config) {
|
||||
|
||||
// Attach the sharejs REST and Socket.io interfaces to the server
|
||||
sharejs.server.attach(server, config.share);
|
||||
var model = server.model;
|
||||
|
||||
|
||||
var mongodataInstance = mongodata(config);
|
||||
|
||||
server.get('/data/:collection/:guid/:attribute.:ext(css|less|js|html)',
|
||||
function getMongoAttribute(req, res, next) {
|
||||
config.debug && console.log('/data/:collection/:guid/:attribute.:ext(less|js|html)');
|
||||
var options = {
|
||||
collection: req.params.collection,
|
||||
attribute: req.params.attribute,
|
||||
ext: req.params.ext,
|
||||
query: {_id:req.params.guid}
|
||||
};
|
||||
mongodataInstance.getMongoAttribute(options,
|
||||
responder(options, res, next)
|
||||
);
|
||||
}
|
||||
);
|
||||
server.get('/data/:collection/:guid.:ext(json)',
|
||||
function getMongoContent(req, res, next) {
|
||||
config.debug && console.log('/data/:collection/:guid.:ext(json)');
|
||||
var options = {
|
||||
collection: req.params.collection,
|
||||
ext: req.params.ext,
|
||||
query: {_id:req.params.guid}
|
||||
};
|
||||
mongodataInstance.getMongoContent(options,
|
||||
responder(options, res, next)
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
server.get('/content/:collection/:name/:attribute.:ext(css|less|js|html)',
|
||||
function getMongoAttribute(req, res, next) {
|
||||
config.debug && console.log('/content/:collection/:name/:attribute.:ext(less|js|html)');
|
||||
var options = {
|
||||
collection: req.params.collection,
|
||||
attribute: req.params.attribute,
|
||||
ext: req.params.ext,
|
||||
query: {name:req.params.name}
|
||||
};
|
||||
mongodataInstance.getMongoAttribute(options,
|
||||
responder(options, res, next)
|
||||
);
|
||||
}
|
||||
);
|
||||
server.get('/content/:collection/:name.:ext(json)',
|
||||
function getMongoContent(req, res, next) {
|
||||
config.debug && console.log('/content/:collection/:name.:ext(json)');
|
||||
var options = {
|
||||
collection: req.params.collection,
|
||||
ext: req.params.ext,
|
||||
query: {name:req.params.name}
|
||||
};
|
||||
mongodataInstance.getMongoContent(options,
|
||||
responder(options, res, next)
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
function handleMongoGetResult(options) {
|
||||
function handleResult(err, result) {
|
||||
if (err) {
|
||||
config.errors && console.log('ERR1 handleMongoGetResult.handleResult Error retrieving document ', options.collection, JSON.stringify(options.query), options.attribute || "", err);
|
||||
} else {
|
||||
if (result) {
|
||||
var operation = null;
|
||||
config.debug && console.log('handleMongoGetResult options',options, result);
|
||||
var data = result;
|
||||
if (options.attribute) {
|
||||
data = result[options.attribute];
|
||||
}
|
||||
var version = 0;
|
||||
if (options.type == 'json') {
|
||||
if (data instanceof String) {
|
||||
data = JSON.parse(data);
|
||||
}
|
||||
operation = { op: [
|
||||
{ p: [], oi: data, od: null }
|
||||
], v: version };
|
||||
} else if (options.type == 'text') {
|
||||
operation = { op: [
|
||||
{i: data, p: 0}
|
||||
], v: version };
|
||||
}
|
||||
if (operation) {
|
||||
model.applyOp(options.documentId, operation, function appliedOp(error, version) {
|
||||
options.debug && console.log('getResult applyOp version', version);
|
||||
if (error) {
|
||||
options.error && console.log('ERR2 handleMongoGetResult', error);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return handleResult;
|
||||
}
|
||||
|
||||
model.on('create', function populateDocument(documentId, data) {
|
||||
console.log('Populating a doc in channel', documentId, data);
|
||||
var splitId = documentId.split(':');
|
||||
var options = {
|
||||
documentId: documentId,
|
||||
type: splitId[0],
|
||||
collection: splitId[1],
|
||||
attribute: null
|
||||
};
|
||||
if (splitId.length == 4) {
|
||||
options.query= {_id:splitId[2]};
|
||||
options.attribute = splitId[3];
|
||||
mongodataInstance.getMongoAttribute(options, handleMongoGetResult(options));
|
||||
} else {
|
||||
options.query={name:splitId[2]};
|
||||
mongodataInstance.getMongoContent(options, handleMongoGetResult(options));
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
function handleMongoSetResult(options, current, callback) {
|
||||
function handleResult(err, result) {
|
||||
if (err) {
|
||||
config.errors && console.log('ERR1 handleMongoSetResult Error while saving document ', options.collection, JSON.stringify(options.query), options.attribute || "", err);
|
||||
return callback && callback(err);
|
||||
}
|
||||
config.debug && console.log('current', current, 'result',result, 'options',options);
|
||||
if ((!current || !current.name) && result.name) {
|
||||
var operation = { op: [
|
||||
{ p: ['name'], oi: result.name, od: null }
|
||||
], v: options.operation.v };
|
||||
model.applyOp(options.documentId, operation, function appliedOp(error, version) {
|
||||
config.debug && console.log('setResult applyOp version', version);
|
||||
if (error) {
|
||||
config.error && console.log('ERR2 handleMongoSetResult',error);
|
||||
return callback && callback(error);
|
||||
}
|
||||
return callback && callback(null,version);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return handleResult;
|
||||
}
|
||||
|
||||
function handleMongoAttributeSetResult(options, current, callback) {
|
||||
function handleResult(err, result) {
|
||||
if (err) {
|
||||
config.errors && console.log('ERR1 handleMongoAttributeSetResult Error while saving document ', options.collection, JSON.stringify(options.query), options.attribute || "", err);
|
||||
return callback && callback(err);
|
||||
}
|
||||
options.debug && console.log('current', current, 'result',result);
|
||||
if (result.hasOwnProperty('_id')) {
|
||||
config.debug && console.log('// new object created. need to update the parent object.');
|
||||
var pieces = options.documentId.split(':');
|
||||
var parentDocId = pieces[0]+ ':' + pieces[1] + ':' + pieces[2];
|
||||
var operation = { op: [
|
||||
{ p: [options.attribute], oi: { guid: result._id } , od: null }
|
||||
], v: options.operation.v };
|
||||
|
||||
model.applyOp(parentDocId, operation, function appliedOp(error, version) {
|
||||
config.debug && console.log('setResult applyOp parent version', version);
|
||||
if (error) {
|
||||
config.error && console.log('ERR2 handleMongoAttributeSetResult',error);
|
||||
return callback && callback(error);
|
||||
}
|
||||
return callback && callback(null,version);
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
return handleResult;
|
||||
}
|
||||
|
||||
// 'applyOp' event is fired when an operational transform is applied to to a shareDoc
|
||||
// a shareDoc has changed and needs to be saved to mongo
|
||||
model.on('applyOp', function persistDocument(documentId, operation, current, previous) {
|
||||
config.debug && console.log('applyOp',documentId,operation,current);
|
||||
var splitId = documentId.split(':');
|
||||
var options = {
|
||||
documentId: documentId,
|
||||
type: splitId[0],
|
||||
collection: splitId[1],
|
||||
attribute: null,
|
||||
operation: operation
|
||||
};
|
||||
if (splitId.length == 4) {
|
||||
options.query= {_id:splitId[2]};
|
||||
options.attribute = splitId[3];
|
||||
var data = current;
|
||||
if (options.type == 'json') {
|
||||
data = JSON.stringify(current);
|
||||
}
|
||||
mongodataInstance.setMongoAttribute(data, options, handleMongoAttributeSetResult(options, current, function (err, result) {
|
||||
if(err) {
|
||||
config.errors && console.log('ERR1 applyOp', err);
|
||||
}
|
||||
}));
|
||||
} else {
|
||||
options.query={name:splitId[2]};
|
||||
mongodataInstance.setMongoContent(current, options, handleMongoSetResult(options, current, function (err, result) {
|
||||
if(err) {
|
||||
config.errors && console.log('ERR2 applyOp', err);
|
||||
}
|
||||
}));
|
||||
}
|
||||
});
|
||||
|
||||
var previewInstance = preview(config);
|
||||
|
||||
server.get('/page/:collection/:name.:ext(html)',
|
||||
function getPreviewContent(req, res, next) {
|
||||
config.debug && console.log('/page/:collection/:name.:ext(html)');
|
||||
var options = {
|
||||
collection: req.params.collection,
|
||||
ext: req.params.ext,
|
||||
query: {name:req.params.name},
|
||||
debug: req.query && req.query.hasOwnProperty('debug')
|
||||
};
|
||||
mongodataInstance.getMongoContent(options, function (err, result) {
|
||||
if (err) {
|
||||
responder(options, res, next)(err, result);
|
||||
}
|
||||
if (result) {
|
||||
var attribute_parts = options.query.name.split('.');
|
||||
var attribute = attribute_parts[attribute_parts.length-1];
|
||||
var content = result[attribute];
|
||||
options.name=attribute_parts[0];
|
||||
//options.attribute=attribute;
|
||||
config.debug && console.log('getPreviewContent content',content);
|
||||
previewInstance.getPreviewHTML(options, content,
|
||||
responder(options, res, next)
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
|
||||
};
|
||||
0
test/test.server.js
Normal file
0
test/test.server.js
Normal file
Loading…
x
Reference in New Issue
Block a user