adding js sample to demonstrate how to use UCWA SDK and subscribe to people status (#378)
* adding js sample to demonstrate how to use UCWA SDK and subscribe to skype status * js-skype-status: fixing extension casing for images links * removing files that are not supposed to be here * js-skype-status: adding missing import for jquery in service * js-skype-status: aligning services with react version * adding missing telemetry code * js-skype-status: updating sample's readme to match standard * updating readme to latest version of the standard
|
@ -0,0 +1,25 @@
|
|||
# EditorConfig helps developers define and maintain consistent
|
||||
# coding styles between different editors and IDEs
|
||||
# editorconfig.org
|
||||
|
||||
root = true
|
||||
|
||||
|
||||
[*]
|
||||
|
||||
# change these settings to your own preference
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
|
||||
# we recommend you to keep these unchanged
|
||||
end_of_line = lf
|
||||
charset = utf-8
|
||||
trim_trailing_whitespace = true
|
||||
insert_final_newline = true
|
||||
|
||||
[*.md]
|
||||
trim_trailing_whitespace = false
|
||||
|
||||
[{package,bower}.json]
|
||||
indent_style = space
|
||||
indent_size = 2
|
|
@ -0,0 +1,32 @@
|
|||
# Logs
|
||||
logs
|
||||
*.log
|
||||
npm-debug.log*
|
||||
|
||||
# Dependency directories
|
||||
node_modules
|
||||
|
||||
# Build generated files
|
||||
dist
|
||||
lib
|
||||
solution
|
||||
temp
|
||||
*.sppkg
|
||||
|
||||
# Coverage directory used by tools like istanbul
|
||||
coverage
|
||||
|
||||
# OSX
|
||||
.DS_Store
|
||||
|
||||
# Visual Studio files
|
||||
.ntvs_analysis.dat
|
||||
.vs
|
||||
bin
|
||||
obj
|
||||
|
||||
# Resx Generated Code
|
||||
*.resx.ts
|
||||
|
||||
# Styles Generated Code
|
||||
*.scss.ts
|
|
@ -0,0 +1,8 @@
|
|||
{
|
||||
"@microsoft/generator-sharepoint": {
|
||||
"version": "1.3.4",
|
||||
"libraryName": "skype-presence-spfx",
|
||||
"libraryId": "fcfeb3e4-bf84-4405-81c1-9c8f5dbaabe6",
|
||||
"environment": "spo"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,69 @@
|
|||
# JavaScript Skype Status WebPart
|
||||
|
||||
## Summary
|
||||
This sample demonstrates how to use the UCWA JS Sdk for skype in the SharePoint Framework. It shows how to subscribe to status change of the different people of the organization but you can get much more information, checkout the [documentation](https://msdn.microsoft.com/en-us/skype/websdk/docs/generalreference?f=255&MSPPError=-2147217396)
|
||||
The goal is to demonstrate how you can leverage the SDK and to have the simplest approach, hence the usage of JQuery. No Framework (React, Angular, Knockout...) is used here but you can use that SDK in conjuction with any framwork.
|
||||
No branding has been applied to keep it simple but you could perfectly leverage Office Ui Fabric to display persona cards.
|
||||
|
||||
Allows you to properly display and subscribe to change of users' availibility.
|
||||
See the demo:
|
||||
![demo](./images/demo.gif)
|
||||
|
||||
## Used SharePoint Framework Version
|
||||
![drop](https://img.shields.io/badge/drop-GA-green.svg)
|
||||
|
||||
## Applies to
|
||||
|
||||
* [SharePoint Framework Developer](http://dev.office.com/sharepoint/docs/spfx/sharepoint-framework-overview)
|
||||
* [Office 365 developer tenant](http://dev.office.com/sharepoint/docs/spfx/set-up-your-developer-tenant)
|
||||
|
||||
## Solution
|
||||
|
||||
Solution|Author(s)
|
||||
--------|---------
|
||||
js-skype-status|[Vincent Biret](https://github.com/baywet)
|
||||
|
||||
|
||||
## Version history
|
||||
|
||||
Version|Date|Comments
|
||||
-------|----|--------
|
||||
1.0|December 1, 2017|Initial release
|
||||
|
||||
## Disclaimer
|
||||
**THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.**
|
||||
|
||||
---
|
||||
|
||||
## Minimal Path to Awesome
|
||||
### Authentication
|
||||
Because the Skype API's are secured, you first need to register an Azure Active Directory application.
|
||||
To do that go to `portal.azure.com` and sign in as your tenant adminstrator.
|
||||
![azure active directory](./images/1.PNG)
|
||||
Click on `Azure Active Directory`.
|
||||
![app registrations](./images/2.PNG)
|
||||
Click on on `App Registrations` and then `New Application Registration`
|
||||
![app details entry](./images/3.PNG)
|
||||
Enter any name, select `Web app / API` in `Application Type` and in `Sign-In URL` enter `https://*.sharepoint.com/*`, then click on `Create`
|
||||
![app details display](./images/4.PNG)
|
||||
Take note of the `application ID`, we'll need it later. Click on `required permissions`.
|
||||
![skype permission](./images/5.PNG)
|
||||
Click on `add` then `select an API` and select `Skype for Business`.
|
||||
![skype scopes](./images/6.PNG)
|
||||
Select under `delegated permissions` both `Read/Write Skype user contacts and groups` and `Read/Write Skype user information (preview)`, then click `select`. Finish by clicking `Done`.
|
||||
![grant permission](./images/7.PNG)
|
||||
Don't forget to click on `Grant permissions` and `yes`.
|
||||
|
||||
### Updating the app
|
||||
After copying that sample to your local machine and running `npm install` to install the depenencies, `/src/webparts/skypePresence/services/Constants.ts` open your favorite editor. Make sure you replace the value of `ApplicationIdKey` to the value application id we kept earlier.
|
||||
|
||||
### Deploying the application
|
||||
Start by running `gulp package-solution` and deploy the application to the app catalog. More information on how to do it [here](https://docs.microsoft.com/en-us/sharepoint/dev/spfx/web-parts/get-started/serve-your-web-part-in-a-sharepoint-page)
|
||||
**At the end select SkypePresence webpart instead**
|
||||
Don't forget to run `gulp serve --nobrowser` to start the debugging server.
|
||||
|
||||
### Addtional page required
|
||||
Because Skype needs to silently redirect the user to a page for the authentication flow, you need to create an additional page called `skypepresence` in your site.
|
||||
You don't need to add anything on that page.
|
||||
|
||||
![tracking image](https://telemetry.sharepointpnp.com/sp-dev-fx-webparts/samples/js-skype-status)
|
|
@ -0,0 +1,20 @@
|
|||
{
|
||||
"$schema": "https://dev.office.com/json-schemas/spfx-build/config.2.0.schema.json",
|
||||
"version": "2.0",
|
||||
"bundles": {
|
||||
"skype-presence-web-part": {
|
||||
"components": [
|
||||
{
|
||||
"entrypoint": "./lib/webparts/skypePresence/SkypePresenceWebPart.js",
|
||||
"manifest": "./src/webparts/skypePresence/SkypePresenceWebPart.manifest.json"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"externals": {
|
||||
"jquery": "https://cdnjs.cloudflare.com/ajax/libs/jquery/2.2.4/jquery.min.js"
|
||||
},
|
||||
"localizedResources": {
|
||||
"SkypePresenceWebPartStrings": "lib/webparts/skypePresence/loc/{locale}.js"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
{
|
||||
"$schema": "https://dev.office.com/json-schemas/spfx-build/copy-assets.schema.json",
|
||||
"deployCdnPath": "temp/deploy"
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
{
|
||||
"$schema": "https://dev.office.com/json-schemas/spfx-build/deploy-azure-storage.schema.json",
|
||||
"workingDir": "./temp/deploy/",
|
||||
"account": "<!-- STORAGE ACCOUNT NAME -->",
|
||||
"container": "skype-presence-spfx",
|
||||
"accessKey": "<!-- ACCESS KEY -->"
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
{
|
||||
"$schema": "https://dev.office.com/json-schemas/spfx-build/package-solution.schema.json",
|
||||
"solution": {
|
||||
"name": "skype-presence-spfx-client-side-solution",
|
||||
"id": "fcfeb3e4-bf84-4405-81c1-9c8f5dbaabe6",
|
||||
"version": "1.0.0.0",
|
||||
"skipFeatureDeployment": true
|
||||
},
|
||||
"paths": {
|
||||
"zippedPackage": "solution/skype-presence-spfx.sppkg"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
{
|
||||
"$schema": "https://dev.office.com/json-schemas/core-build/serve.schema.json",
|
||||
"port": 4321,
|
||||
"https": true,
|
||||
"initialPage": "https://localhost:5432/workbench",
|
||||
"api": {
|
||||
"port": 5432,
|
||||
"entryPath": "node_modules/@microsoft/sp-webpart-workbench/lib/api/"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,45 @@
|
|||
{
|
||||
"$schema": "https://dev.office.com/json-schemas/core-build/tslint.schema.json",
|
||||
// Display errors as warnings
|
||||
"displayAsWarning": true,
|
||||
// The TSLint task may have been configured with several custom lint rules
|
||||
// before this config file is read (for example lint rules from the tslint-microsoft-contrib
|
||||
// project). If true, this flag will deactivate any of these rules.
|
||||
"removeExistingRules": true,
|
||||
// When true, the TSLint task is configured with some default TSLint "rules.":
|
||||
"useDefaultConfigAsBase": false,
|
||||
// Since removeExistingRules=true and useDefaultConfigAsBase=false, there will be no lint rules
|
||||
// which are active, other than the list of rules below.
|
||||
"lintConfig": {
|
||||
// Opt-in to Lint rules which help to eliminate bugs in JavaScript
|
||||
"rules": {
|
||||
"class-name": false,
|
||||
"export-name": false,
|
||||
"forin": false,
|
||||
"label-position": false,
|
||||
"member-access": true,
|
||||
"no-arg": false,
|
||||
"no-console": false,
|
||||
"no-construct": false,
|
||||
"no-duplicate-case": true,
|
||||
"no-duplicate-variable": true,
|
||||
"no-eval": false,
|
||||
"no-function-expression": true,
|
||||
"no-internal-module": true,
|
||||
"no-shadowed-variable": true,
|
||||
"no-switch-case-fall-through": true,
|
||||
"no-unnecessary-semicolons": true,
|
||||
"no-unused-expression": true,
|
||||
"no-use-before-declare": true,
|
||||
"no-with-statement": true,
|
||||
"semicolon": true,
|
||||
"trailing-comma": false,
|
||||
"typedef": false,
|
||||
"typedef-whitespace": false,
|
||||
"use-named-parameter": true,
|
||||
"valid-typeof": true,
|
||||
"variable-name": false,
|
||||
"whitespace": false
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
{
|
||||
"$schema": "https://dev.office.com/json-schemas/spfx-build/write-manifests.schema.json",
|
||||
"cdnBasePath": "<!-- PATH TO CDN -->"
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
'use strict';
|
||||
|
||||
const gulp = require('gulp');
|
||||
const build = require('@microsoft/sp-build-web');
|
||||
|
||||
build.initialize(gulp);
|
After Width: | Height: | Size: 35 KiB |
After Width: | Height: | Size: 20 KiB |
After Width: | Height: | Size: 11 KiB |
After Width: | Height: | Size: 62 KiB |
After Width: | Height: | Size: 69 KiB |
After Width: | Height: | Size: 70 KiB |
After Width: | Height: | Size: 18 KiB |
After Width: | Height: | Size: 636 KiB |
|
@ -0,0 +1,31 @@
|
|||
{
|
||||
"name": "skype-presence-spfx",
|
||||
"version": "0.0.1",
|
||||
"private": true,
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
},
|
||||
"scripts": {
|
||||
"build": "gulp bundle",
|
||||
"clean": "gulp clean",
|
||||
"test": "gulp test"
|
||||
},
|
||||
"dependencies": {
|
||||
"@microsoft/sp-core-library": "~1.3.4",
|
||||
"@microsoft/sp-lodash-subset": "~1.3.4",
|
||||
"@microsoft/sp-office-ui-fabric-core": "~1.3.4",
|
||||
"@microsoft/sp-webpart-base": "~1.3.4",
|
||||
"@types/webpack-env": ">=1.12.1 <1.14.0",
|
||||
"jquery": "^2.2.4"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@microsoft/sp-build-web": "~1.3.4",
|
||||
"@microsoft/sp-module-interfaces": "~1.3.4",
|
||||
"@microsoft/sp-webpart-workbench": "~1.3.4",
|
||||
"@types/chai": ">=3.4.34 <3.6.0",
|
||||
"@types/jquery": "^2.0.48",
|
||||
"@types/mocha": ">=2.2.33 <2.6.0",
|
||||
"ajv": "~5.2.2",
|
||||
"gulp": "~3.9.1"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
{
|
||||
"$schema": "https://dev.office.com/json-schemas/spfx/client-side-web-part-manifest.schema.json",
|
||||
"id": "cd41bf93-187a-47db-8ef1-ee84b37706ce",
|
||||
"alias": "SkypePresenceWebPart",
|
||||
"componentType": "WebPart",
|
||||
|
||||
// The "*" signifies that the version should be taken from the package.json
|
||||
"version": "*",
|
||||
"manifestVersion": 2,
|
||||
|
||||
// If true, the component can only be installed on sites where Custom Script is allowed.
|
||||
// Components that allow authors to embed arbitrary script code should set this to true.
|
||||
// https://support.office.com/en-us/article/Turn-scripting-capabilities-on-or-off-1f2c515f-5d7e-448a-9fd7-835da935584f
|
||||
"requiresCustomScript": false,
|
||||
|
||||
"preconfiguredEntries": [{
|
||||
"groupId": "5c03119e-3074-46fd-976b-c60198311f70", // Other
|
||||
"group": { "default": "Other" },
|
||||
"title": { "default": "SkypePresence" },
|
||||
"description": { "default": "Demonstration webpart leveraging UCWA and presence subscription" },
|
||||
"officeFabricIconFontName": "Page",
|
||||
"properties": {
|
||||
"description": "SkypePresence"
|
||||
}
|
||||
}]
|
||||
}
|
|
@ -0,0 +1,74 @@
|
|||
@import '~@microsoft/sp-office-ui-fabric-core/dist/sass/SPFabricCore.scss';
|
||||
|
||||
.skypePresence {
|
||||
.container {
|
||||
max-width: 700px;
|
||||
margin: 0px auto;
|
||||
box-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.2), 0 25px 50px 0 rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.row {
|
||||
@include ms-Grid-row;
|
||||
@include ms-fontColor-white;
|
||||
background-color: $ms-color-themeDark;
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
.column {
|
||||
@include ms-Grid-col;
|
||||
@include ms-lg10;
|
||||
@include ms-xl8;
|
||||
@include ms-xlPush2;
|
||||
@include ms-lgPush1;
|
||||
}
|
||||
|
||||
.title {
|
||||
@include ms-font-xl;
|
||||
@include ms-fontColor-white;
|
||||
}
|
||||
|
||||
.subTitle {
|
||||
@include ms-font-l;
|
||||
@include ms-fontColor-white;
|
||||
}
|
||||
|
||||
.description {
|
||||
@include ms-font-l;
|
||||
@include ms-fontColor-white;
|
||||
}
|
||||
|
||||
.button {
|
||||
// Our button
|
||||
text-decoration: none;
|
||||
height: 32px;
|
||||
|
||||
// Primary Button
|
||||
min-width: 80px;
|
||||
background-color: $ms-color-themePrimary;
|
||||
border-color: $ms-color-themePrimary;
|
||||
color: $ms-color-white;
|
||||
|
||||
// Basic Button
|
||||
outline: transparent;
|
||||
position: relative;
|
||||
font-family: "Segoe UI WestEuropean","Segoe UI",-apple-system,BlinkMacSystemFont,Roboto,"Helvetica Neue",sans-serif;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
font-size: $ms-font-size-m;
|
||||
font-weight: $ms-font-weight-regular;
|
||||
border-width: 0;
|
||||
text-align: center;
|
||||
cursor: pointer;
|
||||
display: inline-block;
|
||||
padding: 0 16px;
|
||||
|
||||
.label {
|
||||
font-weight: $ms-font-weight-semibold;
|
||||
font-size: $ms-font-size-m;
|
||||
height: 32px;
|
||||
line-height: 32px;
|
||||
margin: 0 4px;
|
||||
vertical-align: top;
|
||||
display: inline-block;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,68 @@
|
|||
import { Version } from "@microsoft/sp-core-library";
|
||||
import {
|
||||
BaseClientSideWebPart,
|
||||
IPropertyPaneConfiguration,
|
||||
PropertyPaneTextField
|
||||
} from "@microsoft/sp-webpart-base";
|
||||
import { escape } from "@microsoft/sp-lodash-subset";
|
||||
import * as jquery from "jquery";
|
||||
|
||||
import styles from "./SkypePresenceWebPart.module.scss";
|
||||
import * as strings from "SkypePresenceWebPartStrings";
|
||||
import { SkypeForBusinessCommunicationService } from "./services";
|
||||
|
||||
export interface ISkypePresenceWebPartProps {
|
||||
description: string;
|
||||
}
|
||||
|
||||
export default class SkypePresenceWebPartWebPart extends BaseClientSideWebPart<ISkypePresenceWebPartProps> {
|
||||
|
||||
public render(): void {
|
||||
const skypeService: SkypeForBusinessCommunicationService = new SkypeForBusinessCommunicationService(() => this.context);
|
||||
this.domElement.innerHTML = `
|
||||
<div class="${ styles.skypePresence }">
|
||||
<div class="${ styles.container }">
|
||||
<div class="${ styles.row }">
|
||||
<div class="${ styles.column }">
|
||||
<span class="${ styles.title }">Skype presence with UCWA JS SDK sample for SPFX</span>
|
||||
<p class="${ styles.subTitle }">Enter the email address of the user you want to see the status change</p>
|
||||
<input type="email" id="emailaddress" /><input type="button" value="subscribe" id="subbutton" /><br />
|
||||
Status <span id="status">Loading...</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>`;
|
||||
jquery("#subbutton").click(async () => {
|
||||
const emailAddress: string = jquery("#emailaddress").val() as string;
|
||||
await skypeService.SubscribeToStatusChangeForUser(emailAddress, "Name", (newStatus, oldStatus, displayName) => {
|
||||
jquery("#status").text(newStatus);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
protected get dataVersion(): Version {
|
||||
return Version.parse("1.0");
|
||||
}
|
||||
|
||||
protected getPropertyPaneConfiguration(): IPropertyPaneConfiguration {
|
||||
return {
|
||||
pages: [
|
||||
{
|
||||
header: {
|
||||
description: strings.PropertyPaneDescription
|
||||
},
|
||||
groups: [
|
||||
{
|
||||
groupName: strings.BasicGroupName,
|
||||
groupFields: [
|
||||
PropertyPaneTextField("description", {
|
||||
label: strings.DescriptionFieldLabel
|
||||
})
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
};
|
||||
}
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
define([], function() {
|
||||
return {
|
||||
"PropertyPaneDescription": "Description",
|
||||
"BasicGroupName": "Group Name",
|
||||
"DescriptionFieldLabel": "Description Field"
|
||||
}
|
||||
});
|
|
@ -0,0 +1,10 @@
|
|||
declare interface ISkypePresenceWebPartStrings {
|
||||
PropertyPaneDescription: string;
|
||||
BasicGroupName: string;
|
||||
DescriptionFieldLabel: string;
|
||||
}
|
||||
|
||||
declare module 'SkypePresenceWebPartStrings' {
|
||||
const strings: ISkypePresenceWebPartStrings;
|
||||
export = strings;
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
import { IWebPartContext} from "@microsoft/sp-webpart-base";
|
||||
import { CommunicationServiceConfiguration, Constants, ICommunicationConfigurationService } from "./";
|
||||
|
||||
export class CommunicationConfigurationService implements ICommunicationConfigurationService {
|
||||
private _currentConfiguration: CommunicationServiceConfiguration;
|
||||
private _webPartContext: IWebPartContext;
|
||||
public constructor(WebPartContext: IWebPartContext) {
|
||||
this._webPartContext = WebPartContext;
|
||||
}
|
||||
public async getCurrentConfiguration(): Promise<CommunicationServiceConfiguration> {
|
||||
if (!this._currentConfiguration) {
|
||||
this._currentConfiguration = new CommunicationServiceConfiguration();
|
||||
this._currentConfiguration.ClientId = Constants.ApplicationIdKey;
|
||||
this._currentConfiguration.RedirectUri =
|
||||
`${this._webPartContext.pageContext.web.absoluteUrl}${Constants.ApplicationRedirectUrl}`;
|
||||
return this._currentConfiguration;
|
||||
} else {
|
||||
return Promise.resolve(this._currentConfiguration);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
export class CommunicationServiceConfiguration {
|
||||
public RedirectUri: string;
|
||||
public ClientId: string;
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
export class Constants {
|
||||
public static ApplicationIdKey = "application id";
|
||||
public static ApplicationRedirectUrl = "/SitePages/skypepresence.aspx";
|
||||
public static ErrorCategory = "communication service";
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
import {CommunicationServiceConfiguration } from "./";
|
||||
|
||||
export interface ICommunicationConfigurationService {
|
||||
getCurrentConfiguration(): Promise<CommunicationServiceConfiguration>;
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
export interface ICommunicationService {
|
||||
SubscribeToStatusChangeForUser(userEmail: string, userDisplayName: string,
|
||||
handler: (newStatus: string, oldStatus: string, displayName: string) => void): Promise<boolean>;
|
||||
}
|
|
@ -0,0 +1,84 @@
|
|||
import { Log } from "@microsoft/sp-core-library";
|
||||
import { IWebPartContext} from "@microsoft/sp-webpart-base";
|
||||
import { Constants, CommunicationConfigurationService, ICommunicationConfigurationService, ICommunicationService } from "./";
|
||||
import * as jQuery from "jquery";
|
||||
declare var Skype: any;
|
||||
|
||||
export class SkypeForBusinessCommunicationService implements ICommunicationService {
|
||||
private static initializePromise: any;
|
||||
private static configurationService: ICommunicationConfigurationService;
|
||||
private static webPartContext: () => IWebPartContext;
|
||||
public constructor(WebPartContext: () => IWebPartContext) {
|
||||
SkypeForBusinessCommunicationService.configurationService = new CommunicationConfigurationService(WebPartContext());
|
||||
SkypeForBusinessCommunicationService.webPartContext = WebPartContext;
|
||||
}
|
||||
public async SubscribeToStatusChangeForUser(userEmail: string, userDisplayName: string,
|
||||
handler: (newStatus: string, oldStatus: string, displayName: string) => void): Promise<boolean> {
|
||||
if (!userEmail || !handler) {
|
||||
return false;
|
||||
}
|
||||
userDisplayName = userDisplayName.replace("(...)", "");
|
||||
const skypeApp: any = await this.Initialize();
|
||||
const personsAndGroupsManager: any = skypeApp.personsAndGroupsManager;
|
||||
const mePerson: any = personsAndGroupsManager.mePerson;
|
||||
if (SkypeForBusinessCommunicationService.webPartContext().pageContext.user.email === userEmail) {
|
||||
Log.info(Constants.ErrorCategory, `Bypassed skype subscription for current user ${userEmail}`);
|
||||
handler("Online", undefined, mePerson.displayName());
|
||||
} else {
|
||||
const query: any = personsAndGroupsManager.createPersonSearchQuery();
|
||||
query.text(userEmail);
|
||||
query.limit(1);
|
||||
await query.getMore();
|
||||
query.results().forEach((result) => {
|
||||
const person: any = result.result;
|
||||
if (person.id().indexOf(userEmail) !== -1) {
|
||||
handler("Offline", undefined, userDisplayName);
|
||||
person.status.changed((newStatus, reason, oldStatus) => {
|
||||
Log.info(Constants.ErrorCategory,
|
||||
`${person.displayName()} status changed from ${oldStatus} to ${newStatus} because ${reason}`);
|
||||
handler(newStatus, oldStatus, person.displayName());
|
||||
});
|
||||
person.status.subscribe();
|
||||
}
|
||||
});
|
||||
}
|
||||
return true;
|
||||
}
|
||||
private Initialize(): Promise<any> {
|
||||
if (!SkypeForBusinessCommunicationService.initializePromise) {
|
||||
SkypeForBusinessCommunicationService.initializePromise = new Promise<any>((resolve, reject) => {
|
||||
return SkypeForBusinessCommunicationService.configurationService.getCurrentConfiguration().then((currentConfiguration) => {
|
||||
return jQuery.getScript("https://swx.cdn.skype.com/shared/v/1.2.36/SkypeBootstrap.min.js").then(() => {
|
||||
const config: {apiKey: string, apiKeyCC: string} = {
|
||||
apiKey: "a42fcebd-5b43-4b89-a065-74450fb91255", // sdk
|
||||
apiKeyCC: "9c967f6b-a846-4df2-b43d-5167e47d81e1", // sdk+ui
|
||||
};
|
||||
if (currentConfiguration && currentConfiguration.ClientId) {
|
||||
Skype.initialize({ apiKey: config.apiKey }, (api) => {
|
||||
const app: any = new api.application();
|
||||
app.signInManager.signIn ({
|
||||
client_id: currentConfiguration.ClientId,
|
||||
cors: true,
|
||||
origins: ["https://webdir.online.lync.com/autodiscover/autodiscoverservice.svc/root"],
|
||||
redirect_uri: currentConfiguration.RedirectUri,
|
||||
}).then(() => {
|
||||
resolve(app);
|
||||
}, (err: any) => {
|
||||
Log.error(Constants.ErrorCategory, new Error(`cannot sign in ${err}`));
|
||||
location.assign("https://login.microsoftonline.com/common/oauth2/authorize?response_type=token" +
|
||||
"&client_id=" + currentConfiguration.ClientId +
|
||||
"&redirect_uri=" + location.href +
|
||||
"&resource=https://webdir.online.lync.com");
|
||||
reject(err);
|
||||
});
|
||||
});
|
||||
} else {
|
||||
Log.error(Constants.ErrorCategory, new Error(`configuration missing for skype presence service`));
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
return SkypeForBusinessCommunicationService.initializePromise;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
export * from "./ICommunicationService";
|
||||
export * from "./SkypeForBusinessCommunicationService";
|
||||
export * from "./ICommunicationConfigurationService";
|
||||
export * from "./CommunicationConfigurationService";
|
||||
export * from "./Constants";
|
||||
export * from "./CommunicationServiceConfiguration";
|
|
@ -0,0 +1,9 @@
|
|||
/// <reference types="mocha" />
|
||||
|
||||
import { assert } from 'chai';
|
||||
|
||||
describe('SkypePresenceWebPart', () => {
|
||||
it('should do something', () => {
|
||||
assert.ok(true);
|
||||
});
|
||||
});
|
|
@ -0,0 +1,16 @@
|
|||
{
|
||||
"compilerOptions": {
|
||||
"target": "es5",
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"module": "commonjs",
|
||||
"jsx": "react",
|
||||
"declaration": true,
|
||||
"sourceMap": true,
|
||||
"experimentalDecorators": true,
|
||||
"types": [
|
||||
"es6-promise",
|
||||
"es6-collections",
|
||||
"webpack-env"
|
||||
]
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
// Type definitions for Microsoft ODSP projects
|
||||
// Project: ODSP
|
||||
|
||||
/* Global definition for UNIT_TEST builds
|
||||
Code that is wrapped inside an if(UNIT_TEST) {...}
|
||||
block will not be included in the final bundle when the
|
||||
--ship flag is specified */
|
||||
declare const UNIT_TEST: boolean;
|
||||
|
||||
/* Global defintion for SPO builds */
|
||||
declare const DATACENTER: boolean;
|
|
@ -0,0 +1 @@
|
|||
/// <reference path="@ms/odsp.d.ts" />
|