From 0a666867b7006aa1b3ee679a0d0619d934731ed2 Mon Sep 17 00:00:00 2001 From: Anatoliy Chakkaev Date: Sat, 7 Apr 2012 18:20:59 +0400 Subject: [PATCH] Init --- .gitignore | 1 + Procfile | 1 + app/controllers/application_controller.js | 3 + app/controllers/books_controller.js | 78 + app/controllers/chapters_controller.js | 91 + app/helpers/books_helper.js | 2 + app/helpers/chapters_helper.js | 2 + app/models/book.js | 1 + app/models/chapter.js | 1 + app/views/books/_form.ejs | 6 + app/views/books/edit.ejs | 9 + app/views/books/index.ejs | 39 + app/views/books/new.ejs | 11 + app/views/books/show.ejs | 17 + app/views/chapters/_form.ejs | 6 + app/views/chapters/edit.ejs | 9 + app/views/chapters/index.ejs | 39 + app/views/chapters/new.ejs | 11 + app/views/chapters/show.ejs | 17 + app/views/layouts/application_layout.ejs | 41 + app/views/layouts/books_layout.ejs | 41 + app/views/layouts/chapters_layout.ejs | 41 + config/database.json | 7 + config/environment.js | 17 + config/environments/development.js | 9 + config/environments/production.js | 10 + config/environments/test.js | 8 + config/initializers/db-tools.js | 51 + config/routes.js | 10 + db/schema.js | 11 + dump.rdb | Bin 0 -> 165 bytes npmfile.js | 3 + package.json | 20 + public/favicon.ico | Bin 0 -> 1406 bytes public/images/glyphicons-halflings-white.png | Bin 0 -> 4352 bytes public/images/glyphicons-halflings.png | Bin 0 -> 4352 bytes public/index.html | 96 + public/javascripts/application.js | 1 + public/javascripts/bootstrap.js | 1720 +++++++++ public/javascripts/rails.js | 139 + public/stylesheets/bootstrap-responsive.css | 581 +++ public/stylesheets/bootstrap.css | 3496 ++++++++++++++++++ public/stylesheets/style.css | 0 server.js | 10 + test/controllers/books_controller_test.js | 120 + test/controllers/chapters_controller_test.js | 120 + test/test_helper.js | 186 + 47 files changed, 7082 insertions(+) create mode 100644 .gitignore create mode 100644 Procfile create mode 100644 app/controllers/application_controller.js create mode 100644 app/controllers/books_controller.js create mode 100644 app/controllers/chapters_controller.js create mode 100644 app/helpers/books_helper.js create mode 100644 app/helpers/chapters_helper.js create mode 100644 app/models/book.js create mode 100644 app/models/chapter.js create mode 100644 app/views/books/_form.ejs create mode 100644 app/views/books/edit.ejs create mode 100644 app/views/books/index.ejs create mode 100644 app/views/books/new.ejs create mode 100644 app/views/books/show.ejs create mode 100644 app/views/chapters/_form.ejs create mode 100644 app/views/chapters/edit.ejs create mode 100644 app/views/chapters/index.ejs create mode 100644 app/views/chapters/new.ejs create mode 100644 app/views/chapters/show.ejs create mode 100644 app/views/layouts/application_layout.ejs create mode 100644 app/views/layouts/books_layout.ejs create mode 100644 app/views/layouts/chapters_layout.ejs create mode 100644 config/database.json create mode 100644 config/environment.js create mode 100644 config/environments/development.js create mode 100644 config/environments/production.js create mode 100644 config/environments/test.js create mode 100644 config/initializers/db-tools.js create mode 100644 config/routes.js create mode 100644 db/schema.js create mode 100644 dump.rdb create mode 100644 npmfile.js create mode 100644 package.json create mode 100644 public/favicon.ico create mode 100644 public/images/glyphicons-halflings-white.png create mode 100644 public/images/glyphicons-halflings.png create mode 100644 public/index.html create mode 100644 public/javascripts/application.js create mode 100644 public/javascripts/bootstrap.js create mode 100644 public/javascripts/rails.js create mode 100644 public/stylesheets/bootstrap-responsive.css create mode 100644 public/stylesheets/bootstrap.css create mode 100644 public/stylesheets/style.css create mode 100755 server.js create mode 100644 test/controllers/books_controller_test.js create mode 100644 test/controllers/chapters_controller_test.js create mode 100644 test/test_helper.js diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..3c3629e --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +node_modules diff --git a/Procfile b/Procfile new file mode 100644 index 0000000..6f86b16 --- /dev/null +++ b/Procfile @@ -0,0 +1 @@ +web: node server.js \ No newline at end of file diff --git a/app/controllers/application_controller.js b/app/controllers/application_controller.js new file mode 100644 index 0000000..8181e8a --- /dev/null +++ b/app/controllers/application_controller.js @@ -0,0 +1,3 @@ +before('protect from forgery', function () { + protectFromForgery('5d016d2ae47dfb552e63b831eb9cecd809d60ed8'); +}); diff --git a/app/controllers/books_controller.js b/app/controllers/books_controller.js new file mode 100644 index 0000000..95372c9 --- /dev/null +++ b/app/controllers/books_controller.js @@ -0,0 +1,78 @@ +load('application'); + +before(loadBook, {only: ['show', 'edit', 'update', 'destroy']}); + +action('new', function () { + this.title = 'New book'; + this.book = new Book; + render(); +}); + +action(function create() { + Book.create(req.body.Book, function (err, book) { + if (err) { + flash('error', 'Book can not be created'); + render('new', { + book: book, + title: 'New book' + }); + } else { + flash('info', 'Book created'); + redirect(path_to.books); + } + }); +}); + +action(function index() { + this.title = 'Books index'; + Book.all(function (err, books) { + render({ + books: books + }); + }); +}); + +action(function show() { + this.title = 'Book show'; + render(); +}); + +action(function edit() { + this.title = 'Book edit'; + render(); +}); + +action(function update() { + this.book.updateAttributes(body.Book, function (err) { + if (!err) { + flash('info', 'Book updated'); + redirect(path_to.book(this.book)); + } else { + flash('error', 'Book can not be updated'); + this.title = 'Edit book details'; + render('edit'); + } + }.bind(this)); +}); + +action(function destroy() { + this.book.destroy(function (error) { + if (error) { + flash('error', 'Can not destroy book'); + } else { + flash('info', 'Book successfully removed'); + } + send("'" + path_to.books + "'"); + }); +}); + +function loadBook() { + Book.find(params.id, function (err, book) { + if (err) { + redirect(path_to.books); + } else { + this.book = book; + next(); + } + }.bind(this)); +} diff --git a/app/controllers/chapters_controller.js b/app/controllers/chapters_controller.js new file mode 100644 index 0000000..9df6822 --- /dev/null +++ b/app/controllers/chapters_controller.js @@ -0,0 +1,91 @@ +load('application'); + +before(loadBook); +before(loadChapter, {only: ['show', 'edit', 'update', 'destroy']}); + +action('new', function () { + this.title = 'New chapter'; + this.chapter = new Chapter; + render(); +}); + +action(function create() { + this.book.chapters.create(req.body.Chapter, function (err, chapter) { + if (err) { + flash('error', 'Chapter can not be created'); + render('new', { + chapter: chapter, + title: 'New chapter' + }); + } else { + flash('info', 'Chapter created'); + redirect(path_to.book_chapters(this.book)); + } + }.bind(this)); +}); + +action(function index() { + this.title = 'Chapters index'; + this.book.chapters(function (err, chapters) { + render({ + chapters: chapters + }); + }); +}); + +action(function show() { + this.title = 'Chapter show'; + render(); +}); + +action(function edit() { + this.title = 'Chapter edit'; + render(); +}); + +action(function update() { + this.chapter.updateAttributes(body.Chapter, function (err) { + if (!err) { + flash('info', 'Chapter updated'); + redirect(path_to.chapter(this.chapter)); + } else { + flash('error', 'Chapter can not be updated'); + this.title = 'Edit chapter details'; + render('edit'); + } + }.bind(this)); +}); + +action(function destroy() { + this.chapter.destroy(function (error) { + if (error) { + flash('error', 'Can not destroy chapter'); + } else { + flash('info', 'Chapter successfully removed'); + } + send("'" + path_to.chapters + "'"); + }); +}); + +function loadChapter() { + this.book.chapters.find(params.id, function (err, chapter) { + if (err) { + console.log(err); + redirect(path_to.book_chapters(this.book)); + } else { + this.chapter = chapter; + next(); + } + }.bind(this)); +} + +function loadBook() { + var self = this; + Book.find(params.book_id, function (err, book) { + if (err) return next(err); + if (!book) return next(new Error(404)); + self.book = book; + next(); + }); +} + diff --git a/app/helpers/books_helper.js b/app/helpers/books_helper.js new file mode 100644 index 0000000..e180b24 --- /dev/null +++ b/app/helpers/books_helper.js @@ -0,0 +1,2 @@ +module.exports = { +}; \ No newline at end of file diff --git a/app/helpers/chapters_helper.js b/app/helpers/chapters_helper.js new file mode 100644 index 0000000..e180b24 --- /dev/null +++ b/app/helpers/chapters_helper.js @@ -0,0 +1,2 @@ +module.exports = { +}; \ No newline at end of file diff --git a/app/models/book.js b/app/models/book.js new file mode 100644 index 0000000..28f9481 --- /dev/null +++ b/app/models/book.js @@ -0,0 +1 @@ +Book.hasMany(Chapter, {as: 'chapters', foreignKey: 'bookId'}); diff --git a/app/models/chapter.js b/app/models/chapter.js new file mode 100644 index 0000000..53beead --- /dev/null +++ b/app/models/chapter.js @@ -0,0 +1 @@ +Chapter.belongsTo(Book, {as: 'book', foreignKey: 'bookId'}); diff --git a/app/views/books/_form.ejs b/app/views/books/_form.ejs new file mode 100644 index 0000000..6babe9c --- /dev/null +++ b/app/views/books/_form.ejs @@ -0,0 +1,6 @@ +
+ <%- form.label("name", false, {class: "control-label"}) %> +
+ <%- form.input("name") %> +
+
diff --git a/app/views/books/edit.ejs b/app/views/books/edit.ejs new file mode 100644 index 0000000..48a2423 --- /dev/null +++ b/app/views/books/edit.ejs @@ -0,0 +1,9 @@ + + +<% form_for(book, {action: path_to.book(book), method: 'PUT', id: "book_form", class: 'form-horizontal'}, function (form) { %> + <%- partial('books/form.ejs', {locals: {form: form, book: book}}) %> +
+ <%- form.submit(' Update book', {class: 'btn btn-primary'}) %> or + <%- link_to('Cancel', path_to.book(book), {class: 'btn'}) %> +
+<% });%> \ No newline at end of file diff --git a/app/views/books/index.ejs b/app/views/books/index.ejs new file mode 100644 index 0000000..fd71fa8 --- /dev/null +++ b/app/views/books/index.ejs @@ -0,0 +1,39 @@ + + +
+
+

<%- link_to(' Add Book', path_to.new_book, {class: 'btn btn-primary'}) %> +

+
+ +
+
+ <% if (books.length > 0) { %> + + + + + + + + + <% books.forEach(function (book) { %> + + + + + <% }); %> + +
IDActions
<%- linkTo(book.name, path_to.book(book)) %> + <%- link_to(' Edit', path_to.edit_book(book), {class: 'btn btn-mini'}) %> + <%- link_to(' Delete', path_to.book(book), {class: 'btn btn-mini btn-danger', method: 'delete', remote: true, jsonp: '(function (u) {location.href = u;})'}) %> +
+ <% } else { %> +

+ No books were found. +

+ <% } %> +
+
diff --git a/app/views/books/new.ejs b/app/views/books/new.ejs new file mode 100644 index 0000000..d701860 --- /dev/null +++ b/app/views/books/new.ejs @@ -0,0 +1,11 @@ + + +<% form_for(book, {action: path_to.books, method: 'POST', id: "book_form", class: 'form-horizontal'}, function (form) { %> + <%- partial('books/form.ejs', {locals: {form: form, book: book}}) %> +
+ <%- form.submit(' Create book', {class: 'btn btn-primary'}) %> or + <%- link_to('Cancel', path_to.books, {class: 'btn'}) %> +
+<% });%> diff --git a/app/views/books/show.ejs b/app/views/books/show.ejs new file mode 100644 index 0000000..ded9da1 --- /dev/null +++ b/app/views/books/show.ejs @@ -0,0 +1,17 @@ + + + + + + + +
name<%= book.name %>
+ +
+ <%- link_to(' Edit', path_to.edit_book(book), {class: 'btn btn-primary'}) %> + <%- link_to(' Delete', path_to.book(book), {class: 'btn btn-danger', method: 'delete', remote: true, jsonp: '(function (u) { location.href = u; })'}) %> + or + <%- link_to('Back to index', path_to.books) %> +
\ No newline at end of file diff --git a/app/views/chapters/_form.ejs b/app/views/chapters/_form.ejs new file mode 100644 index 0000000..1e1980a --- /dev/null +++ b/app/views/chapters/_form.ejs @@ -0,0 +1,6 @@ +
+ <%- form.label("title", false, {class: "control-label"}) %> +
+ <%- form.input("title") %> +
+
diff --git a/app/views/chapters/edit.ejs b/app/views/chapters/edit.ejs new file mode 100644 index 0000000..03b7d3a --- /dev/null +++ b/app/views/chapters/edit.ejs @@ -0,0 +1,9 @@ + + +<% form_for(chapter, {action: path_to.book_chapter(book, chapter), method: 'PUT', id: "chapter_form", class: 'form-horizontal'}, function (form) { %> + <%- partial('chapters/form.ejs', {locals: {form: form, chapter: chapter}}) %> +
+ <%- form.submit(' Update chapter', {class: 'btn btn-primary'}) %> or + <%- link_to('Cancel', path_to.book_chapter(book, chapter), {class: 'btn'}) %> +
+<% });%> diff --git a/app/views/chapters/index.ejs b/app/views/chapters/index.ejs new file mode 100644 index 0000000..bd614c7 --- /dev/null +++ b/app/views/chapters/index.ejs @@ -0,0 +1,39 @@ + + +
+
+

<%- link_to(' New chapter', path_to.new_book_chapter(book), {class: 'btn btn-primary'}) %> +

+
+ +
+
+ <% if (chapters.length > 0) { %> + + + + + + + + + <% chapters.forEach(function (chapter, i) { %> + + + + + <% }); %> + +
IDActions
<%- link_to('chapter #' + (i + 1) + '. ' + chapter.title, path_to.book_chapter(book, chapter)) %> + <%- link_to(' Edit', path_to.edit_book_chapter(book, chapter), {class: 'btn btn-mini'}) %> + <%- link_to(' Delete', path_to.book_chapter(book, chapter), {class: 'btn btn-mini btn-danger', method: 'delete', remote: true, jsonp: '(function (u) {location.href = u;})'}) %> +
+ <% } else { %> +

+ No chapters were found. +

+ <% } %> +
+
diff --git a/app/views/chapters/new.ejs b/app/views/chapters/new.ejs new file mode 100644 index 0000000..d626fea --- /dev/null +++ b/app/views/chapters/new.ejs @@ -0,0 +1,11 @@ + + +<% form_for(chapter, {action: path_to.book_chapters(book), method: 'POST', id: "chapter_form", class: 'form-horizontal'}, function (form) { %> + <%- partial('chapters/form.ejs', {locals: {form: form, chapter: chapter}}) %> +
+ <%- form.submit(' Create chapter', {class: 'btn btn-primary'}) %> or + <%- link_to('Cancel', path_to.book_chapters(book), {class: 'btn'}) %> +
+<% });%> diff --git a/app/views/chapters/show.ejs b/app/views/chapters/show.ejs new file mode 100644 index 0000000..e3ac822 --- /dev/null +++ b/app/views/chapters/show.ejs @@ -0,0 +1,17 @@ + + + + + + + +
title<%= chapter.title %>
+ +
+ <%- link_to(' Edit', path_to.edit_book_chapter(book, chapter), {class: 'btn btn-primary'}) %> + <%- link_to(' Delete', path_to.book_chapter(book, chapter), {class: 'btn btn-danger', method: 'delete', remote: true, jsonp: '(function (u) { location.href = u; })'}) %> + or + <%- link_to('Back to index', path_to.book_chapters(book)) %> +
diff --git a/app/views/layouts/application_layout.ejs b/app/views/layouts/application_layout.ejs new file mode 100644 index 0000000..b6bc993 --- /dev/null +++ b/app/views/layouts/application_layout.ejs @@ -0,0 +1,41 @@ + + + + <%= title %> + <%- stylesheet_link_tag('bootstrap', 'style', 'bootstrap-responsive') %> + <%- javascript_include_tag('http://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js', 'bootstrap', 'rails', 'application') %> + <%- csrf_meta_tag() %> + + + + +
+ <% var flash = request.flash('info').pop(); if (flash) { %> +
+ × + <%- flash %> +
+ <% } %> + + <% flash = request.flash('error').pop(); if (flash) { %> +
+ × + <%- flash %> +
+ <% }; %> + + <%- body %> + +
+
+

© Company 2012

+
+
+ + \ No newline at end of file diff --git a/app/views/layouts/books_layout.ejs b/app/views/layouts/books_layout.ejs new file mode 100644 index 0000000..5c744d9 --- /dev/null +++ b/app/views/layouts/books_layout.ejs @@ -0,0 +1,41 @@ + + + + <%= title %> + <%- stylesheet_link_tag('bootstrap', 'style', 'bootstrap-responsive') %> + <%- javascript_include_tag('http://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js', 'bootstrap', 'rails', 'application') %> + <%- csrf_meta_tag() %> + + + + +
+ <% var flash = request.flash('info').pop(); if (flash) { %> +
+ × + <%- flash %> +
+ <% } %> + + <% flash = request.flash('error').pop(); if (flash) { %> +
+ × + <%- flash %> +
+ <% }; %> + + <%- body %> + +
+
+

© Company 2012

+
+
+ + \ No newline at end of file diff --git a/app/views/layouts/chapters_layout.ejs b/app/views/layouts/chapters_layout.ejs new file mode 100644 index 0000000..5c744d9 --- /dev/null +++ b/app/views/layouts/chapters_layout.ejs @@ -0,0 +1,41 @@ + + + + <%= title %> + <%- stylesheet_link_tag('bootstrap', 'style', 'bootstrap-responsive') %> + <%- javascript_include_tag('http://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js', 'bootstrap', 'rails', 'application') %> + <%- csrf_meta_tag() %> + + + + +
+ <% var flash = request.flash('info').pop(); if (flash) { %> +
+ × + <%- flash %> +
+ <% } %> + + <% flash = request.flash('error').pop(); if (flash) { %> +
+ × + <%- flash %> +
+ <% }; %> + + <%- body %> + +
+
+

© Company 2012

+
+
+ + \ No newline at end of file diff --git a/config/database.json b/config/database.json new file mode 100644 index 0000000..59d602c --- /dev/null +++ b/config/database.json @@ -0,0 +1,7 @@ +{ "development": + { "driver": "redis" + } +, "test": + { "driver": "memory" + } +} diff --git a/config/environment.js b/config/environment.js new file mode 100644 index 0000000..803089e --- /dev/null +++ b/config/environment.js @@ -0,0 +1,17 @@ +var express = require('express'); + +app.configure(function(){ + var cwd = process.cwd(); + + app.use(express.static(cwd + '/public', {maxAge: 86400000})); + app.set('views', cwd + '/app/views'); + app.set('view engine', 'ejs'); + app.set('view options', {complexNames: true}); + app.set('jsDirectory', '/javascripts/'); + app.set('cssDirectory', '/stylesheets/'); + app.use(express.bodyParser()); + app.use(express.cookieParser('secret')); + app.use(express.session({secret: 'secret'})); + app.use(express.methodOverride()); + app.use(app.router); +}); diff --git a/config/environments/development.js b/config/environments/development.js new file mode 100644 index 0000000..5f79b8d --- /dev/null +++ b/config/environments/development.js @@ -0,0 +1,9 @@ +app.configure('development', function () { + app.disable('view cache'); + app.disable('model cache'); + app.disable('eval cache'); + app.enable('log actions'); + app.enable('env info'); + app.use(require('express').errorHandler({ dumpExceptions: true, showStack: true })); +}); + diff --git a/config/environments/production.js b/config/environments/production.js new file mode 100644 index 0000000..ff5a843 --- /dev/null +++ b/config/environments/production.js @@ -0,0 +1,10 @@ +app.configure('production', function () { + app.enable('view cache'); + app.enable('model cache'); + app.enable('eval cache'); + app.enable('merge javascripts'); + app.enable('merge stylesheets'); + app.use(require('express').errorHandler()); + app.settings.quiet = true; +}); + diff --git a/config/environments/test.js b/config/environments/test.js new file mode 100644 index 0000000..5ebb14c --- /dev/null +++ b/config/environments/test.js @@ -0,0 +1,8 @@ +app.configure('test', function(){ + app.use(require('express').errorHandler({ dumpExceptions: true, showStack: true })); + app.settings.quiet = true; + app.enable('view cache'); + app.enable('model cache'); + app.enable('eval cache'); +}); + diff --git a/config/initializers/db-tools.js b/config/initializers/db-tools.js new file mode 100644 index 0000000..165214d --- /dev/null +++ b/config/initializers/db-tools.js @@ -0,0 +1,51 @@ +railway.tools.database = function db() { + var action = process.argv[3]; + switch (action) { + case 'migrate': + case 'update': + perform(action, process.exit); + break; + default: + console.log('Unknown action', action); + break; + } +}; + +railway.tools.database.help = { + shortcut: 'db', + usage: 'db [migrate|update]', + description: 'Migrate or update database(s)' +}; + +function getUniqueSchemas() { + var schemas = []; + Object.keys(app.models).forEach(function (modelName) { + var Model = app.models[modelName]; + var schema = Model.schema; + if (!~schemas.indexOf(schema)) { + schemas.push(schema); + } + }); + return schemas; +} + +function perform(action, callback) { + console.log('Perform', action, 'on'); + var wait = 0; + getUniqueSchemas().forEach(function (schema) { + if (schema['auto' + action]) { + console.log(' - ' + schema.name); + wait += 1; + process.nextTick(function () { + schema['auto' + action](done); + }); + } + }); + + if (wait === 0) done(); else console.log(wait); + + function done() { + if (--wait === 0) callback(); + } +} + diff --git a/config/routes.js b/config/routes.js new file mode 100644 index 0000000..7c2eecf --- /dev/null +++ b/config/routes.js @@ -0,0 +1,10 @@ +exports.routes = function (map) { + map.resources('books', function (book) { + book.resources('chapters'); + }); + + // Generic routes. Add all your routes below this line + // feel free to remove generic routes + map.all(':controller/:action'); + map.all(':controller/:action/:id'); +}; diff --git a/db/schema.js b/db/schema.js new file mode 100644 index 0000000..c6722ef --- /dev/null +++ b/db/schema.js @@ -0,0 +1,11 @@ +define('User', function () { + property('email', String, { index: true }); + property('password', String); + property('activated', Boolean, {default: false}); +}); + +var Book = describe('Book', function () { + property('name', String); +});var Chapter = describe('Chapter', function () { + property('title', String); +}); \ No newline at end of file diff --git a/dump.rdb b/dump.rdb new file mode 100644 index 0000000000000000000000000000000000000000..64685eeded64ae07ead674b38f27b127443182e7 GIT binary patch literal 165 zcmWG?b@2=~FfcIu$H2r{Y~`GhSWuE$#CU*_h0Q5HKikTXi6t*FH#dqGi9bQ8ZvNYroeO@U}O@?gmJ8rfLc9MtPB}Bp#}oYVJo%*nFutRfgPw1#0J`e aP{7Pul39|I%HmX%n8yY&fYA_a&wl{*EHTXh literal 0 HcmV?d00001 diff --git a/npmfile.js b/npmfile.js new file mode 100644 index 0000000..c292464 --- /dev/null +++ b/npmfile.js @@ -0,0 +1,3 @@ +require('ejs-ext'); +require('jugglingdb'); +require('seedjs'); diff --git a/package.json b/package.json new file mode 100644 index 0000000..3e4f0c6 --- /dev/null +++ b/package.json @@ -0,0 +1,20 @@ +{ "name": "libr" +, "version": "0.0.1" +, "engines": ["node >= 0.4.0"] +, "main": "server.js" +, "dependencies": + { "ejs": "*" + , "ejs-ext": "*" + , "express": ">= 2.5.8" + , "railway": ">= 0.1.6" + , "jugglingdb": ">= 0.1.0" + , "coffee-script": ">= 1.1.1" + }, + "devDependencies": + { "nodeunit": "*" + , "sinon": "*" + } +, "scripts": + { "test": "nodeunit test/*/*" + } +} diff --git a/public/favicon.ico b/public/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..18b440283eb2fa907c88dce3d75038beaf247b25 GIT binary patch literal 1406 zcmZQzU<5(|0R}M0U}azs1F|%L7$l?s#Ec9aKoZP=&`4})fz1s6|Nm!*3Oa(28)c1# zz-S1Jh5$GO7?A)-0Ex>;93QL&R7yeBGl7g?0zxPsBoC4XLWuc5OF(LvV0@5zFd)u8 Mm}-dmAU(7L0JFRX-~a#s literal 0 HcmV?d00001 diff --git a/public/images/glyphicons-halflings-white.png b/public/images/glyphicons-halflings-white.png new file mode 100644 index 0000000000000000000000000000000000000000..a20760bfde58d1c92cee95116059fba03c68d689 GIT binary patch literal 4352 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 literal 0 HcmV?d00001 diff --git a/public/index.html b/public/index.html new file mode 100644 index 0000000..856f11b --- /dev/null +++ b/public/index.html @@ -0,0 +1,96 @@ + + + + Welcome to Railway + + + + + + +
+ +
+ Information about application environment +
+
+
+
+
+ Fork me on GitHub +
+
1. Start with generators
+

this is a fastest way to create application:

+
railway g crud post title content date:date published:boolean
+
2. Then describe routes
+

in config/routes.js and remove this file (public/index.html)

+
exports.routes = function (map) {
+    map.get('/', 'posts#index');
+};
+
3. Design your database
+

in db/schema.js and describe models in app/models/*

+
4. Keep you controllers thin
+

write tests, and good luck.
If you have any questions feel free to ask at RailwayJS Google Group.

+

Track RailwayJS project state on trello board, vote for features, discuss. Help us to get better!

+
+
+ + + +
+
+
+ +
+ + diff --git a/public/javascripts/application.js b/public/javascripts/application.js new file mode 100644 index 0000000..37453a7 --- /dev/null +++ b/public/javascripts/application.js @@ -0,0 +1 @@ +// place your application-wide javascripts here diff --git a/public/javascripts/bootstrap.js b/public/javascripts/bootstrap.js new file mode 100644 index 0000000..4412304 --- /dev/null +++ b/public/javascripts/bootstrap.js @@ -0,0 +1,1720 @@ +/* =================================================== + * bootstrap-transition.js v2.0.1 + * http://twitter.github.com/bootstrap/javascript.html#transitions + * =================================================== + * Copyright 2012 Twitter, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ========================================================== */ + +!function( $ ) { + + $(function () { + + "use strict" + + /* CSS TRANSITION SUPPORT (https://gist.github.com/373874) + * ======================================================= */ + + $.support.transition = (function () { + var thisBody = document.body || document.documentElement + , thisStyle = thisBody.style + , support = thisStyle.transition !== undefined || thisStyle.WebkitTransition !== undefined || thisStyle.MozTransition !== undefined || thisStyle.MsTransition !== undefined || thisStyle.OTransition !== undefined + + return support && { + end: (function () { + var transitionEnd = "TransitionEnd" + if ( $.browser.webkit ) { + transitionEnd = "webkitTransitionEnd" + } else if ( $.browser.mozilla ) { + transitionEnd = "transitionend" + } else if ( $.browser.opera ) { + transitionEnd = "oTransitionEnd" + } + return transitionEnd + }()) + } + })() + + }) + +}( window.jQuery );/* ========================================================== + * bootstrap-alert.js v2.0.1 + * http://twitter.github.com/bootstrap/javascript.html#alerts + * ========================================================== + * Copyright 2012 Twitter, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ========================================================== */ + + +!function( $ ){ + + "use strict" + + /* ALERT CLASS DEFINITION + * ====================== */ + + var dismiss = '[data-dismiss="alert"]' + , Alert = function ( el ) { + $(el).on('click', dismiss, this.close) + } + + Alert.prototype = { + + constructor: Alert + + , close: function ( e ) { + var $this = $(this) + , selector = $this.attr('data-target') + , $parent + + if (!selector) { + selector = $this.attr('href') + selector = selector && selector.replace(/.*(?=#[^\s]*$)/, '') //strip for ie7 + } + + $parent = $(selector) + $parent.trigger('close') + + e && e.preventDefault() + + $parent.length || ($parent = $this.hasClass('alert') ? $this : $this.parent()) + + $parent + .trigger('close') + .removeClass('in') + + function removeElement() { + $parent + .trigger('closed') + .remove() + } + + $.support.transition && $parent.hasClass('fade') ? + $parent.on($.support.transition.end, removeElement) : + removeElement() + } + + } + + + /* ALERT PLUGIN DEFINITION + * ======================= */ + + $.fn.alert = function ( option ) { + return this.each(function () { + var $this = $(this) + , data = $this.data('alert') + if (!data) $this.data('alert', (data = new Alert(this))) + if (typeof option == 'string') data[option].call($this) + }) + } + + $.fn.alert.Constructor = Alert + + + /* ALERT DATA-API + * ============== */ + + $(function () { + $('body').on('click.alert.data-api', dismiss, Alert.prototype.close) + }) + +}( window.jQuery );/* ============================================================ + * bootstrap-button.js v2.0.1 + * http://twitter.github.com/bootstrap/javascript.html#buttons + * ============================================================ + * Copyright 2012 Twitter, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================ */ + +!function( $ ){ + + "use strict" + + /* BUTTON PUBLIC CLASS DEFINITION + * ============================== */ + + var Button = function ( element, options ) { + this.$element = $(element) + this.options = $.extend({}, $.fn.button.defaults, options) + } + + Button.prototype = { + + constructor: Button + + , setState: function ( state ) { + var d = 'disabled' + , $el = this.$element + , data = $el.data() + , val = $el.is('input') ? 'val' : 'html' + + state = state + 'Text' + data.resetText || $el.data('resetText', $el[val]()) + + $el[val](data[state] || this.options[state]) + + // push to event loop to allow forms to submit + setTimeout(function () { + state == 'loadingText' ? + $el.addClass(d).attr(d, d) : + $el.removeClass(d).removeAttr(d) + }, 0) + } + + , toggle: function () { + var $parent = this.$element.parent('[data-toggle="buttons-radio"]') + + $parent && $parent + .find('.active') + .removeClass('active') + + this.$element.toggleClass('active') + } + + } + + + /* BUTTON PLUGIN DEFINITION + * ======================== */ + + $.fn.button = function ( option ) { + return this.each(function () { + var $this = $(this) + , data = $this.data('button') + , options = typeof option == 'object' && option + if (!data) $this.data('button', (data = new Button(this, options))) + if (option == 'toggle') data.toggle() + else if (option) data.setState(option) + }) + } + + $.fn.button.defaults = { + loadingText: 'loading...' + } + + $.fn.button.Constructor = Button + + + /* BUTTON DATA-API + * =============== */ + + $(function () { + $('body').on('click.button.data-api', '[data-toggle^=button]', function ( e ) { + var $btn = $(e.target) + if (!$btn.hasClass('btn')) $btn = $btn.closest('.btn') + $btn.button('toggle') + }) + }) + +}( window.jQuery );/* ========================================================== + * bootstrap-carousel.js v2.0.1 + * http://twitter.github.com/bootstrap/javascript.html#carousel + * ========================================================== + * Copyright 2012 Twitter, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ========================================================== */ + + +!function( $ ){ + + "use strict" + + /* CAROUSEL CLASS DEFINITION + * ========================= */ + + var Carousel = function (element, options) { + this.$element = $(element) + this.options = $.extend({}, $.fn.carousel.defaults, options) + this.options.slide && this.slide(this.options.slide) + } + + Carousel.prototype = { + + cycle: function () { + this.interval = setInterval($.proxy(this.next, this), this.options.interval) + return this + } + + , to: function (pos) { + var $active = this.$element.find('.active') + , children = $active.parent().children() + , activePos = children.index($active) + , that = this + + if (pos > (children.length - 1) || pos < 0) return + + if (this.sliding) { + return this.$element.one('slid', function () { + that.to(pos) + }) + } + + if (activePos == pos) { + return this.pause().cycle() + } + + return this.slide(pos > activePos ? 'next' : 'prev', $(children[pos])) + } + + , pause: function () { + clearInterval(this.interval) + this.interval = null + return this + } + + , next: function () { + if (this.sliding) return + return this.slide('next') + } + + , prev: function () { + if (this.sliding) return + return this.slide('prev') + } + + , slide: function (type, next) { + var $active = this.$element.find('.active') + , $next = next || $active[type]() + , isCycling = this.interval + , direction = type == 'next' ? 'left' : 'right' + , fallback = type == 'next' ? 'first' : 'last' + , that = this + + if (!$next.length) return + + this.sliding = true + + isCycling && this.pause() + + $next = $next.length ? $next : this.$element.find('.item')[fallback]() + + if (!$.support.transition && this.$element.hasClass('slide')) { + this.$element.trigger('slide') + $active.removeClass('active') + $next.addClass('active') + this.sliding = false + this.$element.trigger('slid') + } else { + $next.addClass(type) + $next[0].offsetWidth // force reflow + $active.addClass(direction) + $next.addClass(direction) + this.$element.trigger('slide') + this.$element.one($.support.transition.end, function () { + $next.removeClass([type, direction].join(' ')).addClass('active') + $active.removeClass(['active', direction].join(' ')) + that.sliding = false + setTimeout(function () { that.$element.trigger('slid') }, 0) + }) + } + + isCycling && this.cycle() + + return this + } + + } + + + /* CAROUSEL PLUGIN DEFINITION + * ========================== */ + + $.fn.carousel = function ( option ) { + return this.each(function () { + var $this = $(this) + , data = $this.data('carousel') + , options = typeof option == 'object' && option + if (!data) $this.data('carousel', (data = new Carousel(this, options))) + if (typeof option == 'number') data.to(option) + else if (typeof option == 'string' || (option = options.slide)) data[option]() + else data.cycle() + }) + } + + $.fn.carousel.defaults = { + interval: 5000 + } + + $.fn.carousel.Constructor = Carousel + + + /* CAROUSEL DATA-API + * ================= */ + + $(function () { + $('body').on('click.carousel.data-api', '[data-slide]', function ( e ) { + var $this = $(this), href + , $target = $($this.attr('data-target') || (href = $this.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '')) //strip for ie7 + , options = !$target.data('modal') && $.extend({}, $target.data(), $this.data()) + $target.carousel(options) + e.preventDefault() + }) + }) + +}( window.jQuery );/* ============================================================= + * bootstrap-collapse.js v2.0.1 + * http://twitter.github.com/bootstrap/javascript.html#collapse + * ============================================================= + * Copyright 2012 Twitter, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================ */ + +!function( $ ){ + + "use strict" + + var Collapse = function ( element, options ) { + this.$element = $(element) + this.options = $.extend({}, $.fn.collapse.defaults, options) + + if (this.options["parent"]) { + this.$parent = $(this.options["parent"]) + } + + this.options.toggle && this.toggle() + } + + Collapse.prototype = { + + constructor: Collapse + + , dimension: function () { + var hasWidth = this.$element.hasClass('width') + return hasWidth ? 'width' : 'height' + } + + , show: function () { + var dimension = this.dimension() + , scroll = $.camelCase(['scroll', dimension].join('-')) + , actives = this.$parent && this.$parent.find('.in') + , hasData + + if (actives && actives.length) { + hasData = actives.data('collapse') + actives.collapse('hide') + hasData || actives.data('collapse', null) + } + + this.$element[dimension](0) + this.transition('addClass', 'show', 'shown') + this.$element[dimension](this.$element[0][scroll]) + + } + + , hide: function () { + var dimension = this.dimension() + this.reset(this.$element[dimension]()) + this.transition('removeClass', 'hide', 'hidden') + this.$element[dimension](0) + } + + , reset: function ( size ) { + var dimension = this.dimension() + + this.$element + .removeClass('collapse') + [dimension](size || 'auto') + [0].offsetWidth + + this.$element.addClass('collapse') + } + + , transition: function ( method, startEvent, completeEvent ) { + var that = this + , complete = function () { + if (startEvent == 'show') that.reset() + that.$element.trigger(completeEvent) + } + + this.$element + .trigger(startEvent) + [method]('in') + + $.support.transition && this.$element.hasClass('collapse') ? + this.$element.one($.support.transition.end, complete) : + complete() + } + + , toggle: function () { + this[this.$element.hasClass('in') ? 'hide' : 'show']() + } + + } + + /* COLLAPSIBLE PLUGIN DEFINITION + * ============================== */ + + $.fn.collapse = function ( option ) { + return this.each(function () { + var $this = $(this) + , data = $this.data('collapse') + , options = typeof option == 'object' && option + if (!data) $this.data('collapse', (data = new Collapse(this, options))) + if (typeof option == 'string') data[option]() + }) + } + + $.fn.collapse.defaults = { + toggle: true + } + + $.fn.collapse.Constructor = Collapse + + + /* COLLAPSIBLE DATA-API + * ==================== */ + + $(function () { + $('body').on('click.collapse.data-api', '[data-toggle=collapse]', function ( e ) { + var $this = $(this), href + , target = $this.attr('data-target') + || e.preventDefault() + || (href = $this.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '') //strip for ie7 + , option = $(target).data('collapse') ? 'toggle' : $this.data() + $(target).collapse(option) + }) + }) + +}( window.jQuery );/* ============================================================ + * bootstrap-dropdown.js v2.0.1 + * http://twitter.github.com/bootstrap/javascript.html#dropdowns + * ============================================================ + * Copyright 2012 Twitter, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================ */ + + +!function( $ ){ + + "use strict" + + /* DROPDOWN CLASS DEFINITION + * ========================= */ + + var toggle = '[data-toggle="dropdown"]' + , Dropdown = function ( element ) { + var $el = $(element).on('click.dropdown.data-api', this.toggle) + $('html').on('click.dropdown.data-api', function () { + $el.parent().removeClass('open') + }) + } + + Dropdown.prototype = { + + constructor: Dropdown + + , toggle: function ( e ) { + var $this = $(this) + , selector = $this.attr('data-target') + , $parent + , isActive + + if (!selector) { + selector = $this.attr('href') + selector = selector && selector.replace(/.*(?=#[^\s]*$)/, '') //strip for ie7 + } + + $parent = $(selector) + $parent.length || ($parent = $this.parent()) + + isActive = $parent.hasClass('open') + + clearMenus() + !isActive && $parent.toggleClass('open') + + return false + } + + } + + function clearMenus() { + $(toggle).parent().removeClass('open') + } + + + /* DROPDOWN PLUGIN DEFINITION + * ========================== */ + + $.fn.dropdown = function ( option ) { + return this.each(function () { + var $this = $(this) + , data = $this.data('dropdown') + if (!data) $this.data('dropdown', (data = new Dropdown(this))) + if (typeof option == 'string') data[option].call($this) + }) + } + + $.fn.dropdown.Constructor = Dropdown + + + /* APPLY TO STANDARD DROPDOWN ELEMENTS + * =================================== */ + + $(function () { + $('html').on('click.dropdown.data-api', clearMenus) + $('body').on('click.dropdown.data-api', toggle, Dropdown.prototype.toggle) + }) + +}( window.jQuery );/* ========================================================= + * bootstrap-modal.js v2.0.1 + * http://twitter.github.com/bootstrap/javascript.html#modals + * ========================================================= + * Copyright 2012 Twitter, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ========================================================= */ + + +!function( $ ){ + + "use strict" + + /* MODAL CLASS DEFINITION + * ====================== */ + + var Modal = function ( content, options ) { + this.options = options + this.$element = $(content) + .delegate('[data-dismiss="modal"]', 'click.dismiss.modal', $.proxy(this.hide, this)) + } + + Modal.prototype = { + + constructor: Modal + + , toggle: function () { + return this[!this.isShown ? 'show' : 'hide']() + } + + , show: function () { + var that = this + + if (this.isShown) return + + $('body').addClass('modal-open') + + this.isShown = true + this.$element.trigger('show') + + escape.call(this) + backdrop.call(this, function () { + var transition = $.support.transition && that.$element.hasClass('fade') + + !that.$element.parent().length && that.$element.appendTo(document.body) //don't move modals dom position + + that.$element + .show() + + if (transition) { + that.$element[0].offsetWidth // force reflow + } + + that.$element.addClass('in') + + transition ? + that.$element.one($.support.transition.end, function () { that.$element.trigger('shown') }) : + that.$element.trigger('shown') + + }) + } + + , hide: function ( e ) { + e && e.preventDefault() + + if (!this.isShown) return + + var that = this + this.isShown = false + + $('body').removeClass('modal-open') + + escape.call(this) + + this.$element + .trigger('hide') + .removeClass('in') + + $.support.transition && this.$element.hasClass('fade') ? + hideWithTransition.call(this) : + hideModal.call(this) + } + + } + + + /* MODAL PRIVATE METHODS + * ===================== */ + + function hideWithTransition() { + var that = this + , timeout = setTimeout(function () { + that.$element.off($.support.transition.end) + hideModal.call(that) + }, 500) + + this.$element.one($.support.transition.end, function () { + clearTimeout(timeout) + hideModal.call(that) + }) + } + + function hideModal( that ) { + this.$element + .hide() + .trigger('hidden') + + backdrop.call(this) + } + + function backdrop( callback ) { + var that = this + , animate = this.$element.hasClass('fade') ? 'fade' : '' + + if (this.isShown && this.options.backdrop) { + var doAnimate = $.support.transition && animate + + this.$backdrop = $('