This page describes the guidelines that front-end engineers develop and test the components using the UI framework of Portal and quickly familiar with our basic ideas behind the scene.
Installing the following tools before you continue.
If you are working on Mac platform, recommending install them using brew.
brew install git node
gem install gerrit-cli
git clone https://github.com/starandtina/portal
npm install -g grunt-cli
npm install -g bower
npm install && bower install
If you have encountered ERR! like the one below, please run the commands with sudo.
Please try running this command again as root/Administrator
grunt serve // development
grunt serve:dist // production
If you install the environment first time you need run the grunt serve:dist
before run grunt serve
to download related libraries;
if you had encountered the error like follows, you need run the command launchctl limit maxfiles 4096 4096 && ulimit -n 4096
before you do the grunt serve, or you can append this cmd in your ~/.bashrc
or ~/.zshrc
at your choice.
Running “watch” task Waiting…Warning: EMFILE, too many open files ‘tmp’
The development mode is used for local dev environment, it won’t compile source files in order to let you debugging or testing your codes freely.
When it’s booted up in development environment:
The production mode is used for production environment before deploying on staging or production environments, so you could take a glance for that quickly locally.
When it’s booted up in production environment:
By the way, as for the JSON server task, you could find the JSON data file from test/mock/db.json. We wrote one Grunt task which is focus on read data from this file and set up RESTFul API for you automatically.
Example of db.json:
{
"addressBooks": [
{
"name": "3",
"address": "121",
"id": 3
}
],
"services": [
{
"id": "1",
"serviceName": "MSSQL Server",
"icon": "/img/service.png",
"displayName": "Test Service",
"description": "description for service"
}
]
}
And then, the JSON server will set up the API interface below for your CRUD operation, so the development of front-end could be separated from web backend and we don’t care about the changed of schema or whatever other things you could image.
http://localhost:3000/addressBooks
http://localhost:3000/services
Let’s say that you wanna create one About
page in order to give one brief introduction for our product.
We use the descriptor to define the layout.
define({
'type': 'components/layout/simple',
'children': {
'body': {
type: 'components/about'
}
}
});
As for how Descriptor works, please refer to here. The type is the path of your component relative to directory of src/app
.
Here we use the layout of components/layout/simple
, it only contains one body named components/about
that is what we need to create.
First off, we need to create the Angular controller named about.controller.js
which is located at directory of src/app/components/about
.
define([
'angular',
'components/about/about.html'
], function (angular) {
'use strict';
return ['$scope',
function ($scope) {
$scope.name = 'Hello, This is DBaaS!';
}
];
});
Then, we will create one template named about.html.jade
or about.html
(we support JADE and HTML)which is located at directory of src/app/components/about
.
.about-container
.page-header
h1 About US
small DBaaS
or
<div class='about-container'>
<div class='page-header'>
<h1>About US <small>DBaaS</small></h1>
</div>
</div>
Here we support pure HTML and Jade to write your template. However, we strongly recommend to use Jade, as it’s a clean, whitespace sensitive syntax for writing HTML.
grunt serve
After local dev environments starts, then navigate to About.
From simple component Step 1 to 3 got an basic static page by component, but as for the production environment, we always need to get the data from backend in order to generate the dynamic page.
In the agile development, the backend and front developer always need coding at same time, so if there is an mock server to emulate the data, it will be more efficiently.
Currently we use the /test/mock/db.json
as the mock data, the /tasks/data_server_task.js
used to define the web server.
the same as the Step1 of previous one.
Let’s modify src/app/components/about/about.controller.js
.
define([
'angular',
'components/about/about.html'
], function (angular) {
'use strict';
return ['$scope','AddressModel'
function ($scope,AddressModel) {
$scope.addressList = AddressModel.query();
}
];
});
src/app/components/about/about.html
<div class='about-container'>
<div class='page-header'>
<ul>
<li ng-repeat="address in addressList"><span ng-binding="address.name"></li>
</ul>
</div>
</div>
Define the Model with factory
located at app/factories/addressModle.js
:
define([
'angular'
], function (angular) {
'use strict';
angular
.module('vm.vchs.dbaas.factories')
.factory('AddressModel', function ($resource) {
return $resource('/api/addresses/:id');
});
});
Pre insert mock data into /test/mock/db.json
.
{
"addresses":[
{"id":1,"name":"PALO ALTO, CA ,USA "},
{"id":2,"name":"SHANG HAI, CHINA"},
{"id":3,"name":"TOKYO, JAPAN"}
]
}
grunt serve
Here is the unit test for AboutController
located in src/app/about/about.controller.js
using Jasmine
and Karma
.
define([
'base/src/app/components/about/about.controller.js',
'angular-mocks'
], function (Ctrl) {
'use strict';
var scope;
// Initialize a mock scope
beforeEach(inject(function ($rootScope, $injector) {
scope = $rootScope.$new();
$injector.invoke(Ctrl, scope, {
'$scope': scope
});
}));
describe('Test About Controller', function () {
it('check name', function () {
expect(scope.name).toEqual('Hello, This is DBaaS!');
});
});
});
After you finish your coding, next step is to build, release and deploy it on production environments. I’d like to build the whole project and optimize it through Build task, the build files will be put into dist directory by default. It include:
grunt build
If you want to release it, you could generate tar and zip file in the tmp directory through distribute
task.
grunt distribute:release
Finally, you could deploy it using the compressed package on your web server, such as nginx, apache or third-party CDN(such as CloudFront).
server {
### /usr/share/nginx/www/portal is your root directory
root /usr/share/nginx/www/portal
index index.html index.htm
server_name localhost;
location / {
try_files $uri $uri/ /index.html;
}
location /api {
rewrite /api/(.*) /$1 break;
proxy_pass "http://localhost:3000";
}
location /favicon.ico {
log_not_found off;
}
location /docs/docco/ {
root /home/ubuntu/portal ### /home/ubuntu/portal is the directory of documentation
}
location /docs/styleguide/ {
root /home/ubuntu/portal;
}
}