SlideShare a Scribd company logo
Admin UI
Introduction to developing using AngularJS
Xavier Butty
Software Engineer
for the open minded
– 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
First name, Last name
Position
for the open mindedfor the open minded
01
Base concepts
behind AngularJS
– for the open minded
Model-View-Whatever works for you
Template
<!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
– 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
– 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'
};
}
– 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
– 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 scope
scope ApplicationCtrl
scope NavCtrl
x child scopes (ng-repeat)
scope NavCtrl
– 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 navigation
angular.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 = [];
First name, Last name
Position
for the open mindedfor the open minded
02
Main components
– 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 navigation
angular.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;
…
shared/controllers/
navigationController.js
– 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
– 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 navigation
angular.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);
};
/shared/controllers/
navigationController.jsindex.html Definition
Usage
– for the open minded
Services
Create custom object shareable through the App
Lazily instantiated 

Only instantiated when a component requires it
Singleton

Each component requiring a service get a reference to the
same instance instantiated by the service factory.
In the new Admin UI : /shared/services/**/*
– 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();
}]);
/shared/services/authService.js
– 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/**/*
– 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})
});
}
}
});
}]);
/shared/resources/aclResource.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
– 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!
– 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>
/shared/directives/withRoleDirective.js
Usage
Directive definition
– 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
– 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>
/shared/

filters/trustedResourceUrlFilter
Filter definition
Usage
First name, Last name
Position
for the open mindedfor the open minded
Jasmine
for unit testing
03
– 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 {}; },
First name, Last name
Position
for the open mindedfor the open minded
04
Let’s work on it!
– 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.
– for the open minded
Delete series and events
Add (x) icon in the events and series tableview to
allow deletion of single Events/Series
Questions?

thanks for your attention
Xavier Butty
Software Engineer
for the open minded
Ad

Recommended

Bag Of Tricks From Iusethis
Bag Of Tricks From Iusethis
Marcus Ramberg
 
Building iPhone Web Apps using "classic" Domino
Building iPhone Web Apps using "classic" Domino
Rob Bontekoe
 
Django at the Disco
Django at the Disco
Richard Leland
 
Single page webapps & javascript-testing
Single page webapps & javascript-testing
smontanari
 
Introduction to Vue.js
Introduction to Vue.js
Meir Rotstein
 
Django at the Disco
Django at the Disco
Richard Leland
 
jQuery UI Widgets, Drag and Drop, Drupal 7 Javascript
jQuery UI Widgets, Drag and Drop, Drupal 7 Javascript
Darren Mothersele
 
Remy Sharp The DOM scripting toolkit jQuery
Remy Sharp The DOM scripting toolkit jQuery
deimos
 
Modularized Persistence - B Zsoldos
Modularized Persistence - B Zsoldos
mfrancis
 
Symfony2 - from the trenches
Symfony2 - from the trenches
Lukas Smith
 
Joe Walker Interactivewebsites Cometand Dwr
Joe Walker Interactivewebsites Cometand Dwr
deimos
 
AngularJS Compile Process
AngularJS Compile Process
Eyal Vardi
 
W3C XBL 2.0 and Widgets 1.0
W3C XBL 2.0 and Widgets 1.0
Marcos Caceres
 
AngularJS Services
AngularJS Services
Eyal Vardi
 
Big Data for each one of us
Big Data for each one of us
OSCON Byrum
 
Drupal & javascript
Drupal & javascript
Almog Baku
 
JavaScript for Flex Devs
JavaScript for Flex Devs
Aaronius
 
Template-based Modular Architecture
Template-based Modular Architecture
genify
 
HirshHorn theme: how I created it
HirshHorn theme: how I created it
Paul Bearne
 
Jquery ui
Jquery ui
adm_exoplatform
 
Backbone.js — Introduction to client-side JavaScript MVC
Backbone.js — Introduction to client-side JavaScript MVC
pootsbook
 
Magento Dependency Injection
Magento Dependency Injection
Anton Kril
 
Modules and injector
Modules and injector
Eyal Vardi
 
Stripes Framework
Stripes Framework
Johannes Carlén
 
JQuery UI
JQuery UI
Gary Yeh
 
Java Web Development with Stripes
Java Web Development with Stripes
Samuel Santos
 
How many more staff do you need to improve the quality of care?
How many more staff do you need to improve the quality of care?
mckesson
 
Презентация онд нск (2014)
Презентация онд нск (2014)
uosnsk
 
35 Best Inspirational Travel Quotes - DriverCollect
35 Best Inspirational Travel Quotes - DriverCollect
drivercollect
 
Anoop's birthday
Anoop's birthday
arihants14
 

More Related Content

What's hot (18)

Modularized Persistence - B Zsoldos
Modularized Persistence - B Zsoldos
mfrancis
 
Symfony2 - from the trenches
Symfony2 - from the trenches
Lukas Smith
 
Joe Walker Interactivewebsites Cometand Dwr
Joe Walker Interactivewebsites Cometand Dwr
deimos
 
AngularJS Compile Process
AngularJS Compile Process
Eyal Vardi
 
W3C XBL 2.0 and Widgets 1.0
W3C XBL 2.0 and Widgets 1.0
Marcos Caceres
 
AngularJS Services
AngularJS Services
Eyal Vardi
 
Big Data for each one of us
Big Data for each one of us
OSCON Byrum
 
Drupal & javascript
Drupal & javascript
Almog Baku
 
JavaScript for Flex Devs
JavaScript for Flex Devs
Aaronius
 
Template-based Modular Architecture
Template-based Modular Architecture
genify
 
HirshHorn theme: how I created it
HirshHorn theme: how I created it
Paul Bearne
 
Jquery ui
Jquery ui
adm_exoplatform
 
Backbone.js — Introduction to client-side JavaScript MVC
Backbone.js — Introduction to client-side JavaScript MVC
pootsbook
 
Magento Dependency Injection
Magento Dependency Injection
Anton Kril
 
Modules and injector
Modules and injector
Eyal Vardi
 
Stripes Framework
Stripes Framework
Johannes Carlén
 
JQuery UI
JQuery UI
Gary Yeh
 
Java Web Development with Stripes
Java Web Development with Stripes
Samuel Santos
 
Modularized Persistence - B Zsoldos
Modularized Persistence - B Zsoldos
mfrancis
 
Symfony2 - from the trenches
Symfony2 - from the trenches
Lukas Smith
 
Joe Walker Interactivewebsites Cometand Dwr
Joe Walker Interactivewebsites Cometand Dwr
deimos
 
AngularJS Compile Process
AngularJS Compile Process
Eyal Vardi
 
W3C XBL 2.0 and Widgets 1.0
W3C XBL 2.0 and Widgets 1.0
Marcos Caceres
 
AngularJS Services
AngularJS Services
Eyal Vardi
 
Big Data for each one of us
Big Data for each one of us
OSCON Byrum
 
Drupal & javascript
Drupal & javascript
Almog Baku
 
JavaScript for Flex Devs
JavaScript for Flex Devs
Aaronius
 
Template-based Modular Architecture
Template-based Modular Architecture
genify
 
HirshHorn theme: how I created it
HirshHorn theme: how I created it
Paul Bearne
 
Backbone.js — Introduction to client-side JavaScript MVC
Backbone.js — Introduction to client-side JavaScript MVC
pootsbook
 
Magento Dependency Injection
Magento Dependency Injection
Anton Kril
 
Modules and injector
Modules and injector
Eyal Vardi
 
Java Web Development with Stripes
Java Web Development with Stripes
Samuel Santos
 

Viewers also liked (19)

How many more staff do you need to improve the quality of care?
How many more staff do you need to improve the quality of care?
mckesson
 
Презентация онд нск (2014)
Презентация онд нск (2014)
uosnsk
 
35 Best Inspirational Travel Quotes - DriverCollect
35 Best Inspirational Travel Quotes - DriverCollect
drivercollect
 
Anoop's birthday
Anoop's birthday
arihants14
 
ອາຊ່ຽນ
ອາຊ່ຽນ
mikkoIT
 
Iping, england (team 5) final copy
Iping, england (team 5) final copy
KKmck
 
Goodwin analysis- Hey There Delilah
Goodwin analysis- Hey There Delilah
katiess07
 
The real lady gaga project
The real lady gaga project
Hiruni Wasana Mapalagama
 
The rough riders
The rough riders
kcloer
 
practica 7
practica 7
Miguel Angel Alva Pumarejo
 
Deck three
Deck three
TeamSea
 
My magazine pitch
My magazine pitch
katiess07
 
Multiplicacion de dos_numeros
Multiplicacion de dos_numeros
Miguel Angel Alva Pumarejo
 
Tutorial 2
Tutorial 2
Miguel Angel Alva Pumarejo
 
theoretical approach to genre
theoretical approach to genre
katiess07
 
Presentacion
Presentacion
Miguel Angel Alva Pumarejo
 
civic engagement
civic engagement
katiess07
 
Bp
Bp
明翰 楊
 
Celular virtual
Celular virtual
Miguel Angel Alva Pumarejo
 
How many more staff do you need to improve the quality of care?
How many more staff do you need to improve the quality of care?
mckesson
 
Презентация онд нск (2014)
Презентация онд нск (2014)
uosnsk
 
35 Best Inspirational Travel Quotes - DriverCollect
35 Best Inspirational Travel Quotes - DriverCollect
drivercollect
 
Anoop's birthday
Anoop's birthday
arihants14
 
ອາຊ່ຽນ
ອາຊ່ຽນ
mikkoIT
 
Iping, england (team 5) final copy
Iping, england (team 5) final copy
KKmck
 
Goodwin analysis- Hey There Delilah
Goodwin analysis- Hey There Delilah
katiess07
 
The rough riders
The rough riders
kcloer
 
Deck three
Deck three
TeamSea
 
My magazine pitch
My magazine pitch
katiess07
 
theoretical approach to genre
theoretical approach to genre
katiess07
 
civic engagement
civic engagement
katiess07
 
Ad

Similar to Opencast Admin UI - Introduction to developing using AngularJS (20)

[Ebooks PDF] download AngularJS 1st Edition Brad Green full chapters
[Ebooks PDF] download AngularJS 1st Edition Brad Green full chapters
kiciunonge
 
AngularJS and SPA
AngularJS and SPA
Lorenzo Dematté
 
Angular js workshop
Angular js workshop
Rolands Krumbergs
 
Nicolas Embleton, Advanced Angular JS
Nicolas Embleton, Advanced Angular JS
JavaScript Meetup HCMC
 
Angular directive filter and routing
Angular directive filter and routing
jagriti srivastava
 
Angular training - Day 3 - custom directives, $http, $resource, setup with ye...
Angular training - Day 3 - custom directives, $http, $resource, setup with ye...
murtazahaveliwala
 
gDayX - Advanced angularjs
gDayX - Advanced angularjs
gdgvietnam
 
gDayX 2013 - Advanced AngularJS - Nicolas Embleton
gDayX 2013 - Advanced AngularJS - Nicolas Embleton
George Nguyen
 
AngularJS for Web and Mobile
AngularJS for Web and Mobile
Rocket Software
 
Angular js for enteprise application
Angular js for enteprise application
vu van quyet
 
Angular.js Primer in Aalto University
Angular.js Primer in Aalto University
SC5.io
 
GDayX - Advanced Angular.JS
GDayX - Advanced Angular.JS
Nicolas Embleton
 
Learning AngularJS - Complete coverage of AngularJS features and concepts
Learning AngularJS - Complete coverage of AngularJS features and concepts
Suresh Patidar
 
Angular js How, What & Why - MetaRefresh 2014
Angular js How, What & Why - MetaRefresh 2014
shyamsesh
 
Angular js 1.3 presentation for fed nov 2014
Angular js 1.3 presentation for fed nov 2014
Sarah Hudson
 
Introduction to AngularJS By Bharat Makwana
Introduction to AngularJS By Bharat Makwana
Bharat Makwana
 
AngularJS in practice
AngularJS in practice
Eugene Fidelin
 
01 startoff angularjs
01 startoff angularjs
Erhwen Kuo
 
Workshop 12: AngularJS Parte I
Workshop 12: AngularJS Parte I
Visual Engineering
 
Angular Workshop_Sarajevo2
Angular Workshop_Sarajevo2
Christoffer Noring
 
[Ebooks PDF] download AngularJS 1st Edition Brad Green full chapters
[Ebooks PDF] download AngularJS 1st Edition Brad Green full chapters
kiciunonge
 
Angular directive filter and routing
Angular directive filter and routing
jagriti srivastava
 
Angular training - Day 3 - custom directives, $http, $resource, setup with ye...
Angular training - Day 3 - custom directives, $http, $resource, setup with ye...
murtazahaveliwala
 
gDayX - Advanced angularjs
gDayX - Advanced angularjs
gdgvietnam
 
gDayX 2013 - Advanced AngularJS - Nicolas Embleton
gDayX 2013 - Advanced AngularJS - Nicolas Embleton
George Nguyen
 
AngularJS for Web and Mobile
AngularJS for Web and Mobile
Rocket Software
 
Angular js for enteprise application
Angular js for enteprise application
vu van quyet
 
Angular.js Primer in Aalto University
Angular.js Primer in Aalto University
SC5.io
 
GDayX - Advanced Angular.JS
GDayX - Advanced Angular.JS
Nicolas Embleton
 
Learning AngularJS - Complete coverage of AngularJS features and concepts
Learning AngularJS - Complete coverage of AngularJS features and concepts
Suresh Patidar
 
Angular js How, What & Why - MetaRefresh 2014
Angular js How, What & Why - MetaRefresh 2014
shyamsesh
 
Angular js 1.3 presentation for fed nov 2014
Angular js 1.3 presentation for fed nov 2014
Sarah Hudson
 
Introduction to AngularJS By Bharat Makwana
Introduction to AngularJS By Bharat Makwana
Bharat Makwana
 
01 startoff angularjs
01 startoff angularjs
Erhwen Kuo
 
Workshop 12: AngularJS Parte I
Workshop 12: AngularJS Parte I
Visual Engineering
 
Ad

Recently uploaded (20)

"Scaling in space and time with Temporal", Andriy Lupa.pdf
"Scaling in space and time with Temporal", Andriy Lupa.pdf
Fwdays
 
Using the SQLExecutor for Data Quality Management: aka One man's love for the...
Using the SQLExecutor for Data Quality Management: aka One man's love for the...
Safe Software
 
Curietech AI in action - Accelerate MuleSoft development
Curietech AI in action - Accelerate MuleSoft development
shyamraj55
 
GenAI Opportunities and Challenges - Where 370 Enterprises Are Focusing Now.pdf
GenAI Opportunities and Challenges - Where 370 Enterprises Are Focusing Now.pdf
Priyanka Aash
 
ReSTIR [DI]: Spatiotemporal reservoir resampling for real-time ray tracing ...
ReSTIR [DI]: Spatiotemporal reservoir resampling for real-time ray tracing ...
revolcs10
 
OWASP Barcelona 2025 Threat Model Library
OWASP Barcelona 2025 Threat Model Library
PetraVukmirovic
 
CapCut Pro Crack For PC Latest Version {Fully Unlocked} 2025
CapCut Pro Crack For PC Latest Version {Fully Unlocked} 2025
pcprocore
 
Techniques for Automatic Device Identification and Network Assignment.pdf
Techniques for Automatic Device Identification and Network Assignment.pdf
Priyanka Aash
 
cnc-processing-centers-centateq-p-110-en.pdf
cnc-processing-centers-centateq-p-110-en.pdf
AmirStern2
 
The Future of Product Management in AI ERA.pdf
The Future of Product Management in AI ERA.pdf
Alyona Owens
 
OpenPOWER Foundation & Open-Source Core Innovations
OpenPOWER Foundation & Open-Source Core Innovations
IBM
 
AI vs Human Writing: Can You Tell the Difference?
AI vs Human Writing: Can You Tell the Difference?
Shashi Sathyanarayana, Ph.D
 
Python Conference Singapore - 19 Jun 2025
Python Conference Singapore - 19 Jun 2025
ninefyi
 
Mastering AI Workflows with FME by Mark Döring
Mastering AI Workflows with FME by Mark Döring
Safe Software
 
Quantum AI: Where Impossible Becomes Probable
Quantum AI: Where Impossible Becomes Probable
Saikat Basu
 
Salesforce Summer '25 Release Frenchgathering.pptx.pdf
Salesforce Summer '25 Release Frenchgathering.pptx.pdf
yosra Saidani
 
WebdriverIO & JavaScript: The Perfect Duo for Web Automation
WebdriverIO & JavaScript: The Perfect Duo for Web Automation
digitaljignect
 
"Database isolation: how we deal with hundreds of direct connections to the d...
"Database isolation: how we deal with hundreds of direct connections to the d...
Fwdays
 
Smarter Aviation Data Management: Lessons from Swedavia Airports and Sweco
Smarter Aviation Data Management: Lessons from Swedavia Airports and Sweco
Safe Software
 
UserCon Belgium: Honey, VMware increased my bill
UserCon Belgium: Honey, VMware increased my bill
stijn40
 
"Scaling in space and time with Temporal", Andriy Lupa.pdf
"Scaling in space and time with Temporal", Andriy Lupa.pdf
Fwdays
 
Using the SQLExecutor for Data Quality Management: aka One man's love for the...
Using the SQLExecutor for Data Quality Management: aka One man's love for the...
Safe Software
 
Curietech AI in action - Accelerate MuleSoft development
Curietech AI in action - Accelerate MuleSoft development
shyamraj55
 
GenAI Opportunities and Challenges - Where 370 Enterprises Are Focusing Now.pdf
GenAI Opportunities and Challenges - Where 370 Enterprises Are Focusing Now.pdf
Priyanka Aash
 
ReSTIR [DI]: Spatiotemporal reservoir resampling for real-time ray tracing ...
ReSTIR [DI]: Spatiotemporal reservoir resampling for real-time ray tracing ...
revolcs10
 
OWASP Barcelona 2025 Threat Model Library
OWASP Barcelona 2025 Threat Model Library
PetraVukmirovic
 
CapCut Pro Crack For PC Latest Version {Fully Unlocked} 2025
CapCut Pro Crack For PC Latest Version {Fully Unlocked} 2025
pcprocore
 
Techniques for Automatic Device Identification and Network Assignment.pdf
Techniques for Automatic Device Identification and Network Assignment.pdf
Priyanka Aash
 
cnc-processing-centers-centateq-p-110-en.pdf
cnc-processing-centers-centateq-p-110-en.pdf
AmirStern2
 
The Future of Product Management in AI ERA.pdf
The Future of Product Management in AI ERA.pdf
Alyona Owens
 
OpenPOWER Foundation & Open-Source Core Innovations
OpenPOWER Foundation & Open-Source Core Innovations
IBM
 
AI vs Human Writing: Can You Tell the Difference?
AI vs Human Writing: Can You Tell the Difference?
Shashi Sathyanarayana, Ph.D
 
Python Conference Singapore - 19 Jun 2025
Python Conference Singapore - 19 Jun 2025
ninefyi
 
Mastering AI Workflows with FME by Mark Döring
Mastering AI Workflows with FME by Mark Döring
Safe Software
 
Quantum AI: Where Impossible Becomes Probable
Quantum AI: Where Impossible Becomes Probable
Saikat Basu
 
Salesforce Summer '25 Release Frenchgathering.pptx.pdf
Salesforce Summer '25 Release Frenchgathering.pptx.pdf
yosra Saidani
 
WebdriverIO & JavaScript: The Perfect Duo for Web Automation
WebdriverIO & JavaScript: The Perfect Duo for Web Automation
digitaljignect
 
"Database isolation: how we deal with hundreds of direct connections to the d...
"Database isolation: how we deal with hundreds of direct connections to the d...
Fwdays
 
Smarter Aviation Data Management: Lessons from Swedavia Airports and Sweco
Smarter Aviation Data Management: Lessons from Swedavia Airports and Sweco
Safe Software
 
UserCon Belgium: Honey, VMware increased my bill
UserCon Belgium: Honey, VMware increased my bill
stijn40
 

Opencast Admin UI - Introduction to developing using AngularJS

  • 1. Admin UI Introduction to developing using AngularJS Xavier Butty Software Engineer for the open minded
  • 2. – 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
  • 3. First name, Last name Position for the open mindedfor the open minded 01 Base concepts behind AngularJS
  • 4. – for the open minded Model-View-Whatever works for you Template <!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
  • 5. – 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
  • 6. – 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' }; }
  • 7. – 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
  • 8. – 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 scope scope ApplicationCtrl scope NavCtrl x child scopes (ng-repeat) scope NavCtrl
  • 9. – 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 navigation angular.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 = [];
  • 10. First name, Last name Position for the open mindedfor the open minded 02 Main components
  • 11. – 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 navigation angular.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; … shared/controllers/ navigationController.js
  • 12. – 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
  • 13. – 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 navigation angular.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); }; /shared/controllers/ navigationController.jsindex.html Definition Usage
  • 14. – for the open minded Services Create custom object shareable through the App Lazily instantiated 
 Only instantiated when a component requires it Singleton
 Each component requiring a service get a reference to the same instance instantiated by the service factory. In the new Admin UI : /shared/services/**/*
  • 15. – 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(); }]); /shared/services/authService.js
  • 16. – 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/**/*
  • 17. – 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}) }); } } }); }]); /shared/resources/aclResource.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
  • 18. – 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!
  • 19. – 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> /shared/directives/withRoleDirective.js Usage Directive definition
  • 20. – 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
  • 21. – 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> /shared/
 filters/trustedResourceUrlFilter Filter definition Usage
  • 22. First name, Last name Position for the open mindedfor the open minded Jasmine for unit testing 03
  • 23. – 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 {}; },
  • 24. First name, Last name Position for the open mindedfor the open minded 04 Let’s work on it!
  • 25. – 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.
  • 26. – for the open minded Delete series and events Add (x) icon in the events and series tableview to allow deletion of single Events/Series
  • 27. Questions?
 thanks for your attention Xavier Butty Software Engineer for the open minded