gravitonian

Generating an app with Angular CLI and preparing it for use with ADF 1.9.0

Blog Post created by gravitonian Employee on Oct 16, 2017

Introduction 

This article is a deep dive into how an ADF application is configured, built, and run. Specifically for ADF version 1.9.0. It's very much a one-time-only type of read that you would do in the beginning of your first ADF project. It will mostly likely benefit you a lot in the long run to know what's in this article. When you are on top of the stuff in this article you would most likely use generators, or clone a GitHub project, when starting a new ADF project.  

Introduction to ADF

In this section we will look at what ADF really is.

Overview

The Alfresco Application Development Framework, referred to as ADF, is built on top of the Angular 4 JavaScript framework. You can think of ADF as a library of Alfresco web components that can be used to build a content management web application and/or a process management web application.

 

There are a number of web components that you can use to integrate your web application with Alfresco Content Services (ACS):

 

  • Folder Hierarchy Breadcrumbs - display a breadcrumb with clickable folder path
  • Document List - list folders and files
  • Search - search folders and files
  • Tag - manage and list tags
  • Upload - upload files via button or drag-and-drop
  • Viewer - preview files in the browser
  • Webscript - call a Web Script (i.e. a ReST call)

 

And for integrating with Alfresco Process Services (APS) you have the following components:

 

  • Analytics - display graph reports such as process instance overview
  • Diagram - show process definition diagram, if associated with running process instance then the activities are highlighted according to their state
  • Process Apps - shows a list of process applications
  • Process List - show a list of process instances
  • Process Details - multiple components are available to show different details for a process
  • Task List - show a list of task instances for a process instance(s)
  • Task Details - multiple components are available to show different details for a task

 

There are also a number of generic components that are used with both ACS and APS:

 

  • Toolbar - an extension to the Angular Material toolbar with a title and color
  • Card View - displays properties in a nice layout 
  • Data Table - generic data table implementation that is used by, for example, Document List
  • Drag-and-Drop - Drag and drop files into for example a folder
  • Form - display properties from nodes, tasks, and other sources in a form defined in JSON
  • Login - authenticates with both services
  • User Info - display information about a user

Architecture

These ADF components don’t talk directly to the ACS and APS backend services. There are some layers between them that are worth knowing about before you start hacking. The ADF components talk to ADF services, which in turn talks to the Alfresco JS API, which internally calls ACS and APS via their respective ReST APIs. You could use the both the ADF services and the Alfresco JS API directly from your application if there is no ADF component available to do what you want. In fact, you will quite frequently have to use the ADF services in your application to fetch content nodes, process instances, task instances etc.

 

The following picture illustrates the architecture of an ADF solution:

 

Alfresco ADF Architecture

The ADF components and services are implemented in Angular, which in turn is implemented in TypeScript. The Alfresco JavaScript library is pure JavaScript and could be used with any other JavaScript framework. 

Application Generator

Before we move on it is worth mentioning that there is an ADF application generator that can be very useful if you just want to quickly get going with an ADF project, such as for a demo or proof-of-concept scenario. It covers use cases for both ACS and APS. It can be used to generate the following types of ADF applications:

 

  • ADF Content Management App (use this template if your app is only going to talk to ACS)
  • ADF Process Management App (use this template if your app is only going to talk to APS)
  • ADF Content and Process Management App

 

On the other hand, if you want to know how to create an Angular CLI application from scratch, and how to set it up to work with ADF version 1.9.0. And you want to be able to pick and choose what ADF components to use, building your custom content and/or process management interface, then read on.

Make sure you use the latest 2.0.0* version of the ADF App Generator as older ones will generate an application that maybe has more features than you would like when starting out. When using the generator it should look something like this:

 

martins-macbook-pro:ADF mbergljung$ yo

? 'Allo Martin! What would you like to do? Ng2 Alfresco App

 

Make sure you are in the directory you want to scaffold into.

This generator can also be run with: yo ng2-alfresco-app

 

              ,****.          

         ,.**. `*****  <-_    

        ******** ***** ####   

       $********::**** ####; 

       _.-._`***::*** ###### 

     ,*******, *::* .;##### @

     **********,' -=#####',@@@

     ***' .,---, ,.-==@@@@@@@@

      * /@@@@@',@ @\ '@@@@@@@

       '@@@@/ @@@ @@@\ ':#'   

       !@@@@ @@@@ @@@@@@@@@^ 

        @@@@ @@@@@ @@@@@@@'   

         `"$ '@@@@@. '##'     

              '@@@@;'         

     

     ADF Angular app generator for Alfresco

        Version 2.0.0-beta1

                 

? Your project name ADF

? Application blueprint (Use arrow keys)

❯ Process Service and Content Service

  Content Service

  Process Service

 

If you don't see this, then you are running an older version of the generator. Try and install the beta version as follows:

 

martins-macbook-pro:ADF mbergljung$ npm install generator-ng2-alfresco-app@beta -g

Prerequisites

This article is written with the assumption that you are starting out from scratch with your ADF project and that you are new to ADF development. If you have worked with Angular before that would be good, but it is not absolutely necessary.

Source Code

The associated source code for this article can be found in this GitHub project. It is highly recommended that you have it available when walking through this tutorial. If for some reason you cannot get the code from this article working, then you can always go to the GitHub project for the source of truth.

 

Installing Alfresco Content and Process Services

In this section we will discuss how to install both ACS and APS so that we have them ready when working with any of the ADF components. You will need Alfresco Content Services version 5.2 or higher, Enterprise or Community edition. For APS you will need an Enterprise version 1.6 or higher (Activiti community edition is not yet supported). The reason you need these new versions is because the Alfresco JavaScript API wraps ReST APIs that require these versions.

If you intend to build a client that will only talk to an ACS server, then don’t install APS, and vice versa.

Installing Alfresco Content Services (ACS)

  1. Request an Enterprise trial from https://www.alfresco.com/platform/content-services-ecm/trial/download.
  2. Download the installer via the link in the email:
    If you are on a Mac then download Community installer from Download Alfresco Community ECM Now | Alfresco
    ACS Installer Email
  3. Start the installer and use admin as both the username and password.
  4. Start ACS (On Mac you can start using /Applications/alfresco-content-services/Application Manager, on Windows you can start using C:\alfresco-content-services5.2.1\manager-windows.exe).
  5. Verify that you can login to Alfresco Share with the username and password from http://localhost:8080/share

Installing Alfresco Process Services (APS)

  1. Download the installer from the link in the email (Step 1):APS Installer Email
  2. Request an Enterprise trial from https://www.alfresco.com/platform/process-services-bpm/trial/download.
  3. Download a trial license from the link in the above email (Step 2).
  4. Start the installer. At the end make a note of URLs and usernames:
  5. Put the downloaded license file into /Applications/alfresco-process-services170/tomcat/lib.
  6. Change port numbers (e.g. 8080) not to clash with ACS.
    Open up /Applications/alfresco-process-services170/tomcat/conf/server.xml and change 8005 -> 9005, 8080 - 9080, 8009 -> 9009.   
  7. Start APS (On Mac you can start using /Applications/alfresco-process-services170/StartProcessServices.app, on Windows you can start using C:\alfresco-process-services170\start-process-services.bat).
  8. Verify that you can login to Alfresco Process Services with the username and password from http://localhost:9080/activiti-app:

Configure username and password

If your ADF application is only going to talk to ACS, then you don’t have to complete this part, just use the ACS credentials as per installation (e.g. admin/admin).

For the ADF Login component to work properly with both services they need to have the same username and password available. It is also important to make sure that the user has proper permissions within the ACS repository, so files and folders can be managed from ADF applications. The same thing is true for the APS user, which needs to have access to the process applications that should be accessed from the ADF application.

 

It is common to use admin/admin as username/password for ACS. In APS we will have admin@app.activiti.com/admin set up by default. In APS the email address for a user is also used as the username. It is not possible to create a username such as admin in APS.

 

So let’s use admin@app.activiti.com/admin as username/password in both services, which means we need to set up a new user in ACS:

 

  1. Login to ACS at http://localhost:8080/share as admin/admin (or whatever password you specified when installing ACS).
  2. Click on the Admin Tools menu item.
  3. Click on the Users menu item in the left menu.
  4. Click on the New User button.
  5. Fill in the user info as follows:
  6. Make sure the username is admin@app.activiti.com and that the password is admin. Also, add the user to the ALFRESCO_ADMINISTRATORS group so it will have full access to the repository.
  7. Make sure you can login to ACS with the new user:

Installing ADF Prerequisites

Alfresco Application Development Framework (ADF) uses the Node.js JavaScript runtime and the npm package manager. So we need to make sure we have them installed with the correct versions. ADF version 1.9.0 requires Node.js version 8. When setting up an Angular project for ADF development it is recommended to use Angular CLI, so we will install that toolkit as well.

Installing Node.js

  1. Download from https://nodejs.org/en/download/, click the Current tab and then select a package based on architecture. I’m on MacOS, so selecting macOS installer (.pkg):
  1. Run the package installer
  2. When finished we should see (Note. you don't see this dialog on Windows):
  1. Test the installation and make sure you got node version >=8 and npm >=5:

Martins-MacBook-Pro:~ martin$ node -v

v8.6.0

Martins-MacBook-Pro:~ martin$ npm -v

5.4.2

Installing Angular CLI

Angular CLI is a Command Line Interface (CLI) to automate your development workflow when working with Angular applications. It allows you to:

 

  • Create a new Angular application
  • Run a development server with LiveReload support to preview your application during development
  • Add features to your existing Angular application, such as components and services
  • Run your application’s unit tests
  • Run your application’s end-to-end (E2E) tests
  • Build your application for deployment to production

 

To install Angular CLI, run:

 

Martins-MacBook-Pro:~ martin$ npm install -g @angular/cli

Which will install the ng command globally on your system.

On Mac/Linux you might have to run as root with sudo npm install...

On Windows you might have to open a Command prompt and run as Administrator.

Be prepared that installing Angular CLI might take some time...

To verify whether your installation completed successfully, you can run ng version:

 

Martins-MacBook-Pro:~ martin$ ng version

   _                      _                 ____ _     ___

  / \   _ __   __ _ _   _| | __ _ _ __     / ___| |   |_ _|

 / △ \ | '_ \ / _` | | | | |/ _` | '__|   | |   | |    | |

/ ___ \| | | | (_| | |_| | | (_| | |      | |___| |___ | |

/_/   \_\_| |_|\__, |\__,_|_|\__,_|_|       \____|_____|___|

              |___/

@angular/cli: 1.3.2

node: 8.6.0

os: darwin x64

 

Now that you have Angular CLI installed, let’s use it to create a new application that we can prepare for ADF development.

Generating an Angular app with Angular CLI

To create a new app you use the ng new <app-name> command. It will create a new directory with the app-name and generate all the needed files in it.

 

The app should support routing between different components (call them pages if you like), so we will add the --routing option. This creates a separate file src/app/app-routing.module.ts. The file includes an empty Routes object that you can fill with routes to different components (i.e. pages). Routing capabilities will come in handy when you start developing a more realistic application that contains multiple pages.

 

While executing the command stand in the directory where you want to create a subdirectory with the new application:

 

Martins-MacBook-Pro:ADF mbergljung$ ng new adf-workbench --routing

 create adf-workbench/README.md (1103 bytes)

 create adf-workbench/.angular-cli.json (1131 bytes)

 create adf-workbench/.editorconfig (245 bytes)

 create adf-workbench/.gitignore (516 bytes)

 create adf-workbench/src/assets/.gitkeep (0 bytes)

 create adf-workbench/src/environments/environment.prod.ts (51 bytes)

 create adf-workbench/src/environments/environment.ts (387 bytes)

 create adf-workbench/src/favicon.ico (5430 bytes)

 create adf-workbench/src/index.html (299 bytes)

 create adf-workbench/src/main.ts (370 bytes)

 create adf-workbench/src/polyfills.ts (2480 bytes)

 create adf-workbench/src/styles.css (80 bytes)

 create adf-workbench/src/test.ts (1085 bytes)

 create adf-workbench/src/tsconfig.app.json (211 bytes)

 create adf-workbench/src/tsconfig.spec.json (304 bytes)

 create adf-workbench/src/typings.d.ts (104 bytes)

 create adf-workbench/e2e/app.e2e-spec.ts (295 bytes)

 create adf-workbench/e2e/app.po.ts (208 bytes)

 create adf-workbench/e2e/tsconfig.e2e.json (235 bytes)

 create adf-workbench/karma.conf.js (923 bytes)

 create adf-workbench/package.json (1318 bytes)

 create adf-workbench/protractor.conf.js (722 bytes)

 create adf-workbench/tsconfig.json (363 bytes)

 create adf-workbench/tslint.json (3040 bytes)

 create adf-workbench/src/app/app-routing.module.ts (245 bytes)

 create adf-workbench/src/app/app.module.ts (393 bytes)

 create adf-workbench/src/app/app.component.css (0 bytes)

 create adf-workbench/src/app/app.component.html (1107 bytes)

 create adf-workbench/src/app/app.component.spec.ts (1103 bytes)

 create adf-workbench/src/app/app.component.ts (207 bytes)

Installing packages for tooling via npm.

Installed packages for tooling via npm.

Successfully initialized git.

Project 'adf-workbench' successfully created.

Be prepared that the 'Installing packages for tooling via npm' might take some time..., don't Ctrl-C out of it.

You can already see what files that have been created for the adf-workbench app. You can also list the directory to see what’s there:

 

Martins-MacBook-Pro:ADF mbergljung$ cd adf-workbench/

Martins-MacBook-Pro:adf-workbench mbergljung$ ls -l

total 656

-rw-r--r--    1 mbergljung  staff    1103 11 Oct 14:32 README.md

drwxr-xr-x    5 mbergljung  staff     170 11 Oct 14:32 e2e

-rw-r--r--    1 mbergljung  staff     923 11 Oct 14:32 karma.conf.js

drwxr-xr-x  758 mbergljung  staff   25772 11 Oct 14:32 node_modules

-rw-r--r--    1 mbergljung  staff  310433 11 Oct 14:32 package-lock.json

-rw-r--r--    1 mbergljung  staff    1318 11 Oct 14:32 package.json

-rw-r--r--    1 mbergljung  staff     722 11 Oct 14:32 protractor.conf.js

drwxr-xr-x   14 mbergljung  staff     476 11 Oct 14:32 src

-rw-r--r--    1 mbergljung  staff     363 11 Oct 14:32 tsconfig.json

-rw-r--r--    1 mbergljung  staff    3040 11 Oct 14:32 tslint.json

 

Behind the scenes, the following happens:

 

  • A new directory adf-workbench is created containing the new application.
  • The application is created with Angular version 4 runtime dependencies.
  • The application brings in TypeScript as a development dependency and configures it for you.
  • All source files and directories for the new Angular application are created based on the name we specified (adf-workbench) and best practices from the official Angular Style Guide.
  • npm dependencies are installed, which means that all dependencies that are specified by default in package.json are downloaded and installed in the local app node_modules directory. This is why it might take a bit of time before the command is finished. However, with Node.js 8 this should be really fast when you have used it for a while.
  • Karma unit test runner is configured for you.
  • Protractor end-to-end test framework is configured for you.
  • Environment files with default settings are created.
  • Git is initialized (i.e. git init) so whenever you start changing or adding stuff, it will be tracked by git.

 

Let's quickly run through and explain what most of these directories and files mean:

 

  • dist Production or Development builds of our application go here. This directory is not yet there, but will be when you build.
  • src - Application code goes here.
  • src/appOut-of-the-box you get the main app module and component that is bootstrapped with the platformBrowserDynamic bootstrapper. You would typically continue to add modules, components, services etc under the app directory. And then include them in the AppModule.
  • src/assets -  Images and app configuration files. 
  • src/environments - Settings for the different environments, dev, qa, prod.
  • src/index.html - Angular apps are so called Single Page Apps (SPA), this is the single HTML page.
  • src/main.ts - Main application entry point where the AppModule is bootstrapped.
  • src/polyfills.tsA polyfill is a browser fallback, made in JavaScript, that allows functionality you expect to work in modern browsers to work in older browsers. This file contains polyfills for features in ES6 and ES7 not yet supported by browsers.
  • src/styles.css - Global styles file, put stuff here that you want to use in many different components.
  • src/test.ts - Prepares the test environment and runs all the unit tests.
  • src/tsconfig.app.json - Typescript configuration file for the Angular App.
  • src/typings.d.ts - Typescript type definition file.
  • e2e - The End-2-End functional tests for the application goes here.
  • angular-cli.json - Main Angular CLI config file, also serves as Webpack configuration.
  • karma.conf.js - Unit test runner configuration.
  • package.json - Runtime and development dependency declarations. This is also where scripts are defined. Semver is used to specify version numbers for dependencies. We are going to update this file in this article to use exact versions. Basically locking down exactly what library versions the app is using.
  • package-lock.json - This file is used to lock down dependency versions for the whole dependency tree. The dependencies in package.json are what is called direct dependencies. They in turn depend on other libraries (transitive dependencies). With this file we lock down also transitive dependency versions.
  • protractor.conf.js - End-to-End test runner configuration.
  • tsconfig.json - TypeScript configuration on the root level is used for IDE integration.
  • tslint.json -  Lint configuration for TypeScript code checks.

 

It is preferred to work with the Angular application from a JavaScript IDE such as Visual Studio Code (Open Source) or WebStorm (Paid):

 

Running the App in Development Mode

The basic app module and app component have been generated, so you should now be able to run the app from the adf-workbench directory with the ng serve command:

 

Martins-MacBook-Pro:adf-workbench mbergljung$ ng serve

** NG Live Development Server is listening on localhost:4200, open your browser on http://localhost:4200/ **

Date: 2017-10-11T13:39:42.302Z                                                          

Hash: 7dc0622284b0b56b69da

Time: 6149ms

chunk {inline} inline.bundle.js, inline.bundle.js.map (inline) 5.83 kB [entry] [rendered]

chunk {main} main.bundle.js, main.bundle.js.map (main) 10.5 kB {vendor} [initial] [rendered]

chunk {polyfills} polyfills.bundle.js, polyfills.bundle.js.map (polyfills) 217 kB {inline} [initial] [rendered]

chunk {styles} styles.bundle.js, styles.bundle.js.map (styles) 11.3 kB {inline} [initial] [rendered]

chunk {vendor} vendor.bundle.js, vendor.bundle.js.map (vendor) 2.61 MB [initial] [rendered]

 

webpack: Compiled successfully.

 

Access the app from a browser via http://localhost:4200:

 

 

Not much to brag about, but it is a starting point!

 

Behind the scenes, the following happens:

 

  1. Angular CLI loads its configuration from .angular-cli.json
  2. And runs Webpack to build and bundle all JavaScript and CSS code
  3. And starts webpack dev server to preview the result on localhost:4200

 

Notice that the ng serve command does not exit and return to your terminal prompt after step 3. Instead, because it includes LiveReload support, the process actively watches your src directory for file changes. When a file change is detected, step 2 is repeated and a notification is sent to your browser so it can refresh automatically.

 

This also means that if you make any changes to stuff outside the src/ directory, such as .angular-cli.json, then you need to restart the server for them to take effect.

 

To stop the process and return to your prompt, press ctrl-c.

Angular CLI is tightly integrated with Webpack, so you will for example not see a webpack.config.js file in the same directory as package.json. Instead all config for things like webapp assets are done in Angular CLI’s config file, .angular-cli.json.

Introduction to Webpack

You might be wondering what Webpack is. It's an open-source module bundler for JavaScript applications. When Webpack processes your application, it recursively builds a dependency graph that includes every module your application needs, then packages all of those modules into a small number of bundles to be loaded by the browser. 

 

Webpack is a very powerful module bundler. A bundle is a JavaScript file that incorporates assets that belong together and should be served to the client in a response to a single file request. A bundle can include JavaScript, CSS styles, HTML, and almost any other kind of file.

 

Webpack scans your application source code, looking for import statements (e.g. import { Component } from '@angular/core';), building a dependency graph, and emitting one or more bundles. With plugins and rules, Webpack can preprocess and minify different non-JavaScript files such as TypeScript, SASS, and LESS files.

 

You determine what Webpack does and how it does it with a JavaScript configuration file, webpack.config.js. Angular CLI uses Webpack under the hood, but all configuration for it is instead in .angular-cli.json. You will not see a webpack.config.js in an Angular CLI app.

 

You can see the bundles that are generated by Webpack for our app when we started it above:

  • inline.bundle.js - This is the Webpack loader. A tiny file with Webpack utilities that are needed when loading other files. Eventually this will be written inside the index.html file itself and not being generated as a separate file at all.
  • main.bundle.js - Your own code and anything else you imported.
  • vendor.bundle.js - This is generated by default in dev mode, and ignored by default in prod mode (ng build -prodor ng serve -prod). It includes the Angular libraries with little or no modification. This is to speed up the build process. Also some people think it's a good idea to keep these in a separate file when it doesn't change much and then it can be cached for longer.
  • polyfills.bundle.js - Contains the polyfills.
  • styles.bundle.js - Contains the styles.

 

Introduction to Angular CLI Configuration

The Angular CLI configuration is done in the .angular-cli.json file and it is important to understand the different parts of this file before moving on. We have already mentioned this file a couple of times and we know that the Webpack configuration is done via this file too, there is no webpack.config.json.  

 

The following list explains the most important parts of the file:

 

  • apps - an array of application configurations (It is possible to manage more than one app...).
  • apps.root - points to the source code for the application.
  • apps.outDir - points to the output directory for distribution files (created when you run ng build).
  • apps.assets - put here a list of all application assets to include, such as images, i18n resources etc, we will add stuff here a lot.
  • apps.index - points to the index.html file to use
  • apps.main - points to the main JavaScript file that is the entry point into the application
  • apps.polyfills - points to the polyfils file to include
  • apps.test - points to the file with unit test configuration
  • apps.tsconfig - TypeScript configuration for the application
  • apps.prefix - use this prefix for all new component selectors (e.g. selector: 'app-root')
  • apps.styles - put here a list of all stylesheets (CSS) that should be included. We will add stuff here a lot.
  • apps.scripts - put here a list of all scripts (JS) that should be included. We will add stuff here a lot. 

 

As we can see, everything is controlled via this file.

 

Adding Dependencies and Resources to the App

Every ADF based application will of course need a lot of libraries and resources to run. To add these we update the following files in the adf-workbench application:

 

  • package.json - used to configure dependencies (i.e. libraries) that are needed by the application during runtime and development (if you are new to package.json, then it might help to know that it is to npm what a POM file is to maven, it defines dependencies for the application).
  • .angular-cli.json - as seen in previous section, this file is used to configure assets (i.e. resources such icons), styles, and JS files that are used by the application. Angular CLI is integrated with Webpack, which will bundle these files up into something that can be run.

Finding out what library versions ADF 1.9.0 requires

It is very important that the libraries we set up as dependencies for the application matches the library versions that the ADF Components expects to use. We will be using ADF version 1.9.0 so we need to find out what Angular version it expects to use, what Google Material Design version it expects, etc. We can do this by using a utility called npm-remote-ls.

 

Install it like this:

 

Martins-MacBook-Pro:adf-workbench martin$ npm install -g npm-remote-ls

 

This installs this utility globally on your machine (-g), and not in the node_modules for the adf-workbench app. To find out the dependencies that ADF version 1.9.0 uses you can pick one of its libraries, such as ng2-alfresco-core, and run the tool on it:

 

Martins-MacBook-Pro:adf-workbench martin$ npm-remote-ls ng2-alfresco-core@1.9.0

└─ ng2-alfresco-core@1.9.0

  ├─ @angular/cdk@2.0.0-beta.10

  ├─ @angular/material@2.0.0-beta.10

  ├─ @angular/animations@4.3.6

  ├─ @angular/core@4.3.6

  ├─ @angular/http@4.3.6

  ├─ @angular/compiler@4.3.6

  ├─ @angular/forms@4.3.6

  ├─ @angular/common@4.3.6

  ├─ @angular/compiler-cli@4.3.6

  ├─ hammerjs@2.0.8

  ├─ core-js@2.4.1

  ├─ alfresco-js-api@1.9.0

  ├─ @angular/platform-browser-dynamic@4.2.5

  ├─ material-design-lite@1.2.1

  ├─ reflect-metadata@0.1.10

  ├─ moment@2.15.1

  ├─ rxjs@5.1.0

  ├─ zone.js@0.8.12

  ├─ @angular/material@2.0.0-beta.10

  ├─ @angular/platform-browser-dynamic@4.3.6

  ├─ @ngx-translate/core@7.0.0

  ├─ core-js@2.4.1

 

Note that I have not included all listed libraries, just the ones of most importance.

Here we can immediately find out the expected versions for several important libraries:

 

  • Angular libs - 4.3.6
  • Angular CDK - 2.0.0-beta.10
  • Angular Material - 2.0.0-beta.10
  • Core JS - 2.4.1
  • Material Design Lite - 1.2.1
  • Moment - 2.15.1
  • NGX Translate Core - 7.0.0
  • RxJS - 5.1.0
  • Zone - 0.8.12

 

We now have all the necessary version information to be able to configure the application with the necessary dependencies and resources so ADF version 1.9.0 will work smoothly.

 

To check dependencies for a beta version do for example:

 

Martins-MacBook-Pro:workbench-x martin$ npm-remote-ls ng2-alfresco-core@1.9.0-beta7

Update Angular version

Start by updating the generated application to correct Angular version 4.3.6. Open package.json and update it to look as follows:

{
"name": "adf-workbench",
"version": "0.0.0",
"license": "MIT",
"scripts": {
   "ng": "ng",
   "start": "ng serve",
   "build": "ng build",
   "test": "ng test",
   "lint": "ng lint",
   "e2e": "ng e2e"
},
"private": true,
"dependencies": {
   "@angular/animations": "4.3.6",
   "@angular/common": "4.3.6",
   "@angular/compiler": "4.3.6",
   "@angular/core": "4.3.6",
   "@angular/forms": "4.3.6",
   "@angular/http": "4.3.6",
   "@angular/platform-browser": "4.3.6",
   "@angular/platform-browser-dynamic": "4.3.6",
   "@angular/router": "4.3.6",
   "core-js": "^2.4.1",
   "rxjs": "^5.4.2",
   "zone.js": "^0.8.14"
},
"devDependencies": {
   "@angular/cli": "1.4.1",
  "@angular/compiler-cli": "4.3.6",
   "@angular/language-service": "4.3.6",
   "@types/jasmine": "~2.5.53",
   "@types/jasminewd2": "~2.0.2",
   "@types/node": "~6.0.60",
   "codelyzer": "~3.1.1",
   "jasmine-core": "~2.6.2",
   "jasmine-spec-reporter": "~4.1.0",
   "karma": "~1.7.0",
   "karma-chrome-launcher": "~2.1.1",
   "karma-cli": "~1.0.1",
   "karma-coverage-istanbul-reporter": "^1.2.1",
   "karma-jasmine": "~1.1.0",
   "karma-jasmine-html-reporter": "^0.2.2",
   "protractor": "~5.1.2",
   "ts-node": "~3.2.0",
   "tslint": "~5.3.2",
   "typescript": "~2.3.3"
}
}

 

Note here that we changed ^4.2.4 to 4.3.6, removing also the caret, which otherwise will update you to the latest version.

Update Core.js version

The Core.js version is the same. Just need to remove the caret. Open package.json and update the dependencies section to look as follows:

 

{
"name": "adf-workbench",
...
},
"private": true,
"dependencies": {
   "@angular/animations": "4.3.6",
   "@angular/common": "4.3.6",
   "@angular/compiler": "4.3.6",
   "@angular/core": "4.3.6",
   "@angular/forms": "4.3.6",
   "@angular/http": "4.3.6",
   "@angular/platform-browser": "4.3.6",
   "@angular/platform-browser-dynamic": "4.3.6",
   "@angular/router": "4.3.6",
     "core-js": "2.4.1",
   "rxjs": "^5.4.2",
   "zone.js": "^0.8.14"
...

Add Google Material Design

The styling of the ADF Components is based on Google Material Design. In this section we add the necessary styles, images, and JavaScript libraries.

Adding Google Material Design Light

Material Design Lite lets you add a Material Design look and feel to your websites. It doesn’t rely on any JavaScript frameworks and aims to optimize for cross-device use, gracefully degrade in older browsers, and offer an experience that is immediately accessible.

 

Add the material design dependency to the dependencies section in the package.json file:

 

{
"name": "adf-workbench",
...
},
"private": true,
"dependencies": {
   "@angular/animations": "4.3.6",
   "@angular/common": "4.3.6",
   "@angular/compiler": "4.3.6",
   "@angular/core": "4.3.6",
   "@angular/forms": "4.3.6",
   "@angular/http": "4.3.6",
   "@angular/platform-browser": "4.3.6",
   "@angular/platform-browser-dynamic": "4.3.6",
   "@angular/router": "4.3.6",
   "core-js": "2.5.1",
     "material-design-lite": "1.2.1",
   "rxjs": "^5.4.2",
   "zone.js": "^0.8.14"
},
...

The Google Material Design Icons should be loaded via the src/index.html file, update it as follows:

 

<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>AdfWorkbench</title>
<base href="/">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="icon" type="image/x-icon" href="favicon.ico">
<link href="https://fonts.googleapis.com/css?family=Muli" rel="stylesheet">
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
</head>
<body>
<app-root></app-root>
</body>
</html>

 

We also need to make sure these libraries (i.e. styles and JS) are loaded correctly during runtime. The styles and JS files will be packaged up into a bundle by the webpack process. Angular CLI is integrated with webpack behind the scenes.

 

In the styles and scripts sections in the .angular-cli.json file, add as follows:

 

{
"$schema": "./node_modules/@angular/cli/lib/config/schema.json",
"project": {
   "name": "adf-workbench"
},
"apps": [
   {
     "root": "src",
     "outDir": "dist",
     "assets": [
       "assets",
       "favicon.ico"
     ],
     "index": "index.html",
     "main": "main.ts",
     "polyfills": "polyfills.ts",
     "test": "test.ts",
     "tsconfig": "tsconfig.app.json",
     "testTsconfig": "tsconfig.spec.json",
     "prefix": "app",
     "styles": [
       "styles.css",
       "../node_modules/material-design-lite/dist/material.orange-blue.min.css"
     ],
     "scripts": [
       "../node_modules/material-design-lite/material.min.js"
     ],
     "environmentSource": "environments/environment.ts",
     "environments": {
       "dev": "environments/environment.ts",
       "prod": "environments/environment.prod.ts"
     }
   }
],
...

 

These styles will be loaded exactly as if you had added them in a <link> tag inside index.html. And the JavaScript file will be loaded exactly as if you added it in a <script> tag inside index.html. You might be tempted to just specify these in the index.html file directly, doing this will not get them packaged up into a bundle by webpack.

 

The apps[0].styles will end up in the dist/styles.bundle.js bundle file and the apps[0].scripts will end up in the dist/scripts.bundle.js bundle file.

Note that we are referencing the node_modules directory relatively from the src directory, not from the directory where the .angular-cli.json file is located.

Global Styles

As you can see from the above app[0].styles configuration the styles.css file was already included in our .angular-cli.json file.  This is where you add style information that is relevant to the entire application. And that is also why we added the Material Design style sheets here. And so far, this is what you would expect. But, as you know, Angular 2 takes styling to the next level.

Component Styles

Assuming you have done a bit of Angular 2 (4) web development, you know that you can also add style information in your components.  If you open the existing src/app/app.component.ts file, you will notice that there is both a templateUrl and a styleUrls attribute in the @Component() metadata section:

 

import { Component } from '@angular/core';

@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
title = 'app';
}

 

In the styleUrls property you can specify a list of relative URLs of CSS files to include.

If we include CSS information in the CSS files, you will see that when we render the page, the CSS gets rewritten so that the CSS is scoped to the component. Looking at an ADF component, such as the LoginComponent, we can see that this is used:

 

@Component({
selector: 'adf-login, alfresco-login',
templateUrl: './login.component.html',
styleUrls: ['./login.component.scss'],
host: {'(blur)': 'onBlur($event)'},
encapsulation: ViewEncapsulation.None
})
export class LoginComponent implements OnInit {

Add Angular Material Design Components

As ADF is implemented in Angular 4 we need to also install the Material Design components that are built for and with Angular. We can then also use these Angular Material components when building our UI.

 

Open up package.json and add the angular/cdk and angular/material library dependencies:

 

{
"name": "adf-workbench",
...
},
"private": true,
"dependencies": {
   "@angular/animations": "4.3.6",
     "@angular/cdk": "2.0.0-beta.10",
   "@angular/common": "4.3.6",
   "@angular/compiler": "4.3.6",
   "@angular/core": "4.3.6",
   "@angular/forms": "4.3.6",
   "@angular/http": "4.3.6",
     "@angular/material": "2.0.0-beta.10",
   "@angular/platform-browser": "4.3.6",
   "@angular/platform-browser-dynamic": "4.3.6",
   "@angular/router": "4.3.6",
   "core-js": "2.5.1",
   "material-design-lite": "1.2.1",
   "rxjs": "^5.4.2",
   "zone.js": "^0.8.14"
}...

 

The Angular CDK is comprised of a bunch of services, directives, components, classes, modules, etc to make our lives easier when developing Angular components. The CDK actually provides general-purpose tools for building components that are not coupled to Material Design.

Add and Update other General Libraries 

In this section we add some libraries that are used throughout the ADF components.

Add moment to manage date and time in JavaScript

The moment library provides Angular pipes for manipulating display of date and time. Add it as a dependency in package.json:

 

{
"name": "adf-workbench",
...
},
"private": true,
"dependencies": {
   "@angular/animations": "4.3.6",
   "@angular/cdk": "2.0.0-beta.10",
   "@angular/common": "4.3.6",
   "@angular/compiler": "4.3.6",
   "@angular/core": "4.3.6",
   "@angular/forms": "4.3.6",
   "@angular/http": "4.3.6",
   "@angular/material": "2.0.0-beta.10",
   "@angular/platform-browser": "4.3.6",
   "@angular/platform-browser-dynamic": "4.3.6",
   "@angular/router": "4.3.6",
   "core-js": "2.5.1",
   "material-design-lite": "1.2.1",
     "moment": "2.15.1",
   "rxjs": "^5.4.2",
   "zone.js": "^0.8.14"
},

Add ngx-translate to manage internationalization

Ngx-Translate is an internationalization library for Angular 2+. It lets you define translations for your content in different languages and switch between them easily.  Add it as a dependency in package.json:

 

{
"name": "adf-workbench",
...
},
"private": true,
"dependencies": {
   "@angular/animations": "4.3.6",
   "@angular/cdk": "2.0.0-beta.10",
   "@angular/common": "4.3.6",
   "@angular/compiler": "4.3.6",
   "@angular/core": "4.3.6",
   "@angular/forms": "4.3.6",
   "@angular/http": "4.3.6",
   "@angular/material": "2.0.0-beta.10",
   "@angular/platform-browser": "4.3.6",
   "@angular/platform-browser-dynamic": "4.3.6",
   "@angular/router": "4.3.6",
     "@ngx-translate/core": "7.0.0",
   "core-js": "2.5.1",
   "material-design-lite": "1.2.1",
   "moment": "2.15.1",
   "rxjs": "^5.4.2",
   "zone.js": "^0.8.14"
}...

Update Reactive Extensions for JavaScript version

The Reactive Extensions for JavaScript (RxJS) is a set of libraries to compose asynchronous and event-based programs using observable collections and Array#extras style composition in JavaScript.

 

The version of RxJS in the generated project is not correct, update it as follows in package.json:

 

{
"name": "adf-workbench",
...
},
"private": true,
"dependencies": {
   "@angular/animations": "4.3.6",
   "@angular/cdk": "2.0.0-beta.10",
   "@angular/common": "4.3.6",
   "@angular/compiler": "4.3.6",
   "@angular/core": "4.3.6",
   "@angular/forms": "4.3.6",
   "@angular/http": "4.3.6",
   "@angular/material": "2.0.0-beta.10",
   "@angular/platform-browser": "4.3.6",
   "@angular/platform-browser-dynamic": "4.3.6",
   "@angular/router": "4.3.6",
   "@ngx-translate/core": "7.0.0",
   "core-js": "2.5.1",
   "material-design-lite": "1.2.1",
   "moment": "2.15.1",
     "rxjs": "5.1.0",
   "zone.js": "^0.8.14"
},

Fix type warnings related to the RxJS library

To switch off numerous and unnecessary type warnings related to the RxJs library, update the root Typescript configuration (for the IDE) file adf-workbench/tsconfig.json and the skipLibCheck and paths properties as follows:

 

{
"compileOnSave": false,
"compilerOptions": {
   "outDir": "./dist/out-tsc",
   "sourceMap": true,
   "declaration": false,
   "moduleResolution": "node",
   "emitDecoratorMetadata": true,
   "experimentalDecorators": true,
   "target": "es5",
   "typeRoots": [
     "node_modules/@types"
   ],
   "lib": [
     "es2017",
     "dom"
   ],
   "skipLibCheck": true,
   "paths": {
     "rxjs/*": ["../node_modules/rxjs/*" ],
     "@angular/*": ["../node_modules/@angular/*"]
   }
}
}

Update Zone version

The Zone library provides a way to represent the dynamic extent of asynchronous calls in Node. Just like the scope of a function defines where it may be used, the extent of a call represents the lifetime that is it active.

 

The version of Zone in the generated project is not correct, update it as follows in package.json:

 

{
"name": "adf-workbench",
...
},
"private": true,
"dependencies": {
   "@angular/animations": "4.3.6",
   "@angular/cdk": "2.0.0-beta.10",
   "@angular/common": "4.3.6",
   "@angular/compiler": "4.3.6",
   "@angular/core": "4.3.6",
   "@angular/forms": "4.3.6",
   "@angular/http": "4.3.6",
   "@angular/material": "2.0.0-beta.10",
   "@angular/platform-browser": "4.3.6",
   "@angular/platform-browser-dynamic": "4.3.6",
   "@angular/router": "4.3.6",
   "@ngx-translate/core": "7.0.0",
   "core-js": "2.5.1",
   "material-design-lite": "1.2.1",
   "moment": "2.15.1",
   "rxjs": "5.1.0",
     "zone.js": "0.8.12"
}...

Lock down TypeScript version

By default the generated project will have the typescript version configured in a way such as this:

 

"typescript": "~2.3.3"

 

This is not ideal as the tilde character in front of it means that whenever a patch version is released by Microsoft, such as version 2.3.4, our project could be updated with the new version without us realising it. This can be bad news as this could effect some ADF component, and it could take a while before we realise what is going on. So remove the tilde and specify it as follows instead in the dev dependencies section:

 

"devDependencies": {
"@angular/cli": "1.4.1",
"@angular/compiler-cli": "4.3.6",
"@angular/language-service": "4.3.6",
"@types/jasmine": "~2.5.53",
"@types/jasminewd2": "~2.0.2",
"@types/node": "~6.0.60",
"codelyzer": "~3.1.1",
"jasmine-core": "~2.6.2",
"jasmine-spec-reporter": "~4.1.0",
"karma": "~1.7.0",
"karma-chrome-launcher": "~2.1.1",
"karma-cli": "~1.0.1",
"karma-coverage-istanbul-reporter": "^1.2.1",
"karma-jasmine": "~1.1.0",
"karma-jasmine-html-reporter": "^0.2.2",
"protractor": "~5.1.2",
"ts-node": "~3.2.0",
"tslint": "~5.3.2",
   "typescript": "2.3.3"
}

Adding the Core ADF Libraries

There are general libraries used throughout the Application Development Framework (ADF) that are useful to install at the beginning. We can also do basic configuration of the ADF app.

Add the Alfresco JavaScript Library

Alfresco ADF components uses the Alfresco JavaScript library to talk to ACS and APS. This JavaScript library basically abstracts the Content Services REST API and the Process Services REST API.

 

Add it as follows in package.json:

 

{
  "name": "adf-workbench",
  ...
  "dependencies": {
    "@angular/animations": "4.3.6",
    "@angular/cdk": "2.0.0-beta.10",
    "@angular/common": "4.3.6",
    "@angular/compiler": "4.3.6",
    "@angular/core": "4.3.6",
    "@angular/forms": "4.3.6",
    "@angular/http": "4.3.6",
    "@angular/material": "2.0.0-beta.10",
    "@angular/platform-browser": "4.3.6",
    "@angular/platform-browser-dynamic": "4.3.6",
    "@angular/router": "4.3.6",
    "@ngx-translate/core": "7.0.0",
      "alfresco-js-api": "1.9.0",
    "core-js": "2.5.1",
    "material-design-lite": "1.2.1",
    "moment": "2.15.1",
    "ng2-alfresco-core": "1.9.0",
    "rxjs": "5.1.0",
    "zone.js": "0.8.12"
  },

 

This JS library can also be used directly in cases where there are no ADF components that fit the requirements. Note that the Alfresco JavaScript library follows the same versioning as the ADF, so we specify 1.9.0.

Add the ADF Core Library

The ADF Core components and services provide stuff such as Menu component, Toolbar component, Authentication Service, Alfresco Content Services, Notification Service, Search Service etc, which are used throughout the ADF.

 

Add this library in package.json:

 

{
  "name": "adf-workbench",
  ...
  "dependencies": {
    "@angular/animations": "4.3.6",
    "@angular/cdk": "2.0.0-beta.10",
    "@angular/common": "4.3.6",
    "@angular/compiler": "4.3.6",
    "@angular/core": "4.3.6",
    "@angular/forms": "4.3.6",
    "@angular/http": "4.3.6",
    "@angular/material": "2.0.0-beta.10",
    "@angular/platform-browser": "4.3.6",
    "@angular/platform-browser-dynamic": "4.3.6",
    "@angular/router": "4.3.6",
    "@ngx-translate/core": "7.0.0",
    "alfresco-js-api": "1.9.0",
    "core-js": "2.5.1",
    "material-design-lite": "1.2.1",
    "moment": "2.15.1",
      "ng2-alfresco-core": "1.9.0",
    "rxjs": "5.1.0",
    "zone.js": "0.8.12"
  },

 

We also need to tell the app about the assets and styles that are available in the ADF core library. We want these assets and styles to be packaged and bundled up by the webpack tool, making them available during runtime.

 

Add the new asset to the assets sections, new styles to the styles section, and the new stylePreprocessorOptions property in the .angular-cli.json file:

 

{
"$schema": "./node_modules/@angular/cli/lib/config/schema.json",
"project": {
   "name": "adf-workbench"
},
"apps": [
   {
     "root": "src",
     "outDir": "dist",
     "assets": [
       "assets",
       "favicon.ico",
       { "glob": "**/*", "input": "../node_modules/ng2-alfresco-core/bundles/assets", "output": "./assets/" }
     ],
     "index": "index.html",
     "main": "main.ts",
     "polyfills": "polyfills.ts",
     "test": "test.ts",
     "tsconfig": "tsconfig.app.json",
     "testTsconfig": "tsconfig.spec.json",
     "prefix": "app",
     "styles": [
       "styles.css",
       "../node_modules/material-design-lite/dist/material.orange-blue.min.css",
      "../node_modules/ng2-alfresco-core/prebuilt-themes/adf-blue-orange.css"
     ],
     "scripts": [
       "../node_modules/material-design-lite/material.min.js"
     ],
     "environmentSource": "environments/environment.ts",
     "environments": {
       "dev": "environments/environment.ts",
       "prod": "environments/environment.prod.ts"
     },
     "stylePreprocessorOptions": {
       "includePaths": [
         "../node_modules/ng2-alfresco-core/styles"
       ]
     }...

 

What we do here in the app[0].assets section is to tell Angular CLI that all the assets, such as images and i18n resource files, that are located in the ng2-alfresco-core package should be copied into the dist/assets directory.

 

We also configure what ADF theme (Angular Material theme) we want to use, in this case adf-blue-orange.css. The theme will be available to the whole app we are building.

 

In order to simplify style imports we also add style include paths as follows via the stylePreprocessorOptions entry in .angular-cli.json:

 

"stylePreprocessorOptions": {
       "includePaths": [
         "../node_modules/ng2-alfresco-core/styles"
       ]
     }

Files in that folder, for example, src/../node_modules/ng2-alfresco-core/styles/_colors.scss, can be imported from anywhere in your project without the need for a relative path:

 

/* src/app/app.component.scss
  A relative path works */

@import '../node_modules/ng2-alfresco-core/styles/colors';
/* But now this works as well */
@import 'colors';

Install all libraries

It’s time to install all the libraries that we defined in package.json. We need to do this now otherwise it will be difficult to work with the components from our IDE as it would not know anything about the modules and classes we are trying to use. Basically we need to get the local /node_modules directory updated with all the new libraries that we configured and the updated library versions.

 

Remove the node_modules directory and then run npm install to download all the extra libraries that we have defined in package.json to node_modules:

 

Martins-MacBook-Pro:adf-workbench mbergljung$ rm -rf node_modules/

Martins-MacBook-Pro:adf-workbench mbergljung$ npm install

...

Testing binary

Binary is fine

added 1030 packages in 13.195s

Martins-MacBook-Pro:adf-workbench mbergljung$ npm dedup

removed 16 packages in 2.949s

 

After we have run npm install we also run npm dedup. This will remove any duplicate transitive dependencies. If a transitive dependency already exists it will not be downloaded again, but this depends on the order we have specified the libraries in package.json. So always good to do a dedup after an install.

 

You might be tempted to run npm update instead of npm install. This will also work but it changes package.json dependencies version specifications. It will add carets in front of version numbers, so not what we want. So be careful with this command.

List the node_modules directory if you want to find out all the downloaded libs:

 

Martins-MacBook-Pro:node_modules mbergljung$ ls -l|more

total 0

drwxr-xr-x   14 mbergljung  staff    476 11 Oct 15:30 @angular

drwxr-xr-x    5 mbergljung  staff    170 11 Oct 14:32 @angular-devkit

drwxr-xr-x    4 mbergljung  staff    136 11 Oct 14:32 @ngtools

drwxr-xr-x    3 mbergljung  staff    102 11 Oct 15:30 @ngx-translate

drwxr-xr-x    3 mbergljung  staff    102 11 Oct 14:32 @schematics

drwxr-xr-x    7 mbergljung  staff    238 11 Oct 14:32 @types

drwxr-xr-x    6 mbergljung  staff    204 11 Oct 14:32 abbrev

drwxr-xr-x    7 mbergljung  staff    238 11 Oct 14:32 accepts

drwxr-xr-x    9 mbergljung  staff    306 11 Oct 14:32 acorn

drwxr-xr-x    9 mbergljung  staff    306 11 Oct 14:32 acorn-dynamic-import

drwxr-xr-x   10 mbergljung  staff    340 11 Oct 14:32 adm-zip

drwxr-xr-x    9 mbergljung  staff    306 11 Oct 14:32 after

...

Check that no duplicate libs are included

Note here that the ng2-alfresco-core library has all its dependencies specified in its own package.json, as would be expected, and we call these transitive dependencies. As we saw earlier on, we can easily find out the dependencies for a library we use with the npm-remote-ls tool.

 

Now it's time to make sure that the package.json for our adf-workbench application has been configured with matching ADF 1.9 libraries. In your IDE, navigate into the node_modules directory and look up the ng2-alfresco-core library. You should see something like this:

 

 

We should not see any node_modules directory for the ng2-alfresco-core library if we have configured the app’s package.json correctly. On the other hand, if we have not configured the same library versions as ADF 1.9 expects, then we would see something like this:

 

 

And this means that we will most likely experience problems during runtime, if we can get it to work at all.

Make sure that the app you are building uses the same versions for all libraries that ADF depends on.

Import the ADF Core module into the App module

The ADF Core module provides all the services that the ADF components needs, such as

AuthenticationService, AlfrescoContentService, TranslationService etc. It also provides some components, such as Toolbar, Card View, and Accordion, which might be used frequently.

 

Open up the src/app/app.module.ts file and import the ADF CoreModule from the ng2-alfresco-core package:  

 

import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';

import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';

import { CoreModule } from 'ng2-alfresco-core';

@NgModule({
declarations: [
   AppComponent
],
imports: [
   BrowserModule,
   AppRoutingModule,
   CoreModule
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }

 

If you open up the CoreModule file you can see that it defines the following providers:

 

@NgModule({
   imports: [
       ...
   declarations: [
     ...
   ],
   providers: [
       ...providers(),
       ...deprecatedProviders(),
       MomentDateAdapter,
       {
           provide: TRANSLATION_PROVIDER,
           multi: true,
           useValue: {
               name: 'ng2-alfresco-core',
               source: 'assets/ng2-alfresco-core'
           }
       }
   ],
   exports: [
      ...
   ],
   entryComponents: [
      ...
   ]
})
export class CoreModule {

 

If we navigate into the providers() method we can see all services that are exported and available:

 

export function providers() {
  return [
      UserPreferencesService,
      NotificationService,
      LogService,
      LogServiceMock,
      AuthenticationService,
      AlfrescoContentService,
      AlfrescoSettingsService,
      StorageService,
      CookieService,
      AlfrescoApiService,
      AlfrescoTranslateLoader,
      TranslationService,
      RenditionsService,
      ContentService,
      AuthGuard,
      AuthGuardEcm,
      AuthGuardBpm,
      ThumbnailService,
      UploadService,
      SearchService,
      DeletedNodesApiService,
      FavoritesApiService,
      NodesApiService,
      PeopleApiService,
      SearchApiService,
      SharedLinksApiService,
      SitesApiService,
      DiscoveryApiService,
      HighlightTransformService
  ];
}

Configure the ADF App with the locations of ACS and APS

The ADF app needs to be configured with the location of the ACS and the APS servers. We don’t want to hardcode this in component code. Fortunately there is a file called app.config.json that can be used for this. The ADF framework will automatically look for it.

 

Create it with the following content and put it in the src/assets directory:

 

{
"ecmHost": "http://{hostname}:{port}/ecm",
"bpmHost": "http://{hostname}:{port}/bpm",
"application": {
   "name": "ADF Workbench"
}
}

 

You are probably wondering about the URLs. What values would be substituted for the hostname and port variables, and what about the /ecm and /bpm URL paths, they don’t match endpoints in the ACS and APS servers that we installed earlier on.

 

First, at runtime the {hostname} and {port} variables will be replaced with the data from the running application, such as localhost and 4200. Secondly, the /ecm and /bpm paths are used to talk to a proxy configured in Webpack. We need to add a file called adf-workbench/proxy.conf.json with the following content:

 

{
"/ecm": {
   "target": "http://127.0.0.1:8080",
   "secure": false,
   "pathRewrite": {
     "^/ecm": ""
   }
},
"/bpm": {
   "target": "http://127.0.0.1:9080",
   "secure": false,
   "pathRewrite": {
     "^/bpm": ""
   }
}
}

 

The target URLs need to match the installations we did earlier on for ACS and APS. The pathRewrites shows the answer to the second question about the /ecm and /bpm URLs not matching endpoints in ACS or APS. Here they are removed by the proxy. 

If you are using just one of the backend services, for example ACS. Then you don't need to worry about configuring the other one (e.g. /bpm). And vice versa.

Now, the proxy.conf.json file is not magically read by Webpack, we need to configure Webpack with the location of it. Open up package.json and update the start script as follows:

 

{
"name": "adf-workbench",
"version": "0.0.0",
"license": "MIT",
"scripts": {
   "ng": "ng",
     "start": "ng serve --proxy-config proxy.conf.json",
   "build": "ng build",
   "test": "ng test",
   "lint": "ng lint",
   "e2e": "ng e2e"
},

By using the Webpack proxy we don’t need to configure CORS in ACS or APS.

So what all this means is that a call to for example ACS will be using the http://localhost:4200/ecm URL, which does not cause any CORS problems as the host and port are the same as where the app is running. This URL will then be rewritten via the Webpack proxy to http://127.0.0.1:8080/, where the ACS backend is running.

Logging into ACS and APS

The first thing that we are going to need to do in our app is to login to Content Services and/or Process Services. We can do this with the ADF Login component. When we have a session with these services we can start using other components, such as the Document List.

Installing the ADF Login component

The login component is available in the ng2-alfresco-login library. Install version 1.9.0 of it like this:

 

martins-macBook-pro:adf-workbench martin$ npm install --save --save-exact ng2-alfresco-login@1.9.0

+ ng2-alfresco-login@1.9.0

added 2 packages in 5.1s

 

Note that we should not see any other transitive dependencies being downloaded. They should all match what we already have.

 

When we run the install command with the --save switch it will automatically add the ng2-alfresco-login package to our package.json. Adding the --save-exact option writes the exact version, such as 1.9.0, instead of with a caret ^1.9.0. If the library version is added with a caret (^) in front of it, and there were to be a newer version of ADF released such as 1.9.1, then that version would be used instead.

 

In the package.json we should see something like this:

 

{
  "name": "adf-workbench",
  "version": "0.0.0",
  "license": "MIT",
  "scripts": {
    ...
  },
  "private": true,
  "dependencies": {
    "@angular/animations": "4.3.6",
    "@angular/cdk": "2.0.0-beta.10",
    "@angular/common": "4.3.6",
    "@angular/compiler": "4.3.6",
    "@angular/core": "4.3.6",
    "@angular/forms": "4.3.6",
    "@angular/http": "4.3.6",
    "@angular/material": "2.0.0-beta.10",
    "@angular/platform-browser": "4.3.6",
    "@angular/platform-browser-dynamic": "4.3.6",
    "@angular/router": "4.3.6",
    "@ngx-translate/core": "7.0.0",
    "alfresco-js-api": "1.9.0",
    "core-js": "2.5.1",
    "material-design-lite": "1.2.1",
    "moment": "2.15.1",
    "ng2-alfresco-core": "1.9.0",
      "ng2-alfresco-login": "1.9.0",
    "rxjs": "5.1.0",
    "zone.js": "0.8.12"
  },
  "devDependencies": {
   ...
  }
}

 

We also need to tell the app about the assets, such as i18n resources, that are available in the ADF Login library. We want these assets to be packaged and bundled up by the webpack tool, making them available during runtime.

 

Add the login assets to the .angular-cli.json file as follows:

 

{
  "$schema": "./node_modules/@angular/cli/lib/config/schema.json",
  "project": {
    "name": "adf-workbench"
  },
  "apps": [
    {
      "root": "src",
      "outDir": "dist",
      "assets": [
        "assets",
        "favicon.ico",
        { "glob": "**/*", "input": "../node_modules/ng2-alfresco-core/bundles/assets", "output": "./assets/" },
        { "glob": "**/
*", "input": "../node_modules/ng2-alfresco-login/bundles/assets", "output": "./assets/" }
      ],
      "index": "index.html",
      "main": "main.ts",
      "polyfills": "polyfills.ts",
      "test": "test.ts",
      "tsconfig": "tsconfig.app.json",
      "testTsconfig": "tsconfig.spec.json",
      "prefix": "app",
      "styles": [
        "styles.css",
        "../node_modules/material-design-lite/dist/material.orange-blue.min.css",
        "../node_modules/ng2-alfresco-core/prebuilt-themes/adf-blue-orange.css"
      ],
      "scripts": [
        "../node_modules/material-design-lite/material.min.js"
      ],
      "environmentSource": "environments/environment.ts",
      "environments": {
        "dev": "environments/environment.ts",
        "prod": "environments/environment.prod.ts"
      },
      "stylePreprocessorOptions": {
        "includePaths": [
          "../node_modules/ng2-alfresco-core/styles"
        ]
      }
    }
  ],
...
}

Adding the ADF Login component to the App

Every ADF component has extensive documentation available together with the source code in the standard README.md. For example, if you navigate to the Login component source code you would see something like this:

 

 

The page covers everything from documentation, installation, basic usage, to advanced concepts. Click on the Documentation link in the bullet point list to read more about the Login component. The basic markup that will put the login component onto the page looks like this:

<adf-login 
    [providers]="'ALL'"
    (onSuccess)="mySuccessMethod($event)"
    (onError)="myErrorMethod($event)">

</adf-login>

The providers property controls what backing services to connect to. By default it will connect only to the Content Services (i.e. providers value set to 'ECM'). By specifying ALL we make sure to login to both Content Services and Process Services.

If you are using only one of the backend services, such as APS, then make sure to specify only that service in the providers field (e.g. ‘ECM’ if logging in only to ACS and 'BPM' if logging in only to APS). 

The two event callback methods will be invoked when a successful login has completed (onSuccess) or if an error occurs (onError).

Making the Login component available to the App

The application that we generated comes with only one component, the main application component, represented by the TypeScript class AppComponent defined in the src/app/app.component.ts file. The view template is available in the src/app/app.component.html file.

 

To use the login component from the app component we need to first import it. The Alfresco Login Component is defined in the TypeScript class LoginComponent. The import is done implicitly via a module called LoginModule, which should be added to the AppModule in the src/app/app.module.ts file as follows:

 

import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';

import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';

import { CoreModule } from 'ng2-alfresco-core';
import { LoginModule } from 'ng2-alfresco-login';

@NgModule({
declarations: [
   AppComponent
],
imports: [
   BrowserModule,
   AppRoutingModule,
   CoreModule,
   LoginModule
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }

 

If you look in the LoginModule file you can see that it exports the LoginComponent and some directives at the root level. Any component that exist, or we create, can now use the login component.

Adding the Alfresco Login component to the App component template

To quickly test the Login component we will add it to the existing root app component. Open up the src/app/app.component.html template file, you should see some markup like this:

 

<!--The content below is only a placeholder and can be replaced.-->
<divstyle="text-align:center">
<h1>
   Welcome to {{title}}!
</h1>
<img width="300" src="data:image/svg+xml;base64,PD94...">
</div>
<h2>Here are some links to help you start: </h2>
<ul>
<<>li
   h2><a target="_blank" href="https://angular.io/tutorial">Tour of Heroes</a></h2>
</li>
<li>
   <h2><a target="_blank" href="https://github.com/angular/angular-cli/wiki">CLI Documentation</a></h2>
</li>
<li>
   <h2><a target="_blank" href="https://blog.angular.io//">Angular blog</a></h2>
</li>
</ul>

<router-outlet></router-outlet>

 

Change the template to look like this instead, with the Login component added:

 

<div style="text-align:center">
<h1>
   Welcome to {{title}}!
</h1>
</div>

<adf-login
  [providers]="'ALL'"
  (onSuccess)="onLoginSuccess($event)"
  (onError)="onLoginError($event)">

</adf-login>

<router-outlet></router-outlet>

 

Keep the router-outlet as that is where the router will output other components template code. It does not do anything at the moment as we don’t have any other components with routes, but we will keep it anyway.

Note. change [providers]="'ALL'" if you are just using one of the backing services.

Implement the Login event callback methods

The Alfresco Login component emits two events called onSuccess and onError, indicating the outcome of the login attempt. We will define new handler methods in the App component class as follows (src/app/app.component.ts):

 

import { Component } from '@angular/core';

@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
  title = 'ADF Workbench';

  onLoginSuccess($event) {
   console.log('Successful login: ' + $event.value);
  }

  onLoginError($event) {
   console.log('Failed login: ' + $event.value);
  }
}

 

Note. also updated the title property to “ADF Workbench”.

Testing the App with the Login component

It’s time to run the app and see how it looks. We would expect to see a login page.

 

Start the server by running npm start:

 

Martins-MacBook-Pro:workbench-x martin$ npm start

 

> workbench-x@0.0.0 start /Users/martin/ADFProjects/workbench-x

> ng serve --proxy-config proxy.conf.json

 

** NG Live Development Server is listening on localhost:4200, open your browser on http://localhost:4200 **

Date: 2017-09-06T10:17:58.335Z                                                           

Hash: 6216512973110e2481bf

Time: 20194ms

chunk {inline} inline.bundle.js, inline.bundle.js.map (inline) 5.83 kB [entry] [rendered]

chunk {main} main.bundle.js, main.bundle.js.map (main) 18.3 kB {vendor} [initial] [rendered]

chunk {polyfills} polyfills.bundle.js, polyfills.bundle.js.map (polyfills) 174 kB {inline} [initial] [rendered]

chunk {scripts} scripts.bundle.js, scripts.bundle.js.map (scripts) 64.5 kB {inline} [initial] [rendered]

chunk {styles} styles.bundle.js, styles.bundle.js.map (styles) 254 kB {inline} [initial] [rendered]

chunk {vendor} vendor.bundle.js, vendor.bundle.js.map (vendor) 7.91 MB [initial] [rendered]

 

webpack: Compiled successfully.

 

You should see all Webpack bundles created and the app launched successfully. Note that we use npm start instead of ng serve as we want the Webpack proxy to be active.

 

Accessing the app on http://localhost:4200 should show the login page as follows:

 

 

Pretty cool!

 

Let’s try and login with the common username and password:

 

 

 

Clicking SIGN IN should log you in successfully to ACS and/or APS. The login screen will change to the following with a “Login successful” message and the button change message to WELCOME:

 

 

The JavaScript console in the browser should show you log from the callback method onLoginSuccess:

 

 

Everything is working fine now and we are logged in to ACS and/or APS.

Summary

To use Angular CLI to set up an Angular application is really easy. And to configure it to work with ADF 1.9.0 is not that difficult either. It was all done to get you up to speed on how everything hangs together. Of course it is also possible to generate an ADF application with the Yeoman generator when you are on top of how things work together. Or just clone an ADF ready Angular CLI project.

 

We can now start bringing in some more ADF components. However, before we do that it might be a good idea to refactor/restructure the app a bit so it resembles a more realistic application with toolbar, menu, logout etc, read the 

article for more info on how to do that.

Outcomes