Simple custom Angular (Angular2) Pipe that extends Number

We have a lot of code that looks like this in our new Angular (Angular2) module:

<div style="width:210px">
    <div>
        {{ (overviewDetails.TotalTurnoverActualSecured ?
      (overviewDetails.TotalTurnoverActualSecured / 1000000) : 0) | number:'1.2-2' }}
    </div>
    <div>{{ overviewDetails.TotalTurnoverActualSP / 1000000 
      | number:'1.2-2' }}</div>
    <div>{{ overviewDetails.TotalTurnoverActualSPF / 1000000 
      | number:'1.2-2' }}</div>
    <div style="clear:both"></div>
</div>

The main reason is that we just want to display numbers in 1.2 million, not 1200,000.

So obviously, we think about wrapping this in a custom Pipe function.

number is a Pipe name for the DecimalPipe class.  So we can extend that and borrow all the work the DecimalPipe does with parsing and formatting.

import { Pipe } from '@angular/core';
import { DecimalPipe } from '@angular/common';

@Pipe({
  name: 'million'
})
export class MillionPipe extends DecimalPipe {
  transform(value: number): any {
    return super.transform(((value || 0)/ 1000000), "1.2-2");  
  }
}

The Angular2 template then simplifies down to:

<div style="width:210px">
    <div>{{ overviewDetails.TotalTurnoverActualSecured | million }}</div>
    <div>{{ overviewDetails.TotalTurnoverActualSP  | million }}</div>
    <div>{{ overviewDetails.TotalTurnoverActualSPF  | million }}</div>
    <div style="clear:both"></div>
</div>

It is so nice to work with a Proper Object-Oriented language like TypeScript here.  Look at that extends.  <3

 

O365 Customizations in the year 2017

It is the year 2017 - watch out, because O365 customizations are full speed ahead.

This is a MS Australia Ignite 'lightning talk' for Meetup Madness (sorry, I took twice the amount of time than I should) to convince a room full of people that loved O365 to become developers.

MS AU Ignite Meetup Madness - O365 Customizations in 2017

Much laughter was had.  But I stand by what I said - you are now all developers, now go build something amazing!

 

AzureFunctions, PowerShell, MS Graph and AppOnly permission

In a previous blog post, I wrote about connecting to Microsoft Graph with Resource Owner grant.

That particular authentication scheme is for delegate permissions.  So the function, utilizing an account's username/password, is performing actions as that user.

I'm revisiting that post today and instead talk about App-Only Permissions, and the steps are very similar, and to some may be easier.

 

Register App-Only

Head into the New Azure Portal.

Add "Read and write all groups" permission under "Application Permissions"

You should see this:

"1 Application Permission"

Hit the Grant Permission button here.

And set up a Client Secret

Nearly there, one more step we need to make the registered app allow implicit flow.

Hit the Manifest button, change oauth2AllowEmplicitFlow property to true, hit save.

Copy the Application ID - this is the Client ID.

On the first page of Azure AD properties, grab the Directory ID

 

 

You now have:

  • Directory ID (Tenant ID)
  • Application ID (Client ID)
  • Key (Client Secret)
  • And consent for your app has been granted.

 

PowerShell Code

 

$tenant_id = "26e65220-5561-46ef-9783-ce5f20489241";
$client_id = "44da3f20-fc0b-4f90-8bb1-54b1d50e3ecf";
$client_secret = $env:CS2;
$resource = "https://graph.microsoft.com";

$authority = "https://login.microsoftonline.com/$tenant_id";
$tokenEndpointUri = "$authority/oauth2/token";
$content = "grant_type=client_credentials&client_id=$client_id
            &client_secret=$client_secret&resource=$resource";

$response = Invoke-WebRequest `
    -Uri $tokenEndpointUri `
    -Body $content `
    -Method Post `
    -UseBasicParsing

 

The small difference between this time and the previous blog is now we are using AppOnly permissions.  The grant_type is client_credentials.  And you don't need to supply username/password.  The clientid/clientsecret pair is sufficient.

 

The whole thing

$name = "group-name-here"

$client_id = "44da3f20-fc0b-4f90-8bb1-54b1d50e3ecf";
$client_secret = $env:CS2;
$tenant_id = "26e65220-5561-46ef-9783-ce5f20489241";
$resource = "https://graph.microsoft.com";

$authority = "https://login.microsoftonline.com/$tenant_id";
$tokenEndpointUri = "$authority/oauth2/token";
$content = "grant_type=client_credentials&client_id=$client_id&client_secret=$client_secret&resource=$resource";

$response = Invoke-WebRequest -Uri $tokenEndpointUri -Body $content -Method Post -UseBasicParsing
$responseBody = $response.Content | ConvertFrom-JSON
$responseBody
$access_token = $responseBody.access_token

# GET https://graph.microsoft.io/en-us/docs/api-reference/v1.0/api/group_list
# $body = Invoke-RestMethod -Uri "https://graph.microsoft.com/v1.0/groups" -Headers @{"Authorization" = "Bearer $access_token"}
# $body | ConvertTo-JSON

# POST - this creates groups https://graph.microsoft.io/en-us/docs/api-reference/v1.0/api/group_post_groups
$body = @{"displayName"= $name; "mailEnabled"=$false; "groupTypes"=@("Unified"); "securityEnabled"=$false; "mailNickname"=$name } | ConvertTo-Json 
$body = Invoke-RestMethod `
    -Uri "https://graph.microsoft.com/v1.0/groups" `
    -Headers @{"Authorization" = "Bearer $access_token"} `
    -Body $body `
    -ContentType "application/json" `
    -Method POST
$body | ConvertTo-JSON

There are no other dependencies - authenticate and calling MS Graph is really that simple - two web requests!

 

The default "Owner"

Usually, the user that created the group becomes the Owner of the group.

In the Delegate Permission example in the last blog, the group is created with my user account and I'm the owner.

In the Application-Only Permission example in this blog, the group is created with the app account and there is no user owner!

 

 

 

 

Where is SharePoint Customization going in 2017

I'm actually pretty terrible at gambling the future of Technology.  But I like writing these posts because it makes me sit down and think.

User Experience: SPFx is king

 

The user experience is dominated in 2016 with the news of SharePoint Framework (SPFx).  Which shifts development and toolchain to a more modern JavaScript Stack:  NodeJS, Yeoman.  WebPack.  There are component libraries like Office UI Fabric, but we explored options such as Kendo UI and UI Bootstrap and there are many benefits too.  In 2017, SPFx should come down to On-Premises too, we'll have to wait and see what that looks like.

Sure - there are still plenty of gaps where SPFx can't cover - many of us are looking to a solution that allows us to do a site-level script injection or something that will let us do a Single Page Application override.  But I'm very bullish on the SPFx.  I think 2017 will rock.

https://github.com/SharePoint/sp-dev-docs

 

Frameworks: Angular or React

React continues to better suit component development, and Angular might catch up, but we'll see.  In SPG, we are divided into both camps, and for people that aren't familiar with Angular, I am not opposed to them learning React.

I am however, dead serious that no one should try to learn both Angular and React at the same time.  One need to pick one, master it, then the concepts of the other framework will map in the mind and come naturally.  Learning both at the same time without mastering either of them will screw one's learning path.  Don't risk this.

Have an ASPNET MVC background?  Angular will make more sense.  Want a more code / component based approach?  Then React will make more sense.  Pick one and run with it.

I have picked up Angular now and am quite happy with it.  Feel free to reach out with Angular+SharePoint questions.  I can't help with React questions.

 

SP Helper: PnP-JS-Core

I have high hopes that PnP-JS-Core will continue to gain popularity and wrap around the SharePoint REST Services well.  I can totally see a few blog posts in the future using NodeJS, PnP-JS-Core inside an Azure Function to manage SharePoint Online.

As a bonus, it works really well with On-Premises too.  Congrats on hitting 2.0.0 Patrick!

 

Build tool: Webpack

Pick up webpack - do it now.  gulp and grunt are no longer the right tools that manage the build process.  Use them to automate the tasks around the build.

The rise of command-line-interface CLI tools will be the theme of 2017.  We have angular-cli, create-react-app, SharePoint Framework has its own yeoman template.

CLI is just a command line's way of "new file wizard"

 

Dashboards: Power BI

We did a bit of work with embedding Power BI dashboards into SharePoint, and with the rapid pace of releases of upcoming Power BI SPFx, Push data with Flow to PowerBI and PowerBI Streaming Datasets - it will become increasing no brainer to use Power BI to build your reporting dashboard and embed them into your sites.  With a local gateway, Power BI works for on-premises data too.

 

Forms: ???

I would like to say Power Apps is the thing.  But it's not, not yet.  The reason I say this is that business wants Forms.  They want forms to replace paper processes.  They want forms to replace older, aging digital forms (InfoPath).

Power Apps isn't trying to be a Form.  It is trying to be a Mobile App-Builder.  It might get there one day.  But I'm not sure if that's the course they have set.

I was thinking Angular-Forms for heavy customizations and Power Apps for simple ones.

I'm open to suggestions. 

 

Automation: Flow / Logic Apps + Azure Functions

Several products hit the scene - Flow, Logic Apps are fairly basic.  But once you pair them up with an Atomic Hammer (Azure Functions), then everything will look like a nail and everything's easy.

The way I see it, Flow is better for single events and Logic Apps is better for sets of data.

And don't get me started on the dirt cheap price point too. 

 

Server Code as a Service: Azure Functions

You've probably seen from my recent posts where I rant on and on about Azure Functions.  I truly see it as the ultimate power to do anything that we need a server to do.

  • Any Elevate Permissions task - in Workflow, Flow, Logic Apps or JavaScript Front-End Application
  • Any long running task
  • Any scheduled task
  • Any event response task - especially combined with the newly released SharePoint Webhooks
  • Any task that requires you to build a set of microservices for your power user to build complex Flows or Power Apps
  • Choose any language you like: C#, NodeJS or PowerShell, in fact, mix them in your microservices - nobody cares how it runs, and it's great.

 

Auth Helper: ADAL, MSAL

We can't escape this.  As soon as we begin to connect to various APIs we'll need authentication bearer tokens.

We seem to have better and better helper libraries as time goes on.  But regardless, in 2017 - we will need to be able to auth to the Microsoft Graph in any language that we use.

Julie Turner has an excellent series:

 

Summary

And these are my picks for 2017.  Do let me know what you think - I'm really interested in points where you disagree with my choices, because I want to learn.

 

 

 

 

Azure Functions and Punch Cards

This is apparently a computer story, but is actually also very much a human story.  In which we explore the relationship between Azure Functions and Punch Cards.

My mother

It's been very warm in Sydney in this blistering summer.  My mother comes over to visit and relax and enjoy my air cond.  I'm preparing for Microsoft Ignite Australia on Azure Functions, and I was thinking about a human story.

I looked up at mum, this is the frail, little Chinese grandma that plants funny herbs in the garden.  We had a chat.  I then went online and found this picture.

By ArnoldReinhold - Own work, CC BY-SA 3.0, https://commons.wikimedia.org/w/index.php?curid=16041053

By ArnoldReinhold - Own work, CC BY-SA 3.0, https://commons.wikimedia.org/w/index.php?curid=16041053

Our story

I sometimes talk of my parents who met as comp science students in the 70s.  My mother, who sometimes can't remember how to restart her iPad.  Well, she cut her teeth on these punch cards. She tells me how big they are - gesturing with her hands - the box of cards would be nearly the size of A4 - much wider and longer than I thought.

I ask, so you need to pass the cards to an operator to run them and wait.

Of course.

What if you have an error in your code?

She pretends she spends a lot of time checking before submitting the cards.  But later admitted actually, the code would crash.  I think she figures out that it's a funnier story to tell the truth.

And since the output is a printout (the cards are input, there is no keyboard/screen) she'd get pages and pages of invalid instructions handed to her by the operator.

Imagine Developers, if your OPs is responsible to read to you all your compile errors.  Every time.

She will have to resubmit her program.

It'd be quite embarrassing she says.

I sat back, and tell her of @AzureFunctions and how I now submit code to be run in the cloud.

And how first few runs, my code would spit back rows of errors. we laughed.

Some things never change.

And then, some things do change

 

By NARA - http://www.archives.gov/75th/photos/1950s/20.html[dead link], Public Domain, https://commons.wikimedia.org/w/index.php?curid=17413686

I end this story with this picture.  This warehouse stores punch card programs for US National Archives 1959. Equivalent to 4Gb.

While my mother will have a second chance to resubmit her program in the afternoon, I can repeat as many execution as I'd like in the cloud.

The mainframe computer my mother used when she worked in Statistics Bureau of Taiwan is worth hundreds of thousands of dollars, and she has to wait with other programmers to use it.

The Azure Functions that I can write and deploy today, cost me less than $0.01 and most of the time the compute is free.

Future

Bonus: I told her future datacenters will be underwater and completely unmanned #ProjectNatick

Her eyes are full of wonder