Skip to content

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also .

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also .
  • 2 commits
  • 17 files changed
  • 0 commit comments
  • 1 contributor
View
120 Cakefile
@@ -5,18 +5,25 @@ coffee = require 'coffee-script'
templater = require './lib/templater'
watch = require 'watch'
knox = require 'knox'
-
+bucket = null
ansi =
green: '\033[32m'
red: '\033[31m'
yellow: '\033[33m'
none: '\033[0m'
-bucket = knox.createClient
- key: process.env.AWS_ACCESS_KEY_ID
- secret: process.env.AWS_SECRET_ACCESS_KEY
- bucket: process.env.AWS_DEFAULT_BUCKET
+
+getBucket = (options) ->
+ config =
+ key: options.key or process.env.AWS_ACCESS_KEY_ID
+ secret: options.secret or process.env.AWS_SECRET_ACCESS_KEY
+ bucket: options.bucket or process.env.AWS_DEFAULT_BUCKET
+
+ if config.key and config.secret and config.bucket
+ knox.createClient config
+ else
+ false
@@ -68,17 +75,27 @@ handleS3Result = (cb, err, res) ->
uploadFile = (path) ->
+ if path.slice(-1) is '/'
+ isDir = true
+
remotePath = path.replace(/^public/, '')
- remotePath = '/admin/' if remotePath is '/admin/index.html'
+ return if remotePath is '/' or remotePath is '/admin/'
+ remotePath = '/admin/' if remotePath is '/admin/main.html'
- bucket.putFile path, remotePath, handleS3Result.bind null, ->
- growlNotify(remotePath)
- console.log 'uploaded:', ansi.green, path, ansi.none
+ if isDir
+ req = bucket.put(remotePath, 'Content-Length': 0).on('response', handleS3Result.bind null, ->
+ growlNotify(remotePath)
+ console.log 'uploaded:', ansi.green, path, ansi.none
+ , null).end()
+ else
+ bucket.putFile path, remotePath, handleS3Result.bind null, ->
+ growlNotify(remotePath)
+ console.log 'uploaded:', ansi.green, path, ansi.none
deleteFile = (path) ->
remotePath = path.replace(/^public/, '')
- remotePath = '/admin/' if remotePath is '/admin/index.html'
+ remotePath = '/admin/' if remotePath is '/admin/main.html'
bucket.deleteFile remotePath, handleS3Result.bind null, ->
console.log 'deleted:', ansi.green, path, ansi.none
@@ -94,46 +111,87 @@ growlNotify = (uploaded) ->
timeout = null
, 1000
-task 'watch', 'Watch scripts for changes and compile them when they change', ->
+
+
+
+
+
+option '-k', '--key [KEY]', 'AWS access key id. Will attempt to use the environment variable AWS_ACCESS_KEY_ID if not provided.'
+option '-s', '--secret [SECRET]', 'AWS secret access key. Will attempt to use the environment variable AWS_SECRET_ACCESS_KEY if not provided.'
+option '-b', '--bucket [BUCKET]', 'S3 bucket to upload to. Will attempt to use the environment variable AWS_DEFAULT_BUCKET if not provided.'
+
+
+task 'make', 'Compile scripts and upload them', (options) ->
+ bucket = getBucket(options)
+
+ watch.walk 'src', (err, files) ->
+ for filename, stat of files
+ if stat.isDirectory()
+ try
+ fs.mkdirSync(getDest(filename))
+ catch e
+ else
+ compile(filename)
+
+ unless bucket
+ console.log 'key, secret, and/or bucket undefined, will not upload'
+ return
+
+ watch.walk 'public', (err, files) ->
+ for filename, stat of files
+ filename += '/' if stat.isDirectory()
+ uploadFile(filename)
+
+
+
+
+task 'watch', 'Watch scripts and files for changes and compile and upload them when they change', (options) ->
+ bucket = getBucket(options)
watch.createMonitor 'src', interval: 100, (monitor) ->
- for f, stat of monitor.files
+ for filename, stat of monitor.files
if stat.isDirectory()
try
- fs.mkdirSync(getDest(f))
+ fs.mkdirSync(getDest(filename))
catch e
else
- compile(f)
+ compile(filename)
console.log 'watching...'
- monitor.on 'created', (f, curr, prev) ->
+ monitor.on 'created', (filename, curr, prev) ->
if curr.isDirectory()
- dest = getDest(f)
+ dest = getDest(filename)
fs.mkdirSync(dest)
- console.log 'created: ' + dest
+ console.log 'created:', dest
else
- compile(f)
+ compile(filename)
- monitor.on 'changed', (f, curr, prev) ->
- compile(f) unless curr.isDirectory()
+ monitor.on 'changed', (filename, curr, prev) ->
+ compile(filename) unless curr.isDirectory()
- monitor.on 'removed', (f, curr, prev) ->
- remove(f)
+ monitor.on 'removed', (filename, curr, prev) ->
+ remove(filename)
+ unless bucket
+ console.log 'key, secret, and/or bucket undefined, will not upload'
+ return
watch.createMonitor 'public', interval: 100, (monitor) ->
- for f, stat of monitor.files
- unless stat.isDirectory()
- uploadFile(f)
+ for filename, stat of monitor.files
+ filename += '/' if stat.isDirectory()
+ uploadFile(filename)
- monitor.on 'created', (f, curr, prev) ->
- uploadFile(f) unless curr.isDirectory()
+ monitor.on 'created', (filename, curr, prev) ->
+ filename += '/' if stat.isDirectory()
+ uploadFile(filename)
- monitor.on 'changed', (f, curr, prev) ->
- uploadFile(f) unless curr.isDirectory()
+ monitor.on 'changed', (filename, curr, prev) ->
+ filename += '/' if stat.isDirectory()
+ uploadFile(filename)
- monitor.on 'removed', (f, curr, prev) ->
- deleteFile(f) unless curr.isDirectory()
+ monitor.on 'removed', (filename, curr, prev) ->
+ filename += '/' if stat.isDirectory()
+ deleteFile(filename)
View
41 README.md
@@ -42,36 +42,31 @@ policy" link in the properties and paste this in (be sure to replace "mybucket"
Then select the "Website" tab, check "Enabled" and put in "index.html" and "error.html" for the two fields.
From the "Website" tab you'll see the S3 domain you must use to have the website feature. If your bucket is called
-"mywebsite.com" you can point your mywebsite.com domain's DNS to this S3 domain using CNAME to access your S3 website
-from http://mywebsite.com/.
-
-Finally upload the following files from the src/ folder of your cloned git project to your S3 bucket (set their
-content-type appropriately, e.g. text/html, text/css, text/js):
-
-* index.html
-* error.html
-* admin/index.html
-* admin/css/admin.css
-* admin/js/app.js
-* admin/js/login.js
-* admin/login.html
-* admin/index.html
-
-You should be able to go to the url https://s3.amazonaws.com/mybucket/admin/index.html and be presented with the login
+"www.example.com" you can point your www.example.com domain's DNS to this S3 domain using CNAME to access your S3 website
+from http://www.example.com/.
+
+Finally upload the contents of the public directory of your cloned git project to your S3 bucket (make them public-read
+and set their content-type appropriately, e.g. text/html, text/css, text/js).
+
+You should be able to go to the url http://www.example.com/admin/ or https://s3.amazonaws.com/www.example.com/admin/ and
+be presented with the login
page. Click Register and put in your info, then you'll be taken to the blank dashboard page. Later you can come here
and login with the username/password you registered with. Note that because Amazon only allows GETs for the website URL
-you cannot login to the admin from the same URL you access the website from.
+(www.example.com) you are redirected to https://s3.amazonaws.com/www.example.com/admin/ when you go to the admin
+directory at http://www.example.com/admin/.
-You can see [staticsite.org](http://staticsite.org/) set up with the code and if you go to
-[staticsite.org/admin](http://staticsite.org/admin/) you'll be redirected to the correct URL for logging in, though you
+You can see [www.staticsite.org](http://www.staticsite.org/) set up with the code and if you go to
+[www.staticsite.org/admin](http://www.staticsite.org/admin/) you'll be redirected to the correct URL for logging in, though you
won't be able to register with that bucket.
**Building**
-To build the admin.js you need node.js installed, npm, and uglify-js installed. You can get instructions on installing
-[node.js](http://nodejs.org/) from their website, [npm](http://npmjs.org/) from their website, and uglify by calling
-"npm install uglify-js" from the command line.
+To build the project you need node.js installed, npm, and CoffeeScript. You can get instructions on installing
+[node.js](http://nodejs.org/) from their website and [npm](http://npmjs.org/) from their website. To install
+CoffeeScript run `npm install -g coffee-script` with the global flag.
-Once everything is installed go to the root of your project and run `./make.sh`
+Once everything is installed go to the root of your project and run `npm install` to install required modules. Then you
+can run `cake make` to compile the coffeescript in the src/ folder, and
+`cake -k aws_key -s aws_secret -b www.example.com make` to compile and upload the files to your bucket.
If you have any problems or issues you're on your own. Sorry. It's still early.
View
106 public/admin/index.html
@@ -1,100 +1,14 @@
-<!DOCTYPE html>
-<html lang="en">
+<html>
<head>
- <meta charset="utf-8">
- <title>Admin</title>
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
- <meta name="description" content="">
- <meta name="author" content="">
- <link href="css/bootstrap.min.css" rel="stylesheet">
- <link href="css/admin.css" rel="stylesheet">
- <link href="css/icon-sprite.css" rel="stylesheet">
- <!--[if lt IE 9]>
- <script src="http://html5shim.googlecode.com/svn/trunk/html5.js"></script>
- <![endif]-->
- <link rel="shortcut icon" href="img/favicon.ico">
+<title>Admin</title>
+<script>
+var bucket = location.hostname;
+location.href = 'https://s3.amazonaws.com/' + bucket + '/admin/'
+</script>
</head>
-
-<body style="display: none">
-
-<div class="navbar navbar-fixed-top">
- <div class="navbar-inner">
- <div class="container-fluid">
- <a class="btn btn-navbar" data-toggle="collapse" data-target=".nav-collapse">
- <span class="icon-bar"></span>
- <span class="icon-bar"></span>
- <span class="icon-bar"></span>
- </a>
- <a class="brand" href="#">Websights</a>
- <div class="nav-collapse">
- <ul class="nav">
- <li class="active"><a href="#">Site</a></li>
- <li><a href="#templates">Templates</a></li>
- <li><a href="#settings">Settings</a></li>
- </ul>
- </div>
- </div>
- </div>
-</div>
-
-<div id="container" class="container-fluid">
- <div id="sidebar" class="pod">
- <div class="btn-toolbar">
- <div class="btn-group">
- <button class="btn" style="overflow: hidden">
- <span class="icon add"></span> Add
- <input type="file" class="btn" name="files[]" multiple style="position: absolute; opacity: 0; left: 0; right: 0; top: 0; height: 20px;">
- </button>
- <button class="btn dropdown-toggle" data-toggle="dropdown">
- <span class="caret"></span>
- </button>
- <ul class="dropdown-menu">
- <li id="new-file"><a href="#"><span class="icon page-add"></span> Add page</a></li>
- <li id="new-page"><a href="#"><span class="icon layout-add"></span> Add page from template</a></li>
- <li id="new-folder"><a href="#"><span class="icon folder-add"></span> Add folder</a></li>
- </ul>
- </div>
- <div class="btn-group">
- <button id="delete-file" class="btn"><span class="icon delete"></span></button>
- </div>
- </div>
- <div id="menu">
- <ul>
- </ul>
- </div>
- </div>
- <div id="breadcrumbs" class="btn-toolbar">
- <ul class="breadcrumb pod">
- <li>
- <div class="btn-group">
- <a class="btn btn-mini dropdown-toggle" data-toggle="dropdown" href="#">
- <span class="caret"></span>
- </a>
- <ul id="site-list" class="dropdown-menu">
- <li id="new-site"><a href="#"><span class="icon sitemap-add"></span> New...</a></li>
- </ul>
- </div>
- <a id="selected-site" href="/"></a>
- </li>
- <!--<li>-->
- <!--<span class="divider">/</span> <a href="/about-us">about-us</a>-->
- <!--</li>-->
- <!--<li class="active">-->
- <!--<span class="divider">/</span> jobs-->
- <!--</li>-->
- </ul>
- </div>
- <div id="main">
- <div id="editors" class="pod">
- <!--<div id="code-editor"></div>-->
- <iframe id="frame" src="http://www2.rainbowspreschool.com/"></iframe>
- </div>
- </div>
-</div>
-
-<script src="js/jquery.min.js"></script>
-<script src="js/bootstrap.min.js"></script>
-<script src="js/lib/ace/ace-noconflict.js"></script>
-<script src="js/require.min.js" data-main="js/main"></script>
+<body>
+<script type="text/javascript">
+document.write('<a href="https://s3.amazonaws.com/' + bucket + '/admin/">Go to admin</a>');
+</script>
</body>
</html>
View
2 public/admin/js/app/auth.js
@@ -3,7 +3,7 @@
define(['lib/crypto', 'lib/promises', 'lib/s3'], function(crypto, promises, s3) {
var aes, path, sha1;
sha1 = crypto.sha1, aes = crypto.aes;
- path = '/websights/auth/';
+ path = 'auth/';
return {
login: function(username, password, remember) {
var deferred, passwordSha, usernameSha;
View
6 public/admin/js/app/data.js
@@ -3,11 +3,11 @@
EventEmitter = require('events').EventEmitter;
- promises = require('../libs/promises');
+ promises = require('../lib/promises');
_ = require('underscore');
- s3 = require('../libs/s3').s3;
+ s3 = require('../lib/s3').s3;
bucketName = location.pathname.replace(/^\/([^\/]+).*/, '$1');
@@ -24,7 +24,7 @@
return bucket.put('api/' + url, data);
},
destory: function(url) {
- return bucket.destory('api/' + url);
+ return bucket.destroy('api/' + url);
},
refresh: function(options) {
var deferred, promise;
View
2 public/admin/js/app/page.js
@@ -3,7 +3,7 @@
__hasProp = Object.prototype.hasOwnProperty,
__extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor; child.__super__ = parent.prototype; return child; };
- query = require('../libs/query');
+ query = require('../lib/query');
Model = require('Backbone').Model;
View
353 public/admin/js/lib/query.js
@@ -0,0 +1,353 @@
+
+
+function query(field) {
+ if ( !(this instanceof query) ) {
+ return new query(field);
+ }
+
+ if (field) this._field(field);
+ this._eval = '';
+ this._lookups = {};
+ this._sorts = [];
+ this._actions = [];
+ this._map = [];
+ this._reduce = [];
+}
+
+function select(array) {
+ if ( !(this instanceof select) ) {
+ return new select(array);
+ }
+ query.call(this);
+ this.array = array;
+}
+
+query.select = select;
+
+(function() {
+
+ query.prototype = {
+ on: function(array) {
+ var filter = this.getFilter();
+ var sort = this.getSort();
+
+ if (filter) array = array.filter(filter, query);
+ else array = array.slice(); // copy array
+ if (sort) array.sort(sort);
+ if (this._offset) array = array.slice(this._offset, array.length - (this._limit || 0));
+ else if (this._limit) array.length = Math.min(array.length, this._limit);
+ this._actions.forEach(function(action) {
+ array.forEach(action);
+ });
+ this._map.forEach(function(action) {
+ array = array.map(action);
+ });
+ this._reduce.forEach(function(action) {
+ array = array.reduce(action);
+ });
+ return array;
+ },
+ getFilter: function() {
+ var queryStr = this.toString();
+ if (!queryStr) return null;
+ if (this._filterCache && this._filterCache.query == queryStr) return this._filterCache;
+ this._filterCache = new Function('obj', 'try { return ' + queryStr + '; } catch (e) { return false; }').bind(this);
+ this._filterCache.query = queryStr;
+ return this._filterCache;
+ },
+ getSort: function() {
+ if (!this._sorts.length) return null;
+ if (this._sortCache) return this._sortCache;
+ var sorts = this._sorts.map(function(sort) {
+ return sort.toFunction();
+ });
+ return this._sortCache = function(a, b) {
+ var direction = 0, i = 0, len = sorts.length;
+ while (i < len && direction == 0) {
+ direction = sorts[i++](a, b);
+ }
+ return direction;
+ };
+ },
+ getActions: function() {
+ return this._actions;
+ },
+ _field: function(field) {
+ this._expression = new Expression(field);
+ },
+ _add: function(eval, clean) {
+ this._eval += eval;
+ if (clean) this._expression = null;
+ return this;
+ },
+ _term: function(condition, field) {
+ this._flush();
+ this._eval += ' ' + condition + ' ';
+ if (typeof field == 'string') {
+ this._expression = new Expression(field);
+ } else if (field instanceof query) {
+ for (var i in field._lookups) {
+ if (field._lookups.hasOwnProperty(i)) this._lookups[i] = field._lookups[i];
+ }
+ this._eval += '(' + field + ')';
+ } else if (field) {
+ this._eval += '(' + field + ')';
+ }
+ return this;
+ },
+ _oper: function(operator, value) {
+ if (this._expression) {
+ this._expression.operator = operator;
+ this._expression.value = value;
+ }
+ return this;
+ },
+ _store: function(value) {
+ var postFix = Math.round(Math.random()*1000000);
+ this._lookups[postFix] = value;
+ return 'this._lookups[' + postFix + ']';
+ },
+ _sort: function(param, value) {
+ if (this._sorts.length == 0) return;
+ if (this._sortCache) delete this._sortCache;
+ var sort = this._sorts[this._sorts.length - 1];
+ if (typeof param == 'number') sort.direction = param;
+ else {
+ sort.type = sort[param];
+ if (value !== undefined) sort.direction = value;
+ }
+ return this;
+ },
+ _flush: function() {
+ if (this._expression) this._eval += this._expression;
+ this._expression = null;
+ },
+ toString: function() {
+ this._flush();
+ return this._eval;
+ },
+ and: function(field) {
+ return this._term('&&', field);
+ },
+ or: function(field) {
+ return this._term('||', field);
+ },
+ not: function(value) {
+ if (this._expression) {
+ this._expression.not = !this._expression.not;
+ if (value !== undefined) this._expression.value = value;
+ }
+ return this;
+ },
+ equals: function(value) {
+ return this._oper('===', value);
+ },
+ is: function(value) {
+ return this._oper('===', value);
+ },
+ isnt: function(value) {
+ this.not();
+ return this.is(value);
+ },
+ within: function(value) { // when an array of values is passed
+ var lookup = {};
+ for (var i in value) lookup[value[i]] = true;
+
+ if (this._expression) this._expression.template = '%not%operator[%term]';
+ return this._oper(this._store(lookup));
+ },
+ has: function(value) {
+ if (this._expression) this._expression.template = '%not(%term != null && %term.indexOf(%value) != -1)';
+ return this._oper(null, value);
+ },
+ startsWith: function(value) {
+ if (this._expression) this._expression.template = '%not(%term != null && %term.substr(0, %operator) == %value)';
+ return this._oper(value.length, value);
+ },
+ endsWith: function(value) {
+ if (this._expression) this._expression.template = '%not(%term != null && %term.substr(%term.length - %operator) == %value)';
+ return this._oper(value.length, value);
+ },
+ gt: function(value) {
+ return this._oper('>', value);
+ },
+ gte: function(value) {
+ return this._oper('>=', value);
+ },
+ lt: function(value) {
+ return this._oper('<', value);
+ },
+ lte: function(value) {
+ return this._oper('<=', value);
+ },
+ regex: function(value) {
+ if (this._expression) this._expression.template = '%not(%term != null && %operator.test(%term))';
+ return this._oper(this._store(value));
+ },
+ same: function(value) {
+ if (this._expression) this._expression.template = '%not(JSON.stringify(%term) %operator %value)';
+ value = JSON.stringify(value);
+ return this._oper('==', value);
+ },
+ filter: function(value) {
+ if (typeof value != 'function') throw new Error('query.filter() parameter must be a function');
+ if (this._expression) this._expression.template = '%not(%operator(%term))';
+ else {
+ this._expression = new Expression();
+ this._expression.template = '%not(%operator(obj))';
+ }
+ return this._oper(this._store(value));
+ },
+ search: function(words) {
+ words = RegExp.escape(words);
+ var exp = new RegExp('\\b' + words.split(/\s/).join('|\\b'));
+ return this.regex(exp);
+ },
+ type: function(value) {
+ if (typeof value == 'function') {
+ if (!this._expression) { // check the type of the main object
+ this._expression = new Expression();
+ this._expression.template = '%not(obj instanceof %operator)';
+ } else {
+ this._expression.template = '%not(%term instanceof %operator)';
+ }
+ return this._oper(this._store(value));
+ } else {
+ if (this._expression) this._expression.template = '%not(type(%term) %operator %value)';
+ return this._oper('==', value);
+ }
+ },
+ sort: function(field) {
+ if (this._sortCache) delete this._sortCache;
+ this._sorts.push(new Sort(field));
+ return this;
+ },
+ asc: function() {
+ return this._sort(1);
+ },
+ desc: function() {
+ return this._sort(-1);
+ },
+ regular: function() {
+ return this._sort('regular');
+ },
+ numeric: function() {
+ return this._sort('numeric');
+ },
+ date: function() {
+ return this._sort('date');
+ },
+ custom: function(value) {
+ return this._sort('custom', value);
+ },
+ limit: function(value) {
+ this._limit = value;
+ return this;
+ },
+ offset: function(value) {
+ this._offset = value;
+ return this;
+ },
+ set: function(attrs) {
+ this._actions.push(function(model) {
+ model.set(attrs);
+ });
+ return this;
+ }
+ };
+
+
+ select.prototype = Object.create(query.prototype);
+ select.prototype.where = function(field) {
+ if (field) this._expression = new Expression(field);
+ return this;
+ };
+ select.prototype.end = function() {
+ return this.on(this.array);
+ };
+
+
+
+
+ function Expression(term, operator, value, not) {
+ this.term = term;
+ this.operator = operator;
+ this.value = value;
+ this.not = not;
+ this.template = '%not(%term %operator %value)';
+ }
+
+ Expression.prototype = {
+ toString: function() {
+ var self = this;
+ return this.template.replace(/%\w+/g, function(match) {
+ switch(match) {
+ case '%not':
+ return self.not ? '!' : '';
+ case '%term':
+ return '(obj.' + self.term + ' || (typeof obj.get === "function" && obj.get("' + self.term + '")))' + (self.value instanceof Date ? '.getTime()' : '');
+ case '%operator':
+ return self.operator;
+ case '%value':
+ return JSON.stringify(self.value instanceof Date ? self.value.getTime() : self.value);
+ }
+ });
+ }
+ };
+
+
+ function Sort(term, type, direction) {
+ this.term = term;
+ this.type = type || this.regular;
+ this.direction = direction || 1;
+ }
+
+ Sort.prototype = {
+ toFunction: function() {
+ return this.type(this.term, this.direction);
+ },
+ regular: function(prop, order) {
+ return function(a, b) {
+ a = a[prop];
+ b = b[prop];
+ if (b == null) return -1;
+ if (a == null) return 1;
+ return order * (a > b ? 1 : (a < b ? -1 : 0));
+ };
+ },
+ numeric: function(prop, order) {
+ return function(a, b) {
+ a = parseFloat(a[prop]);
+ b = parseFloat(b[prop]);
+ if (b == null || isNaN(b)) return -1;
+ if (a == null || isNaN(a)) return 1;
+ return order * (a - b);
+ };
+ },
+ date: function(prop, order) {
+ return function(a, b) {
+ a = a[prop];
+ b = b[prop];
+ if (b == null) return -1;
+ if (a == null) return 1;
+ return order * (a.getTime() - b.getTime());
+ };
+ },
+ custom: function(prop, func) {
+ if (prop) {
+ return function(a, b) {
+ return func(a[prop], b[prop]);
+ };
+ } else {
+ return function(a, b) {
+ return func(a, b);
+ };
+ }
+ }
+ };
+
+})();
+
+if (typeof exports !== 'undefined' && typeof module !== 'undefined') {
+ module.exports = query;
+}
View
9 public/admin/js/login.js
@@ -1,13 +1,6 @@
(function() {
- require(['app/auth'], function(auth) {
- var path;
- if (location.protocol !== 'https:' || location.host !== 's3.amazonaws.com') {
- path = 'websights' + location.pathname.replace(/^\/websights/, '');
- if (location.host !== 's3.amazonaws.com') path += '#' + location.host;
- location.href = "https://s3.amazonaws.com/" + path;
- throw new Error('Cannot administer site from this location.');
- }
+ require(['app/auth', 'util/admin-redirect'], function(auth) {
return $(function() {
$('body').fadeIn();
$('div.alert-message').hide();
View
11 public/admin/js/main.js
@@ -1,15 +1,8 @@
(function() {
- require(['app', 'view'], function(app) {
- var path;
- if (location.protocol !== 'https:' || location.host !== 's3.amazonaws.com') {
- path = 'websights' + location.pathname.replace(/^\/websights/, '');
- if (location.host !== 's3.amazonaws.com') path += '#' + location.host;
- location.href = "https://s3.amazonaws.com/" + path;
- throw new Error('Cannot administer site from this location.');
- }
+ require(['app', 'view', 'util/admin-redirect'], function(app) {
if (!app.username) {
- location.pathname = '/websights/admin/login.html';
+ location.pathname += 'login.html';
return;
}
return app.load().finished(function(sites) {
View
15 public/admin/js/util/admin-redirect.js
@@ -0,0 +1,15 @@
+(function() {
+
+ (function() {
+ if (location.hostname === 's3.amazonaws.com' && location.protocol === 'https:') {
+ return;
+ }
+ if (location.hostname !== 's3.amazonaws.com') {
+ location.href = '/admin/';
+ } else if (location.protocol !== 'https:') {
+ location.protocol = 'https:';
+ }
+ throw new Error('Cannot administer site from this location. Redirecting...');
+ })();
+
+}).call(this);
View
100 public/admin/main.html
@@ -0,0 +1,100 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+ <meta charset="utf-8">
+ <title>Admin</title>
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
+ <meta name="description" content="">
+ <meta name="author" content="">
+ <link href="css/bootstrap.min.css" rel="stylesheet">
+ <link href="css/admin.css" rel="stylesheet">
+ <link href="css/icon-sprite.css" rel="stylesheet">
+ <!--[if lt IE 9]>
+ <script src="http://html5shim.googlecode.com/svn/trunk/html5.js"></script>
+ <![endif]-->
+ <link rel="shortcut icon" href="img/favicon.ico">
+</head>
+
+<body style="display: none">
+
+<div class="navbar navbar-fixed-top">
+ <div class="navbar-inner">
+ <div class="container-fluid">
+ <a class="btn btn-navbar" data-toggle="collapse" data-target=".nav-collapse">
+ <span class="icon-bar"></span>
+ <span class="icon-bar"></span>
+ <span class="icon-bar"></span>
+ </a>
+ <a class="brand" href="#">Websights</a>
+ <div class="nav-collapse">
+ <ul class="nav">
+ <li class="active"><a href="#">Site</a></li>
+ <li><a href="#templates">Templates</a></li>
+ <li><a href="#settings">Settings</a></li>
+ </ul>
+ </div>
+ </div>
+ </div>
+</div>
+
+<div id="container" class="container-fluid">
+ <div id="sidebar" class="pod">
+ <div class="btn-toolbar">
+ <div class="btn-group">
+ <button class="btn" style="overflow: hidden">
+ <span class="icon add"></span> Add
+ <input type="file" class="btn" name="files[]" multiple style="position: absolute; opacity: 0; left: 0; right: 0; top: 0; height: 20px;">
+ </button>
+ <button class="btn dropdown-toggle" data-toggle="dropdown">
+ <span class="caret"></span>
+ </button>
+ <ul class="dropdown-menu">
+ <li id="new-file"><a href="#"><span class="icon page-add"></span> Add page</a></li>
+ <li id="new-page"><a href="#"><span class="icon layout-add"></span> Add page from template</a></li>
+ <li id="new-folder"><a href="#"><span class="icon folder-add"></span> Add folder</a></li>
+ </ul>
+ </div>
+ <div class="btn-group">
+ <button id="delete-file" class="btn"><span class="icon delete"></span></button>
+ </div>
+ </div>
+ <div id="menu">
+ <ul>
+ </ul>
+ </div>
+ </div>
+ <div id="breadcrumbs" class="btn-toolbar">
+ <ul class="breadcrumb pod">
+ <li>
+ <div class="btn-group">
+ <a class="btn btn-mini dropdown-toggle" data-toggle="dropdown" href="#">
+ <span class="caret"></span>
+ </a>
+ <ul id="site-list" class="dropdown-menu">
+ <li id="new-site"><a href="#"><span class="icon sitemap-add"></span> New...</a></li>
+ </ul>
+ </div>
+ <a id="selected-site" href="/"></a>
+ </li>
+ <!--<li>-->
+ <!--<span class="divider">/</span> <a href="/about-us">about-us</a>-->
+ <!--</li>-->
+ <!--<li class="active">-->
+ <!--<span class="divider">/</span> jobs-->
+ <!--</li>-->
+ </ul>
+ </div>
+ <div id="main">
+ <div id="editors" class="pod">
+ <!--<div id="code-editor"></div>-->
+ <iframe id="frame" src="http://www2.rainbowspreschool.com/"></iframe>
+ </div>
+ </div>
+</div>
+
+<script src="js/jquery.min.js"></script>
+<script src="js/bootstrap.min.js"></script>
+<script src="js/lib/ace/ace-noconflict.js"></script>
+<script src="js/require.min.js" data-main="js/main"></script>
+</body>
+</html>
View
2 src/app/auth.coffee
@@ -3,7 +3,7 @@ define ['lib/crypto', 'lib/promises', 'lib/s3'], (crypto, promises, s3) ->
{sha1, aes} = crypto
- path = '/websights/auth/'
+ path = 'auth/'
login: (username, password, remember) ->
View
6 src/app/data.coffee
@@ -1,7 +1,7 @@
EventEmitter = require('events').EventEmitter
-promises = require('../libs/promises')
+promises = require('../lib/promises')
_ = require('underscore')
-s3 = require('../libs/s3').s3
+s3 = require('../lib/s3').s3
bucketName = location.pathname.replace(/^\/([^\/]+).*/, '$1')
@@ -17,7 +17,7 @@ data = module.exports = _.extend new EventEmitter,
put: (url, data) -> bucket.put('api/' + url, data)
- destory: (url) -> bucket.destory('api/' + url)
+ destory: (url) -> bucket.destroy('api/' + url)
refresh: (options) ->
deferred = new promises.Deferred()
View
2 src/app/page.coffee
@@ -1,4 +1,4 @@
-query = require('../libs/query')
+query = require('../lib/query')
Model = require('Backbone').Model
Collection = require('Backbone').Collection
View
14 src/login.coffee
@@ -1,17 +1,5 @@
-require ['app/auth'], (auth) ->
-
-
- # ensure we are at the correct domain
- if location.protocol isnt 'https:' or location.host isnt 's3.amazonaws.com'
- path = 'websights' + location.pathname.replace(/^\/websights/, '')
-
- if location.host isnt 's3.amazonaws.com'
- path += '#' + location.host
-
- location.href = "https://s3.amazonaws.com/#{path}"
- throw new Error('Cannot administer site from this location.')
-
+require ['app/auth', 'util/admin-redirect'], (auth) ->
# view code
$ ->
View
15 src/main.coffee
@@ -1,19 +1,8 @@
-require ['app', 'view'], (app) ->
-
- # ensure we are at the correct domain and under https
- if location.protocol isnt 'https:' or location.host isnt 's3.amazonaws.com'
- path = 'websights' + location.pathname.replace(/^\/websights/, '')
-
- if location.host isnt 's3.amazonaws.com'
- path += '#' + location.host
-
- location.href = "https://s3.amazonaws.com/#{path}"
- throw new Error('Cannot administer site from this location.')
-
+require ['app', 'view', 'util/admin-redirect'], (app) ->
unless app.username
- location.pathname = '/websights/admin/login.html'
+ location.pathname += 'login.html'
return
app.load().finished (sites) ->
View
12 src/util/admin-redirect.coffee
@@ -0,0 +1,12 @@
+(->
+ return if location.hostname is 's3.amazonaws.com' and location.protocol is 'https:'
+
+ # ensure we are at the correct domain
+ if location.hostname isnt 's3.amazonaws.com'
+ location.href = '/admin/' # send to redirect page which will take to admin-bucket
+ else if location.protocol isnt 'https:'
+ location.protocol = 'https:'
+
+ # stop other javascript from running
+ throw new Error('Cannot administer site from this location. Redirecting...')
+)()

No commit comments for this range

Something went wrong with that request. Please try again.