SlideShare a Scribd company logo
1 of 36
How to customize ADF 1.2
Eugenio Romano
Eugenio Romano
Senior Software Engineer Alfresco
https://twitter.com/RomanoEugenio
https://github.com/eromano
eugenio.romano@alfresco.com
Open-source contributor
(Activiti, ADF, Alfresco-js-api, etc.)
Agenda
1. Intro ADF
2. Customize Document List
3. Customize Viewer
4. Customize Login
ADF 1.2 IS HERE
Monday 27 February we released :
• ADF 1.2
• Alfresco-js-api 1.2
What is new:
https://github.com/Alfresco/alfresco-js-
api/releases/tag/1.2.0
https://github.com/Alfresco/alfresco-
ng2-components/releases/tag/1.2.0
• https://github.com/eromano/customize-alfresco-adf-app-examples
Github repo with all the examples
Generator scaffolder for ADF app
Resources
Generator scaffolder for ADF Components
• https://github.com/Alfresco/generator-ng2-alfresco-component
• https://github.com/Alfresco/generator-ng2-alfresco-app
Technology Angular 2
• One of the big ideas behind Angular is the concept of components.
• When you create a component, essentially you create a new tag <my-new-tag> this tag is
reusable everywhere. we will teach the browser new tags that have custom functionality.
• Components are self contained and by their nature, promote the separation of concern.
So they are easy to test it.
EASY TO TEST
Technology TYPESCRIPT
• ADF is built in a Javascript-like language called TypeScript.
• There are a lot of great reasons to use TypeScript instead of plain Javascript.
• TypeScript isn’t a completely new language, it’s a superset of ES6.
There are a lot of good thing in using TypeScript instead
plain javscript :
• Types
• Classes
• Annotations
• Imports
Technology YEOMAN
Yeoman is a tool which helps you to kickstart new projects. With Yeoman you can share
your ideas and best practices with others by creating a scaffold.
With Yeoman you can improve your productivity and not waste time when starting a
project.
• Speed up the startup development time.
• Have common tools: style, build, test, syntax checker and deploy.
• Standardize the developer experience across all components.
• Enforce rules about quality and code contributions.
Customize Document List
Document list utility links
https://github.com/Alfresco/alfresco-ng2-components/tree/master/ng2-
components/ng2-alfresco-documentlist
https://github.com/Alfresco/alfresco-ng2-components/tree/master/ng2-
components/ng2-alfresco-documentlist/demo
Document list documentation
Document list demo
Standard Document List let’s customize
Goal of this customization:
• Add a new column with
the the file version
Create the customize-app
https://github.com/Alfresco/generator-ng2-alfresco-app
Install the Alfresco generator component scaffolder following the instruction
in the readme :
• yo ng2-alfresco-app
• Provide the name of the app: customize-app
• Go in the appfolder
• Run npm install
Let's create your customize-app app
Now your scaffolder is complete let’s add some code:
Custom Columns How to show file version
Open the files.component.html and add the HTML snippet:
<content-column title="version" key="name" sortable="true" class="full-width ellipsis-cell">
<template let-context="$implicit">
<div>V.{{context.row.getValue('properties.cm:versionLabel')}}</div>
</template>
</content-column>
Custom Columns Show the file version
Hide empty value
<div *ngIf="context.row.getValue('properties.cm:versionLabel')">
V.{{context.row.getValue('properties.cm:versionLabel')}}
</div>
The ngIf directive removes or recreates a portion of the DOM tree
based on an {expression}. If the expression assigned to ngIf evaluates
to a false value then the element is removed from the DOM, otherwise
a clone of the element is reinserted into the DOM.
<div *ngIf="context.row.getValue('properties.cm:versionLabel')" class="version-style">
V.{{context.row.getValue('properties.cm:versionLabel')}}
</div>
files.component.css
Add some style
.version-style {
width: 46px;
text-align: center;
border-radius: 15px;
background: rgb(31, 188, 210);
color: white; }
Custom Columns Show the file version with style
Create our first component
https://github.com/Alfresco/generator-ng2-alfresco-component
• yo ng2-alfresco-component
• Go in the component folder and run npm install
Let's create your ng2-alfresco-version-badge
Follow the instruction in the readme of the project to install the generator
Let’s create our very first component. When we have this component written, we will be
able to use it in our HTML
import { Component, Input } from '@angular/core';
@Component({
selector: 'ng2-alfresco-version-badge',
styles: [`.badge-style {
width: 46px;
text-align: center;
border-radius: 15px;
background: rgb(31, 188, 210);
color: white;}`],
template: ` <div *ngIf="version" class=”badge-style">
V.{{version}}
</div>`})
export class Ng2AlfrescoVersionBadgeComponent {
@Input()
version: string;
}
Open ng2-alfresco-version-badge
and add the pieces of code that we
have done before to create the
custom column
Component version badge Code
<content-column title="version" key="name" sortable="true" class="full-width ellipsis-cell">
<template let-context="$implicit">
<ng2-alfresco-version-badge [version]="context.row.getValue('properties.cm:versionLabel')">
</ng2-alfresco-version-badge>
</template>
</content-column>
Custom Columns with custom component
• Import the new component dependency in the app.module.ts
import { Ng2AlfrescoVersionBadgeModule } from 'ng2-alfresco-version-badge';
• Add the new custom template with our component inside
@NgModule({ imports: […, Ng2AlfrescoVersionBadgeModule, ….]
Npm Link
• Because our new component is not published yet we need a way to resolve this
new component in the local environment
Package linking is a two-step process.
1. run npm link in the package folder will create a globally link to “YOUR_PACAKGE”
2. Open the demo shell folder and run npm link YOUR_PACAKGE
This is handy for installing your own stuff, so that you can work on it and test it before to
publish it online
Custom Columns with custom component change style
:host >>> .badge-style {
width: 46px;
text-align: center;
background: red;
color: white;
}
We can use the /deep/ or the alias >>> selector to force a style down through the child
component tree into all the child component views.
Customize viewer
Viewer utility links
https://github.com/Alfresco/alfresco-ng2-components/tree/master/ng2-
components/ng2-alfresco-viewer
https://github.com/Alfresco/alfresco-ng2-components/tree/master/ng2-
components/ng2-alfresco-viewer/demo
Viewer documentation
Viewer demo
Viewer live demo
https://embed.plnkr.co/iTuG1lFIXfsP95l6bDW6/
Viewer file extensions
How I Can handle other extension in the viewer?
If you want handle other file formats that are
not yet supported by the ng2-alfresco-viewer
you can define your own custom handler.
<extension-viewer [supportedExtensions]="['txt']" #extension>
<template let-urlFileContent="urlFileContent" >
<my-custom-txt-component
urlFileContent="urlFileContent"></my-custom-txt-
component>
</template>
</extension-viewer>
Custom extension format viewer for zip files
• yo ng2-alfresco-component
• Provide the name of the component : ng2-alfresco-zip-viewer
• Go in the component folder
• Run npm install
Let's create your ng2-alfresco-zip-viewer component
Now your scaffolder is complete let’s add some code:
• npm install jszip –save
• npm install --save @types/jszip
https://stuk.github.io/jszip/docu
mentation/examples.html
Add some library
• Install jszip
• Jszip documentation
ngOnChanges() {
this.http.get(this.urlFile, new RequestOptions({
responseType: ResponseContentType.ArrayBuffer
}))
.toPromise().then((res: Response) => {
this.extractZipData(res);
});
}
private extractZipData(res: Response) {
let newZip = new JSZip();
newZip.loadAsync(res.arrayBuffer())
.then((zip) => {
this.zipFiles = Object.keys(zip.files).map((key) => {
return zip.files[key];
});
});
}
<table class="mdl-data-table mdl-js-data-table mdl-shadow--2dp">
<thead>
<tr><th>Name</th></tr>
</thead>
<tbody>
<tr *ngFor="let file of zipFiles; let idx = index">
<td class="mdl-data-table__cell--non-numeric">{{file.name}}</td>
</tr>
</tbody>
</table>
https://getmdl.io/components/index.html#tables-section
Add a template
In order to show the file list we can use the material design table:
Template:
Iterate with ngFor
Result
Customize Login
Login utility links
https://github.com/Alfresco/alfresco-ng2-components/tree/master/ng2-
components/ng2-alfresco-login
https://github.com/Alfresco/alfresco-ng2-components/tree/master/ng2-
components/ng2-alfresco-login/demo
Login documentation
Login demo
http://embed.plnkr.co/PfZytJyHcl3xIsa8pdMo/
Login live demo
Standard Login let’s customize
Goal of this customization:
• Add a profile photo in the login
page
Customize login-demo.component.ts
import { EcmUserService } from 'ng2-alfresco-userinfo';
onLogin($event) {
this.getEcmUserInfo();
this.router.navigate(['/home']);
}
getEcmUserInfo(): void {
this.ecmUserService.getCurrentUserInfo()
.subscribe((res) => {
let ecmUserImageUrl = this.ecmUserService.getUserProfileImage(res.avatarId);
this.saveBase64FromImageUrl(ecmUserImageUrl);
}
);
}
• Get the profile Photo using
the EcmUserService of the
ng2-alfresco-userinfo
component.
saveBase64FromImageUrl(url: string) {
let img = new Image();
img.crossOrigin = 'Anonymous';
img.onload = ()=> {
let canvas: any = document.createElement('CANVAS');
let ctx: any = canvas.getContext('2d');
canvas.height = '64';
canvas.width = '64';
ctx.drawImage(img, 0, 0);
let dataURL = canvas.toDataURL();
this.storage.setItem('imageProfile', dataURL);
canvas = null;
};
img.src = url;
}
Save The profile Image in login-demo.component.ts
• Save the photo in the local
storage.
• In order to save the photo
we need to convert it in
Base64
<login-header>
<template>
<img class="login-profile-img"
[src]="getProfileImageFromStorage()" />
</template>
</login-header>
.login-profile-img {
margin: auto;
border: 3px solid #ff9800;
border-radius: 34px;
width: 64px;
}
Viewer with profile image login-demo.component.html
<login-header>
<template>
<img *ngIf="getProfileImageFromStorage()" class="login-
profile-img” [src]="getProfileImageFromStorage()" />
<img *ngIf="!getProfileImageFromStorage()" class="login-
profile-img" src="https://cdn.rawgit.com/Alfresco/alfresco-
ng2-components/c13c3aae/ng2-components/ng2-alfresco-
userinfo/src/assets/images/anonymous.gif">
</template>
</login-header>
Profile image and default image login-demo.component.html
Where to get Info on ADF
https://community.alfresco.com/community/application-development-
framework/pages/get-started
https://gitter.im/Alfresco/alfresco-ng2-components
https://github.com/Alfresco/alfresco-ng2-components/
Community Web-Site
Gitter
Ghithub readme
Thanks

More Related Content

What's hot

Word press Plugins by WordPress Experts
Word press Plugins by WordPress ExpertsWord press Plugins by WordPress Experts
Word press Plugins by WordPress ExpertsYameen Khan
 
Laravel Forge: Hello World to Hello Production
Laravel Forge: Hello World to Hello ProductionLaravel Forge: Hello World to Hello Production
Laravel Forge: Hello World to Hello ProductionJoe Ferguson
 
You've Got Plugins in Your Plugins: Bundling Plugin Dependencies - Atlassian ...
You've Got Plugins in Your Plugins: Bundling Plugin Dependencies - Atlassian ...You've Got Plugins in Your Plugins: Bundling Plugin Dependencies - Atlassian ...
You've Got Plugins in Your Plugins: Bundling Plugin Dependencies - Atlassian ...Atlassian
 
Developers, Be a Bada$$ with WP-CLI
Developers, Be a Bada$$ with WP-CLIDevelopers, Be a Bada$$ with WP-CLI
Developers, Be a Bada$$ with WP-CLIWP Engine
 
Creating Your First WordPress Plugin
Creating Your First WordPress PluginCreating Your First WordPress Plugin
Creating Your First WordPress PluginBrad Williams
 
Plug in development
Plug in developmentPlug in development
Plug in developmentLucky Ali
 
Behaviour Driven Development con Behat & Drupal
Behaviour Driven Development con Behat & DrupalBehaviour Driven Development con Behat & Drupal
Behaviour Driven Development con Behat & Drupalsparkfabrik
 
Session on Selenium Powertools by Unmesh Gundecha
Session on Selenium Powertools by Unmesh GundechaSession on Selenium Powertools by Unmesh Gundecha
Session on Selenium Powertools by Unmesh GundechaAgile Testing Alliance
 
Migraine Drupal - syncing your staging and live sites
Migraine Drupal - syncing your staging and live sitesMigraine Drupal - syncing your staging and live sites
Migraine Drupal - syncing your staging and live sitesdrupalindia
 
Scalable web application architecture
Scalable web application architectureScalable web application architecture
Scalable web application architecturepostrational
 
LvivPy - Flask in details
LvivPy - Flask in detailsLvivPy - Flask in details
LvivPy - Flask in detailsMax Klymyshyn
 
Writing Your Own WordPress Plugins - WordCamp Kansas City, 2014
Writing Your Own WordPress Plugins - WordCamp Kansas City, 2014Writing Your Own WordPress Plugins - WordCamp Kansas City, 2014
Writing Your Own WordPress Plugins - WordCamp Kansas City, 2014Pippin Williamson
 
Bugzilla Installation Process
Bugzilla Installation ProcessBugzilla Installation Process
Bugzilla Installation ProcessVino Harikrishnan
 
2. auto deploy to tomcat on jenkins
2. auto deploy to tomcat on jenkins2. auto deploy to tomcat on jenkins
2. auto deploy to tomcat on jenkinsHuang Bruce
 
Laravel - Website Development in Php Framework.
Laravel - Website Development in Php Framework.Laravel - Website Development in Php Framework.
Laravel - Website Development in Php Framework.SWAAM Tech
 
Build and deploy Python Django project
Build and deploy Python Django projectBuild and deploy Python Django project
Build and deploy Python Django projectXiaoqi Zhao
 
Python Flask app deployed to OPenShift using Wercker CI
Python Flask app deployed to OPenShift using Wercker CIPython Flask app deployed to OPenShift using Wercker CI
Python Flask app deployed to OPenShift using Wercker CIBruno Rocha
 

What's hot (20)

Word press Plugins by WordPress Experts
Word press Plugins by WordPress ExpertsWord press Plugins by WordPress Experts
Word press Plugins by WordPress Experts
 
Laravel Forge: Hello World to Hello Production
Laravel Forge: Hello World to Hello ProductionLaravel Forge: Hello World to Hello Production
Laravel Forge: Hello World to Hello Production
 
You've Got Plugins in Your Plugins: Bundling Plugin Dependencies - Atlassian ...
You've Got Plugins in Your Plugins: Bundling Plugin Dependencies - Atlassian ...You've Got Plugins in Your Plugins: Bundling Plugin Dependencies - Atlassian ...
You've Got Plugins in Your Plugins: Bundling Plugin Dependencies - Atlassian ...
 
Developers, Be a Bada$$ with WP-CLI
Developers, Be a Bada$$ with WP-CLIDevelopers, Be a Bada$$ with WP-CLI
Developers, Be a Bada$$ with WP-CLI
 
Git setuplinux
Git setuplinuxGit setuplinux
Git setuplinux
 
Creating Your First WordPress Plugin
Creating Your First WordPress PluginCreating Your First WordPress Plugin
Creating Your First WordPress Plugin
 
Plug in development
Plug in developmentPlug in development
Plug in development
 
Behaviour Driven Development con Behat & Drupal
Behaviour Driven Development con Behat & DrupalBehaviour Driven Development con Behat & Drupal
Behaviour Driven Development con Behat & Drupal
 
Installing AtoM with Ansible
Installing AtoM with AnsibleInstalling AtoM with Ansible
Installing AtoM with Ansible
 
Flask
FlaskFlask
Flask
 
Session on Selenium Powertools by Unmesh Gundecha
Session on Selenium Powertools by Unmesh GundechaSession on Selenium Powertools by Unmesh Gundecha
Session on Selenium Powertools by Unmesh Gundecha
 
Migraine Drupal - syncing your staging and live sites
Migraine Drupal - syncing your staging and live sitesMigraine Drupal - syncing your staging and live sites
Migraine Drupal - syncing your staging and live sites
 
Scalable web application architecture
Scalable web application architectureScalable web application architecture
Scalable web application architecture
 
LvivPy - Flask in details
LvivPy - Flask in detailsLvivPy - Flask in details
LvivPy - Flask in details
 
Writing Your Own WordPress Plugins - WordCamp Kansas City, 2014
Writing Your Own WordPress Plugins - WordCamp Kansas City, 2014Writing Your Own WordPress Plugins - WordCamp Kansas City, 2014
Writing Your Own WordPress Plugins - WordCamp Kansas City, 2014
 
Bugzilla Installation Process
Bugzilla Installation ProcessBugzilla Installation Process
Bugzilla Installation Process
 
2. auto deploy to tomcat on jenkins
2. auto deploy to tomcat on jenkins2. auto deploy to tomcat on jenkins
2. auto deploy to tomcat on jenkins
 
Laravel - Website Development in Php Framework.
Laravel - Website Development in Php Framework.Laravel - Website Development in Php Framework.
Laravel - Website Development in Php Framework.
 
Build and deploy Python Django project
Build and deploy Python Django projectBuild and deploy Python Django project
Build and deploy Python Django project
 
Python Flask app deployed to OPenShift using Wercker CI
Python Flask app deployed to OPenShift using Wercker CIPython Flask app deployed to OPenShift using Wercker CI
Python Flask app deployed to OPenShift using Wercker CI
 

Viewers also liked

Flipkart Finds Frugal Ways To Save Costs
Flipkart Finds Frugal Ways To Save CostsFlipkart Finds Frugal Ways To Save Costs
Flipkart Finds Frugal Ways To Save CostseTailing India
 
Posibilidades del ajedrez educativo como recurso innovador
Posibilidades del ajedrez educativo como recurso innovadorPosibilidades del ajedrez educativo como recurso innovador
Posibilidades del ajedrez educativo como recurso innovadordim-edu
 
Sharing knowledge between open cities: how can we start today?
Sharing knowledge between open cities: how can we start today?Sharing knowledge between open cities: how can we start today?
Sharing knowledge between open cities: how can we start today?Open Knowledge Belgium
 
Τα οφέλη του τέννις στην υγεία
Τα οφέλη του τέννις στην υγεία Τα οφέλη του τέννις στην υγεία
Τα οφέλη του τέννις στην υγεία Natalie_N
 
Women empowerment
Women empowermentWomen empowerment
Women empowermentridadoll
 
Alfresco 5.2 REST API
Alfresco 5.2 REST APIAlfresco 5.2 REST API
Alfresco 5.2 REST APIJ V
 
γιορκι καιτη
γιορκι καιτηγιορκι καιτη
γιορκι καιτηtigapiga
 

Viewers also liked (12)

International Women's Day 2017: Be Bold For Change!
International Women's Day 2017: Be Bold For Change!International Women's Day 2017: Be Bold For Change!
International Women's Day 2017: Be Bold For Change!
 
Flipkart Finds Frugal Ways To Save Costs
Flipkart Finds Frugal Ways To Save CostsFlipkart Finds Frugal Ways To Save Costs
Flipkart Finds Frugal Ways To Save Costs
 
Posibilidades del ajedrez educativo como recurso innovador
Posibilidades del ajedrez educativo como recurso innovadorPosibilidades del ajedrez educativo como recurso innovador
Posibilidades del ajedrez educativo como recurso innovador
 
Sharing knowledge between open cities: how can we start today?
Sharing knowledge between open cities: how can we start today?Sharing knowledge between open cities: how can we start today?
Sharing knowledge between open cities: how can we start today?
 
strategi pem
strategi pemstrategi pem
strategi pem
 
мама
мамамама
мама
 
Τα οφέλη του τέννις στην υγεία
Τα οφέλη του τέννις στην υγεία Τα οφέλη του τέννις στην υγεία
Τα οφέλη του τέννις στην υγεία
 
Women empowerment
Women empowermentWomen empowerment
Women empowerment
 
Кожушко
КожушкоКожушко
Кожушко
 
Alfresco 5.2 REST API
Alfresco 5.2 REST APIAlfresco 5.2 REST API
Alfresco 5.2 REST API
 
Fabric cutting
Fabric cuttingFabric cutting
Fabric cutting
 
γιορκι καιτη
γιορκι καιτηγιορκι καιτη
γιορκι καιτη
 

Similar to ADF in action 1.2

Tutorial 1: Your First Science App - Araport Developer Workshop
Tutorial 1: Your First Science App - Araport Developer WorkshopTutorial 1: Your First Science App - Araport Developer Workshop
Tutorial 1: Your First Science App - Araport Developer WorkshopVivek Krishnakumar
 
Alfresco Development Framework Basic
Alfresco Development Framework BasicAlfresco Development Framework Basic
Alfresco Development Framework BasicMario Romano
 
Jenkins Pipelines Advanced
Jenkins Pipelines AdvancedJenkins Pipelines Advanced
Jenkins Pipelines AdvancedOliver Lemm
 
Distributing UI Libraries: in a post Web-Component world
Distributing UI Libraries: in a post Web-Component worldDistributing UI Libraries: in a post Web-Component world
Distributing UI Libraries: in a post Web-Component worldRachael L Moore
 
MobileConf 2021 Slides: Let's build macOS CLI Utilities using Swift
MobileConf 2021 Slides:  Let's build macOS CLI Utilities using SwiftMobileConf 2021 Slides:  Let's build macOS CLI Utilities using Swift
MobileConf 2021 Slides: Let's build macOS CLI Utilities using SwiftDiego Freniche Brito
 
Let's build Developer Portal with Backstage
Let's build Developer Portal with BackstageLet's build Developer Portal with Backstage
Let's build Developer Portal with BackstageOpsta
 
Advanced Eclipse Workshop (held at IPC2010 -spring edition-)
Advanced Eclipse Workshop (held at IPC2010 -spring edition-)Advanced Eclipse Workshop (held at IPC2010 -spring edition-)
Advanced Eclipse Workshop (held at IPC2010 -spring edition-)Bastian Feder
 
How to Implement Micro Frontend Architecture using Angular Framework
How to Implement Micro Frontend Architecture using Angular FrameworkHow to Implement Micro Frontend Architecture using Angular Framework
How to Implement Micro Frontend Architecture using Angular FrameworkRapidValue
 
Extend Eclipse p2 framework capabilities: Add your custom installation steps
Extend Eclipse p2 framework capabilities: Add your custom installation stepsExtend Eclipse p2 framework capabilities: Add your custom installation steps
Extend Eclipse p2 framework capabilities: Add your custom installation stepsDragos_Mihailescu
 
An introduction to maven gradle and sbt
An introduction to maven gradle and sbtAn introduction to maven gradle and sbt
An introduction to maven gradle and sbtFabio Fumarola
 
anugula2setupbyshubham
anugula2setupbyshubhamanugula2setupbyshubham
anugula2setupbyshubhamShubham Verma
 
Adopt DevOps philosophy on your Symfony projects (Symfony Live 2011)
Adopt DevOps philosophy on your Symfony projects (Symfony Live 2011)Adopt DevOps philosophy on your Symfony projects (Symfony Live 2011)
Adopt DevOps philosophy on your Symfony projects (Symfony Live 2011)Fabrice Bernhard
 
5 年後還是新手 - WordPress Plugin 開發大冒險 - GOTY
5 年後還是新手 - WordPress Plugin 開發大冒險 - GOTY5 年後還是新手 - WordPress Plugin 開發大冒險 - GOTY
5 年後還是新手 - WordPress Plugin 開發大冒險 - GOTYWilliam Chong
 
HotPush with Ionic 2 and CodePush
HotPush with Ionic 2 and CodePushHotPush with Ionic 2 and CodePush
HotPush with Ionic 2 and CodePushEvan Schultz
 
Fullstack workshop
Fullstack workshopFullstack workshop
Fullstack workshopAssaf Gannon
 
Spinnaker Summit 2018: CI/CD Patterns for Kubernetes with Spinnaker
Spinnaker Summit 2018: CI/CD Patterns for Kubernetes with SpinnakerSpinnaker Summit 2018: CI/CD Patterns for Kubernetes with Spinnaker
Spinnaker Summit 2018: CI/CD Patterns for Kubernetes with SpinnakerAndrew Phillips
 
Angular 2 Migration - JHipster Meetup 6
Angular 2 Migration - JHipster Meetup 6Angular 2 Migration - JHipster Meetup 6
Angular 2 Migration - JHipster Meetup 6William Marques
 
Django dev-env-my-way
Django dev-env-my-wayDjango dev-env-my-way
Django dev-env-my-wayRobert Lujo
 
Let's play with adf 3.0
Let's play with adf 3.0Let's play with adf 3.0
Let's play with adf 3.0Eugenio Romano
 

Similar to ADF in action 1.2 (20)

Tutorial 1: Your First Science App - Araport Developer Workshop
Tutorial 1: Your First Science App - Araport Developer WorkshopTutorial 1: Your First Science App - Araport Developer Workshop
Tutorial 1: Your First Science App - Araport Developer Workshop
 
Alfresco Development Framework Basic
Alfresco Development Framework BasicAlfresco Development Framework Basic
Alfresco Development Framework Basic
 
Jenkins Pipelines Advanced
Jenkins Pipelines AdvancedJenkins Pipelines Advanced
Jenkins Pipelines Advanced
 
Distributing UI Libraries: in a post Web-Component world
Distributing UI Libraries: in a post Web-Component worldDistributing UI Libraries: in a post Web-Component world
Distributing UI Libraries: in a post Web-Component world
 
An Overview of Angular 4
An Overview of Angular 4 An Overview of Angular 4
An Overview of Angular 4
 
MobileConf 2021 Slides: Let's build macOS CLI Utilities using Swift
MobileConf 2021 Slides:  Let's build macOS CLI Utilities using SwiftMobileConf 2021 Slides:  Let's build macOS CLI Utilities using Swift
MobileConf 2021 Slides: Let's build macOS CLI Utilities using Swift
 
Let's build Developer Portal with Backstage
Let's build Developer Portal with BackstageLet's build Developer Portal with Backstage
Let's build Developer Portal with Backstage
 
Advanced Eclipse Workshop (held at IPC2010 -spring edition-)
Advanced Eclipse Workshop (held at IPC2010 -spring edition-)Advanced Eclipse Workshop (held at IPC2010 -spring edition-)
Advanced Eclipse Workshop (held at IPC2010 -spring edition-)
 
How to Implement Micro Frontend Architecture using Angular Framework
How to Implement Micro Frontend Architecture using Angular FrameworkHow to Implement Micro Frontend Architecture using Angular Framework
How to Implement Micro Frontend Architecture using Angular Framework
 
Extend Eclipse p2 framework capabilities: Add your custom installation steps
Extend Eclipse p2 framework capabilities: Add your custom installation stepsExtend Eclipse p2 framework capabilities: Add your custom installation steps
Extend Eclipse p2 framework capabilities: Add your custom installation steps
 
An introduction to maven gradle and sbt
An introduction to maven gradle and sbtAn introduction to maven gradle and sbt
An introduction to maven gradle and sbt
 
anugula2setupbyshubham
anugula2setupbyshubhamanugula2setupbyshubham
anugula2setupbyshubham
 
Adopt DevOps philosophy on your Symfony projects (Symfony Live 2011)
Adopt DevOps philosophy on your Symfony projects (Symfony Live 2011)Adopt DevOps philosophy on your Symfony projects (Symfony Live 2011)
Adopt DevOps philosophy on your Symfony projects (Symfony Live 2011)
 
5 年後還是新手 - WordPress Plugin 開發大冒險 - GOTY
5 年後還是新手 - WordPress Plugin 開發大冒險 - GOTY5 年後還是新手 - WordPress Plugin 開發大冒險 - GOTY
5 年後還是新手 - WordPress Plugin 開發大冒險 - GOTY
 
HotPush with Ionic 2 and CodePush
HotPush with Ionic 2 and CodePushHotPush with Ionic 2 and CodePush
HotPush with Ionic 2 and CodePush
 
Fullstack workshop
Fullstack workshopFullstack workshop
Fullstack workshop
 
Spinnaker Summit 2018: CI/CD Patterns for Kubernetes with Spinnaker
Spinnaker Summit 2018: CI/CD Patterns for Kubernetes with SpinnakerSpinnaker Summit 2018: CI/CD Patterns for Kubernetes with Spinnaker
Spinnaker Summit 2018: CI/CD Patterns for Kubernetes with Spinnaker
 
Angular 2 Migration - JHipster Meetup 6
Angular 2 Migration - JHipster Meetup 6Angular 2 Migration - JHipster Meetup 6
Angular 2 Migration - JHipster Meetup 6
 
Django dev-env-my-way
Django dev-env-my-wayDjango dev-env-my-way
Django dev-env-my-way
 
Let's play with adf 3.0
Let's play with adf 3.0Let's play with adf 3.0
Let's play with adf 3.0
 

Recently uploaded

Automate your Kamailio Test Calls - Kamailio World 2024
Automate your Kamailio Test Calls - Kamailio World 2024Automate your Kamailio Test Calls - Kamailio World 2024
Automate your Kamailio Test Calls - Kamailio World 2024Andreas Granig
 
Der Spagat zwischen BIAS und FAIRNESS (2024)
Der Spagat zwischen BIAS und FAIRNESS (2024)Der Spagat zwischen BIAS und FAIRNESS (2024)
Der Spagat zwischen BIAS und FAIRNESS (2024)OPEN KNOWLEDGE GmbH
 
Software Project Health Check: Best Practices and Techniques for Your Product...
Software Project Health Check: Best Practices and Techniques for Your Product...Software Project Health Check: Best Practices and Techniques for Your Product...
Software Project Health Check: Best Practices and Techniques for Your Product...Velvetech LLC
 
Unveiling the Future: Sylius 2.0 New Features
Unveiling the Future: Sylius 2.0 New FeaturesUnveiling the Future: Sylius 2.0 New Features
Unveiling the Future: Sylius 2.0 New FeaturesŁukasz Chruściel
 
Open Source Summit NA 2024: Open Source Cloud Costs - OpenCost's Impact on En...
Open Source Summit NA 2024: Open Source Cloud Costs - OpenCost's Impact on En...Open Source Summit NA 2024: Open Source Cloud Costs - OpenCost's Impact on En...
Open Source Summit NA 2024: Open Source Cloud Costs - OpenCost's Impact on En...Matt Ray
 
EY_Graph Database Powered Sustainability
EY_Graph Database Powered SustainabilityEY_Graph Database Powered Sustainability
EY_Graph Database Powered SustainabilityNeo4j
 
Alluxio Monthly Webinar | Cloud-Native Model Training on Distributed Data
Alluxio Monthly Webinar | Cloud-Native Model Training on Distributed DataAlluxio Monthly Webinar | Cloud-Native Model Training on Distributed Data
Alluxio Monthly Webinar | Cloud-Native Model Training on Distributed DataAlluxio, Inc.
 
Cloud Data Center Network Construction - IEEE
Cloud Data Center Network Construction - IEEECloud Data Center Network Construction - IEEE
Cloud Data Center Network Construction - IEEEVICTOR MAESTRE RAMIREZ
 
Building Real-Time Data Pipelines: Stream & Batch Processing workshop Slide
Building Real-Time Data Pipelines: Stream & Batch Processing workshop SlideBuilding Real-Time Data Pipelines: Stream & Batch Processing workshop Slide
Building Real-Time Data Pipelines: Stream & Batch Processing workshop SlideChristina Lin
 
Dealing with Cultural Dispersion — Stefano Lambiase — ICSE-SEIS 2024
Dealing with Cultural Dispersion — Stefano Lambiase — ICSE-SEIS 2024Dealing with Cultural Dispersion — Stefano Lambiase — ICSE-SEIS 2024
Dealing with Cultural Dispersion — Stefano Lambiase — ICSE-SEIS 2024StefanoLambiase
 
BATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASE
BATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASEBATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASE
BATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASEOrtus Solutions, Corp
 
办理学位证(UQ文凭证书)昆士兰大学毕业证成绩单原版一模一样
办理学位证(UQ文凭证书)昆士兰大学毕业证成绩单原版一模一样办理学位证(UQ文凭证书)昆士兰大学毕业证成绩单原版一模一样
办理学位证(UQ文凭证书)昆士兰大学毕业证成绩单原版一模一样umasea
 
CRM Contender Series: HubSpot vs. Salesforce
CRM Contender Series: HubSpot vs. SalesforceCRM Contender Series: HubSpot vs. Salesforce
CRM Contender Series: HubSpot vs. SalesforceBrainSell Technologies
 
Cloud Management Software Platforms: OpenStack
Cloud Management Software Platforms: OpenStackCloud Management Software Platforms: OpenStack
Cloud Management Software Platforms: OpenStackVICTOR MAESTRE RAMIREZ
 
Buds n Tech IT Solutions: Top-Notch Web Services in Noida
Buds n Tech IT Solutions: Top-Notch Web Services in NoidaBuds n Tech IT Solutions: Top-Notch Web Services in Noida
Buds n Tech IT Solutions: Top-Notch Web Services in Noidabntitsolutionsrishis
 
What is Advanced Excel and what are some best practices for designing and cre...
What is Advanced Excel and what are some best practices for designing and cre...What is Advanced Excel and what are some best practices for designing and cre...
What is Advanced Excel and what are some best practices for designing and cre...Technogeeks
 
英国UN学位证,北安普顿大学毕业证书1:1制作
英国UN学位证,北安普顿大学毕业证书1:1制作英国UN学位证,北安普顿大学毕业证书1:1制作
英国UN学位证,北安普顿大学毕业证书1:1制作qr0udbr0
 
Introduction Computer Science - Software Design.pdf
Introduction Computer Science - Software Design.pdfIntroduction Computer Science - Software Design.pdf
Introduction Computer Science - Software Design.pdfFerryKemperman
 
How to Track Employee Performance A Comprehensive Guide.pdf
How to Track Employee Performance A Comprehensive Guide.pdfHow to Track Employee Performance A Comprehensive Guide.pdf
How to Track Employee Performance A Comprehensive Guide.pdfLivetecs LLC
 

Recently uploaded (20)

Automate your Kamailio Test Calls - Kamailio World 2024
Automate your Kamailio Test Calls - Kamailio World 2024Automate your Kamailio Test Calls - Kamailio World 2024
Automate your Kamailio Test Calls - Kamailio World 2024
 
Der Spagat zwischen BIAS und FAIRNESS (2024)
Der Spagat zwischen BIAS und FAIRNESS (2024)Der Spagat zwischen BIAS und FAIRNESS (2024)
Der Spagat zwischen BIAS und FAIRNESS (2024)
 
Software Project Health Check: Best Practices and Techniques for Your Product...
Software Project Health Check: Best Practices and Techniques for Your Product...Software Project Health Check: Best Practices and Techniques for Your Product...
Software Project Health Check: Best Practices and Techniques for Your Product...
 
Unveiling the Future: Sylius 2.0 New Features
Unveiling the Future: Sylius 2.0 New FeaturesUnveiling the Future: Sylius 2.0 New Features
Unveiling the Future: Sylius 2.0 New Features
 
Open Source Summit NA 2024: Open Source Cloud Costs - OpenCost's Impact on En...
Open Source Summit NA 2024: Open Source Cloud Costs - OpenCost's Impact on En...Open Source Summit NA 2024: Open Source Cloud Costs - OpenCost's Impact on En...
Open Source Summit NA 2024: Open Source Cloud Costs - OpenCost's Impact on En...
 
2.pdf Ejercicios de programación competitiva
2.pdf Ejercicios de programación competitiva2.pdf Ejercicios de programación competitiva
2.pdf Ejercicios de programación competitiva
 
EY_Graph Database Powered Sustainability
EY_Graph Database Powered SustainabilityEY_Graph Database Powered Sustainability
EY_Graph Database Powered Sustainability
 
Alluxio Monthly Webinar | Cloud-Native Model Training on Distributed Data
Alluxio Monthly Webinar | Cloud-Native Model Training on Distributed DataAlluxio Monthly Webinar | Cloud-Native Model Training on Distributed Data
Alluxio Monthly Webinar | Cloud-Native Model Training on Distributed Data
 
Cloud Data Center Network Construction - IEEE
Cloud Data Center Network Construction - IEEECloud Data Center Network Construction - IEEE
Cloud Data Center Network Construction - IEEE
 
Building Real-Time Data Pipelines: Stream & Batch Processing workshop Slide
Building Real-Time Data Pipelines: Stream & Batch Processing workshop SlideBuilding Real-Time Data Pipelines: Stream & Batch Processing workshop Slide
Building Real-Time Data Pipelines: Stream & Batch Processing workshop Slide
 
Dealing with Cultural Dispersion — Stefano Lambiase — ICSE-SEIS 2024
Dealing with Cultural Dispersion — Stefano Lambiase — ICSE-SEIS 2024Dealing with Cultural Dispersion — Stefano Lambiase — ICSE-SEIS 2024
Dealing with Cultural Dispersion — Stefano Lambiase — ICSE-SEIS 2024
 
BATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASE
BATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASEBATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASE
BATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASE
 
办理学位证(UQ文凭证书)昆士兰大学毕业证成绩单原版一模一样
办理学位证(UQ文凭证书)昆士兰大学毕业证成绩单原版一模一样办理学位证(UQ文凭证书)昆士兰大学毕业证成绩单原版一模一样
办理学位证(UQ文凭证书)昆士兰大学毕业证成绩单原版一模一样
 
CRM Contender Series: HubSpot vs. Salesforce
CRM Contender Series: HubSpot vs. SalesforceCRM Contender Series: HubSpot vs. Salesforce
CRM Contender Series: HubSpot vs. Salesforce
 
Cloud Management Software Platforms: OpenStack
Cloud Management Software Platforms: OpenStackCloud Management Software Platforms: OpenStack
Cloud Management Software Platforms: OpenStack
 
Buds n Tech IT Solutions: Top-Notch Web Services in Noida
Buds n Tech IT Solutions: Top-Notch Web Services in NoidaBuds n Tech IT Solutions: Top-Notch Web Services in Noida
Buds n Tech IT Solutions: Top-Notch Web Services in Noida
 
What is Advanced Excel and what are some best practices for designing and cre...
What is Advanced Excel and what are some best practices for designing and cre...What is Advanced Excel and what are some best practices for designing and cre...
What is Advanced Excel and what are some best practices for designing and cre...
 
英国UN学位证,北安普顿大学毕业证书1:1制作
英国UN学位证,北安普顿大学毕业证书1:1制作英国UN学位证,北安普顿大学毕业证书1:1制作
英国UN学位证,北安普顿大学毕业证书1:1制作
 
Introduction Computer Science - Software Design.pdf
Introduction Computer Science - Software Design.pdfIntroduction Computer Science - Software Design.pdf
Introduction Computer Science - Software Design.pdf
 
How to Track Employee Performance A Comprehensive Guide.pdf
How to Track Employee Performance A Comprehensive Guide.pdfHow to Track Employee Performance A Comprehensive Guide.pdf
How to Track Employee Performance A Comprehensive Guide.pdf
 

ADF in action 1.2

  • 1. How to customize ADF 1.2 Eugenio Romano
  • 2. Eugenio Romano Senior Software Engineer Alfresco https://twitter.com/RomanoEugenio https://github.com/eromano eugenio.romano@alfresco.com Open-source contributor (Activiti, ADF, Alfresco-js-api, etc.)
  • 3. Agenda 1. Intro ADF 2. Customize Document List 3. Customize Viewer 4. Customize Login
  • 4. ADF 1.2 IS HERE Monday 27 February we released : • ADF 1.2 • Alfresco-js-api 1.2 What is new: https://github.com/Alfresco/alfresco-js- api/releases/tag/1.2.0 https://github.com/Alfresco/alfresco- ng2-components/releases/tag/1.2.0
  • 5. • https://github.com/eromano/customize-alfresco-adf-app-examples Github repo with all the examples Generator scaffolder for ADF app Resources Generator scaffolder for ADF Components • https://github.com/Alfresco/generator-ng2-alfresco-component • https://github.com/Alfresco/generator-ng2-alfresco-app
  • 6. Technology Angular 2 • One of the big ideas behind Angular is the concept of components. • When you create a component, essentially you create a new tag <my-new-tag> this tag is reusable everywhere. we will teach the browser new tags that have custom functionality. • Components are self contained and by their nature, promote the separation of concern. So they are easy to test it. EASY TO TEST
  • 7. Technology TYPESCRIPT • ADF is built in a Javascript-like language called TypeScript. • There are a lot of great reasons to use TypeScript instead of plain Javascript. • TypeScript isn’t a completely new language, it’s a superset of ES6. There are a lot of good thing in using TypeScript instead plain javscript : • Types • Classes • Annotations • Imports
  • 8. Technology YEOMAN Yeoman is a tool which helps you to kickstart new projects. With Yeoman you can share your ideas and best practices with others by creating a scaffold. With Yeoman you can improve your productivity and not waste time when starting a project. • Speed up the startup development time. • Have common tools: style, build, test, syntax checker and deploy. • Standardize the developer experience across all components. • Enforce rules about quality and code contributions.
  • 10. Document list utility links https://github.com/Alfresco/alfresco-ng2-components/tree/master/ng2- components/ng2-alfresco-documentlist https://github.com/Alfresco/alfresco-ng2-components/tree/master/ng2- components/ng2-alfresco-documentlist/demo Document list documentation Document list demo
  • 11. Standard Document List let’s customize Goal of this customization: • Add a new column with the the file version
  • 12. Create the customize-app https://github.com/Alfresco/generator-ng2-alfresco-app Install the Alfresco generator component scaffolder following the instruction in the readme : • yo ng2-alfresco-app • Provide the name of the app: customize-app • Go in the appfolder • Run npm install Let's create your customize-app app Now your scaffolder is complete let’s add some code:
  • 13. Custom Columns How to show file version Open the files.component.html and add the HTML snippet: <content-column title="version" key="name" sortable="true" class="full-width ellipsis-cell"> <template let-context="$implicit"> <div>V.{{context.row.getValue('properties.cm:versionLabel')}}</div> </template> </content-column>
  • 14. Custom Columns Show the file version Hide empty value <div *ngIf="context.row.getValue('properties.cm:versionLabel')"> V.{{context.row.getValue('properties.cm:versionLabel')}} </div> The ngIf directive removes or recreates a portion of the DOM tree based on an {expression}. If the expression assigned to ngIf evaluates to a false value then the element is removed from the DOM, otherwise a clone of the element is reinserted into the DOM.
  • 15. <div *ngIf="context.row.getValue('properties.cm:versionLabel')" class="version-style"> V.{{context.row.getValue('properties.cm:versionLabel')}} </div> files.component.css Add some style .version-style { width: 46px; text-align: center; border-radius: 15px; background: rgb(31, 188, 210); color: white; } Custom Columns Show the file version with style
  • 16. Create our first component https://github.com/Alfresco/generator-ng2-alfresco-component • yo ng2-alfresco-component • Go in the component folder and run npm install Let's create your ng2-alfresco-version-badge Follow the instruction in the readme of the project to install the generator Let’s create our very first component. When we have this component written, we will be able to use it in our HTML
  • 17. import { Component, Input } from '@angular/core'; @Component({ selector: 'ng2-alfresco-version-badge', styles: [`.badge-style { width: 46px; text-align: center; border-radius: 15px; background: rgb(31, 188, 210); color: white;}`], template: ` <div *ngIf="version" class=”badge-style"> V.{{version}} </div>`}) export class Ng2AlfrescoVersionBadgeComponent { @Input() version: string; } Open ng2-alfresco-version-badge and add the pieces of code that we have done before to create the custom column Component version badge Code
  • 18. <content-column title="version" key="name" sortable="true" class="full-width ellipsis-cell"> <template let-context="$implicit"> <ng2-alfresco-version-badge [version]="context.row.getValue('properties.cm:versionLabel')"> </ng2-alfresco-version-badge> </template> </content-column> Custom Columns with custom component • Import the new component dependency in the app.module.ts import { Ng2AlfrescoVersionBadgeModule } from 'ng2-alfresco-version-badge'; • Add the new custom template with our component inside @NgModule({ imports: […, Ng2AlfrescoVersionBadgeModule, ….]
  • 19. Npm Link • Because our new component is not published yet we need a way to resolve this new component in the local environment Package linking is a two-step process. 1. run npm link in the package folder will create a globally link to “YOUR_PACAKGE” 2. Open the demo shell folder and run npm link YOUR_PACAKGE This is handy for installing your own stuff, so that you can work on it and test it before to publish it online
  • 20. Custom Columns with custom component change style :host >>> .badge-style { width: 46px; text-align: center; background: red; color: white; } We can use the /deep/ or the alias >>> selector to force a style down through the child component tree into all the child component views.
  • 23. Viewer file extensions How I Can handle other extension in the viewer? If you want handle other file formats that are not yet supported by the ng2-alfresco-viewer you can define your own custom handler. <extension-viewer [supportedExtensions]="['txt']" #extension> <template let-urlFileContent="urlFileContent" > <my-custom-txt-component urlFileContent="urlFileContent"></my-custom-txt- component> </template> </extension-viewer>
  • 24. Custom extension format viewer for zip files • yo ng2-alfresco-component • Provide the name of the component : ng2-alfresco-zip-viewer • Go in the component folder • Run npm install Let's create your ng2-alfresco-zip-viewer component Now your scaffolder is complete let’s add some code:
  • 25. • npm install jszip –save • npm install --save @types/jszip https://stuk.github.io/jszip/docu mentation/examples.html Add some library • Install jszip • Jszip documentation ngOnChanges() { this.http.get(this.urlFile, new RequestOptions({ responseType: ResponseContentType.ArrayBuffer })) .toPromise().then((res: Response) => { this.extractZipData(res); }); } private extractZipData(res: Response) { let newZip = new JSZip(); newZip.loadAsync(res.arrayBuffer()) .then((zip) => { this.zipFiles = Object.keys(zip.files).map((key) => { return zip.files[key]; }); }); }
  • 26. <table class="mdl-data-table mdl-js-data-table mdl-shadow--2dp"> <thead> <tr><th>Name</th></tr> </thead> <tbody> <tr *ngFor="let file of zipFiles; let idx = index"> <td class="mdl-data-table__cell--non-numeric">{{file.name}}</td> </tr> </tbody> </table> https://getmdl.io/components/index.html#tables-section Add a template In order to show the file list we can use the material design table: Template: Iterate with ngFor
  • 30. Standard Login let’s customize Goal of this customization: • Add a profile photo in the login page
  • 31. Customize login-demo.component.ts import { EcmUserService } from 'ng2-alfresco-userinfo'; onLogin($event) { this.getEcmUserInfo(); this.router.navigate(['/home']); } getEcmUserInfo(): void { this.ecmUserService.getCurrentUserInfo() .subscribe((res) => { let ecmUserImageUrl = this.ecmUserService.getUserProfileImage(res.avatarId); this.saveBase64FromImageUrl(ecmUserImageUrl); } ); } • Get the profile Photo using the EcmUserService of the ng2-alfresco-userinfo component.
  • 32. saveBase64FromImageUrl(url: string) { let img = new Image(); img.crossOrigin = 'Anonymous'; img.onload = ()=> { let canvas: any = document.createElement('CANVAS'); let ctx: any = canvas.getContext('2d'); canvas.height = '64'; canvas.width = '64'; ctx.drawImage(img, 0, 0); let dataURL = canvas.toDataURL(); this.storage.setItem('imageProfile', dataURL); canvas = null; }; img.src = url; } Save The profile Image in login-demo.component.ts • Save the photo in the local storage. • In order to save the photo we need to convert it in Base64
  • 33. <login-header> <template> <img class="login-profile-img" [src]="getProfileImageFromStorage()" /> </template> </login-header> .login-profile-img { margin: auto; border: 3px solid #ff9800; border-radius: 34px; width: 64px; } Viewer with profile image login-demo.component.html
  • 34. <login-header> <template> <img *ngIf="getProfileImageFromStorage()" class="login- profile-img” [src]="getProfileImageFromStorage()" /> <img *ngIf="!getProfileImageFromStorage()" class="login- profile-img" src="https://cdn.rawgit.com/Alfresco/alfresco- ng2-components/c13c3aae/ng2-components/ng2-alfresco- userinfo/src/assets/images/anonymous.gif"> </template> </login-header> Profile image and default image login-demo.component.html
  • 35. Where to get Info on ADF https://community.alfresco.com/community/application-development- framework/pages/get-started https://gitter.im/Alfresco/alfresco-ng2-components https://github.com/Alfresco/alfresco-ng2-components/ Community Web-Site Gitter Ghithub readme

Editor's Notes

  1. https://github.com/Alfresco/alfresco-js-api/blob/master/src/alfresco-core-rest-api/docs/NodesApi.md#getNode