Skip to content

Commit

Permalink
Updated: Integrated into Microsoft Teams
Browse files Browse the repository at this point in the history
  • Loading branch information
WrathOfZombies committed Jan 7, 2017
1 parent f87db12 commit 604aa97
Show file tree
Hide file tree
Showing 14 changed files with 373 additions and 4 deletions.
15 changes: 15 additions & 0 deletions config.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<!doctype html>
<html lang="en" data-framework="typescript">

<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>React • TodoMVC • Config</title>
</head>

<body class="config">
<section class="configApp"></section>
<script src="https://statics.teams.microsoft.com/sdk/v0.2/js/MicrosoftTeams.js"></script>
</body>

</html>
14 changes: 13 additions & 1 deletion config/webpack.common.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ var ExtractTextPlugin = require('extract-text-webpack-plugin');
module.exports = {
entry: {
'app': './src/app.tsx',
'config': './src/config.tsx',
'vendor': './src/vendor.ts'
},

Expand Down Expand Up @@ -35,7 +36,11 @@ module.exports = {

preLoaders: [
// All output '.js' files will have any sourcemaps re-processed by 'source-map-loader'.
{ test: /\.js$/, loader: 'source-map-loader' }
{
test: /\.js$/,
loader: 'source-map-loader',
exclude: /node_modules/
}
]
},

Expand All @@ -47,6 +52,13 @@ module.exports = {
chunks: ['app', 'vendor']
}),

new HtmlWebpackPlugin({
title: 'Config • TodoMVC',
filename: 'config.html',
template: path.resolve('config.html'),
chunks: ['config', 'vendor']
}),

new ExtractTextPlugin('[name].css'),

new webpack.ProvidePlugin({
Expand Down
1 change: 1 addition & 0 deletions index.html
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
</footer>

<script type="text/javascript" src="node_modules/director/build/director.min.js"></script>
<script src="https://statics.teams.microsoft.com/sdk/v0.2/js/MicrosoftTeams.js"></script>
</body>

</html>
28 changes: 28 additions & 0 deletions package/manifest.dev.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
{
"$schema": "https://statics.teams.microsoft.com/sdk/v0.2/manifest/MicrosoftTeams.schema.json",
"manifestVersion": "0.2",
"id": "com.example.microsoftteamstabs.tododev",
"version": "0.2",
"name": "ToDo [Dev]",
"developer": {
"name": "Example company",
"websiteUrl": "http://www.example.com",
"privacyUrl": "http://www.example.com/privacy",
"termsOfUseUrl": "http://www.example.com/termsofuse"
},
"description": {
"short": "Create and manange your Outlook tasks.",
"full": "Create and manange your Outlook tasks. Sign in using your Office 365 work/school account, and click Save."
},
"icons": {
"44": "todo44.png",
"88": "todo88.png"
},
"accentColor": "#004578",
"configUrl": "https://localhost:3000/config.html",
"canUpdateConfig": true,
"needsIdentity": true,
"validDomains": [
"*.login.microsoftonline.com"
]
}
28 changes: 28 additions & 0 deletions package/manifest.prod.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
{
"$schema": "https://statics.teams.microsoft.com/sdk/v0.2/manifest/MicrosoftTeams.schema.json",
"manifestVersion": "0.2",
"id": "com.example.microsoftteamstabs.todoprod",
"version": "0.2",
"name": "ToDo",
"developer": {
"name": "Example company",
"websiteUrl": "http://www.example.com",
"privacyUrl": "http://www.example.com/privacy",
"termsOfUseUrl": "http://www.example.com/termsofuse"
},
"description": {
"short": "Create and manange your Outlook tasks.",
"full": "Create and manange your Outlook tasks. Sign in using your Office 365 work/school account, and click Save."
},
"icons": {
"44": "todo44.png",
"88": "todo88.png"
},
"accentColor": "#004578",
"configUrl": "https://teams-todo-sample.azurewebsites.net/config.html",
"canUpdateConfig": true,
"needsIdentity": true,
"validDomains": [
"*.login.microsoftonline.com"
]
}
Binary file added package/todo.dev.zip
Binary file not shown.
Binary file added package/todo.prod.zip
Binary file not shown.
Binary file added package/todo44.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added package/todo88.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
148 changes: 148 additions & 0 deletions src/MicrosoftTeams.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,148 @@
declare namespace microsoftTeams
{
// Initializes the library. This must be called before any other API calls.
// The caller should only call this once the frame is loaded successfully.
function initialize(): void;

// Retrieves the current context the frame is running in.
function getContext(callback: (context: Context) => void): void;

// Registers a handler for when the user changes their theme.
// Only one handler may be registered at a time. Subsequent registrations will override the first.
function registerOnThemeChangeHandler(handler: (theme: string) => void): void;

// Navigates the frame to a new cross-domain URL. The domain of this URL must match at least one of the
// valid domains specified in the tab manifest; otherwise, an exception will be thrown. This API only
// needs to be used when navigating the frame to a URL in a different domain than the current one in
// a way that keeps the SkypeTeams app informed of the change and allows the API to continue working.
function navigateCrossDomain(url: string): void;

// Namespace to interact with the settings view-specific API.
// This object is only usable on the settings frame.
namespace settings
{
// Sets the validity state for the settings.
// The inital value is false so the user will not be able to save the settings until this is called with true.
function setValidityState(validityState: boolean): void;

// Gets the settings for the current instance.
function getSettings(callback: (settings: Settings) => void): void;

// Sets the settings for the current instance.
// Note that this is an asynchronous operation so there are no guarentees as to when calls
// to getSettings will reflect the changed state.
function setSettings(settings: Settings): void;

// Registers a handler for when the user attempts to save the settings. This handler should be used
// to create or update the underlying resource powering the content.
// The object passed to the handler must be used to notify whether to proceed with the save.
// Only one handler may be registered at a time. Subsequent registrations will override the first.
function registerOnSaveHandler(handler: (evt: SaveEvent) => void): void;

// Registers a handler for when the user attempts to remove the content. This handler should be used
// to remove the underlying resource powering the content.
// The object passed to the handler must be used to notify whether to proceed with the remove
// Only one handler may be registered at a time. Subsequent registrations will override the first.
function registerOnRemoveHandler(handler: (evt: RemoveEvent) => void): void;

interface Settings
{
// A suggested display name for the new content.
// In the settings for an existing instance being updated, this call has no effect.
suggestedDisplayName?: string;

// Sets the url to use for the content of this instance.
contentUrl: string;

// Sets the remove URL for the remove config experience
removeUrl?: string;

// Sets the url to use for the external link to view the underlying resource in a browser.
websiteUrl?: string;

// The custom settings for this content instance.
// The developer may use this for generic storage specific to this instance,
// for example a JSON blob describing the previously selected options used to pre-populate the UI.
// The string must be less than 1kb.
customSettings?: string;
}

interface SaveEvent
{
// Notifies that the underlying resource has been created and the settings may be saved.
notifySuccess(): void;

// Notifies that the underlying resource creation failed and that the settings may not be saved.
notifyFailure(reason?: string): void;
}

interface RemoveEvent
{
// Notifies that the underlying resource has been removed and the content may be removed.
notifySuccess(): void;

// Notifies that the underlying resource removal failed and that the content may not be removed.
notifyFailure(reason?: string): void;
}
}

namespace authentication
{
// Initiates an authentication request which pops up a new windows with the specified settings.
function authenticate(authenticateParameters: AuthenticateParameters): void;

// Notifies the frame that initiated this authentication request that the request was successful.
// This function is only usable on the authentication window.
// This call causes the authentication window to be closed.
function notifySuccess(result?: string): void;

// Notifies the frame that initiated this authentication request that the request failed.
// This function is only usable on the authentication window.
// This call causes the authentication window to be closed.
function notifyFailure(reason?: string): void;

interface AuthenticateParameters
{
// The url for the authentication popup
url: string,

// The preferred width for the popup. Note that this value may be ignored if outside the acceptable bounds.
width?: number,

// The preferred height for the popup. Note that this value may be ignored if outside the acceptable bounds.
height?: number,

// A function which is called if the authentication succeeds with the result returned from the authentication popup.
successCallback?: (result?: string) => void,

// A function which is called if the authentication fails with the reason for the failure returned from the authentication popup.
failureCallback?: (reason?: string) => void
}
}

interface Context
{
// The O365 group id for the team with which the content is associated.
// This field is only available when needsIdentity is set in the manifest.
groupId?: string;

// The current locale that the user has configured for the app formatted as
// languageId-countryId (e.g. en-us).
locale: string;

// The current user's upn.
// As a malicious party can host content in a malicious browser, this value should only
// be used as a hint as to who the user is and never as proof of identity.
// This field is only available when needsIdentity is set in the manifest.
upn?: string;

// The current user's AAD tenant id.
// As a malicious party can host content in a malicious browser, this value should only
// be used as a hint as to who the user is and never as proof of identity.
// This field is only available when needsIdentity is set in the manifest.
tid?: string;

// The current UI theme the user is using.
theme?: string;
}
}
29 changes: 29 additions & 0 deletions src/app.css
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,35 @@ body {
background-color: #004578;
}

body.config {
background-color: #FFFFFF;
margin: 0;
padding: 0;
}

.config p {
padding: 0;
margin: 0;
}

.config .ms-Persona {
margin-top: 30px;
}

.config .ms-Persona-details p:first-child {
margin-bottom: 15px;
opacity: 0.6;
}

.config .ms-Persona-details p:last-child {
margin-top: 8px;
opacity: 0.6;
}

.config .ms-Button {
margin-top: 20px;
}

.todoapp h1 {
color: #c7e0f4;
}
Expand Down
15 changes: 13 additions & 2 deletions src/app.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import * as React from 'react';
import * as ReactDOM from 'react-dom';
import { TodoApp } from './todoApp';
import { TodoModel } from './core';
import { Authenticator } from '@microsoft/office-js-helpers';

var model = new TodoModel('react-todos');

Expand All @@ -12,5 +13,15 @@ function render() {
);
}

model.subscribe(render);
render();
/** initialize throws if called more than once and hence is wrapped in a try-catch to perform a safe initialization. */

try {
microsoftTeams.initialize();
}
catch (e) {
}

if (!Authenticator.isAuthDialog(true /* Use Microsoft Teams Dialog */)) {
model.subscribe(render);
render();
}
Loading

0 comments on commit 604aa97

Please sign in to comment.