├── .bowerrc
├── .gitignore
├── .jshintrc
├── .openshift
├── README.md
├── action_hooks
│ └── README.md
├── cron
│ ├── README.cron
│ ├── daily
│ │ └── .gitignore
│ ├── hourly
│ │ └── .gitignore
│ ├── minutely
│ │ └── .gitignore
│ ├── monthly
│ │ └── .gitignore
│ └── weekly
│ │ ├── README
│ │ ├── chrono.dat
│ │ ├── chronograph
│ │ ├── jobs.allow
│ │ └── jobs.deny
└── markers
│ ├── README.md
│ └── hot_deploy
├── .travis.yml
├── Gruntfile.js
├── README.md
├── app
├── favicon.ico
├── images
│ └── 404.png
├── index.handlebars
├── magma
│ ├── app.js
│ └── directives
│ │ ├── mgBind_directive.js
│ │ ├── mgInclude_directive.js
│ │ ├── mgScope_directive.js
│ │ ├── mgSubmit_directive.js
│ │ └── mgView_directive.js
├── scripts
│ ├── app.js
│ ├── controllers
│ │ └── Header_controller.js
│ ├── directives
│ │ ├── book_directive.js
│ │ └── books_directive.js
│ └── services
│ │ ├── appInterceptor_service.js
│ │ ├── mgViewInterceptor_service.js
│ │ └── progressInterceptor_service.js
├── styles
│ └── main.scss
└── views
│ ├── 404.handlebars
│ ├── author.handlebars
│ ├── book.handlebars
│ ├── home.handlebars
│ ├── search.handlebars
│ └── templates
│ ├── book.handlebars
│ ├── books.handlebars
│ └── pagination.handlebars
├── bower.json
├── ci
├── before_deploy.sh
└── build.sh
├── docs
├── architecture.png
├── client.png
├── index.png
└── server.png
├── grunt
├── bump.js
├── clean.js
├── copy.js
├── express.js
├── filerev.js
├── imagemin.js
├── jshint.js
├── karma.js
├── ngAnnotate.js
├── open.js
├── sass.js
├── uglify.js
├── usemin.js
├── useminPrepare.js
└── watch.js
├── index.js
├── karma.conf.js
├── magma.min.js
├── models
├── 404.js
├── ROUTES.json
├── author.js
├── book.js
├── home.js
├── search.js
└── templates
│ └── books.js
├── package.json
├── routes
├── root.js
└── static.js
├── services
└── goodreads.js
└── test
└── spec
└── directives
├── mgBind_directive.spec.js
├── mgInclude_directive.spec.js
├── mgScope_directive.spec.js
├── mgSubmit_directive.spec.js
└── mgView_directive.spec.js
/.bowerrc:
--------------------------------------------------------------------------------
1 | {
2 | "directory": "app/components"
3 | }
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | dist
3 | .idea
4 | app/components
5 | .tmp
6 | .sass-cache
7 | coverage
--------------------------------------------------------------------------------
/.jshintrc:
--------------------------------------------------------------------------------
1 | {
2 | // JSHint Default Configuration File (as on JSHint website)
3 | // See http://jshint.com/docs/ for more details
4 |
5 | "maxerr" : 50, // {int} Maximum error before stopping
6 |
7 | // Enforcing
8 | "bitwise" : true, // true: Prohibit bitwise operators (&, |, ^, etc.)
9 | "camelcase" : false, // true: Identifiers must be in camelCase
10 | "curly" : true, // true: Require {} for every new block or scope
11 | "eqeqeq" : true, // true: Require triple equals (===) for comparison
12 | "forin" : true, // true: Require filtering for..in loops with obj.hasOwnProperty()
13 | "freeze" : true, // true: prohibits overwriting prototypes of native objects such as Array, Date etc.
14 | "immed" : false, // true: Require immediate invocations to be wrapped in parens e.g. `(function () { } ());`
15 | "indent" : 4, // {int} Number of spaces to use for indentation
16 | "latedef" : false, // true: Require variables/functions to be defined before being used
17 | "newcap" : false, // true: Require capitalization of all constructor functions e.g. `new F()`
18 | "noarg" : true, // true: Prohibit use of `arguments.caller` and `arguments.callee`
19 | "noempty" : true, // true: Prohibit use of empty blocks
20 | "nonbsp" : true, // true: Prohibit "non-breaking whitespace" characters.
21 | "nonew" : false, // true: Prohibit use of constructors for side-effects (without assignment)
22 | "plusplus" : false, // true: Prohibit use of `++` & `--`
23 | "quotmark" : false, // Quotation mark consistency:
24 | // false : do nothing (default)
25 | // true : ensure whatever is used is consistent
26 | // "single" : require single quotes
27 | // "double" : require double quotes
28 | "undef" : true, // true: Require all non-global variables to be declared (prevents global leaks)
29 | "unused" : true, // true: Require all defined variables be used
30 | "strict" : true, // true: Requires all functions run in ES5 Strict Mode
31 | "maxparams" : false, // {int} Max number of formal params allowed per function
32 | "maxdepth" : false, // {int} Max depth of nested blocks (within functions)
33 | "maxstatements" : false, // {int} Max number statements per function
34 | "maxcomplexity" : false, // {int} Max cyclomatic complexity per function
35 | "maxlen" : false, // {int} Max number of characters per line
36 |
37 | // Relaxing
38 | "asi" : false, // true: Tolerate Automatic Semicolon Insertion (no semicolons)
39 | "boss" : false, // true: Tolerate assignments where comparisons would be expected
40 | "debug" : false, // true: Allow debugger statements e.g. browser breakpoints.
41 | "eqnull" : false, // true: Tolerate use of `== null`
42 | "es5" : false, // true: Allow ES5 syntax (ex: getters and setters)
43 | "esnext" : false, // true: Allow ES.next (ES6) syntax (ex: `const`)
44 | "moz" : false, // true: Allow Mozilla specific syntax (extends and overrides esnext features)
45 | // (ex: `for each`, multiple try/catch, function expression…)
46 | "evil" : false, // true: Tolerate use of `eval` and `new Function()`
47 | "expr" : false, // true: Tolerate `ExpressionStatement` as Programs
48 | "funcscope" : false, // true: Tolerate defining variables inside control statements
49 | "globalstrict" : true, // true: Allow global "use strict" (also enables 'strict')
50 | "iterator" : false, // true: Tolerate using the `__iterator__` property
51 | "lastsemic" : false, // true: Tolerate omitting a semicolon for the last statement of a 1-line block
52 | "laxbreak" : false, // true: Tolerate possibly unsafe line breakings
53 | "laxcomma" : false, // true: Tolerate comma-first style coding
54 | "loopfunc" : false, // true: Tolerate functions being defined in loops
55 | "multistr" : false, // true: Tolerate multi-line strings
56 | "noyield" : false, // true: Tolerate generator functions with no yield statement in them.
57 | "notypeof" : false, // true: Tolerate invalid typeof operator values
58 | "proto" : false, // true: Tolerate using the `__proto__` property
59 | "scripturl" : false, // true: Tolerate script-targeted URLs
60 | "shadow" : false, // true: Allows re-define variables later in code e.g. `var x=1; x=2;`
61 | "sub" : false, // true: Tolerate using `[]` notation when it can still be expressed in dot notation
62 | "supernew" : false, // true: Tolerate `new function () { ... };` and `new Object;`
63 | "validthis" : false, // true: Tolerate using this in a non-constructor function
64 |
65 | // Environments
66 | "browser" : true, // Web Browser (window, document, etc)
67 | "browserify" : false, // Browserify (node.js code in the browser)
68 | "couch" : false, // CouchDB
69 | "devel" : true, // Development/debugging (alert, confirm, etc)
70 | "dojo" : false, // Dojo Toolkit
71 | "jasmine" : false, // Jasmine
72 | "jquery" : false, // jQuery
73 | "mocha" : true, // Mocha
74 | "mootools" : false, // MooTools
75 | "node" : false, // Node.js
76 | "nonstandard" : false, // Widely adopted globals (escape, unescape, etc)
77 | "prototypejs" : false, // Prototype and Scriptaculous
78 | "qunit" : false, // QUnit
79 | "rhino" : false, // Rhino
80 | "shelljs" : false, // ShellJS
81 | "worker" : false, // Web Workers
82 | "wsh" : false, // Windows Scripting Host
83 | "yui" : false, // Yahoo User Interface
84 |
85 | // Custom Globals
86 | "globals" : {
87 | "process": true,
88 | "__dirname": true,
89 | "console": true,
90 | "require": true,
91 | "module": true,
92 | "angular": true,
93 | "describe": true,
94 | "expect": true,
95 | "it": true,
96 | "inject": true,
97 | "beforeEach": true,
98 | "afterEach": true,
99 | "spyOn": true
100 | } // additional predefined global variables
101 | }
--------------------------------------------------------------------------------
/.openshift/README.md:
--------------------------------------------------------------------------------
1 | For information about .openshift directory, consult the documentation:
2 |
3 | http://openshift.github.io/documentation/oo_user_guide.html#the-openshift-directory
4 |
--------------------------------------------------------------------------------
/.openshift/action_hooks/README.md:
--------------------------------------------------------------------------------
1 | For information about action hooks, consult the documentation:
2 |
3 | http://openshift.github.io/documentation/oo_user_guide.html#action-hooks
4 |
--------------------------------------------------------------------------------
/.openshift/cron/README.cron:
--------------------------------------------------------------------------------
1 | Run scripts or jobs on a periodic basis
2 | =======================================
3 | Any scripts or jobs added to the minutely, hourly, daily, weekly or monthly
4 | directories will be run on a scheduled basis (frequency is as indicated by the
5 | name of the directory) using run-parts.
6 |
7 | run-parts ignores any files that are hidden or dotfiles (.*) or backup
8 | files (*~ or *,) or named *.{rpmsave,rpmorig,rpmnew,swp,cfsaved}
9 |
10 | The presence of two specially named files jobs.deny and jobs.allow controls
11 | how run-parts executes your scripts/jobs.
12 | jobs.deny ===> Prevents specific scripts or jobs from being executed.
13 | jobs.allow ===> Only execute the named scripts or jobs (all other/non-named
14 | scripts that exist in this directory are ignored).
15 |
16 | The principles of jobs.deny and jobs.allow are the same as those of cron.deny
17 | and cron.allow and are described in detail at:
18 | http://docs.redhat.com/docs/en-US/Red_Hat_Enterprise_Linux/6/html/Deployment_Guide/ch-Automating_System_Tasks.html#s2-autotasks-cron-access
19 |
20 | See: man crontab or above link for more details and see the the weekly/
21 | directory for an example.
22 |
23 | PLEASE NOTE: The Cron cartridge must be installed in order to run the configured jobs.
24 |
25 | For more information about cron, consult the documentation:
26 | http://openshift.github.io/documentation/oo_cartridge_guide.html#cron
27 | http://openshift.github.io/documentation/oo_user_guide.html#cron
28 |
--------------------------------------------------------------------------------
/.openshift/cron/daily/.gitignore:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vilmosioo/magma/eddd7cff5f4214975347d1941ba26c81be4d2427/.openshift/cron/daily/.gitignore
--------------------------------------------------------------------------------
/.openshift/cron/hourly/.gitignore:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vilmosioo/magma/eddd7cff5f4214975347d1941ba26c81be4d2427/.openshift/cron/hourly/.gitignore
--------------------------------------------------------------------------------
/.openshift/cron/minutely/.gitignore:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vilmosioo/magma/eddd7cff5f4214975347d1941ba26c81be4d2427/.openshift/cron/minutely/.gitignore
--------------------------------------------------------------------------------
/.openshift/cron/monthly/.gitignore:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vilmosioo/magma/eddd7cff5f4214975347d1941ba26c81be4d2427/.openshift/cron/monthly/.gitignore
--------------------------------------------------------------------------------
/.openshift/cron/weekly/README:
--------------------------------------------------------------------------------
1 | Run scripts or jobs on a weekly basis
2 | =====================================
3 | Any scripts or jobs added to this directory will be run on a scheduled basis
4 | (weekly) using run-parts.
5 |
6 | run-parts ignores any files that are hidden or dotfiles (.*) or backup
7 | files (*~ or *,) or named *.{rpmsave,rpmorig,rpmnew,swp,cfsaved} and handles
8 | the files named jobs.deny and jobs.allow specially.
9 |
10 | In this specific example, the chronograph script is the only script or job file
11 | executed on a weekly basis (due to white-listing it in jobs.allow). And the
12 | README and chrono.dat file are ignored either as a result of being black-listed
13 | in jobs.deny or because they are NOT white-listed in the jobs.allow file.
14 |
15 | For more details, please see ../README.cron file.
16 |
17 |
--------------------------------------------------------------------------------
/.openshift/cron/weekly/chrono.dat:
--------------------------------------------------------------------------------
1 | Time And Relative D...n In Execution (Open)Shift!
2 |
--------------------------------------------------------------------------------
/.openshift/cron/weekly/chronograph:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | echo "`date`: `cat $(dirname \"$0\")/chrono.dat`"
4 |
--------------------------------------------------------------------------------
/.openshift/cron/weekly/jobs.allow:
--------------------------------------------------------------------------------
1 | #
2 | # Script or job files listed in here (one entry per line) will be
3 | # executed on a weekly-basis.
4 | #
5 | # Example: The chronograph script will be executed weekly but the README
6 | # and chrono.dat files in this directory will be ignored.
7 | #
8 | # The README file is actually ignored due to the entry in the
9 | # jobs.deny which is checked before jobs.allow (this file).
10 | #
11 | chronograph
12 |
13 |
--------------------------------------------------------------------------------
/.openshift/cron/weekly/jobs.deny:
--------------------------------------------------------------------------------
1 | #
2 | # Any script or job files listed in here (one entry per line) will NOT be
3 | # executed (read as ignored by run-parts).
4 | #
5 |
6 | README
7 |
8 |
--------------------------------------------------------------------------------
/.openshift/markers/README.md:
--------------------------------------------------------------------------------
1 | For information about markers, consult the documentation:
2 |
3 | http://openshift.github.io/documentation/oo_user_guide.html#markers
4 |
--------------------------------------------------------------------------------
/.openshift/markers/hot_deploy:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vilmosioo/magma/eddd7cff5f4214975347d1941ba26c81be4d2427/.openshift/markers/hot_deploy
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: node_js
2 | node_js:
3 | - '0.10'
4 | before_script:
5 | - npm install -g grunt-cli bower
6 | - gem install sass
7 | - npm install && bower install
8 | script:
9 | - npm run build
10 | branches:
11 | only:
12 | - master
13 | before_deploy:
14 | - npm run before_deploy
15 | deploy:
16 | provider: openshift
17 | skip_cleanup: true
18 | user: cool.villi@gmail.com
19 | password:
20 | secure: R7xHX/PC/is4ihGdFFo/kXGEi7A9e5rAZN5byZjTVFIxgzqCtn2H9E/ocfANRkO3LKPyg4zCT9safK9JudTucHkwQwycmkEXR6em4BBWG3zpWDks8dUNk9es4RDCobEP3WyZ3OZH3eyOiG/+3H4lbOQ9ECHDUiTUaammtVOHAps=
21 | app: magma
22 | domain: vilmosioo
23 | on:
24 | repo: vilmosioo/magma
25 | branch: master
26 | env:
27 | global:
28 | - secure: eLszokkjZWQEGgK5Fm3dWriftasGvOjlLoQyBAcNGth2IG6az7sW22w/xCqCAbks1nUvcZFMxeRFofeusUoIvum8t5xEr3bpfNAjHvdT63qQf9zxlH2S32yTgujbwb6ZBeoowH0t6EGD7AZqh5U3WfTJe8FWn9A5+DpRfL0zPvI=
--------------------------------------------------------------------------------
/Gruntfile.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | module.exports = function (grunt) {
4 |
5 | // Load grunt tasks automatically
6 | require('matchdep').filterDev('grunt-*').forEach(grunt.loadNpmTasks);
7 |
8 | var pck = grunt.file.readJSON('./package.json');
9 |
10 | // Define the configuration for all the tasks
11 | grunt.initConfig({
12 | pck: pck,
13 | clean: require('./grunt/clean'),
14 | copy: require('./grunt/copy'),
15 | express: require('./grunt/express'),
16 | watch: require('./grunt/watch'),
17 | open: require('./grunt/open'),
18 | useminPrepare: require('./grunt/useminPrepare'),
19 | usemin: require('./grunt/usemin'),
20 | filerev: require('./grunt/filerev'),
21 | sass: require('./grunt/sass'),
22 | ngAnnotate: require('./grunt/ngAnnotate'),
23 | jshint: require('./grunt/jshint'),
24 | imagemin: require('./grunt/imagemin'),
25 | bump: require('./grunt/bump'),
26 | uglify: require('./grunt/uglify'),
27 | karma: require('./grunt/karma')
28 | });
29 |
30 | grunt.registerTask('test', [
31 | 'jshint',
32 | 'karma'
33 | ]);
34 |
35 | grunt.registerTask('server', [
36 | 'clean:server',
37 | 'sass:server',
38 | 'express:server',
39 | 'open',
40 | 'watch'
41 | ]);
42 |
43 | grunt.registerTask('build', [
44 | 'clean:dist',
45 | 'sass:dist',
46 | 'useminPrepare',
47 | 'concat',
48 | 'ngAnnotate',
49 | 'uglify',
50 | 'copy:magma',
51 | 'cssmin',
52 | 'filerev',
53 | 'copy:static',
54 | 'imagemin',
55 | 'usemin'
56 | ]);
57 |
58 | grunt.registerTask('dist', [
59 | 'test',
60 | 'build',
61 | 'express:dist'
62 | ]);
63 |
64 | grunt.registerTask('default', [
65 | 'test',
66 | 'build'
67 | ]);
68 | };
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Magma [](https://travis-ci.org/vilmosioo/magma)
2 |
3 | ### A new way of building web apps by taking advantage of both server and client side templating.
4 |
5 | ## Working Demo
6 |
7 | [http://magma-vilmosioo.rhcloud.com/](http://magma-vilmosioo.rhcloud.com/)
8 |
9 | A web-app that allows you to browse books and authors.
10 |
11 | ## Context
12 |
13 | Complex websites have multiple sources to generate the data. A modular architecture allows you to aggregate different components before sending the final document to the user. Let's assume our website's wireframe looks like this. A, B, C, D are separate components built to display various data.
14 |
15 | 
16 |
17 | Server-side rendering is the common approach to deliver a document. A user makes a request, the server identifies the resources requested, builds the document and sends it back.
18 |
19 | 
20 |
21 | Client-side architecture works in a similar way, except the templating engine is the browser itself. The components are built by JavaScript.
22 |
23 | 
24 |
25 | Client vs server templating is an on-going debate today. Magma suggests a hybrid approach, taking the advantages of both and disadvantages of neither.
26 |
27 | ## How it works
28 |
29 | Magma is not a framework. You don't need any code from this repository. it does not require you to use a particular tech stack.
30 |
31 | It is an architecture. It leverages the main content to the server for fast delivery, while everything else is rendered on the client.
32 |
33 | For example, referencing the wireframe above, your home page contains 4 components: A, B, C, D. On page load, the server will render A and B and send the document to the client. At this point the website is viewable and useful to the user. Once your JavaScript loads, components C and D are loaded using a client rendering engine. After this point the website behaves as a single page application. If you need to render A and B on the client later on, you may call their individual endpoints.
34 | // example code from demo
35 |
36 | 
37 |
38 | **TLDR** Magma is an architecture that requires the main content to be delivered by the server on page load, and initialising a single page app as soon as JS is loaded. Components should be exposed by individual endpoints.
39 |
40 | ## Magma AngularJS module
41 |
42 | ```
43 | npm install magma --save
44 | ```
45 |
46 | ```
47 | bower install magma --save
48 | ```
49 |
50 | ### mgView
51 |
52 | mgView directive allows you to delay route initialisation in your angular application. On `$routechangeSuccess` mgView will replace itself with the standard ngView and the application will behave as a regular SPA.
53 |
54 | ```
55 |
56 | Server side content that will only get updated after the first $onRouteChangeSuccess event
57 |
58 | ```
59 |
60 | ### mgSubmit
61 |
62 | To allow your forms to work before JS is loaded (or if a grievous error happened during bootstrap) you should include method and action attributes to it. This allows standard form functionality to work. As soon as angular is ready, mgSubmit will replace itself with the standard ngSubmit.
63 |
64 | ```
65 |
69 | ```
70 |
71 | ### mgInclude & mgBind
72 |
73 | The problem with ngInclude and ngBind is that they will replace your content immediately after bootstrap, even if data is already exist. mgInclude and mgBind allows you to display persistent server side content, until client side templateing is necessary.
74 |
75 | ```
76 |
77 | Server side content that will be replaced only when template is defined to a truthy value.
78 |
79 | ```
80 |
81 | ### mgScope
82 |
83 | mgScope is a very simple directive that allows you to extend an element's scope using a stringified object.
84 |
85 | ```
86 |
87 | ```
88 |
89 | In the example above, the element's scope will have a new property called numberOfResults that equals 10.
90 |
91 | ## Developers
92 |
93 | To run the demo, first install it on your computer.
94 |
95 | ```
96 | git clone https://github.com/vilmosioo/magma.git
97 | cd magma
98 | npm install && bower install
99 | ```
100 |
101 | The following grunt tasks are made available
102 |
103 | * `grunt server` - Fires an express instance on port 9000 on your local machine, in development mode (CSS/JS is not minified, view caching disabled, angular debug mode is true).
104 | * `grunt dist` - Fires an express instance on port 9000 on your local machine, in production mode (CSS/JS is minified, view caching enabled, angular debug mode is false)
105 | * `grunt build` - Generates the artefacts.
106 | * `grunt test` - Runs the tests
107 |
108 | ## Demo roadmap
109 |
110 | - [x] Search books
111 | - [x] Paginate search results
112 | - [x] View individual book
113 | - [x] View similar books
114 | - [x] View author details
115 | - [ ] Sign-in with Goodreads
116 | - [ ] View your collection
117 | - [ ] Enable grid and list view
118 |
119 | ## Contributing
120 |
121 | ## Attributions
122 |
123 | Kindly hosted by [Openshift](https://www.openshift.com/).
124 | Data provided by [Goodreads](https://www.goodreads.com/).
--------------------------------------------------------------------------------
/app/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vilmosioo/magma/eddd7cff5f4214975347d1941ba26c81be4d2427/app/favicon.ico
--------------------------------------------------------------------------------
/app/images/404.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vilmosioo/magma/eddd7cff5f4214975347d1941ba26c81be4d2427/app/images/404.png
--------------------------------------------------------------------------------
/app/index.handlebars:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | {{app.title}}
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |