spout - building a restful web app with angular.js and bear.sunday
DESCRIPTION
Spout is a RESTful CMS created with Angular.js and BEAR.Sunday, we are just getting started but here is your your chance to get involved in a new CMS project.TRANSCRIPT
![Page 1: Spout - Building a RESTful web app with Angular.js and BEAR.Sunday](https://reader033.vdocuments.us/reader033/viewer/2022052819/53fe04438d7f72a81c8b4c72/html5/thumbnails/1.jpg)
BUILDING A RESTFUL WEB APP WITHANGULAR.JS AND BEAR.SUNDAY
![Page 2: Spout - Building a RESTful web app with Angular.js and BEAR.Sunday](https://reader033.vdocuments.us/reader033/viewer/2022052819/53fe04438d7f72a81c8b4c72/html5/thumbnails/2.jpg)
RICHARD MCINTYRE@MACKSTAR
![Page 3: Spout - Building a RESTful web app with Angular.js and BEAR.Sunday](https://reader033.vdocuments.us/reader033/viewer/2022052819/53fe04438d7f72a81c8b4c72/html5/thumbnails/3.jpg)
![Page 4: Spout - Building a RESTful web app with Angular.js and BEAR.Sunday](https://reader033.vdocuments.us/reader033/viewer/2022052819/53fe04438d7f72a81c8b4c72/html5/thumbnails/4.jpg)
GOAL RESTFUL CMSFRONT-END ANGULAR.JSBACK-END BEAR.SUNDAY
![Page 5: Spout - Building a RESTful web app with Angular.js and BEAR.Sunday](https://reader033.vdocuments.us/reader033/viewer/2022052819/53fe04438d7f72a81c8b4c72/html5/thumbnails/5.jpg)
WHY ANOTHER CMS?
▸ Building RESOURCES▸ Power through simplicity▸ Easy overrides with AOP▸ Kill plugin culture
▸ Build re-usable libraries
![Page 6: Spout - Building a RESTful web app with Angular.js and BEAR.Sunday](https://reader033.vdocuments.us/reader033/viewer/2022052819/53fe04438d7f72a81c8b4c72/html5/thumbnails/6.jpg)
CONTINUED...
▸ Embed in any PHP project▸ Testable
▸ Relationships between resources / Hypermedia▸ Templating through TWIG
![Page 7: Spout - Building a RESTful web app with Angular.js and BEAR.Sunday](https://reader033.vdocuments.us/reader033/viewer/2022052819/53fe04438d7f72a81c8b4c72/html5/thumbnails/7.jpg)
BEAR.SUNDAY▸ REST▸ DI▸ AOP
![Page 8: Spout - Building a RESTful web app with Angular.js and BEAR.Sunday](https://reader033.vdocuments.us/reader033/viewer/2022052819/53fe04438d7f72a81c8b4c72/html5/thumbnails/8.jpg)
In most MVC application frameworks, CRUD and OOP paradigms are mapped
to HTTP methods and resources. But the opposite is not true. - Akihito Koriyama
![Page 9: Spout - Building a RESTful web app with Angular.js and BEAR.Sunday](https://reader033.vdocuments.us/reader033/viewer/2022052819/53fe04438d7f72a81c8b4c72/html5/thumbnails/9.jpg)
EVERYTHING IS A RESOURCERequest: /api/resources/index?_start=1
Request Method: GETStatus Code: 200 OK
![Page 10: Spout - Building a RESTful web app with Angular.js and BEAR.Sunday](https://reader033.vdocuments.us/reader033/viewer/2022052819/53fe04438d7f72a81c8b4c72/html5/thumbnails/10.jpg)
{ "resources": [ { "id": "16", "slug": "2332", "type": "blog", "title": "2332", "type_name": "Blog", "title_label": "Title" } ], "_model": "resources", "_pager": { "maxPerPage": 5, "current": "1", "total": 1, "hasNext": false, "hasPrevious": false }, "_links": { "self": { "href": "spout/app/resources/index/?_start=1" } }}
![Page 11: Spout - Building a RESTful web app with Angular.js and BEAR.Sunday](https://reader033.vdocuments.us/reader033/viewer/2022052819/53fe04438d7f72a81c8b4c72/html5/thumbnails/11.jpg)
Request: /api/resources/typesRequest Method: POSTStatus Code: 200 OK
![Page 12: Spout - Building a RESTful web app with Angular.js and BEAR.Sunday](https://reader033.vdocuments.us/reader033/viewer/2022052819/53fe04438d7f72a81c8b4c72/html5/thumbnails/12.jpg)
{ "title_label": "Title", "resource_fields": [ { "field_type": { "id": "1", "name": "String", "slug": "string" }, "multiple": 0, "weight": 1, "label": "Body", "slug": "body" } ], "name": "Page", "slug": "page"}
![Page 13: Spout - Building a RESTful web app with Angular.js and BEAR.Sunday](https://reader033.vdocuments.us/reader033/viewer/2022052819/53fe04438d7f72a81c8b4c72/html5/thumbnails/13.jpg)
Request: /api/menus/links?menu=primaryRequest Method: GETStatus Code: 200 OK
![Page 14: Spout - Building a RESTful web app with Angular.js and BEAR.Sunday](https://reader033.vdocuments.us/reader033/viewer/2022052819/53fe04438d7f72a81c8b4c72/html5/thumbnails/14.jpg)
{ "links": [ { "id": "6", "name": "Link 1", "url": "/url1", "type": "url", "resource": null, "resource_type": null, "weight": "999", "depth": null, "parent_id": "0", "menu": "primary" }, { "id": "7", "name": "Link 2", "url": "/url2", "type": "url", "resource": null, "resource_type": null, "weight": "999", "depth": null, "parent_id": "0", "menu": "primary" } ], "_model": "links"}
![Page 15: Spout - Building a RESTful web app with Angular.js and BEAR.Sunday](https://reader033.vdocuments.us/reader033/viewer/2022052819/53fe04438d7f72a81c8b4c72/html5/thumbnails/15.jpg)
namespace Mackstar\Spout\Admin\Resource\App\Resources;
/** * Resources Index * * @Db */class Index extends ResourceObject{
/** * @Link(rel="type", href="app://self/resources/detail?type={slug}&slug={slug}") * @DbPager(5) */ public function onGet() { $sql = "SELECT {$this->table}.*, type.name as type_name, type.title_label FROM {$this->table} "; $sql .= "INNER JOIN resource_types AS type "; $sql .= "ON type.slug = {$this->table}.type";
$stmt = $this->db->query($sql); $this['resources'] = $stmt->fetchAll(PDO::FETCH_ASSOC);
return $this; }
![Page 16: Spout - Building a RESTful web app with Angular.js and BEAR.Sunday](https://reader033.vdocuments.us/reader033/viewer/2022052819/53fe04438d7f72a81c8b4c72/html5/thumbnails/16.jpg)
CUSTOM RESOURCES CAN CALL OTHER RESOURCES
public function onGet($id = null) { $this['types'] = $this->resource->get->uri('app://self/resources/types') }
RESOURCES OF A TYPE HAVE RESOURCE AND RESOURCE INDEX RELATIONSHIPS
![Page 17: Spout - Building a RESTful web app with Angular.js and BEAR.Sunday](https://reader033.vdocuments.us/reader033/viewer/2022052819/53fe04438d7f72a81c8b4c72/html5/thumbnails/17.jpg)
OVERRIDES THROUGH AOP▸ Validation▸ Permissions
▸ Template Switching▸ Other custom events
![Page 18: Spout - Building a RESTful web app with Angular.js and BEAR.Sunday](https://reader033.vdocuments.us/reader033/viewer/2022052819/53fe04438d7f72a81c8b4c72/html5/thumbnails/18.jpg)
DEPENDENCIESINJECTED
![Page 19: Spout - Building a RESTful web app with Angular.js and BEAR.Sunday](https://reader033.vdocuments.us/reader033/viewer/2022052819/53fe04438d7f72a81c8b4c72/html5/thumbnails/19.jpg)
namespace Mackstar\Spout\Admin\Interceptor\Users;
use Ray\Aop\MethodInterceptor;use Ray\Aop\MethodInvocation;use Ray\Di\Di\Inject;use Symfony\Component\HttpFoundation\Session\Session as PhpSession;
class Session implements MethodInterceptor{
private $session;
/** * @Inject */ public function setSession(PhpSession $session) { $this->session = $session; }
public function invoke(MethodInvocation $invocation) { $response = $invocation->proceed(); $response->body['_user'] = $this->session->get('user'); return $response; }
![Page 20: Spout - Building a RESTful web app with Angular.js and BEAR.Sunday](https://reader033.vdocuments.us/reader033/viewer/2022052819/53fe04438d7f72a81c8b4c72/html5/thumbnails/20.jpg)
BIND USING MODULES
![Page 21: Spout - Building a RESTful web app with Angular.js and BEAR.Sunday](https://reader033.vdocuments.us/reader033/viewer/2022052819/53fe04438d7f72a81c8b4c72/html5/thumbnails/21.jpg)
private function installUserSessionAppender() { $session = $this->requestInjection('\Mackstar\Spout\Admin\Interceptor\Users\Session');
$this->bindInterceptor( $this->matcher->subclassesOf('BEAR\Resource\ResourceObject'), $this->matcher->startsWith('onGet'), [$session] ); }
![Page 22: Spout - Building a RESTful web app with Angular.js and BEAR.Sunday](https://reader033.vdocuments.us/reader033/viewer/2022052819/53fe04438d7f72a81c8b4c72/html5/thumbnails/22.jpg)
TESTS
![Page 23: Spout - Building a RESTful web app with Angular.js and BEAR.Sunday](https://reader033.vdocuments.us/reader033/viewer/2022052819/53fe04438d7f72a81c8b4c72/html5/thumbnails/23.jpg)
namespace Mackstar\Spout\Admin\Test\Interceptor\Validators;
use Mackstar\Spout\Admin\Interceptor\Validators\UserValidator;
class UserValidatorTest extends \PHPUnit_Framework_TestCase{
public function testErrorsWhenNoEmailIsPassedIn() { ... }}
![Page 24: Spout - Building a RESTful web app with Angular.js and BEAR.Sunday](https://reader033.vdocuments.us/reader033/viewer/2022052819/53fe04438d7f72a81c8b4c72/html5/thumbnails/24.jpg)
FRONT-END INTEGRATION{{ resource | app://spout/resources/detail?type=photo-gallery&slug=spout-is-live | detail-blog.twig }}
![Page 25: Spout - Building a RESTful web app with Angular.js and BEAR.Sunday](https://reader033.vdocuments.us/reader033/viewer/2022052819/53fe04438d7f72a81c8b4c72/html5/thumbnails/25.jpg)
PAGINATION{{ resource | app://spout/resources/index?type=blog | index-blog.twig | paged(1)}}
![Page 26: Spout - Building a RESTful web app with Angular.js and BEAR.Sunday](https://reader033.vdocuments.us/reader033/viewer/2022052819/53fe04438d7f72a81c8b4c72/html5/thumbnails/26.jpg)
MENU{{ resource | app://spout/menus?slug=primary | primary-menu.twig}}
![Page 27: Spout - Building a RESTful web app with Angular.js and BEAR.Sunday](https://reader033.vdocuments.us/reader033/viewer/2022052819/53fe04438d7f72a81c8b4c72/html5/thumbnails/27.jpg)
ARCHITECTURE
![Page 28: Spout - Building a RESTful web app with Angular.js and BEAR.Sunday](https://reader033.vdocuments.us/reader033/viewer/2022052819/53fe04438d7f72a81c8b4c72/html5/thumbnails/28.jpg)
![Page 29: Spout - Building a RESTful web app with Angular.js and BEAR.Sunday](https://reader033.vdocuments.us/reader033/viewer/2022052819/53fe04438d7f72a81c8b4c72/html5/thumbnails/29.jpg)
![Page 30: Spout - Building a RESTful web app with Angular.js and BEAR.Sunday](https://reader033.vdocuments.us/reader033/viewer/2022052819/53fe04438d7f72a81c8b4c72/html5/thumbnails/30.jpg)
![Page 31: Spout - Building a RESTful web app with Angular.js and BEAR.Sunday](https://reader033.vdocuments.us/reader033/viewer/2022052819/53fe04438d7f72a81c8b4c72/html5/thumbnails/31.jpg)
ANGULAR.JSADMIN
![Page 32: Spout - Building a RESTful web app with Angular.js and BEAR.Sunday](https://reader033.vdocuments.us/reader033/viewer/2022052819/53fe04438d7f72a81c8b4c72/html5/thumbnails/32.jpg)
BE YOUR OWNCONSUMER
![Page 33: Spout - Building a RESTful web app with Angular.js and BEAR.Sunday](https://reader033.vdocuments.us/reader033/viewer/2022052819/53fe04438d7f72a81c8b4c72/html5/thumbnails/33.jpg)
COMPONENTS▸ Routes▸ Directives▸ Controllers▸ Services
![Page 34: Spout - Building a RESTful web app with Angular.js and BEAR.Sunday](https://reader033.vdocuments.us/reader033/viewer/2022052819/53fe04438d7f72a81c8b4c72/html5/thumbnails/34.jpg)
2 WAY DATA BINDING
![Page 35: Spout - Building a RESTful web app with Angular.js and BEAR.Sunday](https://reader033.vdocuments.us/reader033/viewer/2022052819/53fe04438d7f72a81c8b4c72/html5/thumbnails/35.jpg)
TEMPLATE<input type="email" ng-model="login.email" required>
CONTROLLERscope.$watch('login.email', function () { console.log("Login Email Changed To:" + scope.login.email);});
![Page 36: Spout - Building a RESTful web app with Angular.js and BEAR.Sunday](https://reader033.vdocuments.us/reader033/viewer/2022052819/53fe04438d7f72a81c8b4c72/html5/thumbnails/36.jpg)
ROUTESANGULAR-UI ROUTER
![Page 37: Spout - Building a RESTful web app with Angular.js and BEAR.Sunday](https://reader033.vdocuments.us/reader033/viewer/2022052819/53fe04438d7f72a81c8b4c72/html5/thumbnails/37.jpg)
app.config(['$stateProvider', function($stateProvider) {
$stateProvider.state('login', { url: "/login", controller: 'LoginCtrl', templateUrl: '/js/templates/login/index.html', resolve: { authentication: ['Restangular', function (Restangular) { return Restangular.all('users/authenticate'); }] } }) .state('logout', { url: "/logout", controller: "LogoutCtrl", resolve: { authenticate: ['Restangular', function (Restangular) { return Restangular.all('users/authenticate'); }] } });
}]);
![Page 38: Spout - Building a RESTful web app with Angular.js and BEAR.Sunday](https://reader033.vdocuments.us/reader033/viewer/2022052819/53fe04438d7f72a81c8b4c72/html5/thumbnails/38.jpg)
DIRECTIVES<SP-THUMBNAIL />
![Page 39: Spout - Building a RESTful web app with Angular.js and BEAR.Sunday](https://reader033.vdocuments.us/reader033/viewer/2022052819/53fe04438d7f72a81c8b4c72/html5/thumbnails/39.jpg)
app.directive('spThumbnail', function (Restangular) { return { restrict: 'E', template: "<img src='/img/spinner.gif' ng-click='select()' />", scope: { media: "=media"}, replace: true, link: function(scope, element, attrs) {
var src = '/uploads/media/' + scope.media.directory + '/140x140_' + scope.media.file, img = new Image();
function loadImage() { element[0].src = src; }
img.src = src; img.onerror = function() { Restangular.all('media/resize').post( {media: scope.media, height: 140, width: 140} ).then(function() { loadImage(); }); };
...
![Page 40: Spout - Building a RESTful web app with Angular.js and BEAR.Sunday](https://reader033.vdocuments.us/reader033/viewer/2022052819/53fe04438d7f72a81c8b4c72/html5/thumbnails/40.jpg)
DEPENDENCY INJECTION
![Page 41: Spout - Building a RESTful web app with Angular.js and BEAR.Sunday](https://reader033.vdocuments.us/reader033/viewer/2022052819/53fe04438d7f72a81c8b4c72/html5/thumbnails/41.jpg)
Declarevar module = angular.module('restangular', []);module.provider('Restangular', function() {}
Implementvar app = angular.module('myApp', ['restangular']);
app.controller('MyController', ['Restangular', function (Restangular) { Restangular.all('users/authenticate').get().then(function(auth) { ... });}]);
![Page 42: Spout - Building a RESTful web app with Angular.js and BEAR.Sunday](https://reader033.vdocuments.us/reader033/viewer/2022052819/53fe04438d7f72a81c8b4c72/html5/thumbnails/42.jpg)
TESTS
![Page 43: Spout - Building a RESTful web app with Angular.js and BEAR.Sunday](https://reader033.vdocuments.us/reader033/viewer/2022052819/53fe04438d7f72a81c8b4c72/html5/thumbnails/43.jpg)
describe('Roles Directive', function () {
var scope, $element;
beforeEach(function () { module('Application'); angular.mock.inject( function ($rootScope, $compile) { var element = angular.element('<roles-selector></roles-selector>'); scope = $rootScope; scope.roles = [{"id": 1, "name": "Admin"},{"id": 2, "name": "Contributor"}]; $compile(element)(scope); scope.$digest(); $element = $(element); } ); });
it('should have a select menu', function () { expect($element.prop("tagName")).toEqual('SELECT'); expect($element.find("option").length).toBe(2); });
![Page 44: Spout - Building a RESTful web app with Angular.js and BEAR.Sunday](https://reader033.vdocuments.us/reader033/viewer/2022052819/53fe04438d7f72a81c8b4c72/html5/thumbnails/44.jpg)
DEMO
![Page 45: Spout - Building a RESTful web app with Angular.js and BEAR.Sunday](https://reader033.vdocuments.us/reader033/viewer/2022052819/53fe04438d7f72a81c8b4c72/html5/thumbnails/45.jpg)
STUFF TO DO▸ Security
▸ DB/API Schema lock-down▸ Create as composer component / Assetic▸ More field types (locations/times/md etc)
▸ Blocks▸ Get others input
![Page 46: Spout - Building a RESTful web app with Angular.js and BEAR.Sunday](https://reader033.vdocuments.us/reader033/viewer/2022052819/53fe04438d7f72a81c8b4c72/html5/thumbnails/46.jpg)
GET INVOLVEDGITHUB.COM/MACKSTAR/SPOUT