├── .gitignore
├── lib
├── hb
│ ├── label.hb
│ ├── boolean.hb
│ ├── object.hb
│ ├── hidden.hb
│ ├── descend.hb
│ ├── union.hb
│ ├── number.hb
│ ├── enum.hb
│ ├── date.hb
│ ├── time.hb
│ ├── text.hb
│ ├── ref.hb
│ ├── string.hb
│ ├── datetime-local.hb
│ ├── dispatch.hb
│ ├── form.hb
│ └── array.hb
├── client
│ ├── loader.gif
│ ├── edit-item.html
│ ├── load-indicator.html
│ ├── confirm-delete-item.html
│ ├── messages.html
│ ├── pagination.html
│ ├── user.html
│ ├── couth-core.css
│ ├── couth-resource-api.tmpl.js
│ └── couth-client.js
├── couth.js
├── design.js
├── users.js
├── static.js
├── server.js
├── resources.js
├── couch
│ └── design-utils.js
├── core.js
├── tester.js
├── deploy.js
├── forms.js
└── type.js
├── example
├── static
│ ├── bootstrap
│ │ ├── img
│ │ │ ├── glyphicons-halflings.png
│ │ │ └── glyphicons-halflings-white.png
│ │ ├── css
│ │ │ └── bootstrap-responsive.min.css
│ │ └── js
│ │ │ └── bootstrap.min.js
│ ├── templates
│ │ ├── home.html
│ │ └── books.html
│ ├── core.js
│ └── index.html
├── README.md
└── app.js
├── package.json
├── README.md
└── vendor
└── jquery-ui-1.10.1.custom.min.js
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | npm-debug.log
3 |
--------------------------------------------------------------------------------
/lib/hb/label.hb:
--------------------------------------------------------------------------------
1 | {{description}}
2 |
--------------------------------------------------------------------------------
/lib/client/loader.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/darobin/couth/master/lib/client/loader.gif
--------------------------------------------------------------------------------
/lib/client/edit-item.html:
--------------------------------------------------------------------------------
1 | Edit
--------------------------------------------------------------------------------
/lib/hb/boolean.hb:
--------------------------------------------------------------------------------
1 | {{> label}}
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/lib/hb/object.hb:
--------------------------------------------------------------------------------
1 |
2 | {{#if description}}{{description}} {{/if}}
3 | {{> descend}}
4 |
5 |
--------------------------------------------------------------------------------
/example/static/bootstrap/img/glyphicons-halflings.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/darobin/couth/master/example/static/bootstrap/img/glyphicons-halflings.png
--------------------------------------------------------------------------------
/lib/hb/hidden.hb:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/example/static/bootstrap/img/glyphicons-halflings-white.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/darobin/couth/master/example/static/bootstrap/img/glyphicons-halflings-white.png
--------------------------------------------------------------------------------
/lib/client/load-indicator.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/lib/hb/descend.hb:
--------------------------------------------------------------------------------
1 | {{#each fields}}
2 | {{#if isHidden}}
3 | {{> hidden}}
4 | {{else}}
5 |
6 | {{> dispatch}}
7 |
8 | {{/if}}
9 | {{/each}}
10 |
--------------------------------------------------------------------------------
/lib/hb/union.hb:
--------------------------------------------------------------------------------
1 |
2 | {{#each fields}}
3 |
4 |
5 | {{> dispatch}}
6 |
7 | {{/each}}
8 |
9 |
--------------------------------------------------------------------------------
/lib/hb/number.hb:
--------------------------------------------------------------------------------
1 | {{> label}}
2 |
3 |
5 |
6 |
--------------------------------------------------------------------------------
/lib/hb/enum.hb:
--------------------------------------------------------------------------------
1 | {{> label}}
2 |
3 |
4 | {{#each values}}
5 | {{this}}
6 | {{/each}}
7 |
8 |
9 |
--------------------------------------------------------------------------------
/lib/hb/date.hb:
--------------------------------------------------------------------------------
1 | {{> label}}
2 |
3 |
5 |
6 |
--------------------------------------------------------------------------------
/lib/hb/time.hb:
--------------------------------------------------------------------------------
1 | {{> label}}
2 |
3 |
5 |
6 |
--------------------------------------------------------------------------------
/lib/hb/text.hb:
--------------------------------------------------------------------------------
1 | {{> label}}
2 |
3 |
5 |
6 |
--------------------------------------------------------------------------------
/example/static/templates/home.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
Hello, world!
4 |
5 | This is a template that gets called for the front page. Nothing much currently happens
6 | here but you can navigate to the books (and to anything else you may have added).
7 |
8 |
9 |
--------------------------------------------------------------------------------
/lib/couth.js:
--------------------------------------------------------------------------------
1 |
2 | var Couth = require("./core").Couth;
3 | require("./deploy");
4 | require("./server");
5 | require("./design");
6 | require("./static");
7 | require("./type");
8 | require("./resources");
9 | require("./users");
10 |
11 | module.exports = function () {
12 | return new Couth();
13 | };
14 |
--------------------------------------------------------------------------------
/lib/hb/ref.hb:
--------------------------------------------------------------------------------
1 | {{> label}}
2 |
3 |
4 | Pick
6 |
7 |
8 |
--------------------------------------------------------------------------------
/lib/hb/string.hb:
--------------------------------------------------------------------------------
1 | {{> label}}
2 |
3 |
6 |
7 |
--------------------------------------------------------------------------------
/lib/hb/datetime-local.hb:
--------------------------------------------------------------------------------
1 | {{> label}}
2 |
3 |
4 |
7 |
8 |
--------------------------------------------------------------------------------
/lib/client/confirm-delete-item.html:
--------------------------------------------------------------------------------
1 | ×
3 |
4 | confirm
5 | cancel
6 |
7 |
--------------------------------------------------------------------------------
/lib/client/messages.html:
--------------------------------------------------------------------------------
1 |
2 |
3 | ×
4 |
Error
5 | {{$couthError}}
6 |
7 |
8 | ×
9 |
Success!
10 | {{$couthSuccess}}
11 |
12 |
13 |
--------------------------------------------------------------------------------
/lib/hb/dispatch.hb:
--------------------------------------------------------------------------------
1 | {{#if isHidden }}{{> hidden}}{{/if
2 | }}{{#if isString }}{{> string}}{{/if
3 | }}{{#if isText }}{{> text}}{{/if
4 | }}{{#if isNumber }}{{> number}}{{/if
5 | }}{{#if isBoolean }}{{> boolean}}{{/if
6 | }}{{#if isObject }}{{> object}}{{/if
7 | }}{{#if isUnion }}{{> union}}{{/if
8 | }}{{#if isArray }}{{> array}}{{/if
9 | }}{{#if isEnum }}{{> enum}}{{/if
10 | }}{{#if isRef }}{{> ref}}{{/if
11 | }}{{#if isDate }}{{> date}}{{/if
12 | }}{{#if isTime }}{{> time}}{{/if
13 | }}{{#if isDatetimeLocal }}{{> datetime-local}}{{/if}}
14 |
--------------------------------------------------------------------------------
/lib/client/pagination.html:
--------------------------------------------------------------------------------
1 |
14 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "couth"
3 | , "description": "Refined Relaxation"
4 | , "version": "0.5.0"
5 | , "author": "Robin Berjon "
6 | , "dependencies": {
7 | "nopt": "2.1.1"
8 | , "underscore": "1.4.4"
9 | , "cradle": "0.6.4"
10 | , "mime": "1.2.9"
11 | , "request": "2.12.0"
12 | , "async": "0.2.5"
13 | , "web-schema": "1.1.0"
14 | , "wrench": "1.4.4"
15 | , "handlebars": "1.0.9"
16 | }
17 | , "devDependencies": {
18 | "mocha": "1.7.3"
19 | , "expect.js":"0.2.0"
20 | }
21 | , "repository": "git://github.com/darobin/couth"
22 | , "main": "lib/couth"
23 | }
24 |
--------------------------------------------------------------------------------
/lib/hb/form.hb:
--------------------------------------------------------------------------------
1 |
16 |
--------------------------------------------------------------------------------
/lib/hb/array.hb:
--------------------------------------------------------------------------------
1 |
2 | {{#if description}}{{description}} {{/if}}
3 |
4 |
5 |
6 |
7 | {{#with items}}{{> dispatch}}{{/with}}
8 |
9 |
10 |
11 |
12 | Add {{#if items.description}}{{items.description}}{{else}}item{{/if}}
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/lib/design.js:
--------------------------------------------------------------------------------
1 |
2 | var Couth = require("./core").Couth
3 | ;
4 |
5 | Couth.prototype.addRewrite = function (from, to, method, query) {
6 | var rew = { from: from, to: to };
7 | if (method) rew.method = method;
8 | if (query) {
9 | rew.query = query;
10 | for (var k in rew.query) {
11 | if (typeof rew.query[k] === "boolean" ||
12 | typeof rew.query[k] === "number") rew.query[k] = "" + rew.query[k];
13 | }
14 | }
15 | this.rewrites.push(rew);
16 | return this;
17 | };
18 | Couth.prototype.addLib = function (libName, libPath) {
19 | if (!this.design.lib) this.design.lib = {};
20 | if (!this.design.views.lib) this.design.views.lib = {};
21 | if (this.libCache[libName]) return;
22 | this.libCache[libName] = true;
23 | this.design.lib[libName] = this.loadContent(libPath).toString("utf8");
24 | this.design.views.lib[libName] = this.design.lib[libName];
25 | };
26 |
--------------------------------------------------------------------------------
/lib/users.js:
--------------------------------------------------------------------------------
1 | var Couth = require("./core").Couth
2 | ;
3 |
4 | Couth.prototype.couthUserRoutes = function () {
5 | // NOTE: this requires secure_rewrites to be set to false
6 | var sessionDB = "../../../_session";
7 | this.addRewrite("couth/session", sessionDB, "GET");
8 | this.addRewrite("couth/login", sessionDB, "POST");
9 | this.addRewrite("couth/logout", sessionDB, "DELETE");
10 | this.addRewrite("couth/signup/*", "../../../_users/*", "PUT");
11 |
12 | // note that it's also worth checking if the client API knows how to handle
13 | // names with a hyphen -> CouthUsers
14 | if (this.conf.exposeUsers) {
15 | this.addRewrite("couth-users/*", "../../../_users/*", "GET");
16 | this.addRewrite("couth-users/", "../../../_users/_all_docs", "GET", {
17 | startkey: "org.couchdb.user:"
18 | , endkey: "org.couchdb.userz"
19 | , include_docs: true
20 | });
21 | // http://deploy.berjon.dev/_users/_all_docs?startkey=%22org.couchdb.user:%22&endkey=%22org.couchdb.userz%22&include_docs=true
22 | }
23 | };
24 |
--------------------------------------------------------------------------------
/example/static/templates/books.html:
--------------------------------------------------------------------------------
1 |
2 |
Books
3 |
4 |
5 |
6 | Title
7 | Authors
8 | ISBN
9 | Actions
10 |
11 |
12 | {{ book.title }}
13 |
14 | {{author.name}}, et al.
16 |
17 | {{ book.isbn }}
18 |
19 |
20 |
22 |
23 |
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/example/static/core.js:
--------------------------------------------------------------------------------
1 | /*global angular */
2 |
3 | angular.module("my-stuff", ["CouthClient", "CouthResourceAPI"])
4 | .config(function ($routeProvider, $locationProvider) {
5 | $locationProvider.html5Mode(true);
6 | $routeProvider
7 | .when("/", { templateUrl: "/templates/home.html" })
8 | .when("/app/books/", { controller: "BooksCtrl", templateUrl: "/templates/books.html" })
9 | .otherwise({ redirectTo: "/" });
10 | })
11 | .controller("NavCtrl", function ($scope, $rootScope, $location) {
12 | $rootScope.pathActive = function (path) {
13 | return ($location.path().substr(0, path.length) === path) ? "active" : "";
14 | };
15 | })
16 | .controller("BooksCtrl", function ($scope, Books, CouthSimpleCRUD) {
17 | CouthSimpleCRUD.runForType({
18 | type: Books
19 | , name: "Book"
20 | , scope: $scope
21 | , onload: function (data) {
22 | $scope.books = data.rows;
23 | $scope.count = data.total_rows;
24 | }
25 | , pagination: {
26 | pageSize: 10
27 | , countExpr: "count"
28 | }
29 | });
30 | })
31 | ;
32 |
--------------------------------------------------------------------------------
/example/README.md:
--------------------------------------------------------------------------------
1 |
2 | ## How to get this running
3 |
4 | To get this example running, you will need to have Couth installed and CouchDB running.
5 |
6 | You will also need to have the two hostnames configured `books.dev` and
7 | `deploy.books.dev` to point to where your CouchDB instance is running. They can be anything
8 | else but you will need to change the example to match.
9 |
10 | You will need to set the username and password to something real. If your CouchDB is running
11 | in Admin Party mode, then you can just delete that line.
12 |
13 | Then you run:
14 |
15 | node app.js
16 |
17 | This ought to deploy to Couch. You should then be able to get to: http://books.dev:5984/ and
18 | see the site.
19 |
20 | Obviously in a real-world setting you would likely use an HTTP proxy on port 80 in front of
21 | CouchDB. For nginx the set up would be:
22 |
23 |
24 | upstream couch {
25 | server 127.0.0.1:5984;
26 | }
27 |
28 | server {
29 | listen 80;
30 | server_name deploy.books.dev books.dev;
31 |
32 | location / {
33 | proxy_set_header X-Real-IP $remote_addr;
34 | proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
35 | proxy_set_header Host $http_host;
36 | proxy_set_header X-NginX-Proxy true;
37 |
38 | proxy_pass http://couch/;
39 | proxy_redirect off;
40 | }
41 | }
42 |
43 |
44 | If you do want to hack on this, you probably want to read the documentation section
45 | on "Continuous Execution" as it will make your life much nicer.
46 |
--------------------------------------------------------------------------------
/example/app.js:
--------------------------------------------------------------------------------
1 | var couth = require("couth")
2 | , app = couth()
3 | ;
4 |
5 | app
6 | .deployTo("http://deploy.books.dev/")
7 | .auth({ username: "you", password: "secret" })
8 | .vhost("books.dev")
9 | .db("mybooks")
10 | .index("/index.html")
11 | .webAppRoot("/app/")
12 | .addStaticDir("static")
13 | ;
14 |
15 | app.type("books")
16 | .schema({
17 | type: "object"
18 | , description: "Book"
19 | , properties: {
20 | title: {
21 | type: "string"
22 | , description: "Title"
23 | , required: true
24 | }
25 | , isbn: {
26 | type: "string"
27 | , description: "ISBN"
28 | , pattern: "\\d{3}-\\d-\\d\\d-\\d{6}-\\d"
29 | }
30 | , authors: {
31 | type: "array"
32 | , description: "Authors"
33 | , items: {
34 | type: "object"
35 | , properties: {
36 | name: { type: "string", required: true }
37 | }
38 | }
39 | }
40 | , etAl: { type: "boolean", description: "Et al." }
41 | }
42 | })
43 | .permissions({
44 | create: "logged"
45 | , update: "logged"
46 | , del: "admin"
47 | })
48 | .crudify({ jsonp: true })
49 | ;
50 |
51 | // process command line options and deploy
52 | app
53 | .cli()
54 | .deploy(function (err) {
55 | console.log(err ? "BAD!" : "ALL OK!");
56 | })
57 | ;
58 |
--------------------------------------------------------------------------------
/lib/client/user.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Sign Up
6 |
21 |
22 |
23 |
24 |
25 | Login
26 |
41 |
42 |
43 |
44 | Logout
45 |
46 |
47 |
--------------------------------------------------------------------------------
/lib/static.js:
--------------------------------------------------------------------------------
1 |
2 | var Couth = require("./core").Couth
3 | , pth = require("path")
4 | , wrench = require("wrench")
5 | , fs = require("fs")
6 | , mime = require("mime")
7 | , _ = require("underscore")
8 | ;
9 |
10 | Couth.prototype.addStaticDir = function (path, opts) {
11 | opts = opts || { keepDotFiles: false };
12 | var files = wrench.readdirSyncRecursive(path)
13 | , statics = []
14 | ;
15 | for (var i = 0, n = files.length; i < n; i++) {
16 | var f = files[i]
17 | , fullPath = pth.join(path, f)
18 | , basename = pth.basename(fullPath)
19 | ;
20 | if (fs.statSync(fullPath).isDirectory()) continue;
21 | if (basename.indexOf(".") === 0 && !opts.keepDotFiles) continue;
22 | statics.push({ path: "/" + f, content: fullPath });
23 | }
24 | return this.addStatics(statics);
25 | };
26 | Couth.prototype.addStatics = function (statics) {
27 | if (!_.isArray(statics)) statics = [statics];
28 | var self = this;
29 | _.each(statics, function (stat) {
30 | // the rewrite to self is actually needed
31 | self.addRewrite(stat.path, stat.path);
32 | self.addAttachment(stat.path.replace(/^\//, ""), stat.content, stat.type);
33 | });
34 | return this;
35 | };
36 | Couth.prototype.addAttachment = function (url, source, mediaType) {
37 | var mt = mediaType || mime.lookup(source)
38 | , showURL = _.isString(source)
39 | , body = this.loadContent(source)
40 | , self = this
41 | ;
42 | this.seenAttachment[url] = true;
43 | this.addRequest({
44 | run: function (cradle, cb) {
45 | cradle.addAttachment(self.design, {
46 | name: url
47 | , contentType: mt
48 | , body: body
49 | }, function (err, res) {
50 | if (err) self.error(err);
51 | self.design._rev = res._rev;
52 | cb();
53 | });
54 | }
55 | , reason: "Uploading attachment of type " + mt + " to " + url + " from " + (showURL ? source : "[memory]")
56 | });
57 | return this;
58 | };
59 |
--------------------------------------------------------------------------------
/example/static/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | My Stuff
7 |
8 |
9 |
10 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
My Stuff
41 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
--------------------------------------------------------------------------------
/lib/server.js:
--------------------------------------------------------------------------------
1 |
2 | var Couth = require("./core").Couth
3 | , _ = require("underscore")
4 | , urlParser = require("url")
5 | , request = require("request")
6 | ;
7 |
8 | Couth.prototype.addRequest = function (req) {
9 | this.requests.push(req);
10 | };
11 | Couth.prototype.vhostInfo = function () {
12 | var conf = this.conf
13 | , res = []
14 | ;
15 | if (!conf.vhost) return;
16 | if (!_.isArray(conf.vhost)) conf.vhost = [conf.vhost];
17 | _.each(conf.vhost, function (vh) {
18 | var url = urlParser.parse(conf.deployTo);
19 | delete url.host;
20 | if (conf.port) url.port = conf.port;
21 | if (conf.auth) url.auth = conf.auth.username + ":" + conf.auth.password;
22 | url.pathname = "/_config/vhosts/" + vh;
23 | res.push({ url: urlParser.format(url), body: "\"/" + conf.db + "/_design/couth/_rewrite\"", vh: vh });
24 | });
25 | return res;
26 | };
27 | Couth.prototype.enforceConfig = function () {
28 | var conf = this.conf;
29 | // prepare url
30 | var url = urlParser.parse(conf.deployTo);
31 | delete url.host;
32 | if (conf.port) url.port = conf.port;
33 | if (conf.auth) url.auth = conf.auth.username + ":" + conf.auth.password;
34 | // session
35 | url.pathname = "/_config/couch_httpd_auth/timeout";
36 | var sessURL = urlParser.format(url);
37 | this.addRequest({
38 | run: function (cradle, cb) {
39 | request.put({
40 | url: sessURL
41 | , body: '"' + conf.session + '"'
42 | }, cb);
43 | }
44 | , reason: "enforcing session duration to " + conf.session + " (PUT " + urlParser.format(url) + ")"
45 | });
46 | // secure rewrites off (these aren't secure anyway)
47 | url.pathname = "/_config/httpd/secure_rewrites";
48 | var rewURL = urlParser.format(url);
49 | this.addRequest({
50 | run: function (cradle, cb) {
51 | request.put({
52 | url: rewURL
53 | , body: '"false"'
54 | }, cb);
55 | }
56 | , reason: "enforcing secure rewrites to false (PUT " + urlParser.format(url) + ")"
57 | });
58 | };
59 | // sets up the vhost server configuration
60 | // curl -X PUT http://${user}:${pass}@${host}/_config/vhosts/${vhost} -d '"/${db}/_design/${something}/_rewrite"'
61 | Couth.prototype.prepareVHost = function () {
62 | var vhostInfo = this.vhostInfo()
63 | , self = this
64 | ;
65 | _.each(vhostInfo, function (vh) {
66 | self.addRequest({
67 | // we roll our own request because it's rather specific for the configuration
68 | run: function (cradle, cb) {
69 | request.put({
70 | url: vh.url
71 | , body: vh.body
72 | }, cb);
73 | }
74 | , reason: "installing virtual host " + vh.vh + " (PUT " + vh.url + " with " + vh.body + ")"
75 | });
76 | });
77 | };
78 |
--------------------------------------------------------------------------------
/lib/client/couth-core.css:
--------------------------------------------------------------------------------
1 |
2 | .couth-item {
3 | background: #fff;
4 | /* margin: 10px 0;*/
5 | }
6 |
7 | .couth-placeholder {
8 | background: #eee;
9 | border: 1px dashed #ccc;
10 | border-radius: 5px;
11 | }
12 |
13 | .couth-move {
14 | float: right;
15 | margin-right: 10px;
16 | }
17 |
18 | .couth-item-delete {
19 | float: right;
20 | }
21 |
22 | /* just to make sure we're on the safe side, FOUC wise */
23 | [ng\:cloak], [ng-cloak], .ng-cloak {
24 | display: none;
25 | }
26 |
27 | .couth-signup {
28 | margin-right: 10px;
29 | }
30 |
31 | .dropdown-menu .form-inline {
32 | margin: 10px 20px;
33 | }
34 |
35 | .couth-form-controls {
36 | margin-bottom: 10px;
37 | text-align: right;
38 | }
39 |
40 | td.couth-actions, th.couth-actions {
41 | text-align: right;
42 | white-space: nowrap
43 | }
44 |
45 | .couth-pagination {
46 | text-align: center;
47 | }
48 |
49 | .couth-inlined {
50 | display: inline-block;
51 | }
52 |
53 | .couth-success, .couth-error {
54 | left: auto;
55 | right: 0;
56 | background-clip: padding-box;
57 | border: 1px solid #000;
58 | border-radius: 6px 6px 6px 6px;
59 | box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);
60 | min-width: 400px;
61 | margin: 0 20px 20px 0;
62 | padding: 8px 35px 14px 14px;
63 | position: fixed;
64 | z-index: 1000;
65 | opacity: 0.9;
66 | }
67 | .couth-success h4, .couth-error h4 {
68 | margin-top: 0;
69 | }
70 |
71 | .couth-success {
72 | background-color: #dff0d8;
73 | border-color: #d6e9c6;
74 | color: #468847;
75 |
76 | }
77 | .couth-error {
78 | background-color: #f2dede;
79 | border-color: #eed3d7;
80 | color: #b94a48;
81 | }
82 |
83 | .couth-close {
84 | line-height: 20px;
85 | position: relative;
86 | right: -21px;
87 | top: -2px;
88 | vertical-align: middle;
89 | background: none repeat scroll 0 0 transparent;
90 | border: 0 none;
91 | cursor: pointer;
92 | padding: 0;
93 | float: right;
94 | font-size: 20px;
95 | font-weight: bold;
96 | opacity: 0.2;
97 | text-shadow: 0 1px 0 #FFFFFF;
98 | }
99 |
100 | fieldset fieldset legend {
101 | border: none;
102 | font-size: 1em;
103 | font-weight: bold;
104 | margin: 0;
105 | text-transform: lowercase;
106 | font-variant: small-caps;
107 | padding-top: 5px;
108 | text-align: right;
109 | width: 160px;
110 | }
111 |
112 | fieldset fieldset fieldset legend {
113 | font-weight: normal;
114 | margin: 0;
115 | padding: 0;
116 | line-height: inherit;
117 | color: #999;
118 | }
119 |
120 | /*! jQuery UI - v1.10.1 - 2013-02-26
121 | * http://jqueryui.com
122 | * Includes: jquery.ui.core.css
123 | * Copyright (c) 2013 jQuery Foundation and other contributors Licensed MIT */
124 |
125 | .ui-helper-hidden{display:none}.ui-helper-hidden-accessible{border:0;clip:rect(0 0 0 0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.ui-helper-reset{margin:0;padding:0;border:0;outline:0;line-height:1.3;text-decoration:none;font-size:100%;list-style:none}.ui-helper-clearfix:before,.ui-helper-clearfix:after{content:"";display:table;border-collapse:collapse}.ui-helper-clearfix:after{clear:both}.ui-helper-clearfix{min-height:0}.ui-helper-zfix{width:100%;height:100%;top:0;left:0;position:absolute;opacity:0;filter:Alpha(Opacity=0)}.ui-front{z-index:100}.ui-state-disabled{cursor:default!important}.ui-icon{display:block;text-indent:-99999px;overflow:hidden;background-repeat:no-repeat}.ui-widget-overlay{position:fixed;top:0;left:0;width:100%;height:100%}
126 |
--------------------------------------------------------------------------------
/lib/resources.js:
--------------------------------------------------------------------------------
1 | var Couth = require("./core").Couth
2 | , pth = require("path")
3 | , type2form = require("./forms").generate
4 | ;
5 |
6 | Couth.prototype.couthResources = function () {
7 | if (!Object.keys(this.types).length) return;
8 | var allTypes = [];
9 | for (var t in this.types) {
10 | allTypes.push({
11 | name: t
12 | , crudOptions: this.types[t].crudOptions
13 | });
14 | var path = "/couth/types/" + t + ".json";
15 | this.addRewrite(path, path);
16 | this.addAttachment(path.replace(/^\//, ""),
17 | new Buffer(JSON.stringify(this.types[t].jsonSchema)),
18 | "application/json");
19 | var form = "/couth/forms/" + t + ".html";
20 | this.addRewrite(form, form);
21 | this.addAttachment(form.replace(/^\//, ""),
22 | new Buffer(type2form(this.types[t].jsonSchema, t, this.types[t].hints)),
23 | "text/html");
24 | }
25 | if (this.conf.exposeUsers) {
26 | allTypes.push({
27 | name: "couth-users"
28 | , crudOptions: {
29 | id: "_id",
30 | paths: {
31 | list: "/couth-users",
32 | create: "/couth/signup",
33 | read: "/couth-users/:key",
34 | update: "XXX",
35 | del: "XXX"
36 | }
37 | }
38 | });
39 | }
40 |
41 | // generate one big JS with all the dependencies
42 | var js = this.readRelFile("../vendor/jquery.min.js") +
43 | this.readRelFile("../vendor/jquery-ui-1.10.1.custom.min.js") +
44 | this.readRelFile("../vendor/angular.min.js") +
45 | this.readRelFile("client/couth-resource-api.tmpl.js")
46 | .replace('["REPLACE ME"]', JSON.stringify(allTypes, null, 4)) +
47 | this.readRelFile("client/couth-client.js");
48 | // XXX at some point, build one big HTML file with all the HTML templates in