mirror of
https://github.com/Hopiu/webapi-eca.git
synced 2026-03-16 22:10:31 +00:00
user command enhancements, module forge
This commit is contained in:
parent
1342d0b2de
commit
ad362967ed
12 changed files with 315 additions and 75 deletions
|
|
@ -61,19 +61,28 @@ exports.addHandlers = ( fShutDown ) ->
|
|||
log.print 'HL', 'no session backbone'
|
||||
|
||||
# **Accepted requests to paths:**
|
||||
|
||||
|
||||
# GET Requests
|
||||
|
||||
# - **`GET` to _"/"_:** Static redirect to the _"webpages/public"_ directory
|
||||
app.use '/', express.static path.resolve __dirname, '..', 'webpages', 'public'
|
||||
# - **`POST` to _"/event"_:** Events coming from remote systems are passed to the engine
|
||||
app.post '/event', requestHandler.handleEvent
|
||||
# - **`GET` to _"/user"_:** User requests are possible for all users with an account
|
||||
app.get '/user', requestHandler.handleUser
|
||||
# - **`GET` to _"/admin"_:** Only admins can issue requests to this handler
|
||||
app.get '/admin', requestHandler.handleAdmin
|
||||
# - **`GET` to _"/forge\_modules"_:** Webpages that lets the user to create modules
|
||||
app.get '/forge_modules', requestHandler.handleForgeModules
|
||||
# - **`GET` to _"/invoke\_event"_:** Webpage that lets the user invoke events
|
||||
app.get '/invoke_event', requestHandler.handleInvokeEvent
|
||||
|
||||
# POST Requests
|
||||
|
||||
# - **`POST` to _"/event"_:** Events coming from remote systems are passed to the engine
|
||||
app.post '/event', requestHandler.handleEvent
|
||||
# - **`POST` to _"/login"_:** Credentials will be verified
|
||||
app.post '/login', requestHandler.handleLogin
|
||||
# - **`POST` to _"/logout"_:** User will be logged out
|
||||
app.post '/logout', requestHandler.handleLogout
|
||||
# - **`POST` to _"/user"_:** User requests are possible for all users with an account
|
||||
app.post '/usercommand', requestHandler.handleUserCommand
|
||||
try
|
||||
http_port = config.getHttpPort()
|
||||
if http_port
|
||||
|
|
|
|||
|
|
@ -29,13 +29,19 @@ qs = require 'querystring'
|
|||
mustache = require 'mustache'
|
||||
crypto = require 'crypto-js'
|
||||
|
||||
# Prepare the admin command handlers that are invoked via HTTP requests.
|
||||
# Prepare the admin command handlers which are invoked via HTTP requests.
|
||||
objAdminCmds =
|
||||
'loadrules': mm.loadRulesFromFS,
|
||||
'loadaction': mm.loadActionModuleFromFS,
|
||||
'loadactions': mm.loadActionModulesFromFS,
|
||||
'loadevent': mm.loadEventModuleFromFS,
|
||||
'loadevents': mm.loadEventModulesFromFS
|
||||
|
||||
# Prepare the user command handlers which are invoked via HTTP requests.
|
||||
objUserCmds =
|
||||
'store_action': mm.storeActionModule
|
||||
'store_event': mm.storeEventModule
|
||||
'store_rule': mm.storeRule
|
||||
|
||||
|
||||
exports = module.exports = ( args ) ->
|
||||
|
|
@ -79,7 +85,7 @@ exports.handleEvent = ( req, resp ) =>
|
|||
obj = qs.parse body
|
||||
# If required event properties are present we process the event #
|
||||
if obj and obj.event and obj.eventid
|
||||
resp.send 'Thank you for the event (' + obj.event + '[' + obj.eventid + '])!'
|
||||
resp.send 'Thank you for the event: ' + obj.event + ' (' + obj.eventid + ')!'
|
||||
db.pushEvent obj
|
||||
else
|
||||
resp.writeHead 400, { "Content-Type": "text/plain" }
|
||||
|
|
@ -152,6 +158,41 @@ getHandlerFileAsString = ( name ) ->
|
|||
fs.readFileSync getHandlerPath( name ), 'utf8'
|
||||
|
||||
###
|
||||
Renders a page depending on the user session and returns it.
|
||||
|
||||
@private renderPage( *name, sess* )
|
||||
@param {String} name
|
||||
@param {Object} sess
|
||||
###
|
||||
renderPage = ( name, sess ) ->
|
||||
template = getHandlerFileAsString name
|
||||
menubar = getHandlerFileAsString 'menubar'
|
||||
view =
|
||||
user: sess.user,
|
||||
div_menubar: menubar
|
||||
mustache.render template, view
|
||||
|
||||
###
|
||||
Sends the desired page or the login to the user.
|
||||
|
||||
*Requires
|
||||
the [request](http://nodejs.org/api/http.html#http_class_http_clientrequest)
|
||||
and [response](http://nodejs.org/api/http.html#http_class_http_serverresponse)
|
||||
objects.*
|
||||
|
||||
@public renderPageOrLogin( *req, resp, pagename* )
|
||||
@param {String} pagename
|
||||
###
|
||||
sendLoginOrPage = ( pagename, req, resp ) ->
|
||||
if req.session and req.session.user
|
||||
resp.send renderPage pagename, req.session
|
||||
else
|
||||
resp.sendfile getHandlerPath 'login'
|
||||
|
||||
|
||||
###
|
||||
Handles the user command requests.
|
||||
|
||||
*Requires
|
||||
the [request](http://nodejs.org/api/http.html#http_class_http_clientrequest)
|
||||
and [response](http://nodejs.org/api/http.html#http_class_http_serverresponse)
|
||||
|
|
@ -159,19 +200,50 @@ objects.*
|
|||
|
||||
@public handleUser( *req, resp* )
|
||||
###
|
||||
exports.handleUser = ( req, resp ) ->
|
||||
if req.session and req.session.user
|
||||
welcome = getHandlerFileAsString 'welcome'
|
||||
menubar = getHandlerFileAsString 'menubar'
|
||||
view = {
|
||||
user: req.session.user,
|
||||
div_menubar: menubar
|
||||
}
|
||||
resp.send mustache.render welcome, view
|
||||
exports.handleUserCommand = ( req, resp ) ->
|
||||
if not req.session or not req.session.user
|
||||
resp.send 401, 'Login first!'
|
||||
else
|
||||
resp.sendfile getHandlerPath 'login'
|
||||
body = ''
|
||||
req.on 'data', ( data ) ->
|
||||
body += data
|
||||
req.on 'end', ->
|
||||
obj = qs.parse body
|
||||
if objUserCmds[obj.command] is 'function'
|
||||
resp.send 'Command accepted!'
|
||||
objUserCmds[obj.command] req.session.user, obj
|
||||
else
|
||||
resp.send 404, 'Command unknown!'
|
||||
|
||||
###
|
||||
Present the module forge to the user.
|
||||
|
||||
*Requires
|
||||
the [request](http://nodejs.org/api/http.html#http_class_http_clientrequest)
|
||||
and [response](http://nodejs.org/api/http.html#http_class_http_serverresponse)
|
||||
objects.*
|
||||
|
||||
@public handleForgeModules( *req, resp* )
|
||||
###
|
||||
exports.handleForgeModules = ( req, resp ) ->
|
||||
sendLoginOrPage 'forge_modules', req, resp
|
||||
|
||||
###
|
||||
Present the event invoke page to the user.
|
||||
|
||||
*Requires
|
||||
the [request](http://nodejs.org/api/http.html#http_class_http_clientrequest)
|
||||
and [response](http://nodejs.org/api/http.html#http_class_http_serverresponse)
|
||||
objects.*
|
||||
|
||||
@public handleInvokeEvent( *req, resp* )
|
||||
###
|
||||
exports.handleInvokeEvent = ( req, resp ) ->
|
||||
sendLoginOrPage 'push_event', req, resp
|
||||
|
||||
|
||||
###
|
||||
Handles the admin command requests.
|
||||
|
||||
*Requires
|
||||
the [request](http://nodejs.org/api/http.html#http_class_http_clientrequest)
|
||||
|
|
@ -183,19 +255,9 @@ objects.*
|
|||
exports.handleAdmin = ( req, resp ) ->
|
||||
if req.session and req.session.user
|
||||
if req.session.user.isAdmin is "true"
|
||||
welcome = getHandlerFileAsString 'welcome'
|
||||
menubar = getHandlerFileAsString 'menubar'
|
||||
view =
|
||||
user: req.session.user,
|
||||
div_menubar: menubar
|
||||
resp.send mustache.render welcome, view
|
||||
resp.send renderPage 'welcome', req.session
|
||||
else
|
||||
unauthorized = getHandlerFileAsString 'unauthorized'
|
||||
menubar = getHandlerFileAsString 'menubar'
|
||||
view =
|
||||
user: req.session.user,
|
||||
div_menubar: menubar
|
||||
resp.send mustache.render unauthorized, view
|
||||
resp.send renderPage 'unauthorized', req.session
|
||||
else
|
||||
resp.sendfile getHandlerPath 'login'
|
||||
|
||||
|
|
|
|||
|
|
@ -29,8 +29,6 @@ exports = module.exports = function(args) {
|
|||
*/
|
||||
exports.addDBLinkAndLoadActionsAndRules = function(db_link) {
|
||||
db = db_link;
|
||||
if(!db) log.error('EN', 'No DB!');
|
||||
console.log(db);
|
||||
if(ml && db) db.getActionModules(function(err, obj) {
|
||||
if(err) log.error('EN', 'retrieving Action Modules from DB!');
|
||||
else {
|
||||
|
|
@ -109,10 +107,6 @@ function pollQueue() {
|
|||
}
|
||||
setTimeout(pollQueue, 50); //TODO adapt to load
|
||||
});
|
||||
// var evt = qEvents.dequeue();
|
||||
// if(evt) {
|
||||
// processEvent(evt);
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -173,6 +167,7 @@ function invokeAction(evt, action) {
|
|||
var srvc = listActionModules[arrModule[0]];
|
||||
if(srvc && srvc[arrModule[1]]) {
|
||||
//FIXME preprocessing not only on data
|
||||
//FIXME no preprocessing at all, why don't we just pass the whole event to the action?'
|
||||
preprocessActionArguments(evt.payload, action.arguments, actionargs);
|
||||
try {
|
||||
if(srvc[arrModule[1]]) srvc[arrModule[1]](actionargs);
|
||||
|
|
|
|||
|
|
@ -57,11 +57,13 @@ HTTP Listener
|
|||
}));
|
||||
log.print('HL', 'no session backbone');
|
||||
app.use('/', express["static"](path.resolve(__dirname, '..', 'webpages', 'public')));
|
||||
app.post('/event', requestHandler.handleEvent);
|
||||
app.get('/user', requestHandler.handleUser);
|
||||
app.get('/admin', requestHandler.handleAdmin);
|
||||
app.get('/forge_modules', requestHandler.handleForgeModules);
|
||||
app.get('/invoke_event', requestHandler.handleInvokeEvent);
|
||||
app.post('/event', requestHandler.handleEvent);
|
||||
app.post('/login', requestHandler.handleLogin);
|
||||
app.post('/logout', requestHandler.handleLogout);
|
||||
app.post('/usercommand', requestHandler.handleUserCommand);
|
||||
try {
|
||||
http_port = config.getHttpPort();
|
||||
if (http_port) {
|
||||
|
|
|
|||
|
|
@ -27,6 +27,24 @@ exports.addDBLink = function(db_link) {
|
|||
// funcLoadRule = fLoadRule;
|
||||
};
|
||||
|
||||
exports.storeEventModule = function (user, obj) {
|
||||
log.print('MM', 'implement storeEventModule');
|
||||
};
|
||||
|
||||
exports.storeActionModule = function (user, obj) {
|
||||
log.print('MM', 'implement storeActionModule');
|
||||
};
|
||||
|
||||
exports.storeRule = function (user, obj) {
|
||||
log.print('MM', 'implement storeRule');
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* Legacy file system loaders
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* Load Rules from fs
|
||||
* ------------------
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ Request Handler
|
|||
|
||||
|
||||
(function() {
|
||||
var crypto, db, exports, fAdminCommands, fs, getHandlerFileAsString, getHandlerPath, log, mm, mustache, objAdminCmds, onAdminCommand, path, qs,
|
||||
var crypto, db, exports, fAdminCommands, fs, getHandlerFileAsString, getHandlerPath, log, mm, mustache, objAdminCmds, objUserCmds, onAdminCommand, path, qs, renderPage, sendLoginOrPage,
|
||||
_this = this;
|
||||
|
||||
log = require('./logging');
|
||||
|
|
@ -35,6 +35,12 @@ Request Handler
|
|||
'loadevents': mm.loadEventModulesFromFS
|
||||
};
|
||||
|
||||
objUserCmds = {
|
||||
'store_action': mm.storeActionModule,
|
||||
'store_event': mm.storeEventModule,
|
||||
'store_rule': mm.storeRule
|
||||
};
|
||||
|
||||
exports = module.exports = function(args) {
|
||||
var user, users, _i, _len;
|
||||
args = args != null ? args : {};
|
||||
|
|
@ -87,7 +93,7 @@ Request Handler
|
|||
var obj;
|
||||
obj = qs.parse(body);
|
||||
if (obj && obj.event && obj.eventid) {
|
||||
resp.send('Thank you for the event (' + obj.event + '[' + obj.eventid + '])!');
|
||||
resp.send('Thank you for the event: ' + obj.event + ' (' + obj.eventid + ')!');
|
||||
return db.pushEvent(obj);
|
||||
} else {
|
||||
resp.writeHead(400, {
|
||||
|
|
@ -182,6 +188,49 @@ Request Handler
|
|||
};
|
||||
|
||||
/*
|
||||
Renders a page depending on the user session and returns it.
|
||||
|
||||
@private renderPage( *name, sess* )
|
||||
@param {String} name
|
||||
@param {Object} sess
|
||||
*/
|
||||
|
||||
|
||||
renderPage = function(name, sess) {
|
||||
var menubar, template, view;
|
||||
template = getHandlerFileAsString(name);
|
||||
menubar = getHandlerFileAsString('menubar');
|
||||
view = {
|
||||
user: sess.user,
|
||||
div_menubar: menubar
|
||||
};
|
||||
return mustache.render(template, view);
|
||||
};
|
||||
|
||||
/*
|
||||
Sends the desired page or the login to the user.
|
||||
|
||||
*Requires
|
||||
the [request](http://nodejs.org/api/http.html#http_class_http_clientrequest)
|
||||
and [response](http://nodejs.org/api/http.html#http_class_http_serverresponse)
|
||||
objects.*
|
||||
|
||||
@public renderPageOrLogin( *req, resp, pagename* )
|
||||
@param {String} pagename
|
||||
*/
|
||||
|
||||
|
||||
sendLoginOrPage = function(pagename, req, resp) {
|
||||
if (req.session && req.session.user) {
|
||||
return resp.send(renderPage(pagename, req.session));
|
||||
} else {
|
||||
return resp.sendfile(getHandlerPath('login'));
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
Handles the user command requests.
|
||||
|
||||
*Requires
|
||||
the [request](http://nodejs.org/api/http.html#http_class_http_clientrequest)
|
||||
and [response](http://nodejs.org/api/http.html#http_class_http_serverresponse)
|
||||
|
|
@ -191,22 +240,62 @@ Request Handler
|
|||
*/
|
||||
|
||||
|
||||
exports.handleUser = function(req, resp) {
|
||||
var menubar, view, welcome;
|
||||
if (req.session && req.session.user) {
|
||||
welcome = getHandlerFileAsString('welcome');
|
||||
menubar = getHandlerFileAsString('menubar');
|
||||
view = {
|
||||
user: req.session.user,
|
||||
div_menubar: menubar
|
||||
};
|
||||
return resp.send(mustache.render(welcome, view));
|
||||
exports.handleUserCommand = function(req, resp) {
|
||||
var body;
|
||||
if (!req.session || !req.session.user) {
|
||||
return resp.send(401, 'Login first!');
|
||||
} else {
|
||||
return resp.sendfile(getHandlerPath('login'));
|
||||
body = '';
|
||||
req.on('data', function(data) {
|
||||
return body += data;
|
||||
});
|
||||
return req.on('end', function() {
|
||||
var obj;
|
||||
obj = qs.parse(body);
|
||||
if (objUserCmds[obj.command] === 'function') {
|
||||
resp.send('Command accepted!');
|
||||
return objUserCmds[obj.command](req.session.user, obj);
|
||||
} else {
|
||||
return resp.send(404, 'Command unknown!');
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
Present the module forge to the user.
|
||||
|
||||
*Requires
|
||||
the [request](http://nodejs.org/api/http.html#http_class_http_clientrequest)
|
||||
and [response](http://nodejs.org/api/http.html#http_class_http_serverresponse)
|
||||
objects.*
|
||||
|
||||
@public handleForgeModules( *req, resp* )
|
||||
*/
|
||||
|
||||
|
||||
exports.handleForgeModules = function(req, resp) {
|
||||
return sendLoginOrPage('forge_modules', req, resp);
|
||||
};
|
||||
|
||||
/*
|
||||
Present the event invoke page to the user.
|
||||
|
||||
*Requires
|
||||
the [request](http://nodejs.org/api/http.html#http_class_http_clientrequest)
|
||||
and [response](http://nodejs.org/api/http.html#http_class_http_serverresponse)
|
||||
objects.*
|
||||
|
||||
@public handleInvokeEvent( *req, resp* )
|
||||
*/
|
||||
|
||||
|
||||
exports.handleInvokeEvent = function(req, resp) {
|
||||
return sendLoginOrPage('push_event', req, resp);
|
||||
};
|
||||
|
||||
/*
|
||||
Handles the admin command requests.
|
||||
|
||||
*Requires
|
||||
the [request](http://nodejs.org/api/http.html#http_class_http_clientrequest)
|
||||
|
|
@ -218,24 +307,11 @@ Request Handler
|
|||
|
||||
|
||||
exports.handleAdmin = function(req, resp) {
|
||||
var menubar, unauthorized, view, welcome;
|
||||
if (req.session && req.session.user) {
|
||||
if (req.session.user.isAdmin === "true") {
|
||||
welcome = getHandlerFileAsString('welcome');
|
||||
menubar = getHandlerFileAsString('menubar');
|
||||
view = {
|
||||
user: req.session.user,
|
||||
div_menubar: menubar
|
||||
};
|
||||
return resp.send(mustache.render(welcome, view));
|
||||
return resp.send(renderPage('welcome', req.session));
|
||||
} else {
|
||||
unauthorized = getHandlerFileAsString('unauthorized');
|
||||
menubar = getHandlerFileAsString('menubar');
|
||||
view = {
|
||||
user: req.session.user,
|
||||
div_menubar: menubar
|
||||
};
|
||||
return resp.send(mustache.render(unauthorized, view));
|
||||
return resp.send(renderPage('unauthorized', req.session));
|
||||
}
|
||||
} else {
|
||||
return resp.sendfile(getHandlerPath('login'));
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@
|
|||
<body>
|
||||
{{{div_menubar}}}
|
||||
<div id="mainbody">
|
||||
<div id="pagetitle">{{user.username}} unauthorized!</div>
|
||||
<div id="pagetitle">Hi {{user.username}}, that was unauthorized!</div>
|
||||
<p>
|
||||
Sorry this roles is missing for you.<br />
|
||||
You only have these privileges: {{user.roles}}
|
||||
|
|
|
|||
77
webpages/handlers/forge_modules.html
Normal file
77
webpages/handlers/forge_modules.html
Normal file
|
|
@ -0,0 +1,77 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<title>Forge A Module</title>
|
||||
<link rel="stylesheet" type="text/css" href="style.css">
|
||||
<script src='//ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js' type='text/javascript'></script>
|
||||
<script type = "text/template" id="templ_action">
|
||||
exports.myOwnActionFunction = function( args ) {
|
||||
var data = {
|
||||
companyId: '961',
|
||||
context: '17936',
|
||||
text: 'Binder entry based on event: ' + args.info
|
||||
};
|
||||
needle.post('https://probinder.com/service/27/save', data);
|
||||
};
|
||||
</script>
|
||||
|
||||
<script type = "text/template" id="templ_event">
|
||||
exports.myOwnEventFunction = function( callback ) {
|
||||
var myEvent = {
|
||||
event: 'mail',
|
||||
eventid: 'mail_0',
|
||||
payload: {
|
||||
subject: 'My mail event subject'
|
||||
body: 'Complex text body'
|
||||
}
|
||||
}
|
||||
callback( myEvent );
|
||||
};
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
{{{div_menubar}}}
|
||||
<div id="mainbody">
|
||||
<div id="pagetitle">Hi {{user.username}}, forge your own modules!</div>
|
||||
<p>
|
||||
<select id="select_type">
|
||||
<option value="0">Action Module</option>
|
||||
<option value="1">Event Module</option>
|
||||
</select>
|
||||
</p>
|
||||
<p>
|
||||
<textarea id="textarea_module" rows="30" cols="100">
|
||||
</textarea>
|
||||
</p>
|
||||
<p>
|
||||
<button id="but_submit">save</button>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<script type="text/javascript">
|
||||
$('#select_type').change(function(e) {
|
||||
if($(this).val() === '0') {
|
||||
$('#textarea_module').val($('#templ_action').html());
|
||||
} else {
|
||||
$('#textarea_module').val($('#templ_event').html());
|
||||
}
|
||||
});
|
||||
$('#but_submit').click(function() {
|
||||
var obj = { data: $('#textarea_event').val() };
|
||||
if($('#select_type').val() === '0') obj.command = 'store_action';
|
||||
else obj.command = 'store_event';
|
||||
console.log('posting:');
|
||||
console.log(obj);
|
||||
$.post('usercommand', obj)
|
||||
.done(function(data) {
|
||||
alert(data);
|
||||
})
|
||||
.fail(function(err) {
|
||||
console.log(err);
|
||||
alert('Posting of module failed: ' + err.responseText);
|
||||
});
|
||||
});
|
||||
$('#textarea_module').val($('#templ_action').html());
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -6,8 +6,9 @@
|
|||
<script src='//ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js' type='text/javascript'></script>
|
||||
</head>
|
||||
<body>
|
||||
{{{div_menubar}}}
|
||||
<div id="mainbody">
|
||||
<div id="pagetitle">Invoke an Event</div>
|
||||
<div id="pagetitle">Hi {{user.username}}, invoke your own Event!</div>
|
||||
<p>
|
||||
<textarea id="textarea_event" rows="20" cols="50">
|
||||
{
|
||||
|
|
@ -25,15 +26,13 @@
|
|||
</div>
|
||||
|
||||
<script>
|
||||
//{ \"event\": \"mail\", \"eventid\": \"0\",... }"
|
||||
$('#but_submit').click(function() {
|
||||
$.post('../event', JSON.parse($('#textarea_event').val()))
|
||||
.done(function(data) {
|
||||
alert(data);
|
||||
})
|
||||
.fail(function(err) {
|
||||
console.log(err);
|
||||
alert('Posting of event failed: ' + err);
|
||||
alert('Posting of event failed: ' + err.responseText);
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
|
@ -8,7 +8,7 @@
|
|||
<body>
|
||||
{{{div_menubar}}}
|
||||
<div id="mainbody">
|
||||
<div id="pagetitle">{{user.username}} unauthorized!</div>
|
||||
<div id="pagetitle">Tsts... {{user.username}}, that was unauthorized!</div>
|
||||
<p>
|
||||
Sorry this roles is missing for you.<br />
|
||||
You only have these privileges: {{user.roles}}
|
||||
|
|
|
|||
|
|
@ -1,14 +1,14 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<title>Welcome {{user.username}}</title>
|
||||
<title>Welcome {{user.username}}!</title>
|
||||
<link rel="stylesheet" type="text/css" href="style.css">
|
||||
<script src='//ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js' type='text/javascript'></script>
|
||||
</head>
|
||||
<body>
|
||||
{{{div_menubar}}}
|
||||
<div id="mainbody">
|
||||
<div id="pagetitle">Welcome {{user.username}}</div>
|
||||
<div id="pagetitle">Welcome {{user.username}}!</div>
|
||||
<p>
|
||||
We're glad you're back!<br />
|
||||
Your roles are: {{user.roles}}
|
||||
|
|
|
|||
|
|
@ -6,9 +6,11 @@ body {
|
|||
}
|
||||
|
||||
textarea {
|
||||
font-family: Tahoma, sans-serif;
|
||||
font-size: 0.9em;
|
||||
-moz-tab-size: 2;
|
||||
-o-tab-size:2;
|
||||
tab-size:2;
|
||||
-o-tab-size: 2;
|
||||
tab-size: 2;
|
||||
}
|
||||
|
||||
#menubar {
|
||||
|
|
|
|||
Loading…
Reference in a new issue