EUGENIO SOUZA CARVALHO 5 years ago
commit
fee1c33491

+ 7 - 0
.gitignore

@@ -0,0 +1,7 @@
+logs/*
+!.gitkeep
+node_modules/
+app/lib/
+tmp
+.DS_Store
+.idea

+ 24 - 0
.jshintrc

@@ -0,0 +1,24 @@
+{
+  "strict": "global",
+  "globals": {
+    // AngularJS
+    "angular": false,
+
+    // AngularJS mocks
+    "module": false,
+    "inject": false,
+
+    // Jasmine
+    "jasmine": false,
+    "describe": false,
+    "beforeEach": false,
+    "afterEach": false,
+    "it": false,
+    "expect": false,
+
+    // Protractor
+    "browser": false,
+    "element": false,
+    "by": false
+  }
+}

+ 19 - 0
.travis.yml

@@ -0,0 +1,19 @@
+dist: trusty
+
+language: node_js
+node_js:
+  - 10
+
+addons:
+  chrome: stable
+
+cache:
+  directories:
+    - "$HOME/.npm"
+
+install:
+  - npm install
+
+script:
+  - npm run test-single-run -- --browsers ChromeHeadless
+  - (npm start > /dev/null &) && npm run protractor -- --capabilities.chromeOptions.args headless

+ 22 - 0
LICENSE

@@ -0,0 +1,22 @@
+The MIT License
+
+Copyright (c) 2010-2016 Google, Inc. http://angularjs.org
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+

+ 297 - 0
README.md

@@ -0,0 +1,297 @@
+# `angular-seed` — the seed for AngularJS apps
+
+This project is an application skeleton for a typical [AngularJS][angularjs] web app. You can use it
+to quickly bootstrap your angular webapp projects and dev environment for these projects.
+
+The seed contains a sample AngularJS application and is preconfigured to install the AngularJS
+framework and a bunch of development and testing tools for instant web development gratification.
+
+The seed app doesn't do much, just shows how to wire two controllers and views together.
+
+
+## Getting Started
+
+To get you started you can simply clone the `angular-seed` repository and install the dependencies:
+
+### Prerequisites
+
+You need git to clone the `angular-seed` repository. You can get git from [here][git].
+
+We also use a number of Node.js tools to initialize and test `angular-seed`. You must have Node.js
+and its package manager (npm) installed. You can get them from [here][node].
+
+### Clone `angular-seed`
+
+Clone the `angular-seed` repository using git:
+
+```
+git clone https://github.com/angular/angular-seed.git
+cd angular-seed
+```
+
+If you just want to start a new project without the `angular-seed` commit history then you can do:
+
+```
+git clone --depth=1 https://github.com/angular/angular-seed.git <your-project-name>
+```
+
+The `depth=1` tells git to only pull down one commit worth of historical data.
+
+### Install Dependencies
+
+We have two kinds of dependencies in this project: tools and AngularJS framework code. The tools
+help us manage and test the application.
+
+* We get the tools we depend upon and the AngularJS code via `npm`, the [Node package manager][npm].
+* In order to run the end-to-end tests, you will also need to have the
+  [Java Development Kit (JDK)][jdk] installed on your machine. Check out the section on
+  [end-to-end testing](#e2e-testing) for more info.
+
+We have preconfigured `npm` to automatically copy the downloaded AngularJS files to `app/lib` so we
+can simply do:
+
+```
+npm install
+```
+
+Behind the scenes this will also call `npm run copy-libs`, which copies the AngularJS files and
+other front end dependencies. After that, you should find out that you have two new directories in
+your project.
+
+* `node_modules` - contains the npm packages for the tools we need
+* `app/lib` - contains the AngularJS framework files and other front end dependencies
+
+*Note copying the AngularJS files from `node_modules` to `app/lib` makes it easier to serve the
+files by a web server.*
+
+### Run the Application
+
+We have preconfigured the project with a simple development web server. The simplest way to start
+this server is:
+
+```
+npm start
+```
+
+Now browse to the app at [`localhost:8000/index.html`][local-app-url].
+
+
+## Directory Layout
+
+```
+app/                  --> all of the source files for the application
+  app.css               --> default stylesheet
+  core/                 --> all app specific modules
+    version/              --> version related components
+      version.js                 --> version module declaration and basic "version" value service
+      version_test.js            --> "version" value service tests
+      version-directive.js       --> custom directive that returns the current app version
+      version-directive_test.js  --> version directive tests
+      interpolate-filter.js      --> custom interpolation filter
+      interpolate-filter_test.js --> interpolate filter tests
+  view1/                --> the view1 view template and logic
+    view1.html            --> the partial template
+    view1.js              --> the controller logic
+    view1_test.js         --> tests of the controller
+  view2/                --> the view2 view template and logic
+    view2.html            --> the partial template
+    view2.js              --> the controller logic
+    view2_test.js         --> tests of the controller
+  app.js                --> main application module
+  index.html            --> app layout file (the main html template file of the app)
+  index-async.html      --> just like index.html, but loads js files asynchronously
+e2e-tests/            --> end-to-end tests
+  protractor-conf.js    --> Protractor config file
+  scenarios.js          --> end-to-end scenarios to be run by Protractor
+karma.conf.js         --> config file for running unit tests with Karma
+package.json          --> Node.js specific metadata, including development tools dependencies
+package-lock.json     --> Npm specific metadata, including versions of installed development tools dependencies
+```
+
+
+## Testing
+
+There are two kinds of tests in the `angular-seed` application: Unit tests and end-to-end tests.
+
+### Running Unit Tests
+
+The `angular-seed` app comes preconfigured with unit tests. These are written in [Jasmine][jasmine],
+which we run with the [Karma][karma] test runner. We provide a Karma configuration file to run them.
+
+* The configuration is found at `karma.conf.js`.
+* The unit tests are found next to the code they are testing and have a `.spec.js` suffix (e.g.
+  `view1.spec.js`).
+
+The easiest way to run the unit tests is to use the supplied npm script:
+
+```
+npm test
+```
+
+This script will start the Karma test runner to execute the unit tests. Moreover, Karma will start
+watching the source and test files for changes and then re-run the tests whenever any of them
+changes.
+This is the recommended strategy; if your unit tests are being run every time you save a file then
+you receive instant feedback on any changes that break the expected code functionality.
+
+You can also ask Karma to do a single run of the tests and then exit. This is useful if you want to
+check that a particular version of the code is operating as expected. The project contains a
+predefined script to do this:
+
+```
+npm run test-single-run
+```
+
+
+<a name="e2e-testing"></a>
+### Running End-to-End Tests
+
+The `angular-seed` app comes with end-to-end tests, again written in [Jasmine][jasmine]. These tests
+are run with the [Protractor][protractor] End-to-End test runner. It uses native events and has
+special features for AngularJS applications.
+
+* The configuration is found at `e2e-tests/protractor-conf.js`.
+* The end-to-end tests are found in `e2e-tests/scenarios.js`.
+
+Protractor simulates interaction with our web app and verifies that the application responds
+correctly. Therefore, our web server needs to be serving up the application, so that Protractor can
+interact with it.
+
+**Before starting Protractor, open a separate terminal window and run:**
+
+```
+npm start
+```
+
+In addition, since Protractor is built upon WebDriver, we need to ensure that it is installed and
+up-to-date. The `angular-seed` project is configured to do this automatically before running the
+end-to-end tests, so you don't need to worry about it. If you want to manually update the WebDriver,
+you can run:
+
+```
+npm run update-webdriver
+```
+
+Once you have ensured that the development web server hosting our application is up and running, you
+can run the end-to-end tests using the supplied npm script:
+
+```
+npm run protractor
+```
+
+This script will execute the end-to-end tests against the application being hosted on the
+development server.
+
+**Note:**
+Under the hood, Protractor uses the [Selenium Standalone Server][selenium], which in turn requires
+the [Java Development Kit (JDK)][jdk] to be installed on your local machine. Check this by running
+`java -version` from the command line.
+
+If JDK is not already installed, you can download it [here][jdk-download].
+
+
+## Updating AngularJS and other dependencies
+
+Since the AngularJS framework library code and tools are acquired through package managers (e.g.
+npm) you can use these tools to easily update the dependencies. Simply run the preconfigured script:
+
+```
+npm run update-deps
+```
+
+This will call `npm update` and `npm run copy-libs`, which in turn will find and install the latest
+versions that match the version ranges specified in the `package.json` file.
+
+If you want to update a dependency to a version newer than what the specificed range would permit,
+you can change the version range in `package.json` and then run `npm run update-deps` as usual.
+
+
+## Loading AngularJS Asynchronously
+
+The `angular-seed` project supports loading the framework and application scripts asynchronously.
+The special `index-async.html` is designed to support this style of loading. For it to work you must
+inject a piece of AngularJS JavaScript into the HTML page. The project has a predefined script to help
+do this:
+
+```
+npm run update-index-async
+```
+
+This will copy the contents of the `angular-loader.js` library file into the `index-async.html`
+page. You can run this every time you update the version of AngularJS that you are using.
+
+
+## Serving the Application Files
+
+While AngularJS is client-side-only technology and it is possible to create AngularJS web apps that
+do not require a backend server at all, we recommend serving the project files using a local
+web server during development to avoid issues with security restrictions (sandbox) in browsers. The
+sandbox implementation varies between browsers, but quite often prevents things like cookies, XHR,
+etc to function properly when an HTML page is opened via the `file://` scheme instead of `http://`.
+
+### Running the App during Development
+
+The `angular-seed` project comes preconfigured with a local development web server. It is a Node.js
+tool called [http-server][http-server]. You can start this web server with `npm start`, but you may
+choose to install the tool globally:
+
+```
+sudo npm install -g http-server
+```
+
+Then you can start your own development web server to serve static files from any folder by running:
+
+```
+http-server -a localhost -p 8000
+```
+
+Alternatively, you can choose to configure your own web server, such as Apache or Nginx. Just
+configure your server to serve the files under the `app/` directory.
+
+### Running the App in Production
+
+This really depends on how complex your app is and the overall infrastructure of your system, but
+the general rule is that all you need in production are the files under the `app/` directory.
+Everything else should be omitted.
+
+AngularJS apps are really just a bunch of static HTML, CSS and JavaScript files that need to be
+hosted somewhere they can be accessed by browsers.
+
+If your AngularJS app is talking to the backend server via XHR or other means, you need to figure
+out what is the best way to host the static files to comply with the same origin policy if
+applicable. Usually this is done by hosting the files by the backend server or through
+reverse-proxying the backend server(s) and web server(s).
+
+
+## Continuous Integration
+
+### Travis CI
+
+[Travis CI][travis] is a continuous integration service, which can monitor GitHub for new commits to
+your repository and execute scripts such as building the app or running tests. The `angular-seed`
+project contains a Travis configuration file, `.travis.yml`, which will cause Travis to run your
+tests when you push to GitHub.
+
+You will need to enable the integration between Travis and GitHub. See the
+[Travis website][travis-docs] for instructions on how to do this.
+
+
+## Contact
+
+For more information on AngularJS please check out [angularjs.org][angularjs].
+
+
+[angularjs]: https://angularjs.org/
+[git]: https://git-scm.com/
+[http-server]: https://github.com/indexzero/http-server
+[jasmine]: https://jasmine.github.io/
+[jdk]: https://wikipedia.org/wiki/Java_Development_Kit
+[jdk-download]: http://www.oracle.com/technetwork/java/javase/downloads
+[karma]: https://karma-runner.github.io/
+[local-app-url]: http://localhost:8000/index.html
+[node]: https://nodejs.org/
+[npm]: https://www.npmjs.org/
+[protractor]: http://www.protractortest.org/
+[selenium]: http://docs.seleniumhq.org/
+[travis]: https://travis-ci.org/
+[travis-docs]: https://docs.travis-ci.com/user/getting-started

+ 1 - 0
app/app.component.html

@@ -0,0 +1 @@
+<ng-outlet></ng-outlet>

+ 2 - 0
app/app.component.js

@@ -0,0 +1,2 @@
+'use strict';
+

+ 16 - 0
app/app.component.spec.js

@@ -0,0 +1,16 @@
+'use strict';
+
+describe('myApp.view1 module', function() {
+
+  beforeEach(module('myApp.view1'));
+
+  describe('view1 controller', function(){
+
+    it('should ....', inject(function($controller) {
+      //spec body
+      var view1Ctrl = $controller('View1Ctrl');
+      expect(view1Ctrl).toBeDefined();
+    }));
+
+  });
+});

File diff suppressed because it is too large
+ 359 - 0
app/app.css


+ 32 - 0
app/app.js

@@ -0,0 +1,32 @@
+'use strict';
+
+angular
+  .module('app', [
+    'ngComponentRouter',
+    'angularMoment',
+    'ngMaterial',
+    'ngSanitize',
+    'api.cms.ufmg'
+  ])
+  .value('$routerRootComponent', 'app')
+  .config(($locationProvider) => {
+    $locationProvider.html5Mode(true);
+  })
+  .run((amMoment) => {
+    amMoment.changeLocale('pt-br');
+
+
+  })
+  .component('app', {
+    templateUrl: 'app.component.html',
+    controller: ['$scope', '$location', 'cms', ($scope, $location, cms) => {
+      cms.Authenticated().then(
+        _ => { $location.path("/a/dashboard"); },
+        _ => { $location.path("/signin"); }
+      );
+    }],
+    $routeConfig: [
+      { path: '/a/...', name: 'Main', component: 'main' },
+      { path: '/signin', name: 'Signin', component: 'signin' },
+    ]
+  });

BIN
app/assets/backgroud-img.png


+ 94 - 0
app/common/api.js

@@ -0,0 +1,94 @@
+'use strict';
+
+const A = Object.assign;
+
+angular.module('api.cms.ufmg', ['ngResource'])
+    .constant('BASE_URL', 'http://150.164.180.61:9999')
+    .service('cms', ['$resource', '$q', 'BASE_URL', function ($resource, $q, BASE_URL) {
+        const cms = this;
+        A(cms, {
+            user: {},
+            session: {},
+            setSession: function (session) {
+                cms.session = session;
+                return cms.init();
+            },
+            Logout: () => {
+                return $q((res, rej) => {
+                    setTimeout(() => {
+                        window.localStorage.removeItem('access_roken')
+                        cms.session = {};
+                        res()
+                    })
+                })
+            },
+            Authenticated: function () {
+                return $q((res, rej) => {
+                    setTimeout(() => {
+                        const session = window.localStorage.getItem('access_roken')
+                        if (session) {
+                            cms.setSession(JSON.parse(session)).then(user => res(user))
+                        } else {
+                            rej()
+                        }
+                    })
+                })
+            },
+            Authenticate: function (input) {
+                return $q((res, rej) => {
+
+                    return cms.auth.save(input).$promise.then(data => {
+
+                        this.setSession({
+                            access_token: data.access_token,
+                            expires_in: data.expires_in,
+                            refresh_token: data.refresh_token,
+                            scope: data.scope,
+                            token_type: data.token_type
+                        })
+                        window.localStorage.setItem('access_roken', JSON.stringify(cms.session))
+                        res(cms.session)
+                    }, rej)
+                })
+            },
+
+            auth: $resource(`${BASE_URL}/authenticate`, {}, {}),
+
+            init: function () {
+                let base = { headers: { 'Authorization': 'Bearer ' + cms.session.access_token } }
+                A(this, {
+                    account: $resource(`${BASE_URL}/account`, {}, {
+                        get: A(base, {
+                            method: "GET",
+                            // params: {},
+                        })
+                    }),
+                    news: $resource(`${BASE_URL}/news/:id`, { id: '@id' }, {
+                        query: A(base, {
+                            method: "GET",
+                            params: {},
+                        }),
+                        get: A(base, {
+                            method: "GET",
+                            params: {},
+                        })
+                    })
+                });
+
+                return $q((res, rej) => {
+                    cms.account.get().$promise.then(user => { cms.user = user; res(user) }, rej);
+                })
+            }
+        })
+    }]).run((cms) => {
+
+    })
+                 // console.log('(this.auth)', this.auth)
+                    // console.log($resource(`${BASE_URL}/authenticate`, {}, {
+                    //     save: {
+                    //         method: "POST",
+                    //         params: {},
+                    //     }
+                    // }), this.auth)
+                    // console.dir(this.auth)
+                    // console.log('this.auth.save(input)'.this.auth.save(input))

+ 9 - 0
app/core/version/interpolate-filter.js

@@ -0,0 +1,9 @@
+'use strict';
+
+angular.module('myApp.version.interpolate-filter', [])
+
+.filter('interpolate', ['version', function(version) {
+  return function(text) {
+    return String(text).replace(/\%VERSION\%/mg, version);
+  };
+}]);

+ 15 - 0
app/core/version/interpolate-filter.spec.js

@@ -0,0 +1,15 @@
+'use strict';
+
+describe('myApp.version module', function() {
+  beforeEach(module('myApp.version'));
+
+  describe('interpolate filter', function() {
+    beforeEach(module(function($provide) {
+      $provide.value('version', 'TEST_VER');
+    }));
+
+    it('should replace VERSION', inject(function(interpolateFilter) {
+      expect(interpolateFilter('before %VERSION% after')).toEqual('before TEST_VER after');
+    }));
+  });
+});

+ 9 - 0
app/core/version/version-directive.js

@@ -0,0 +1,9 @@
+'use strict';
+
+angular.module('myApp.version.version-directive', [])
+
+.directive('appVersion', ['version', function(version) {
+  return function(scope, elm, attrs) {
+    elm.text(version);
+  };
+}]);

+ 17 - 0
app/core/version/version-directive.spec.js

@@ -0,0 +1,17 @@
+'use strict';
+
+describe('myApp.version module', function() {
+  beforeEach(module('myApp.version'));
+
+  describe('app-version directive', function() {
+    it('should print current version', function() {
+      module(function($provide) {
+        $provide.value('version', 'TEST_VER');
+      });
+      inject(function($compile, $rootScope) {
+        var element = $compile('<span app-version></span>')($rootScope);
+        expect(element.text()).toEqual('TEST_VER');
+      });
+    });
+  });
+});

+ 8 - 0
app/core/version/version.js

@@ -0,0 +1,8 @@
+'use strict';
+
+angular.module('myApp.version', [
+  'myApp.version.interpolate-filter',
+  'myApp.version.version-directive'
+])
+
+.value('version', '0.1');

+ 11 - 0
app/core/version/version.spec.js

@@ -0,0 +1,11 @@
+'use strict';
+
+describe('myApp.version module', function() {
+  beforeEach(module('myApp.version'));
+
+  describe('version service', function() {
+    it('should return current version', inject(function(version) {
+      expect(version).toEqual('0.1');
+    }));
+  });
+});

+ 53 - 0
app/index.html

@@ -0,0 +1,53 @@
+<!DOCTYPE html>
+<!--[if lt IE 7]>      <html lang="en" ng-app="myApp" class="no-js lt-ie9 lt-ie8 lt-ie7"> <![endif]-->
+<!--[if IE 7]>         <html lang="en" ng-app="myApp" class="no-js lt-ie9 lt-ie8"> <![endif]-->
+<!--[if IE 8]>         <html lang="en" ng-app="myApp" class="no-js lt-ie9"> <![endif]-->
+<!--[if gt IE 8]><!-->
+<html lang="en" class="no-js">
+<!--<![endif]-->
+
+<head>
+  <meta charset="utf-8">
+  <meta http-equiv="X-UA-Compatible" content="IE=edge">
+  <title>CMS Dashboard | Teste</title>
+  <meta name="description" content="">
+  <base href="/">
+  <meta name="viewport" content="width=device-width, initial-scale=1">
+  <link href="https://fonts.googleapis.com/css?family=Roboto" rel="stylesheet">
+  <link rel="stylesheet" href="lib/html5-boilerplate/dist/css/normalize.css">
+  <link rel="stylesheet" href="lib/html5-boilerplate/dist/css/main.css">
+  <link rel="stylesheet" href="app.css">
+  <script src="lib/html5-boilerplate/dist/js/vendor/modernizr-2.8.3.min.js"></script>
+  <link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
+  <!-- Angular Material style sheet -->
+  <link rel="stylesheet" href="https://ajax.googleapis.com/ajax/libs/angular_material/1.1.12/angular-material.min.css">
+</head>
+
+<body ng-app="app">
+  <app></app>
+  <!-- Angular Material requires Angular.js Libraries -->
+  <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.7.6/angular.min.js"></script>
+  <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.7.6/angular-animate.min.js"></script>
+  <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.7.6/angular-resource.js"></script>
+  <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.7.6/angular-aria.min.js"></script>
+  <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.7.6/angular-messages.min.js"></script>
+  <!-- <script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.7.6/angular-route.min.js"></script> -->
+  <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.7.6/angular-sanitize.min.js"></script>
+  <!-- Angular Material Library -->
+  <script src="https://ajax.googleapis.com/ajax/libs/angular_material/1.1.12/angular-material.min.js"></script>
+  <script src="https://unpkg.com/@angular/router@0.2.0/angular1/angular_1_router.js"></script>
+  <script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.24.0/moment-with-locales.min.js"></script>
+  <script src="https://cdnjs.cloudflare.com/ajax/libs/angular-moment/1.3.0/angular-moment.min.js"></script>
+
+  <script src="common/api.js"></script>
+
+  <script src="app.js"></script>
+  <script src="resources/main/main.component.js"></script>
+  <script src="resources/news/news.component.js"></script>
+  <script src="resources/signin/signin.component.js"></script>
+  <script src="resources/dashboard/dashboard.component.js"></script>
+  <script src="resources/post/news.component.js"></script>
+
+</body>
+
+</html>

+ 2 - 0
app/resources/dashboard/dashboard.component.html

@@ -0,0 +1,2 @@
+
+<h1>dashboard!!</h1>

+ 13 - 0
app/resources/dashboard/dashboard.component.js

@@ -0,0 +1,13 @@
+'use strict';
+
+angular
+  .module('app')
+  .component('dashboard', {
+    templateUrl: '/resources/dashboard/dashboard.component.html',
+    controller: ['$scope', 'cms', function ($scope, cms) {
+      // cms.Authenticated().then(
+      //   _ => { $location.path("/"); },
+      //   _ => { $location.path("/signin"); }
+      // );
+    }]
+  });

+ 22 - 0
app/resources/main/main.component.html

@@ -0,0 +1,22 @@
+<md-toolbar class="md-hue-2 _md _md-toolbar-transitions">
+    <div class="md-toolbar-tools">
+        <h2 flex="" md-truncate="" class="md-truncate flex">
+            <i class="material-icons">edit</i>
+            CMS
+        </h2>
+        <a ng-href="/a/news" class="md-primary md-raised md-button md-ink-ripple"> Notícias </a>
+        <div class="header-user">
+            <i class="material-icons">account_circle</i>
+            <ul>
+                <li>{{user.name}}</li>
+                <li>{{user.email}}</li>
+            </ul>
+            <a href="#" ng-click="logout()">
+                <i class="material-icons">exit_to_app</i>
+            </a>
+        </div>
+    </div>
+</md-toolbar>
+<div class="content">
+    <ng-outlet></ng-outlet>
+</div>

+ 32 - 0
app/resources/main/main.component.js

@@ -0,0 +1,32 @@
+'use strict';
+
+angular
+  .module('app')
+  .component('main', {
+    templateUrl: '/resources/main/main.component.html',
+    controller: ['$rootScope', '$scope', '$location', 'cms', function ($rootScope, $scope, $location, cms) {
+      Object.assign($scope, {
+        user: cms.user,
+        logout: _ => {
+          cms.Logout().then(_ => { $location.path('/signin') })
+        }
+      })
+
+      let locker = false;
+      const app = document.querySelector('app');
+
+      app.addEventListener('scroll', e => {
+        const position = (app.offsetHeight + app.scrollTop) >= (app.scrollHeight - 200);
+        if (position && !locker) {
+          locker = true;
+          setTimeout(() => { locker = false }, 1000);
+          $rootScope.$emit('scroll-end', {})
+        }
+      })
+    }],
+    $routeConfig: [
+      { path: '/dashboard', name: 'Dashboard', component: 'dashboard' },
+      { path: '/news', name: 'News', component: 'news' },
+      { path: '/news/:id', name: 'Post', component: 'post' }
+    ]
+  });

+ 34 - 0
app/resources/news/news.component.html

@@ -0,0 +1,34 @@
+<div class="noticias-container">
+    <h2 class="h2-center"></h2>
+    <ul class="noticias-painel">
+        <li class="animate" ng-repeat="item in news">
+            <div class="noticia" ng-click="open(item)">
+                <div class="noticia-img">
+                    <img alt="" src="https://images.vexels.com/media/users/3/148174/isolated/preview/36028f4f9f896e3f7f1a221c565dc8a3-abstract-rounded-rectangle-background-by-vexels.png">
+                </div>
+                <div class="noticia-header-box">
+                    <div ng-if="item.post_date" class="publicado-em">Publicado
+                        <span am-time-ago="item.post_date | amParse:'YYYY-MM-DDTHH:mm:ss'"></span>
+                    </div>
+                    <div class="noticia-h3 block-with-text">
+                        {{item.title}}
+                    </div>
+                </div>
+                <ul class="tags">
+                    <li ng-repeat="tag in item.tags">{{tag.name}}</li>
+                </ul>
+                <ul class="noticia-actions">
+                    <li> <i class="material-icons">account_circle</i></li>
+                    <li>
+                        <!-- <div>{{item.author.name}}</div> -->
+                        <!-- <div class="">{{item.author.email}}</div> -->
+                    </li>
+                    <li>
+                        <object ng-if="item.status=='published'"><a href=""><i class="material-icons">public</i></a></object>
+                        <object><a href="#"><i class="material-icons">edit</i></a></object>
+                    </li>
+                </ul>
+            </div>
+        </li>
+    </ul>
+</div>

+ 39 - 0
app/resources/news/news.component.js

@@ -0,0 +1,39 @@
+'use strict';
+
+angular
+  .module('app')
+  .component('news', {
+    templateUrl: '/resources/news/news.component.html',
+    controller: ['$rootScope', '$scope', '$location', 'cms', function ($rootScope, $scope, $location, cms) {
+      let page = 0;
+      const loadNews = () => {
+        cms.news.query({
+          page: page++,
+          page_size: 30
+        }).$promise.then(
+          account => {
+            console.log('news', account)
+            $scope.news = $scope.news.concat(account.items.map(i => {
+              i.news_url = i.news_url.replace("http://150.164.180.61:9999", "http://150.164.180.61:9999/")
+              return i;
+            }));
+          },
+          error => {
+            console.log('news', error)
+          }
+        )
+      }
+
+      Object.assign($scope, {
+        news: [],
+        open: post => {
+          $location.path(`/a/news/${post.id}`)
+        }
+      })
+
+      $rootScope.$on('scroll-end', _ => loadNews())
+
+      loadNews();
+
+    }]
+  });

+ 24 - 0
app/resources/post/news.component.js

@@ -0,0 +1,24 @@
+'use strict';
+
+angular
+  .module('app')
+  .component('post', {
+    templateUrl: '/resources/post/post.component.html',
+    controller: ['$scope', '$location', 'cms', function ($scope, $location, cms) {
+
+      Object.assign($scope, { post: {}, })
+
+      this.$routerOnActivate = function (next, previous) {
+        cms.news.get({ id: next.params.id }).$promise.then(
+          post => {
+            console.log('post', post)
+            $scope.post = post;
+          },
+          error => {
+            console.log('news', error)
+          }
+        )
+      };
+
+    }]
+  });

+ 32 - 0
app/resources/post/post.component.html

@@ -0,0 +1,32 @@
+<div class="post-container">
+    <div class="post-actions">
+        <ul>
+            <li><a ng-href="/a/news"><i class="material-icons">arrow_back</i></a></li>
+        </ul>
+        <ul>
+            <li><a><i class="material-icons">edit</i></a></li>
+        </ul>
+    </div>
+
+    <h1>{{post.title}}</h1>
+    <h5>{{post.subtitle}}</h5>
+
+    <div ng-bind-html=post.text></div>
+</div>
+
+<style>
+    figure {
+        margin: 1em 0px;
+    }
+
+    .post-actions {
+        width: 100%;
+        display: flex;
+        justify-content: space-between;
+    }
+
+    .post-container {
+        width: 740px;
+        margin: 60px auto;
+    }
+</style>

+ 34 - 0
app/resources/signin/signin.component.html

@@ -0,0 +1,34 @@
+<div class="login">
+    <div class="login-container">
+        <div class="logo-container">
+            <div>
+            </div>
+            <div class="project-name">
+                CMS
+            </div>
+        </div>
+        <form class="login-step-container">
+            <div class="login-input-container">
+                <md-input-container class="md-icon-float md-block md-input-has-value md-icon-left">
+                    <label for="input_219">Usuário</label>
+                    <i class="material-icons">person</i>
+                    <input ng-model="user.username" type="text" class="md-input">
+                    <div class="md-errors-spacer"></div>
+                </md-input-container>
+
+                <md-input-container class="md-icon-float md-block md-input-has-value md-icon-left">
+                    <label for="input_219">Senha</label>
+                    <i class="material-icons">lock</i>
+                    <input ng-model="user.password" type="password" class="md-input">
+                    <div class="md-errors-spacer"></div>
+                </md-input-container>
+                <div class="signin-actions">
+                    <a href="http://">Esqueceu sua senha?</a>
+                    <button class="md-raised md-primary md-button md-ink-ripple" type="button" ng-click="login(user)">
+                        Acessar
+                    </button>
+                </div>
+            </div>
+        </form>
+    </div>
+</div>

+ 30 - 0
app/resources/signin/signin.component.js

@@ -0,0 +1,30 @@
+'use strict';
+
+angular
+  .module('app')
+  .component('signin', {
+    templateUrl: '/resources/signin/signin.component.html',
+    controller: ['$scope', '$location', 'cms', function ($scope, $location, cms) {
+
+      Object.assign($scope, {
+        login: user => {
+          cms.Authenticate({
+            grant_type: 'password',
+            client_id: 'cms',
+            username: user.username,
+            password: user.password,
+          }).then(
+            auth => {
+              $location.path('/a/dashboard')
+            },
+            error => {
+              console.log('auth-error', error)
+            })
+        },
+        user: {
+          password: 123456789,
+          username: 'portal@portal',
+        }
+      })
+    }]
+  });

+ 22 - 0
e2e-tests/protractor.conf.js

@@ -0,0 +1,22 @@
+//jshint strict: false
+exports.config = {
+
+  allScriptsTimeout: 11000,
+
+  specs: [
+    '*.js'
+  ],
+
+  capabilities: {
+    browserName: 'chrome'
+  },
+
+  baseUrl: 'http://localhost:8000/',
+
+  framework: 'jasmine',
+
+  jasmineNodeOpts: {
+    defaultTimeoutInterval: 30000
+  }
+
+};

+ 42 - 0
e2e-tests/scenarios.js

@@ -0,0 +1,42 @@
+'use strict';
+
+/* https://github.com/angular/protractor/blob/master/docs/toc.md */
+
+describe('my app', function() {
+
+
+  it('should automatically redirect to /view1 when location hash/fragment is empty', function() {
+    browser.get('index.html');
+    expect(browser.getLocationAbsUrl()).toMatch("/view1");
+  });
+
+
+  describe('view1', function() {
+
+    beforeEach(function() {
+      browser.get('index.html#!/view1');
+    });
+
+
+    it('should render view1 when user navigates to /view1', function() {
+      expect(element.all(by.css('[ng-view] p')).first().getText()).
+        toMatch(/partial for view 1/);
+    });
+
+  });
+
+
+  describe('view2', function() {
+
+    beforeEach(function() {
+      browser.get('index.html#!/view2');
+    });
+
+
+    it('should render view2 when user navigates to /view2', function() {
+      expect(element.all(by.css('[ng-view] p')).first().getText()).
+        toMatch(/partial for view 2/);
+    });
+
+  });
+});

+ 28 - 0
karma.conf.js

@@ -0,0 +1,28 @@
+//jshint strict: false
+module.exports = function(config) {
+  config.set({
+
+    basePath: './app',
+
+    files: [
+      'lib/angular/angular.js',
+      'lib/angular-route/angular-route.js',
+      '../node_modules/angular-mocks/angular-mocks.js',
+      'core/**/*.js',
+      'view*/**/*.js'
+    ],
+
+    autoWatch: true,
+
+    frameworks: ['jasmine'],
+
+    browsers: ['Chrome'],
+
+    plugins: [
+      'karma-chrome-launcher',
+      'karma-firefox-launcher',
+      'karma-jasmine'
+    ]
+
+  });
+};

File diff suppressed because it is too large
+ 4736 - 0
package-lock.json


File diff suppressed because it is too large
+ 42 - 0
package.json