-
Notifications
You must be signed in to change notification settings - Fork 27
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit f87db12
Showing
25 changed files
with
1,436 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
node_modules/** | ||
typings/** | ||
dist/** | ||
.vscode/** |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
microsoft-teams-sample-todo | ||
|
||
Copyright (c) Microsoft Corporation. All rights reserved. | ||
|
||
MIT License | ||
|
||
Permission is hereby granted, free of charge, to any person obtaining | ||
a copy of this software and associated documentation files (the | ||
"Software"), to deal in the Software without restriction, including | ||
without limitation the rights to use, copy, modify, merge, publish, | ||
distribute, sublicense, and/or sell copies of the Software, and to | ||
permit persons to whom the Software is furnished to do so, subject to | ||
the following conditions: | ||
|
||
The above copyright notice and this permission notice shall be | ||
included in all copies or substantial portions of the Software. | ||
|
||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | ||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | ||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND | ||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE | ||
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION | ||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION | ||
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,146 @@ | ||
# Microsoft Teams 'Todo List' sample tab app | ||
|
||
This is an example [tab app for Microsoft Teams](https://aka.ms/microsoftteamstabsplatform). The point of this sample to illustrate how simple it is to convert an existing web app into a Microsoft Teams tab app. The existing web app, [**TodoMVC for React**](https://github.com/tastejs/todomvc/tree/gh-pages/examples/typescript-react), provides a basic task manager which integrates with your personal Outlook Tasks. With only a few minor modifications, this web view can be added to a channel as a tab app. Take a look at the [code diff between the 'before' and 'after' branches](https://github.com/OfficeDev/microsoft-teams-sample-todo/compare/85ac809a2b52b528e8323a0a14e419afca21da12...9a1224eb276fa15a76f9e4882c4abe5ae8b68a99) to see what changes were made. | ||
|
||
> **Note:** This is not a realistic example of a team collaboration app. The tasks shown belong to the user's individual account and not to a shared team account. | ||
**For more information on developing experiences for Microsoft Teams, please review the Microsoft Teams [developer documentation](https://msdn.microsoft.com/en-us/microsoft-teams/index).** | ||
|
||
## Prerequisites | ||
|
||
1. An [Office 365 account with access to Microsoft Teams](https://msdn.microsoft.com/en-us/microsoft-teams/setup). | ||
2. This sample is built using [Node.js](https://nodejs.org). Download and install the recommended version if you don't already have it. | ||
|
||
## Run the app | ||
|
||
### Host the tab apps "configuration page" and "content page" | ||
|
||
To enable the app in Dev mode: | ||
1. Clone the repo. | ||
2. Open a command line in the repo subdirectory. | ||
3. Run `npm install` (included as part of Node.js) from the command line. | ||
4. Run `npm start` to start the `webpack-dev-server` to enable the dev app to function. | ||
5. Alternatively, run `npm run build` to generate a deployable build, which you can host in your own environment. Note: you will need to modify the config.url in the manifest to point to your hosting location. [More information](#registering-an-application-to-authenticate-with-microsoft) | ||
|
||
### Add the tab to Microsoft Teams | ||
|
||
1. Download the [tab app dev package](https://github.com/OfficeDev/microsoft-teams-sample-todo/raw/before-final/package/todo.dev.zip) zip file for this sample. | ||
2. Create a new team for testing, if necessary. Click **Create team** at the bottom of the left-hand panel. | ||
3. Select the team from the left-hand panel, select **... (more options)** and then select **View Team**. | ||
4. Select the **Developer (Preview)** tab, and then select **Upload**. | ||
5. Navigate to the downloaded zip file from step 1 above and select it. | ||
6. Go to any channel in the team. Click the '+' to the right of the existing tabs. | ||
7. Select your tab from the gallery that appears. | ||
8. Accept the consent prompt. | ||
9. If needed, sign in using your Office 365 work/school account. Note that the code will try to do silent authentication if possible. | ||
10. Validate authentication information. | ||
11. Hit Save to add the tab to channel. | ||
|
||
> **Note:** To re-upload an updated package, with the same `id`, click the 'Replace' icon at the end of the tab's table row. Don't click 'Upload' again: Microsoft Teams will say the tab already exists. | ||
> It is advisable to have multiple configs, one per environment. The names of the zip files can be anything such as `todo.dev.zip`, `todo.prod.zip` etc. but the zip must contain a `manifest.json` with a unique `id`. See [Creating a manifest for your tab](https://msdn.microsoft.com/en-us/microsoft-teams/createpackage). | ||
## Code walk through | ||
|
||
While the `master` branch shows the latest state of the sample, take a look at the following [code diff](https://github.com/OfficeDev/microsoft-teams-sample-todo/compare/85ac809a2b52b528e8323a0a14e419afca21da12...9a1224eb276fa15a76f9e4882c4abe5ae8b68a99) between: | ||
|
||
* [`before`](https://github.com/OfficeDev/microsoft-teams-sample-todo/commit/85ac809a2b52b528e8323a0a14e419afca21da12): the initial app | ||
|
||
* [`after`](https://github.com/OfficeDev/microsoft-teams-sample-todo/commit/9a1224eb276fa15a76f9e4882c4abe5ae8b68a99): the app after integration with Microsoft Teams. | ||
|
||
Going through this step by step: | ||
|
||
1. We have added a new `config.html` and `config.tsx` page which is responsible for the the application to allow the user to manipulate any settings, perform single signon Authentication etc. during the first launch. This is required so that the team administrator can configure the application/settings. See [Create the configuration page](https://msdn.microsoft.com/en-us/microsoft-teams/createconfigpage). | ||
|
||
2. We have added the same `config.html` file to our `webpack.common.js` configuration so that it can inject the right bundles during runtime. | ||
|
||
3. We add a reference to `MicrosoftTeams.js` in our index.html and added `MicrosoftTeams.d.ts` for Typescript intellisense. | ||
|
||
4. We have added a `manifest.dev.json`, `manifest.prod.json` and two logos for size *44x44* and *88x88*. Remember to rename these as `manifest.json` in your zip files that you upload to Microsoft Teams. | ||
|
||
5. We have added some styles to our `app.css`. | ||
|
||
6. Finally we have modified the `authentication` in outlook.tasks.ts to depend instead on 'useMicrosoftTeamsAuth', a new feature from the beta version of OfficeHelpers referenced in this sample. | ||
|
||
### Invoking the Authentication dialog | ||
|
||
When the user adds the tab, the configuration page is presented (config.html). In this case, the code authenticates the user if possible. | ||
|
||
Authentication leverages a new Teams-specific function in the latest (>0.4.0) version of the [office-js-helpers](https://github.com/OfficeDev/office-js-helpers) library. This helper function will attempt to silently authenticate, but if it cannot, it will call the Microsoft Teams specific auth dialog for you. For more information on the full Authentication process in Microsoft Teams, please review [Authenticating a user](https://msdn.microsoft.com/en-us/microsoft-teams/auth) in the Microsoft Teams [developer documentation](https://msdn.microsoft.com/en-us/microsoft-teams/index). | ||
|
||
In outlook.tasks.ts: | ||
```typescript | ||
return this.authenticator.authenticate('Microsoft') | ||
.then(token => this._token = token) | ||
.catch(error => { | ||
Utilities.log(error); | ||
throw new Error('Failed to login using your Microsoft Account'); | ||
}); | ||
``` | ||
|
||
### Handling the 'Save' event | ||
|
||
After successful sign-in, the user will Save the tab into the channel. The following code enables the Save button, and sets the SaveHandler, which will store what content to display in the tab (in this case, just the project's index.html). | ||
|
||
In config.tsx: | ||
```typescript | ||
initialize({ groupId, upn}) { | ||
this.setState({ groupId, upn }); | ||
console.log(this.state); | ||
/** Enable the Save button */ | ||
microsoftTeams.settings.setValidityState(true); | ||
/** Register the save handler */ | ||
microsoftTeams.settings.registerOnSaveHandler(saveEvent => { | ||
/** Store Tab content settings */ | ||
microsoftTeams.settings.setSettings({ | ||
contentUrl: `${location.origin}/index.html`, | ||
suggestedDisplayName: "My Tasks", | ||
websiteUrl: `${location.origin}/index.html` | ||
}); | ||
saveEvent.notifySuccess(); | ||
}); | ||
} | ||
``` | ||
|
||
## Technology used | ||
|
||
|
||
It uses the following stack: | ||
|
||
1. [`React by Facebook`](https://facebook.github.io/react/) as the UI Framework. | ||
2. [`TypeScript`](https://www.typescriptlang.org/) as the transpiler. | ||
4. [`TodoMVC`](http://todomvc.com/examples/typescript-react/#/) base for TodoMVC functionality. | ||
5. [`Webpack`](https://webpack.github.io/) as the build tool. | ||
|
||
## Additional Resources | ||
|
||
### Registering an application to authenticate with Microsoft | ||
Note that this will not be necessary if you use the local Dev option above, but if you choose to host this tab in your own environment, you must register the application in order to authenticate. | ||
|
||
1. Go to the [Microsoft Application Registration Portal](https://apps.dev.microsoft.com). | ||
2. Sign in with your Office 365 work/school account. Don't use your personal Microsoft account. | ||
2. Add a new app. | ||
2. Take note of your new `Application ID`. | ||
2. Click on `Add Platform` and choose `Web`. | ||
3. Check `Allow Implicit Flow` and configure the redirect URL to be `https://<mywebsite>/config.html`. | ||
|
||
For more information on hosting your own tab pages, see the [Microsoft Teams 'Get Started' sample README](https://github.com/OfficeDev/microsoft-teams-sample-get-started#host-tab-pages-over-https). | ||
|
||
>**Note:** By defult, your organization should allow you to create new apps. But if it doesn't, you can use a one-year trial subscription of Office 365 Developer at no charge. [Here's how](https://msdn.microsoft.com/en-us/microsoft-teams/setup). | ||
|
||
## Credits | ||
|
||
This project is based on the TodoMVC Typescript - React template located [here](https://github.com/tastejs/todomvc/tree/gh-pages/examples/typescript-react). | ||
|
||
## Contributing | ||
|
||
Please read [Contributing](contributing.md) for details on our code of conduct, and the process for submitting pull requests to us. | ||
|
||
## Versioning | ||
|
||
We use [SemVer](http://semver.org/) for versioning. For the versions available, see the [tags on this repository](https://github.com/officedev/microsoft-teams-sample-todo/tags). | ||
|
||
## License | ||
|
||
This project is licensed under the MIT License - see the [License](LICENSE) file for details |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
var path = require('path'); | ||
var webpack = require('webpack'); | ||
var HtmlWebpackPlugin = require('html-webpack-plugin'); | ||
var ExtractTextPlugin = require('extract-text-webpack-plugin'); | ||
|
||
module.exports = { | ||
entry: { | ||
'app': './src/app.tsx', | ||
'vendor': './src/vendor.ts' | ||
}, | ||
|
||
// Enable sourcemaps for debugging webpack's output. | ||
devtool: 'source-map', | ||
|
||
resolve: { | ||
// Add '.ts' and '.tsx' as resolvable extensions. | ||
extensions: ['', '.css', '.ts', '.tsx', '.js', '.jsx'] | ||
}, | ||
|
||
module: { | ||
loaders: [ | ||
// All files with a '.ts' or '.tsx' extension will be handled by 'ts-loader'. | ||
{ | ||
test: /\.tsx?$/, | ||
loader: 'ts-loader', | ||
exclude: /node_modules/ | ||
}, | ||
|
||
// All files with a '.css' extension will be handled by 'extract-text-plugin and css-loader'. | ||
{ | ||
test: /\.css$/, | ||
loader: ExtractTextPlugin.extract('css') | ||
} | ||
], | ||
|
||
preLoaders: [ | ||
// All output '.js' files will have any sourcemaps re-processed by 'source-map-loader'. | ||
{ test: /\.js$/, loader: 'source-map-loader' } | ||
] | ||
}, | ||
|
||
plugins: [ | ||
new HtmlWebpackPlugin({ | ||
title: 'React • TodoMVC', | ||
filename: 'index.html', | ||
template: path.resolve('index.html'), | ||
chunks: ['app', 'vendor'] | ||
}), | ||
|
||
new ExtractTextPlugin('[name].css'), | ||
|
||
new webpack.ProvidePlugin({ | ||
Router: 'director' | ||
}) | ||
] | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
var path = require('path'); | ||
var webpack = require('webpack'); | ||
var webpackMerge = require('webpack-merge'); | ||
var commonConfig = require('./webpack.common.js'); | ||
|
||
module.exports = webpackMerge(commonConfig, { | ||
output: { | ||
path: path.resolve('dist'), | ||
filename: '[name].[hash].js', | ||
chunkFilename: '[id].chunk.js', | ||
sourceMapFilename: '[name].[hash].map' | ||
}, | ||
|
||
devServer: { | ||
https: true, | ||
historyApiFallback: true, | ||
stats: 'minimal', | ||
watchOptions: { | ||
aggregateTimeout: 300, | ||
poll: 1000 | ||
}, | ||
outputPath: path.resolve('dist') | ||
} | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
var path = require('path'); | ||
var webpack = require('webpack'); | ||
var webpackMerge = require('webpack-merge'); | ||
var ExtractTextPlugin = require('extract-text-webpack-plugin'); | ||
var commonConfig = require('./webpack.common.js'); | ||
|
||
const ENV = process.env.NODE_ENV = process.env.ENV = 'production'; | ||
|
||
module.exports = webpackMerge(commonConfig, { | ||
devtool: 'source-map', | ||
|
||
externals: { | ||
'react': 'React', | ||
'react-dom': 'ReactDOM' | ||
}, | ||
|
||
output: { | ||
path: path.resolve('dist'), | ||
filename: '[name].js', | ||
chunkFilename: '[id].chunk.js', | ||
sourceMapFilename: '[name].map' | ||
}, | ||
|
||
plugins: [ | ||
new webpack.NoErrorsPlugin(), | ||
new webpack.optimize.DedupePlugin(), | ||
new webpack.optimize.UglifyJsPlugin(), | ||
new ExtractTextPlugin('[name].css'), | ||
new webpack.DefinePlugin({ | ||
'process.env': { | ||
'ENV': JSON.stringify(ENV) | ||
} | ||
}) | ||
] | ||
}); |
Oops, something went wrong.