Top Banner
Admin UI Introduction to developing using AngularJS Xavier Butty Software Engineer for the open minded
27

Opencast Admin UI - Introduction to developing using AngularJS

Aug 16, 2015

Download

Technology

buttyx
Welcome message from author
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
Page 1: Opencast Admin UI - Introduction to developing using AngularJS

Admin UIIntroduction to developing using AngularJS

Xavier Butty Software Engineer

for the open minded

Page 2: Opencast Admin UI - Introduction to developing using AngularJS

– for the open minded

This is not an extensive AngularJS course…

.. but a short introduction to this framework using portions of the new Admin UI

Aimed to help developer to start extending the Admin UI

Page 3: Opencast Admin UI - Introduction to developing using AngularJS

First name, Last name Position

for the open mindedfor the open minded

01

Base conceptsbehind AngularJS

Page 4: Opencast Admin UI - Introduction to developing using AngularJS

– for the open minded

Model-View-Whatever works for youTemplate

<!doctype html> <html ng-app="myApp"> <head> <title>My little AngularJS app</title> </head> <body> Hello {{ user }}! <script src="angular.js"></script> </body> </html>

Model (Scope)

{ 'user': 'Georges Bregy' }

Controller

Directive

View (DOM)

Resource

Compilation

Service

Page 5: Opencast Admin UI - Introduction to developing using AngularJS

– for the open minded

Data binding

Two-way binding

Use Markup {{ myVar }} to represent data in the template

Rendered into a live view

Updating the view update the model…

…and vice-versa

Page 6: Opencast Admin UI - Introduction to developing using AngularJS

– for the open minded

Data binding<!doctype html><html ng-app="myApp"> <head> <title>My little AngularJS app</title> </head> <body> <h1>Welcome {{ user }}!</h1>

<ul> <li ng-repeat="link in links"> <a ng-href="{{link.href}}">{{link.name}}</a> </li> <ul> <select ng-model="currentLang" name="language" ng-options="l.name for l in languages"> <option value="">-- choose language --</option> </select>

</span> <script src="angular.js"></script> </body></html>

{ 'user': 'Georges Bregy' 'links': [ { 'href': 'http://www.google.ch', 'name': 'Search' }, { 'href': 'http://www.opencastcommunity.com', 'name': 'Opencast community' } ], 'languages': [ { 'name': 'English' }, { 'name': 'German' } ],

'currentLang': { 'name': 'English' };}

Page 7: Opencast Admin UI - Introduction to developing using AngularJS

– for the open minded

Scope

Model attached to a portion of a view

One root scope…

…with unlimited child scopes that inherit from the parent scope

Page 8: Opencast Admin UI - Introduction to developing using AngularJS

– for the open minded

<!doctype html> <html lang="en" ng-app="adminNg"> <head>…</head> <body ng-cloak ng-controller="ApplicationCtrl" ng-click="bodyClicked()">

<header ng-controller="NavCtrl" class="primary-header"> <div class=“header-branding”>…</div> <nav id="nav-dd-container" class="nav-dd-container">

<div class="nav-dd" id="lang-dd" old-admin-ng-dropdown=""> <div class="lang" ng-class="currentLanguageCode"></div> <ul class="dropdown-ul"> <li> <a href="#" ng-repeat="language in availableLanguages | orderBy:'displayLanguage'" ng-click="changeLanguage(language.code)"> <i class="lang {{ toLanguageClass(language) }}"></i>{{ language.displayLanguage }} </a> </li> </ul> </div>

<div ng-if="documentationUrl" class="nav-dd help" id="help-dd" ng-click="toDoc()"></div>

<div class="nav-dd" id="user-dd" old-admin-ng-dropdown=“”>…</div> </nav> </header>

<footer id="main-footer" ng-controller="NavCtrl"> <div class="default-footer"> <div ng-if="version.version" class="meta"> Opencast Video Capture Software (v.{{ version.version }} - build: {{ version.buildNumber }}) </div> <div ng-if="feedbackUrl" class="feedback-btn" id=“feedback-btn”>…</div> </div> </footer> </body> </html>

Root scopescope ApplicationCtrl

scope NavCtrl

x child scopes (ng-repeat)

scope NavCtrl

Page 9: Opencast Admin UI - Introduction to developing using AngularJS

– for the open minded

Dependancy injection

Injection of defined component

Most common way: Inline Array Annotation

Alternative: Manual injection with $inject

// A controller for global page navigationangular.module('adminNg.controllers').controller('NavCtrl', ['$scope', '$rootScope', '$location', '$window', '$resource', '$routeParams', 'Language', function ($scope, $rootScope, $location, $window, $resource, $routeParams, Language) {

$scope.category = $routeParams.category || $rootScope.category;

$scope.availableLanguages = [];

Page 10: Opencast Admin UI - Introduction to developing using AngularJS

First name, Last name Position

for the open mindedfor the open minded

02

Main components

Page 11: Opencast Admin UI - Introduction to developing using AngularJS

– for the open minded

Modules

Use to organise the components of an app in package

Simplify unit tests and make them faster. Only the required modules can be loaded.

For the admin UI, we have modules for:

Main app (adminNG), Controllers, Services, Filters, Directives

Other module are external components

// A controller for global page navigationangular.module('adminNg.controllers').controller('NavCtrl', ['$scope', '$rootScope', '$location', '$window', '$resource', '$routeParams', 'Language', function ($scope, $rootScope, $location, $window, $resource, $routeParams, Language) {

$scope.category = $routeParams.category || $rootScope.category;…sh

ared

/con

trol

lers

/na

viga

tionC

ontr

olle

r.js

Page 12: Opencast Admin UI - Introduction to developing using AngularJS

– for the open minded

Controllers

Set the initial state of a scope

Linked to a defined portion of a view

Allow to augment the scope

Override properties/methods inherit defined in parent controllers

In the new Admin UI:

/shared/controllers/**/*

/modules/*/controllers

Page 13: Opencast Admin UI - Introduction to developing using AngularJS

– for the open minded

<header ng-controller="NavCtrl" class="primary-header"> <div class="header-branding"> <div class="text-logo">Opencast</div> <div class="logo-tag">Beta</div> </div> <nav id="nav-dd-container" class="nav-dd-container"> <div class="nav-dd" id="lang-dd" old-admin-ng-dropdown=""> <div class="lang" ng-class="currentLanguageCode"></div> <ul class="dropdown-ul"> <li><a href="#" ng-repeat="language in availableLanguages | orderBy:'displayLanguage'" ng-click="changeLanguage(language.code)"> <i class="lang {{ toLanguageClass(language) }}"></i>

// A controller for global page navigationangular.module('adminNg.controllers').controller('NavCtrl', ['$scope', '$rootScope', '$location', '$window', '$resource', '$routeParams', 'Language', function ($scope, $rootScope, $location, $window, $resource, $routeParams, Language) {

$scope.category = $routeParams.category || $rootScope.category;

$scope.availableLanguages = [];

$scope.changeLanguage = function (key) { Language.changeLanguage(key); };

$scope.toLanguageClass = function (language) { return Language.$convertLanguageToCode(language.code); };

/sha

red/

cont

rolle

rs/

navi

gatio

nCon

trol

ler.j

sin

dex.

htm

lDefinition

Usage

Page 14: Opencast Admin UI - Introduction to developing using AngularJS

– for the open minded

Services

Create custom object shareable through the App

Lazily instantiated Only instantiated when a component requires it

SingletonEach component requiring a service get a reference to the

same instance instantiated by the service factory.

In the new Admin UI : /shared/services/**/*

Page 15: Opencast Admin UI - Introduction to developing using AngularJS

– for the open minded

angular.module('adminNg.services') .factory('AuthService', ['IdentityResource', function (IdentityResource) { var AuthService = function () { var me = this, isAdmin = false, isUserLoaded = false, callbacks = [], identity, isAuthorizedAs = function (role) { if (angular.isUndefined(me.user.roles)) { return false; } return isAdmin || (angular.isArray(me.user.roles) && me.user.roles.indexOf(role) > -1) || me.user.roles === role; };

this.user = {};

this.loadUser = function () { identity = IdentityResource.get(); identity.$promise.then(function (user) { var adminRole = user.org.adminRole; me.user = user; isAdmin = angular.isDefined(adminRole) && user.roles.indexOf(adminRole) > -1; isUserLoaded = true; angular.forEach(callbacks, function (item) { isAuthorizedAs(item.role) ? item.success() : item.error(); }); }); };

this.getUser = function () { return identity; };

this.loadUser(); };

return new AuthService(); }]);

/sha

red/

serv

ices

/aut

hSer

vice

.js

Page 16: Opencast Admin UI - Introduction to developing using AngularJS

– for the open minded

Resources

Synchronisation with the RESTfull data source

Natively use JSON for the data transfer

Using the $http service

In the new Admin UI : /shared/resources/**/*

Page 17: Opencast Admin UI - Introduction to developing using AngularJS

– for the open minded

angular.module('adminNg.resources') .factory('AclResource', ['$resource', function ($resource) { return $resource('/admin-ng/acl/:id', { id: '@id' }, { get: { method: 'GET', transformResponse: function (data) { return JSON.parse(data); } }, save: { method: 'PUT', headers: { 'Content-Type': 'application/x-www-form-urlencoded' }, transformRequest: function (data) { if (angular.isUndefined(data)) { return data; }

return $.param({ name : data.name, acl : JSON.stringify({acl: data.acl}) }); } } }); }]);

/sha

red/

reso

urce

s/ac

lRes

ourc

e.js

AclResource.save({id: $scope.resourceId}, { acl: { ace: ace }, name: $scope.metadata.name}, function () { Notifications.add('success', 'ACL_UPDATED', 'acl-form');}, function () { Notifications.add('error', 'ACL_NOT_SAVED', 'acl-form');});

Resource definition

Usage

Page 18: Opencast Admin UI - Introduction to developing using AngularJS

– for the open minded

Directives

Allow to create custom view component

Can be cascaded

Each directive instance has its own scope

Take care to not overload the stack!

Non-native element wrapped in directive have to be managed carefully!

Page 19: Opencast Admin UI - Introduction to developing using AngularJS

– for the open minded

angular.module('adminNg.directives').directive('withRole', ['AuthService', function (AuthService) { return { priority: 1000, link: function ($scope, element, attr) { element.addClass('hide');

AuthService.userIsAuthorizedAs(attr.withRole, function () { element.removeClass('hide'); }, function () { element.remove(); }); } };}]);

<div class="btn-group">

<button data-open-modal="user-modal" data-action="add" class="add" with-role="ROLE_UI_USERS_CREATE"> <i class="fa fa-plus"></i> <span translate="USERS.ACTIONS.ADD_USER"><!--Add User--></span> </button>

</div>

/sha

red/

dire

ctiv

es/w

ithR

oleD

irec

tive.

js

Usage

Directive definition

Page 20: Opencast Admin UI - Introduction to developing using AngularJS

– for the open minded

Filters

Function to be used within the expression {{ value | filter:argument1 }}

Use it for input formatting - Date presentation - Text translation - Array presentation

Can also be used within the controller

Page 21: Opencast Admin UI - Introduction to developing using AngularJS

– for the open minded

angular.module('adminNg.filters') .filter('trusted', ['$sce', function ($sce) { return function(url) { return $sce.trustAsResourceUrl(url); }; }]);

<video id="player" ng-if="controls === 'false'"> <source ng-repeat="preview in video.previews" ng-src="{{ preview.uri | trusted }}" type="video/mp4" /> Your browser does not support HTML5 video.</video>

/sha

red/

filte

rs/t

rust

edR

esou

rceU

rlFi

lter

Filter definition

Usage

Page 22: Opencast Admin UI - Introduction to developing using AngularJS

First name, Last name Position

for the open mindedfor the open minded

Jasminefor unit testing

03

Page 23: Opencast Admin UI - Introduction to developing using AngularJS

– for the open minded

How does a Jasmine specs look like?describe('Navigation controller', function () {

var $scope, $httpBackend, Language;

beforeEach(module('adminNg'));

beforeEach(module(function ($provide) {

var service = {

configureFromServer: function () {},

formatDate: function (val, date) { return date; },

formatTime: function (val, date) { return date; },

changeLanguage: function () {},

getLanguageCode: function () { return 'ja_JP'; },

getLanguage: function () { return {}; },

Page 24: Opencast Admin UI - Introduction to developing using AngularJS

First name, Last name Position

for the open mindedfor the open minded

04

Let’s work on it!

Page 25: Opencast Admin UI - Introduction to developing using AngularJS

– for the open minded

The summary of "create event" show empty element

Some items show in the summary of the new event wizard are empty, and should therefore not be displayed.

Page 26: Opencast Admin UI - Introduction to developing using AngularJS

– for the open minded

Delete series and events

Add (x) icon in the events and series tableview to allow deletion of single Events/Series

Page 27: Opencast Admin UI - Introduction to developing using AngularJS

Questions?

thanks for your attentionXavier Butty Software Engineer

for the open minded