mirror of
https://github.com/HabitRPG/habitica.git
synced 2025-12-18 15:17:25 +01:00
Adding empty derby project
This commit is contained in:
4
.gitignore
vendored
Normal file
4
.gitignore
vendored
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
.DS_Store
|
||||||
|
public/gen
|
||||||
|
node_modules
|
||||||
|
*.swp
|
||||||
83
lib/app/index.js
Normal file
83
lib/app/index.js
Normal file
@@ -0,0 +1,83 @@
|
|||||||
|
var app = require('derby').createApp(module)
|
||||||
|
, get = app.get
|
||||||
|
, view = app.view
|
||||||
|
, ready = app.ready
|
||||||
|
, start
|
||||||
|
|
||||||
|
// ROUTES //
|
||||||
|
|
||||||
|
start = +new Date()
|
||||||
|
|
||||||
|
// Derby routes can be rendered on the client and the server
|
||||||
|
get('/:roomName?', function(page, model, params) {
|
||||||
|
var roomName = params.roomName || 'home'
|
||||||
|
|
||||||
|
// Subscribes the model to any updates on this room's object. Calls back
|
||||||
|
// with a scoped model equivalent to:
|
||||||
|
// room = model.at('rooms.' + roomName)
|
||||||
|
model.subscribe('rooms.' + roomName, function(err, room) {
|
||||||
|
model.ref('_room', room)
|
||||||
|
|
||||||
|
// setNull will set a value if the object is currently null or undefined
|
||||||
|
room.setNull('welcome', 'Welcome to ' + roomName + '!')
|
||||||
|
|
||||||
|
room.incr('visits')
|
||||||
|
|
||||||
|
// This value is set for when the page initially renders
|
||||||
|
model.set('_timer', '0.0')
|
||||||
|
// Reset the counter when visiting a new route client-side
|
||||||
|
start = +new Date()
|
||||||
|
|
||||||
|
// Render will use the model data as well as an optional context object
|
||||||
|
page.render({
|
||||||
|
roomName: roomName
|
||||||
|
, randomUrl: parseInt(Math.random() * 1e9).toString(36)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
// CONTROLLER FUNCTIONS //
|
||||||
|
|
||||||
|
ready(function(model) {
|
||||||
|
var timer
|
||||||
|
|
||||||
|
// Expose the model as a global variable in the browser. This is fun in
|
||||||
|
// development, but it should be removed when writing an app
|
||||||
|
window.model = model
|
||||||
|
|
||||||
|
// Exported functions are exposed as a global in the browser with the same
|
||||||
|
// name as the module that includes Derby. They can also be bound to DOM
|
||||||
|
// events using the "x-bind" attribute in a template.
|
||||||
|
exports.stop = function() {
|
||||||
|
|
||||||
|
// Any path name that starts with an underscore is private to the current
|
||||||
|
// client. Nothing set under a private path is synced back to the server.
|
||||||
|
model.set('_stopped', true)
|
||||||
|
clearInterval(timer)
|
||||||
|
}
|
||||||
|
|
||||||
|
exports.start = function() {
|
||||||
|
model.set('_stopped', false)
|
||||||
|
timer = setInterval(function() {
|
||||||
|
model.set('_timer', (((+new Date()) - start) / 1000).toFixed(1))
|
||||||
|
}, 100)
|
||||||
|
}
|
||||||
|
exports.start()
|
||||||
|
|
||||||
|
|
||||||
|
model.set('_showReconnect', true)
|
||||||
|
exports.connect = function() {
|
||||||
|
// Hide the reconnect link for a second after clicking it
|
||||||
|
model.set('_showReconnect', false)
|
||||||
|
setTimeout(function() {
|
||||||
|
model.set('_showReconnect', true)
|
||||||
|
}, 1000)
|
||||||
|
model.socket.socket.connect()
|
||||||
|
}
|
||||||
|
|
||||||
|
exports.reload = function() {
|
||||||
|
window.location.reload()
|
||||||
|
}
|
||||||
|
|
||||||
|
})
|
||||||
53
lib/server/index.js
Normal file
53
lib/server/index.js
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
var http = require('http')
|
||||||
|
, path = require('path')
|
||||||
|
, express = require('express')
|
||||||
|
, gzippo = require('gzippo')
|
||||||
|
, derby = require('derby')
|
||||||
|
, app = require('../app')
|
||||||
|
, serverError = require('./serverError')
|
||||||
|
|
||||||
|
|
||||||
|
// SERVER CONFIGURATION //
|
||||||
|
|
||||||
|
var ONE_YEAR = 1000 * 60 * 60 * 24 * 365
|
||||||
|
, root = path.dirname(path.dirname(__dirname))
|
||||||
|
, publicPath = path.join(root, 'public')
|
||||||
|
, expressApp, server, store
|
||||||
|
|
||||||
|
;(expressApp = express())
|
||||||
|
.use(express.favicon())
|
||||||
|
// Gzip static files and serve from memory
|
||||||
|
.use(gzippo.staticGzip(publicPath, {maxAge: ONE_YEAR}))
|
||||||
|
|
||||||
|
// Gzip dynamically rendered content
|
||||||
|
.use(express.compress())
|
||||||
|
|
||||||
|
// Uncomment to add form data parsing support
|
||||||
|
// .use(express.bodyParser())
|
||||||
|
// .use(express.methodOverride())
|
||||||
|
|
||||||
|
// Derby session middleware creates req.model and subscribes to _session
|
||||||
|
// .use(express.cookieParser('secret_sauce'))
|
||||||
|
// .use(express.session({
|
||||||
|
// cookie: {maxAge: ONE_YEAR}
|
||||||
|
// })
|
||||||
|
// .use(app.session())
|
||||||
|
|
||||||
|
// The router method creates an express middleware from the app's routes
|
||||||
|
.use(app.router())
|
||||||
|
.use(expressApp.router)
|
||||||
|
.use(serverError(root))
|
||||||
|
|
||||||
|
module.exports = server = http.createServer(expressApp)
|
||||||
|
|
||||||
|
|
||||||
|
// SERVER ONLY ROUTES //
|
||||||
|
|
||||||
|
expressApp.all('*', function(req) {
|
||||||
|
throw '404: ' + req.url
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
// STORE SETUP //
|
||||||
|
|
||||||
|
store = app.createStore({listen: server})
|
||||||
21
lib/server/serverError.js
Normal file
21
lib/server/serverError.js
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
var derby = require('derby')
|
||||||
|
, isProduction = derby.util.isProduction
|
||||||
|
|
||||||
|
module.exports = function(root) {
|
||||||
|
var staticPages = derby.createStatic(root)
|
||||||
|
|
||||||
|
return function(err, req, res, next) {
|
||||||
|
if (err == null) return next()
|
||||||
|
|
||||||
|
console.log(err.stack ? err.stack : err)
|
||||||
|
|
||||||
|
// Customize error handling here
|
||||||
|
var message = err.message || err.toString()
|
||||||
|
, status = parseInt(message)
|
||||||
|
if (status === 404) {
|
||||||
|
staticPages.render('404', res, {url: req.url}, 404)
|
||||||
|
} else {
|
||||||
|
res.send( ((status >= 400) && (status < 600)) ? status : 500)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
12
package.json
Normal file
12
package.json
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
{
|
||||||
|
"name": "first-project",
|
||||||
|
"description": "",
|
||||||
|
"version": "0.0.0",
|
||||||
|
"main": "./server.js",
|
||||||
|
"dependencies": {
|
||||||
|
"derby": "*",
|
||||||
|
"express": "3.x",
|
||||||
|
"gzippo": ">=0.1.4"
|
||||||
|
},
|
||||||
|
"private": true
|
||||||
|
}
|
||||||
1
styles/404.styl
Normal file
1
styles/404.styl
Normal file
@@ -0,0 +1 @@
|
|||||||
|
@import "./base";
|
||||||
20
styles/app/index.styl
Normal file
20
styles/app/index.styl
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
@import "../base";
|
||||||
|
|
||||||
|
#alert {
|
||||||
|
position: absolute;
|
||||||
|
text-align: center;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 0;
|
||||||
|
z-index: 99;
|
||||||
|
}
|
||||||
|
#alert > p {
|
||||||
|
background: #fff1a8;
|
||||||
|
border: 1px solid #999;
|
||||||
|
border-top: 0;
|
||||||
|
border-radius: 0 0 3px 3px;
|
||||||
|
display: inline-block;
|
||||||
|
line-height: 21px;
|
||||||
|
padding: 0 12px;
|
||||||
|
}
|
||||||
13
styles/base.styl
Normal file
13
styles/base.styl
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
@import "./reset";
|
||||||
|
@import "nib/vendor";
|
||||||
|
|
||||||
|
body {
|
||||||
|
padding: 2em;
|
||||||
|
}
|
||||||
|
h1 {
|
||||||
|
font-size: 2em;
|
||||||
|
margin-bottom: .5em;
|
||||||
|
}
|
||||||
|
p {
|
||||||
|
line-height: 2em;
|
||||||
|
}
|
||||||
21
styles/reset.styl
Normal file
21
styles/reset.styl
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
body,h1,h2,h3,h4,th {
|
||||||
|
font: 13px/normal Arial,sans-serif;
|
||||||
|
}
|
||||||
|
body {
|
||||||
|
background: #fff;
|
||||||
|
color: #000;
|
||||||
|
}
|
||||||
|
body,fieldset,form,h1,h2,h3,h4,li,ol,p,td,th,ul {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
ul {
|
||||||
|
margin: 0 normal;
|
||||||
|
}
|
||||||
|
table {
|
||||||
|
border-collapse: collapse;
|
||||||
|
border-spacing: 0;
|
||||||
|
}
|
||||||
|
fieldset,img {
|
||||||
|
border: 0;
|
||||||
|
}
|
||||||
16
views/404.html
Normal file
16
views/404.html
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
<!--
|
||||||
|
This is a static template file, so it doesn't have an associated app.
|
||||||
|
It is rendered by the server via a staticPages renderer.
|
||||||
|
|
||||||
|
Since static pages don't include the Derby client library, they can't have
|
||||||
|
bound variables that automatically update. However, they do support initial
|
||||||
|
template tag rendering from a context object and/or model.
|
||||||
|
-->
|
||||||
|
|
||||||
|
<Title:>
|
||||||
|
Not found
|
||||||
|
|
||||||
|
<Body:>
|
||||||
|
<h1>404</h1>
|
||||||
|
<p>Sorry, we can't find anything at <b>{{url}}</b>.
|
||||||
|
<p>Try heading back to the <a href="/">home page</a>.
|
||||||
57
views/app/index.html
Normal file
57
views/app/index.html
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
<!--
|
||||||
|
Derby templates are similar to Handlebars, except that they are first
|
||||||
|
parsed as HTML, and there are a few extensions to make them work directly
|
||||||
|
with models. A single HTML template defines the HTML output, the event
|
||||||
|
handlers that update the model after user interaction, and the event handlers
|
||||||
|
that update the DOM when the model changes.
|
||||||
|
|
||||||
|
As in Handlebars, double curly braces output a value literally. Derby
|
||||||
|
templates add single curly braces, which output a value and set up
|
||||||
|
model <- -> view bindings for that object.
|
||||||
|
|
||||||
|
Elements that end in colon define template names. Pre-defined templates
|
||||||
|
are capitalized by convention, but template names are case-insensitive.
|
||||||
|
Pre-defined templates are automatically included when the page is rendered.
|
||||||
|
-->
|
||||||
|
|
||||||
|
<Title:>
|
||||||
|
{{roomName}} - {_room.visits} visits
|
||||||
|
|
||||||
|
<Header:>
|
||||||
|
<!-- Other templates are referenced like custom HTML elements -->
|
||||||
|
<app:alert>
|
||||||
|
|
||||||
|
<Body:>
|
||||||
|
<h1>{_room.welcome}</h1>
|
||||||
|
<p><label>Welcome message: <input value="{_room.welcome}"></label></p>
|
||||||
|
|
||||||
|
<p>This page has been visted {_room.visits} times. <app:timer></p>
|
||||||
|
|
||||||
|
<p>Let's go <a href="/{{randomUrl}}">somewhere random</a>.</p>
|
||||||
|
|
||||||
|
<timer:>
|
||||||
|
{#if _stopped}
|
||||||
|
<a x-bind="click:start">Start timer</a>
|
||||||
|
{else}
|
||||||
|
You have been here for {_timer} seconds. <a x-bind="click:stop">Stop</a>
|
||||||
|
{/}
|
||||||
|
|
||||||
|
<!--
|
||||||
|
connected and canConnect are built-in properties of model. If a variable
|
||||||
|
is not defined in the current context, it will be looked up in the model
|
||||||
|
data and the model properties
|
||||||
|
-->
|
||||||
|
<alert:>
|
||||||
|
<div id="alert">
|
||||||
|
{#unless connected}
|
||||||
|
<p>
|
||||||
|
{#if canConnect}
|
||||||
|
<!-- Leading space is removed, and trailing space is maintained -->
|
||||||
|
Offline
|
||||||
|
{#if _showReconnect}– <a x-bind="click:connect">Reconnect</a>{/}
|
||||||
|
{else}
|
||||||
|
Unable to reconnect – <a x-bind="click:reload">Reload</a>
|
||||||
|
{/}
|
||||||
|
</p>
|
||||||
|
{/}
|
||||||
|
</div>
|
||||||
Reference in New Issue
Block a user