Office UI Fabric Persona with Skype for Business status integration

Today I want to show you simple SPFx Web Part solution, how you could connect new Office UI Fabric React component named Persona with status from Skype for Business (Lync).

Persona is used for rendering an individual’s avatar, user information and presence.
We will use Name.NameCtrl ActiveX component to get presence status of each person from Skype for Business. This ActiveX component was written by Microsoft and works only on IE because it use NPAPI plugins which are disabled in Chrome since 1 Sep 2015.

So, lets start.

Because Skype for Business status is dynamic data, you have to put it into State of your React Component.

export interface IAddressBookState {
    userPresences: {};
}

In constructor of your React Component class you have to initialize NameCtrl ActiveX component and append OnStatusChange event listener method.

export default class AddressBook extends React.Component<IAddressBookProps, IAddressBookState> {
    private nameCtrl: AXO;

    constructor(props: IAddressBookProps) {
        super(props);

        this.state = {
          userPresences: {}
        };

        try {
            if ((window as any).ActiveXObject) {
                this.nameCtrl = new AXO("Name.NameCtrl");
            } else {
                this.nameCtrl = this.CreateNPApiOnWindowsPlugin("application/x-sharepoint-uc");
            }

            if (!this.nameCtrl) {
              return;
            }

            this.nameCtrl.OnStatusChange = this.OnLyncPresenceStatusChange.bind(this);
        }
        catch (ex) {
            console.log(ex);
        }
    }

    private CreateNPApiOnWindowsPlugin(b) {
        var c = null;
        try {
            c = document.getElementById(b);
            if (!Boolean(c) && this.IsNPAPIOnWinPluginInstalled(b)) {
                var a = document.createElement("object");
                a.id = b;
                a.type = b;
                a.width = "0";
                a.height = "0";
                a.style.setProperty("visibility", "hidden", "");
                document.body.appendChild(a);
                c = document.getElementById(b);
            }
        } catch (d) {
            c = null;
        }
        return c;
    }

    private IsNPAPIOnWinPluginInstalled(a) {
        return Boolean(navigator.mimeTypes) && navigator.mimeTypes[a];
    }
}

I used AXO as ActiveX component loader. You have to install this NPM package:

npm install --save axo

In render method for each user item you have to call GetStatus method from ActiveX component with user email and then you can render each person with Persona Fabric UI Component.

private onRenderItem(props: IPickerItemProps<IPersonaProps>):JSX.Element {
    if (!this.state.userPresences[props.item.tertiaryText]) {
        if (this.nameCtrl) {
            this.nameCtrl.GetStatus(props.item.tertiaryText, "user");
        }
    }

    return (
        <div className={ "ms-FocusZone ms-PickerPersona-container personaContainer_894c3072" }>
          <div className={ "ms-PickerItem-content itemContent_894c3072" }>
            <Persona
                { ...props.item }
                size={ PersonaSize.regular }
                presence={ this.state.userPresences[props.item.tertiaryText] }
                hidePersonaDetails={ false }
                onMouseOver={ (event) => { this.showLyncPresencePopup(props.item.tertiaryText, event.currentTarget); } }
                onMouseOut={ this.hideLyncPresencePopup.bind(this) }
            />
          </div>
        </div>);
}

Next one is Presence Status Change Event Handler method for NameCtrl ActiveX Component. This method convert status Id from ActiveX Component to PersonaPresence status for our Persona Office UI Fabric React Component and save it into State for our React Component.

private OnLyncPresenceStatusChange(userName, status, id) {
    var tempUserPresences = this.state.userPresences;

    switch (status) {
      case 0:
          tempUserPresences[userName] = PersonaPresence.online;
          break;
      case 1:
          tempUserPresences[userName] = PersonaPresence.offline;
          break;
      case 2:
      case 4:
      case 16:
          tempUserPresences[userName] = PersonaPresence.away;
          break;
      case 3:
      case 5:
      case 6:
      case 7:
      case 8:
      case 10:
          tempUserPresences[userName] = PersonaPresence.busy;
          break;
      case 9:
      case 15:
          tempUserPresences[userName] = PersonaPresence.dnd;
          break;
      default:
          tempUserPresences[userName] = PersonaPresence.none;
    }

    this.setState({
      userPresences: tempUserPresences
    });
}

The last two methods are for showing and hiding Lync Presence popup.

private showLyncPresencePopup(userName, target) {
    if (!this.nameCtrl) {
        return;
    }

    var eLeft = $(target).offset().left;
    var x = eLeft - $(window).scrollLeft();

    var eTop = $(target).offset().top;
    var y = eTop - $(window).scrollTop();

    this.nameCtrl.ShowOOUI(userName, 0, x, y);
}

private hideLyncPresencePopup() {
    if (!this.nameCtrl) {
        return;
    }
    this.nameCtrl.HideOOUI();
}

That’s all folks. Happy coding (or swimming with cold beer of course 🙂 ).

Cheers!
Gašper Rupnik

{End.}

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

Powered by WordPress.com.

Up ↑

%d bloggers like this: