Serenity FrontStack
Technical revolution in the Frontend More Quality, More Productivity, More Scope
1. What is it?
2. Components
3. Installation
4. Application Scaffolding
5. What offers Angular Basic?
6. Let's make something awesome
7. Production phase
Angular Basic begins from the need to create projects with the sole aim of being more productive, to solve all tasks that are not really development and guide the developer in using best practices.
While we're saving the world, Angular Basic takes care of us
The web components are fully functional and independent parts that works individually or interacts with other components.
<ab-navbar>
<ab-cover-image>
<ab-layout>
<ab-guide-item>
Download
Install
Run!
git clone https://github.com/serenity-frontstack/angular-basic.git
npm install & bower install
gulp serve
src
app
assets
index.html
is our application startup file. This file is generated dynamically. Our dependencies, styles, javascript and templateCache are injected on it.
Dynamic Index.html
src
app
assets
index.html
The assets folder will contain all of our global resources used in our application. Keep it organized ;)
css
fonts
images
src
app
assets
index.html
Application folder
components
features
filters
services
app.config.js
app.constants.js
app.environment.js
app.module.js
app.run.js
app.route.js
src
app
assets
index.html
Application folder
components
features
filters
services
app.config.js
app.constants.js
app.environment.js
app.module.js
app.run.js
app.route.js
app.environment.js is a dynamic file of constants, it is generated everytime we serve or build the project depending of each arguments we give to gulp task.
src
app
assets
index.html
Application folder
components
features
filters
services
app.config.js
app.constants.js
app.environment.js
app.module.js
app.run.js
app.route.js
Everything is a component. We divide the components in two types, Components and Features. Features are the father of all his children, they normally have routing modules. On the other hand, Components folder contains all individuals components re-used on every place of your application.
src
app
assets
index.html
Application folder
components
features
filters
services
assets
name.component.js
name.componet.spec.js
name.html
name.service.js
name.service.spec.js
name.css
name.route.js
prefix-componentname
What offers Angular Basic?
Preview
Build
Tests
Docs
Env Config
1. Preview
2. Build
COMPACTED
MINIFIED
COMPACTED
Used to debug code easier
Prepare for production
TEMPLATES JS
TEMPLATES JS
3. Test
ESLINT
+
3. Test
Angular Basic provides configuration for build our applications with minimun coverage thresholds and requirements.
If those parameters doesn't pass our test and thresholds, the application won't be built.
4. Documentation
5. Environment Config
config/app.config.json
src/app/app.enviroment.js
Show me the code!
gulp serve --dev
*Looks how index.html and app.environment.js has been generated dynamically
Let's make
something awesome!
InstaPics component
Feature component
First of all we are going to create a feature component inside the features folder.
Step 1
features / ab-insta-pics / ab-insta-pics.component.js
(function() {
'use strict';
angular
.module('app')
.component('abInstaPics', {
templateUrl: 'app/features/ab-insta-pics/ab-insta-pics.html',
controller: InstaPicsController,
controllerAs: 'vm'
});
/** @ngInject */
function InstaPicsController(abInstaPictures, navbarPaths, toastr, creation) {
var vm = this;
vm.pageData = {
section: 'Insta Pictures',
pictures: abInstaPictures.getPics(),
creationDate: creation.getDate(),
brand: 'Angular Basic',
paths: navbarPaths.getPaths()
};
}
})();
Step 1
features / ab-insta-pics / ab-insta-pics.html
<div layout="vertical">
<md-content layout-fill>
<header>
<ab-navbar
creation-date="vm.pageData.creationDate"
brand="vm.pageData.brand"
paths="vm.pageData.paths">
</ab-navbar>
</header>
<div class="mdl-layout mdl-js-layout background-grey">
<main class="mdl-layout__content">
<div class="mdl-grid">
<md-card class="mdl-cell mdl-cell--4-col-desktop mdl-cell--8-col-tablet mdl-cell--4-col-phone"
ng-repeat="picture in vm.pageData.pictures">
<ab-picture picture="picture"></ab-picture>
</md-card>
</div>
</main>
</div>
</md-content>
</div>
Step 1
navbar component
picture component
features / ab-insta-pics / ab-insta-pics.service.js
(function() {
'use strict';
angular
.module('app')
.service('abInstaPictures', pictures);
/** @ngInject */
function pictures() {
var data = [
{
'url': 'https://cdn.pastemagazine.com/www/system/images/photo_albums/instagram-photographers/large/8-ig-photog-fagfrag.jpg?1384968217',
'title': 'My beautiful semaphore',
'like': false
},
{
'url': 'http://i.amz.mshcdn.com/kl6WpszKWhL3lMM26iJBXKZNBpk=/fit-in/850x850/http%3A%2F%2Fmashable.com%2Fwp-content%2Fgallery%2Fbest-instagram-images%2F1mattrubin.jpg',
'title': 'My beautiful car',
'like': false
},
{
'url': 'http://www.cestchristine.com/wp-content/uploads/2012/06/c8f1fe32667511e180c9123138016265_7.jpg',
'title': 'My beautiful palm tree',
'like': false
},
{
'url': 'https://i.kinja-img.com/gawker-media/image/upload/s--aqzWMB91--/17jvp3a19o6gpjpg.jpg',
'title': 'My beautiful rain',
'like': false
},
{
'url': 'http://media.vogue.com/r/h_480,w_480//wp-content/uploads/2015/02/13/02-karlie-kloss-taylor-swift-best-friends-bff.jpg',
'title': 'My beautiful jump',
'like': false
},
{
'url': 'https://cdn.pastemagazine.com/www/system/images/photo_albums/instagram-photographers/large/8-ig-photog-fagfrag.jpg?1384968217',
'title': 'My beautiful laugh',
'like': false
},
{
'url': 'http://www.wix.com/blog/wp-content/uploads/2013/05/Instagram_10_514.jpg',
'title': 'My beautiful painting',
'like': false
},
{
'url': 'http://cdn.shutterbug.com/images/styles/600_wide/public/Shark-Week-Instagram.jpg?itok=w0rYc4f-',
'title': 'My beautiful shark',
'like': false
},
{
'url': 'https://tid.al/blog/wp-content/uploads/2015/09/best-instagram-marketing-brands.jpg',
'title': 'My beautiful glasses',
'like': false
}
];
this.getPics = getPics;
function getPics() {
return data;
}
}
})();
Step 1
features / ab-insta-pics / ab-insta-pics.route.js
(function() {
'use strict';
angular
.module('app')
.config(routeConfig);
function routeConfig($stateProvider) {
$stateProvider
.state('instaPics', {
url: '/instaPics',
template: '<ab-insta-pics></ab-insta-pics>'
});
}
})();
Step 1
features / ab-insta-pics / ab-insta-pics.css
.background-grey{
background-color: #867892;
background-size: cover;
}
Step 1
services / navbarPaths.service.js
Step 1
We have to add our new feature to our navbar component. To do that, we have mocked the paths of our navbar inside the navbarPaths service.
Add this lines inside the variable paths as a new element of the array:
{
url: '#instaPics',
name: 'InstaPics',
icon: 'photo'
}
Component
In the next step, we are going to create a component inside the components folder.
Step 2
components / ab-picture / ab-picture.component.js
(function() {
'use strict';
angular
.module('app')
.component('abPicture', {
templateUrl: 'app/components/ab-picture/ab-picture.html',
controller: ABPictureController,
controllerAs: 'vm',
bindings:{
picture : '<'
}
});
/** @ngInject */
function ABPictureController() {
var vm = this;
vm.setPictureLike = setPictureLike;
function setPictureLike( picture ){
picture.like = picture.like === true ? false : true;
}
}
})();
Step 2
components / ab-picture / ab-picture.html
<div class="image-container" ng-class='{active: vm.picture.like === true}' ng-dblclick="vm.setPictureLike( vm.picture )">
<img ng-src="{{ vm.picture.url }}" alt="{{ vm.picture.title }}" ng-dblclick="vm.setPictureLike( vm.picture )">
<div class="heart-container noselect">
<img src="data:image/svg+xml;base64,PHN2ZyB2ZXJzaW9uPSIxLjEiIGlkPSJMYXllcl8xIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiB4PSIwcHgiIHk9IjBweCINCgkgd2lkdGg9IjEwMHB4IiBoZWlnaHQ9Ijg3LjVweCIgdmlld0JveD0iMCAwIDEwMCA4Ny41IiBlbmFibGUtYmFja2dyb3VuZD0ibmV3IDAgMCAxMDAgODcuNSIgeG1sOnNwYWNlPSJwcmVzZXJ2ZSI+DQo8cGF0aCBmaWxsPSIjRkZGRkZGIiBkPSJNNTAsMTkuMUMzNy0xMS4yLDAuMi00LjEsMCwzMS4xYy0wLjEsMTkuMyw0OC44LDUyLjEsNTAuMSw1Ni40YzEuMS00LjMsNTAuMS0zNy4zLDUwLTU2LjYNCglDOTkuOC00LjQsNjIuMy0xMCw1MCwxOS4xeiIvPg0KPC9zdmc+DQo=" alt="heart" id="js-heart-image"/>
</div>
</div>
<md-card-footer>
<label class="insta-pic-label">{{vm.picture.title}}</label>
<md-button class="right md-icon-button" aria-label="Favorite" ng-click='vm.setPictureLike( vm.picture )'>
<i class="material-icons md-48" ng-class='{active: vm.picture.like === true}'>favorite</i>
</md-button>
</md-card-footer>
Step 2
components / ab-picture / ab-picture.css
.insta-pic-label{
position: relative;
top: 10px;
}
.image-container {
position: relative;
overflow: hidden;
}
.image-container:focus{
outline-color: transparent;
}
.image-container > img {
display: block;
max-width: 100%;
}
.image-container .heart-container {
position: absolute;
width: 100%;
height: 100%;
top: 50%;
left: 50%;
margin: -50% 0 0 -50%;
text-align: center;
white-space: nowrap;
cursor: pointer;
}
.noselect {
-webkit-touch-callout: none; /* iOS Safari */
-webkit-user-select: none; /* Chrome/Safari/Opera */
-khtml-user-select: none; /* Konqueror */
-moz-user-select: none; /* Firefox */
-ms-user-select: none; /* Internet Explorer/Edge */
user-select: none; /* Non-prefixed version, currently
not supported by any browser */
}
.image-container .heart-container:before {
content: '';
display: inline-block;
height: 100%;
vertical-align: middle;
}
.image-container .heart-container > img {
display: inline-block;
width: 100px;
height: 88px;
opacity: 0;
vertical-align: middle;
-webkit-transition: all .5s ease-in;
transition: all .5s ease-in;
}
.image-container.active .heart-container > img {
opacity: 1;
}
Step 2
Done!
To Production?
Test? Build? Docs?
Test
gulp serve
gulp test
gulp protractor
ESLINT
Build
gulp build
Docs
gulp serve:apidoc
Questions
Links
by
By Serenity FrontStack
Technical revolution in the Frontend More Quality, More Productivity, More Scope