mirror of
https://github.com/pnp/sp-dev-fx-webparts.git
synced 2025-02-19 19:37:22 +00:00
Merge pull request #1293 from siddharth-vaghasia/react-teams-message
This commit is contained in:
commit
52c5c06b3d
25
samples/react-teams-message/.editorconfig
Normal file
25
samples/react-teams-message/.editorconfig
Normal file
@ -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
|
32
samples/react-teams-message/.gitignore
vendored
Normal file
32
samples/react-teams-message/.gitignore
vendored
Normal file
@ -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
|
12
samples/react-teams-message/.yo-rc.json
Normal file
12
samples/react-teams-message/.yo-rc.json
Normal file
@ -0,0 +1,12 @@
|
||||
{
|
||||
"@microsoft/generator-sharepoint": {
|
||||
"isCreatingSolution": true,
|
||||
"environment": "spo",
|
||||
"version": "1.10.0",
|
||||
"libraryName": "react-teams-message",
|
||||
"libraryId": "13a092c0-6eb6-46b0-bbc2-17e2ae11adbe",
|
||||
"packageManager": "npm",
|
||||
"isDomainIsolated": false,
|
||||
"componentType": "webpart"
|
||||
}
|
||||
}
|
118
samples/react-teams-message/README.md
Normal file
118
samples/react-teams-message/README.md
Normal file
@ -0,0 +1,118 @@
|
||||
---
|
||||
page_type: sample
|
||||
products:
|
||||
- office-365
|
||||
- office-sp
|
||||
languages:
|
||||
- javascript
|
||||
- typescript
|
||||
extensions:
|
||||
contentType: samples
|
||||
technologies:
|
||||
- SharePoint Framework
|
||||
platforms:
|
||||
- React
|
||||
createdDate: 1/1/2016 12:00:00 AM
|
||||
---
|
||||
# Web part showing Current User's MS Teams and send message.
|
||||
|
||||
## Summary
|
||||
|
||||
This is a sample web part that displays currently logged in user's Microsoft Teams(user is member of), its channels and will allow sending messages to any Team's channel. It will also allow the user to open the team's channel via the link. This web part can be useful on the Intranet home page which can be added as My Teams web part.
|
||||
|
||||
|
||||
* Web Part in Action
|
||||
|
||||
![WebPart in Action](./assets/myteamsmessage.gif)
|
||||
|
||||
* Configurable Web Part Properties
|
||||
|
||||
![Web Part Properties](./assets/webpartproperties.jpg)
|
||||
|
||||
## Features
|
||||
|
||||
* Show Current logged in user's Teams in Tree View
|
||||
* On Expanding any Team, it will show selected team's channels.
|
||||
* Message can send to any Team's channel by either by selecting any channel(configurable as web part properties)
|
||||
* Context menu for every channel to 1) To open channel's link in Teams. 2) To send message to team.
|
||||
* A dialog box to send message.
|
||||
|
||||
Configurable Web part Properties
|
||||
* Web Part Title to be displayed On top of tree view (like My Teams).
|
||||
* Toggle to Show/hide Teams and channel's Description.
|
||||
* Toggle On/Off whether to open send message popup should open soon as a channel is selected.
|
||||
|
||||
* Please refer this [link](https://www.c-sharpcorner.com/article/microsoft-teams-operations-in-spfx-webpart-using-graph-api/) if you are interested in learning step by step on how to call Team graph API from SPFx web part.
|
||||
|
||||
## Used SharePoint Framework Version
|
||||
|
||||
![1.10.0](https://img.shields.io/badge/version-1.10.0-green.svg)
|
||||
|
||||
## Applies to
|
||||
|
||||
* [SharePoint Framework](http://dev.office.com/sharepoint/docs/spfx/sharepoint-framework-overview)
|
||||
* [Office 365 tenant](http://dev.office.com/sharepoint/docs/spfx/set-up-your-developer-tenant)
|
||||
|
||||
|
||||
## Prerequisites
|
||||
|
||||
* SharePoint Online tenant
|
||||
* You have provided permission in SharePoint admin for accessing Graph API on behalf of your solution. We can do it before deployment as proactive steps, or after deployment. You can refer to [steps about how to do this post-deployment](https://docs.microsoft.com/en-us/sharepoint/dev/spfx/use-aad-tutorial#deploy-the-solution-and-grant-permissions). Basically you have to use API Access Page of SharePoint admin and add below permission for our use case.
|
||||
|
||||
```
|
||||
"webApiPermissionRequests": [
|
||||
{
|
||||
"resource": "Microsoft Graph",
|
||||
"scope": "User.Read.All"
|
||||
},
|
||||
{
|
||||
"resource": "Microsoft Graph",
|
||||
"scope": "User.ReadWrite.All"
|
||||
},
|
||||
{
|
||||
"resource": "Microsoft Graph",
|
||||
"scope": "Group.Read.All"
|
||||
},
|
||||
{
|
||||
"resource": "Microsoft Graph",
|
||||
"scope": "Group.ReadWrite.All"
|
||||
}
|
||||
]
|
||||
|
||||
```
|
||||
## Concepts
|
||||
|
||||
This Web Part illustrates the following concepts on top of the SharePoint Framework:
|
||||
|
||||
* Using react framework in SPFx webpart
|
||||
* Calling Teams Graph API in SPFx webpart
|
||||
* Usage of PnP Tree View Control
|
||||
* Usage of Fluent UI/Office UI Fabric Controls
|
||||
|
||||
## Solution
|
||||
|
||||
Solution|Author(s)
|
||||
--------|---------
|
||||
react-teams-message | Siddharth Vaghasia(@siddh_me)
|
||||
|
||||
## Version history
|
||||
|
||||
Version|Date|Comments
|
||||
-------|----|--------
|
||||
1.0.0|May 23, 2020|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
|
||||
|
||||
* Clone this repository
|
||||
* in the command line run:
|
||||
* `npm install`
|
||||
* `gulp serve`
|
||||
|
||||
|
||||
<img src="https://telemetry.sharepointpnp.com/sp-dev-fx-webparts/samples/react-teams-message" />
|
BIN
samples/react-teams-message/assets/myteamsmessage.gif
Normal file
BIN
samples/react-teams-message/assets/myteamsmessage.gif
Normal file
Binary file not shown.
After Width: | Height: | Size: 944 KiB |
BIN
samples/react-teams-message/assets/webpartproperties.jpg
Normal file
BIN
samples/react-teams-message/assets/webpartproperties.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 48 KiB |
19
samples/react-teams-message/config/config.json
Normal file
19
samples/react-teams-message/config/config.json
Normal file
@ -0,0 +1,19 @@
|
||||
{
|
||||
"$schema": "https://developer.microsoft.com/json-schemas/spfx-build/config.2.0.schema.json",
|
||||
"version": "2.0",
|
||||
"bundles": {
|
||||
"my-teams-web-part": {
|
||||
"components": [
|
||||
{
|
||||
"entrypoint": "./lib/webparts/myTeams/MyTeamsWebPart.js",
|
||||
"manifest": "./src/webparts/myTeams/MyTeamsWebPart.manifest.json"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"externals": {},
|
||||
"localizedResources": {
|
||||
"MyTeamsWebPartStrings": "lib/webparts/myTeams/loc/{locale}.js",
|
||||
"ControlStrings": "node_modules/@pnp/spfx-controls-react/lib/loc/{locale}.js"
|
||||
}
|
||||
}
|
4
samples/react-teams-message/config/copy-assets.json
Normal file
4
samples/react-teams-message/config/copy-assets.json
Normal file
@ -0,0 +1,4 @@
|
||||
{
|
||||
"$schema": "https://developer.microsoft.com/json-schemas/spfx-build/copy-assets.schema.json",
|
||||
"deployCdnPath": "temp/deploy"
|
||||
}
|
@ -0,0 +1,7 @@
|
||||
{
|
||||
"$schema": "https://developer.microsoft.com/json-schemas/spfx-build/deploy-azure-storage.schema.json",
|
||||
"workingDir": "./temp/deploy/",
|
||||
"account": "<!-- STORAGE ACCOUNT NAME -->",
|
||||
"container": "react-teams-message",
|
||||
"accessKey": "<!-- ACCESS KEY -->"
|
||||
}
|
32
samples/react-teams-message/config/package-solution.json
Normal file
32
samples/react-teams-message/config/package-solution.json
Normal file
@ -0,0 +1,32 @@
|
||||
{
|
||||
"$schema": "https://developer.microsoft.com/json-schemas/spfx-build/package-solution.schema.json",
|
||||
"solution": {
|
||||
"name": "react-teams-message-client-side-solution",
|
||||
"id": "13a092c0-6eb6-46b0-bbc2-17e2ae11adbe",
|
||||
"version": "1.0.0.0",
|
||||
"includeClientSideAssets": true,
|
||||
"isDomainIsolated": false,
|
||||
"webApiPermissionRequests": [
|
||||
{
|
||||
"resource": "Microsoft Graph",
|
||||
"scope": "User.Read.All"
|
||||
},
|
||||
{
|
||||
"resource": "Microsoft Graph",
|
||||
"scope": "User.ReadWrite.All"
|
||||
},
|
||||
{
|
||||
"resource": "Microsoft Graph",
|
||||
"scope": "Group.Read.All"
|
||||
},
|
||||
{
|
||||
"resource": "Microsoft Graph",
|
||||
"scope": "Group.ReadWrite.All"
|
||||
}
|
||||
]
|
||||
},
|
||||
"paths": {
|
||||
"zippedPackage": "solution/react-teams-message.sppkg"
|
||||
}
|
||||
|
||||
}
|
10
samples/react-teams-message/config/serve.json
Normal file
10
samples/react-teams-message/config/serve.json
Normal file
@ -0,0 +1,10 @@
|
||||
{
|
||||
"$schema": "https://developer.microsoft.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/"
|
||||
}
|
||||
}
|
4
samples/react-teams-message/config/write-manifests.json
Normal file
4
samples/react-teams-message/config/write-manifests.json
Normal file
@ -0,0 +1,4 @@
|
||||
{
|
||||
"$schema": "https://developer.microsoft.com/json-schemas/spfx-build/write-manifests.schema.json",
|
||||
"cdnBasePath": "<!-- PATH TO CDN -->"
|
||||
}
|
7
samples/react-teams-message/gulpfile.js
vendored
Normal file
7
samples/react-teams-message/gulpfile.js
vendored
Normal file
@ -0,0 +1,7 @@
|
||||
'use strict';
|
||||
|
||||
const build = require('@microsoft/sp-build-web');
|
||||
|
||||
build.addSuppression(`Warning - [sass] The local CSS class 'ms-Grid' is not camelCase and will not be type-safe.`);
|
||||
|
||||
build.initialize(require('gulp'));
|
17687
samples/react-teams-message/package-lock.json
generated
Normal file
17687
samples/react-teams-message/package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
45
samples/react-teams-message/package.json
Normal file
45
samples/react-teams-message/package.json
Normal file
@ -0,0 +1,45 @@
|
||||
{
|
||||
"name": "react-teams-message",
|
||||
"version": "0.0.1",
|
||||
"private": true,
|
||||
"main": "lib/index.js",
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
},
|
||||
"scripts": {
|
||||
"build": "gulp bundle",
|
||||
"clean": "gulp clean",
|
||||
"test": "gulp test"
|
||||
},
|
||||
"dependencies": {
|
||||
"@microsoft/sp-core-library": "1.10.0",
|
||||
"@microsoft/sp-lodash-subset": "1.10.0",
|
||||
"@microsoft/sp-office-ui-fabric-core": "1.10.0",
|
||||
"@microsoft/sp-property-pane": "1.10.0",
|
||||
"@microsoft/sp-webpart-base": "1.10.0",
|
||||
"@pnp/graph": "^2.0.4",
|
||||
"@pnp/sp": "^2.0.4",
|
||||
"@pnp/spfx-controls-react": "1.18.0",
|
||||
"@types/es6-promise": "0.0.33",
|
||||
"@types/react": "16.8.8",
|
||||
"@types/react-dom": "16.8.3",
|
||||
"@types/webpack-env": "1.13.1",
|
||||
"office-ui-fabric-react": "6.189.2",
|
||||
"react": "16.8.5",
|
||||
"react-dom": "16.8.5"
|
||||
},
|
||||
"resolutions": {
|
||||
"@types/react": "16.8.8"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@microsoft/sp-build-web": "1.10.0",
|
||||
"@microsoft/sp-tslint-rules": "1.10.0",
|
||||
"@microsoft/sp-module-interfaces": "1.10.0",
|
||||
"@microsoft/sp-webpart-workbench": "1.10.0",
|
||||
"@microsoft/rush-stack-compiler-3.3": "0.3.5",
|
||||
"gulp": "~3.9.1",
|
||||
"@types/chai": "3.4.34",
|
||||
"@types/mocha": "2.2.38",
|
||||
"ajv": "~5.2.2"
|
||||
}
|
||||
}
|
1
samples/react-teams-message/src/index.ts
Normal file
1
samples/react-teams-message/src/index.ts
Normal file
@ -0,0 +1 @@
|
||||
// A file is required to be in the root of the /src directory by the TypeScript compiler
|
@ -0,0 +1,56 @@
|
||||
import { WebPartContext } from "@microsoft/sp-webpart-base";
|
||||
import { MSGraphClient } from "@microsoft/sp-http";
|
||||
|
||||
export class ServiceProvider {
|
||||
public _graphClient: MSGraphClient;
|
||||
private spcontext: WebPartContext;
|
||||
public constructor(spcontext: WebPartContext) {
|
||||
this.spcontext = spcontext;
|
||||
}
|
||||
|
||||
public getmyTeams = async (): Promise<[]> => {
|
||||
this._graphClient = await this.spcontext.msGraphClientFactory.getClient(); //TODO
|
||||
|
||||
let myTeams: [] = [];
|
||||
try {
|
||||
const teamsResponse = await this._graphClient.api('me/joinedTeams').version('v1.0').get();
|
||||
myTeams = teamsResponse.value as [];
|
||||
} catch (error) {
|
||||
console.log('Unable to get teams', error);
|
||||
}
|
||||
return myTeams;
|
||||
}
|
||||
|
||||
public getChannel = async (teamID): Promise<[]> => {
|
||||
this._graphClient = await this.spcontext.msGraphClientFactory.getClient(); //TODO
|
||||
|
||||
let myTeams: [] = [];
|
||||
try {
|
||||
const teamsResponse = await this._graphClient.api('teams/' + teamID + '/channels').version('v1.0').get();
|
||||
myTeams = teamsResponse.value as [];
|
||||
} catch (error) {
|
||||
console.log('unable to get channels', error);
|
||||
}
|
||||
return myTeams;
|
||||
}
|
||||
|
||||
public sendMessage = async (teamId, channelId, message): Promise<[]> => {
|
||||
this._graphClient = await this.spcontext.msGraphClientFactory.getClient();
|
||||
try {
|
||||
// https://graph.microsoft.com/beta/teams/{team-id}/channels/{channel-id}/messages
|
||||
var content = {
|
||||
"body": {
|
||||
"content": message
|
||||
}
|
||||
};
|
||||
const messageResponse = await this._graphClient.api('/teams/' + teamId + '/channels/' + channelId + "/messages/")
|
||||
.version("beta").post(content);
|
||||
return messageResponse;
|
||||
|
||||
} catch (error) {
|
||||
console.log('Unable to send message', error);
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@ -0,0 +1,27 @@
|
||||
{
|
||||
"$schema": "https://developer.microsoft.com/json-schemas/spfx/client-side-web-part-manifest.schema.json",
|
||||
"id": "a540a9b2-82b3-466a-83b7-7caeeb0e464d",
|
||||
"alias": "MyTeamsWebPart",
|
||||
"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,
|
||||
"supportedHosts": ["SharePointWebPart"],
|
||||
|
||||
"preconfiguredEntries": [{
|
||||
"groupId": "5c03119e-3074-46fd-976b-c60198311f70", // Other
|
||||
"group": { "default": "Other" },
|
||||
"title": { "default": "myTeams" },
|
||||
"description": { "default": "myTeams description" },
|
||||
"officeFabricIconFontName": "Page",
|
||||
"properties": {
|
||||
"description": "myTeams"
|
||||
}
|
||||
}]
|
||||
}
|
@ -0,0 +1,72 @@
|
||||
import * as React from 'react';
|
||||
import * as ReactDom from 'react-dom';
|
||||
import { Version } from '@microsoft/sp-core-library';
|
||||
import {
|
||||
IPropertyPaneConfiguration,
|
||||
PropertyPaneTextField,
|
||||
PropertyPaneToggle,
|
||||
} from '@microsoft/sp-property-pane';
|
||||
import { BaseClientSideWebPart } from '@microsoft/sp-webpart-base';
|
||||
|
||||
import * as strings from 'MyTeamsWebPartStrings';
|
||||
import MyTeams from './components/MyTeams';
|
||||
import { IMyTeamsProps } from './components/IMyTeamsProps';
|
||||
|
||||
export interface IMyTeamsWebPartProps {
|
||||
WebpartTitle: string;
|
||||
ShowDescription:boolean;
|
||||
OpenPopupOnSelectingChannel:boolean;
|
||||
}
|
||||
|
||||
export default class MyTeamsWebPart extends BaseClientSideWebPart <IMyTeamsWebPartProps> {
|
||||
|
||||
public render(): void {
|
||||
const element: React.ReactElement<IMyTeamsProps> = React.createElement(
|
||||
MyTeams,
|
||||
{
|
||||
context: this.context,
|
||||
webparttitle:this.properties.WebpartTitle,
|
||||
showdescription:this.properties.ShowDescription,
|
||||
openpopuponselectingchannel:this.properties.OpenPopupOnSelectingChannel
|
||||
}
|
||||
);
|
||||
|
||||
ReactDom.render(element, this.domElement);
|
||||
}
|
||||
|
||||
protected onDispose(): void {
|
||||
ReactDom.unmountComponentAtNode(this.domElement);
|
||||
}
|
||||
|
||||
protected get dataVersion(): Version {
|
||||
return Version.parse('1.0');
|
||||
}
|
||||
|
||||
protected getPropertyPaneConfiguration(): IPropertyPaneConfiguration {
|
||||
return {
|
||||
pages: [
|
||||
{
|
||||
header: {
|
||||
description: strings.PropertyPaneDescription
|
||||
},
|
||||
groups: [
|
||||
{
|
||||
groupName: strings.BasicGroupName,
|
||||
groupFields: [
|
||||
PropertyPaneTextField('WebpartTitle', {
|
||||
label: "WebPart Heading"
|
||||
}),
|
||||
PropertyPaneToggle('ShowDescription', {
|
||||
label: "Show Description"
|
||||
}),
|
||||
PropertyPaneToggle('OpenPopupOnSelectingChannel', {
|
||||
label: "Open Popup Selecting Channel"
|
||||
})
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
};
|
||||
}
|
||||
}
|
@ -0,0 +1,8 @@
|
||||
import { WebPartContext } from "@microsoft/sp-webpart-base";
|
||||
|
||||
export interface IMyTeamsProps {
|
||||
context: WebPartContext;
|
||||
webparttitle: string;
|
||||
showdescription:boolean;
|
||||
openpopuponselectingchannel:boolean;
|
||||
}
|
@ -0,0 +1,37 @@
|
||||
@import '~office-ui-fabric-react/dist/sass/References.scss';
|
||||
|
||||
.myTeams {
|
||||
|
||||
label{
|
||||
font-size: 16px;
|
||||
line-height: 1.5;
|
||||
}
|
||||
.radio{
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
}
|
||||
|
||||
.textbox{
|
||||
height: 30px;
|
||||
width: 300px;
|
||||
}
|
||||
|
||||
h4{
|
||||
font-style: italic;
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
.buttons{
|
||||
background-color: $ms-color-themePrimary;
|
||||
width: 200px;
|
||||
height: 40px;
|
||||
color: white;
|
||||
font-size: 18px;
|
||||
|
||||
}
|
||||
.webpartitle {
|
||||
color: $ms-color-themePrimary;
|
||||
margin: 0px;
|
||||
|
||||
}
|
||||
}
|
@ -0,0 +1,237 @@
|
||||
import * as React from 'react';
|
||||
import styles from './MyTeams.module.scss';
|
||||
import { IMyTeamsProps } from './IMyTeamsProps';
|
||||
import { escape } from '@microsoft/sp-lodash-subset';
|
||||
import { ServiceProvider } from '../../../shared/services/ServiceProvider';
|
||||
import { TreeView, ITreeItem, TreeItemActionsDisplayMode, TreeViewSelectionMode } from "@pnp/spfx-controls-react/lib/TreeView";
|
||||
import { PrimaryButton, DefaultButton, Dialog, DialogFooter, DialogType, TextField, MessageBar,MessageBarType } from 'office-ui-fabric-react';
|
||||
import { initializeIcons } from '@uifabric/icons';
|
||||
|
||||
export interface IMyTeamsState {
|
||||
myteams: any[];
|
||||
selectedTeam: any;
|
||||
teamChannels: any;
|
||||
selectedChannel: any;
|
||||
hideDailog: boolean;
|
||||
currentMessage: string;
|
||||
showMessage: boolean;
|
||||
}
|
||||
|
||||
export default class MyTeams extends React.Component<IMyTeamsProps, IMyTeamsState> {
|
||||
private serviceProvider;
|
||||
private selectedItems;
|
||||
|
||||
public constructor(props: IMyTeamsProps, state: IMyTeamsState) {
|
||||
super(props);
|
||||
this.serviceProvider = new ServiceProvider(this.props.context);
|
||||
this.state = {
|
||||
myteams: [],
|
||||
selectedTeam: null,
|
||||
selectedChannel: null,
|
||||
teamChannels: [],
|
||||
hideDailog: true,
|
||||
currentMessage: "",
|
||||
showMessage: false
|
||||
|
||||
};
|
||||
initializeIcons();
|
||||
}
|
||||
|
||||
public async componentDidMount() {
|
||||
this.GetmyTeams();
|
||||
}
|
||||
|
||||
private GetmyTeams() {
|
||||
|
||||
this.serviceProvider.
|
||||
getmyTeams()
|
||||
.then(
|
||||
(result: any[]): void => {
|
||||
console.log(result);
|
||||
this.createRequiredTreeItems(result);
|
||||
}
|
||||
)
|
||||
.catch(error => {
|
||||
console.log(error);
|
||||
});
|
||||
}
|
||||
|
||||
private async createRequiredTreeItems(result) {
|
||||
var array = [];
|
||||
let i = 0;
|
||||
result.forEach(element => {
|
||||
array.push({
|
||||
index: i,
|
||||
key: element.id,
|
||||
label: element.displayName,
|
||||
subLabel: this.props.showdescription ? element.description : "",
|
||||
data: element,
|
||||
type: "team",
|
||||
selectable: false,
|
||||
children: [{ key: element.id + "_d", label: "Loading channels" }]
|
||||
});
|
||||
i++;
|
||||
});
|
||||
|
||||
this.setState({ myteams: array });
|
||||
}
|
||||
|
||||
private async loadChannels(teamid, index) {
|
||||
var array = this.state.myteams;
|
||||
|
||||
var firstTeamChannels = await this.getChannels(teamid);
|
||||
array[index].children = [];
|
||||
firstTeamChannels.forEach(channel => {
|
||||
array[index].children.push({
|
||||
key: channel.id,
|
||||
label: channel.displayName,
|
||||
subLabel: this.props.showdescription ? channel.description : "",
|
||||
data: channel,
|
||||
type: "channel",
|
||||
parent: array[index],
|
||||
iconProps: {
|
||||
iconName: 'TeamsLogoInverse'
|
||||
},
|
||||
actions: [{
|
||||
title: "Open Channel",
|
||||
iconProps: {
|
||||
iconName: 'Link'
|
||||
},
|
||||
id: "GetItem",
|
||||
actionCallback: async (treeItem: ITreeItem) => {
|
||||
console.log(treeItem.data.webUrl);
|
||||
window.open(treeItem.data.webUrl);
|
||||
}
|
||||
},
|
||||
{
|
||||
title: "Send Message",
|
||||
iconProps: {
|
||||
iconName: 'Send'
|
||||
},
|
||||
id: "Send Message",
|
||||
actionCallback: async (treeItem: ITreeItem) => {
|
||||
this.selectedItems = [treeItem];
|
||||
|
||||
this.setState({ hideDailog: false });
|
||||
}
|
||||
}]
|
||||
});
|
||||
});
|
||||
|
||||
this.setState({ myteams: array });
|
||||
|
||||
}
|
||||
|
||||
public render(): React.ReactElement<IMyTeamsProps> {
|
||||
return (
|
||||
<React.Fragment>
|
||||
<div className={styles.myTeams}>
|
||||
<i className="ms-Icon ms-Icon--TeamsLogo" aria-hidden="true"></i>
|
||||
<h1 className={styles.webpartitle}>
|
||||
|
||||
{this.props.webparttitle}</h1>
|
||||
|
||||
{this.state.showMessage &&
|
||||
<React.Fragment>
|
||||
<br></br>
|
||||
< MessageBar onDismiss={()=>{this.setState({showMessage:false});}} style={{height:'20px'}} messageBarType={MessageBarType.success} >
|
||||
Message Posted Successfully.
|
||||
</MessageBar >
|
||||
</React.Fragment>
|
||||
}
|
||||
<TreeView
|
||||
items={this.state.myteams}
|
||||
defaultExpanded={false}
|
||||
selectChildrenIfParentSelected={false}
|
||||
selectionMode={TreeViewSelectionMode.Single}
|
||||
showCheckboxes={false}
|
||||
treeItemActionsDisplayMode={TreeItemActionsDisplayMode.ContextualMenu}
|
||||
onSelect={(items) => this.onTreeItemSelect(items)}
|
||||
onExpandCollapse={(items, isExpanded) => this.onTreeItemExpandCollapse(items, isExpanded)}
|
||||
/>
|
||||
{!this.state.hideDailog &&
|
||||
<Dialog
|
||||
hidden={this.state.hideDailog}
|
||||
onDismiss={this._closeDialog}
|
||||
dialogContentProps={{
|
||||
type: DialogType.largeHeader,
|
||||
title: this.selectedItems[0].parent.label
|
||||
|
||||
}}
|
||||
modalProps={{
|
||||
isBlocking: false,
|
||||
styles: { main: { minWidth: 600 } }
|
||||
}}
|
||||
>
|
||||
<span>{"Sending to channel: " + this.selectedItems[0].label}</span>
|
||||
<TextField required onChange={evt => this.updateInputValue(evt)} value={this.state.currentMessage} label="Message" multiline resizable={true} />
|
||||
<DialogFooter>
|
||||
<PrimaryButton onClick={() => this._sendMessage()} text="Send" />
|
||||
<DefaultButton onClick={this._closeDialog} text="Cancel" />
|
||||
</DialogFooter>
|
||||
</Dialog>
|
||||
}
|
||||
</div>
|
||||
</React.Fragment >
|
||||
);
|
||||
}
|
||||
|
||||
private onTreeItemSelect(items: ITreeItem[]) {
|
||||
console.log("Items selected: ", items);
|
||||
if (this.props.openpopuponselectingchannel) {
|
||||
this.selectedItems = items;
|
||||
this.setState({ hideDailog: false });
|
||||
}
|
||||
}
|
||||
|
||||
private async onTreeItemExpandCollapse(item: any, isExpanded: boolean) {
|
||||
console.log((isExpanded ? "Item expanded: " : "Item collapsed: ") + item);
|
||||
|
||||
this.loadChannels(item.data.id, item.index);
|
||||
|
||||
}
|
||||
|
||||
private updateInputValue(evt) {
|
||||
this.setState({
|
||||
currentMessage: evt.target.value
|
||||
});
|
||||
}
|
||||
|
||||
private _closeDialog = (): void => {
|
||||
this.setState({ hideDailog: true });
|
||||
}
|
||||
|
||||
private async getChannels(teamid) {
|
||||
|
||||
var returnResult = await this.serviceProvider.
|
||||
getChannel(teamid)
|
||||
.then(
|
||||
(result): void => {
|
||||
console.log(result);
|
||||
return result;
|
||||
}
|
||||
)
|
||||
.catch(error => {
|
||||
console.log(error);
|
||||
});
|
||||
|
||||
return returnResult;
|
||||
}
|
||||
|
||||
private async _sendMessage() {
|
||||
var selecteTeamId = this.selectedItems[0].parent.key;
|
||||
var selectedChannelId = this.selectedItems[0].key;
|
||||
await this.serviceProvider.
|
||||
sendMessage(selecteTeamId, selectedChannelId, this.state.currentMessage)
|
||||
.then(
|
||||
(result: any[]): void => {
|
||||
console.log(result);
|
||||
this.setState({ hideDailog: true, currentMessage: "",showMessage:true });
|
||||
}
|
||||
)
|
||||
.catch(error => {
|
||||
console.log(error);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
7
samples/react-teams-message/src/webparts/myTeams/loc/en-us.js
vendored
Normal file
7
samples/react-teams-message/src/webparts/myTeams/loc/en-us.js
vendored
Normal file
@ -0,0 +1,7 @@
|
||||
define([], function() {
|
||||
return {
|
||||
"PropertyPaneDescription": "Description",
|
||||
"BasicGroupName": "Group Name",
|
||||
"DescriptionFieldLabel": "Description Field"
|
||||
}
|
||||
});
|
10
samples/react-teams-message/src/webparts/myTeams/loc/mystrings.d.ts
vendored
Normal file
10
samples/react-teams-message/src/webparts/myTeams/loc/mystrings.d.ts
vendored
Normal file
@ -0,0 +1,10 @@
|
||||
declare interface IMyTeamsWebPartStrings {
|
||||
PropertyPaneDescription: string;
|
||||
BasicGroupName: string;
|
||||
DescriptionFieldLabel: string;
|
||||
}
|
||||
|
||||
declare module 'MyTeamsWebPartStrings' {
|
||||
const strings: IMyTeamsWebPartStrings;
|
||||
export = strings;
|
||||
}
|
Binary file not shown.
After Width: | Height: | Size: 3.0 KiB |
Binary file not shown.
After Width: | Height: | Size: 1.4 KiB |
38
samples/react-teams-message/tsconfig.json
Normal file
38
samples/react-teams-message/tsconfig.json
Normal file
@ -0,0 +1,38 @@
|
||||
{
|
||||
"extends": "./node_modules/@microsoft/rush-stack-compiler-3.3/includes/tsconfig-web.json",
|
||||
"compilerOptions": {
|
||||
"target": "es5",
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"module": "esnext",
|
||||
"moduleResolution": "node",
|
||||
"jsx": "react",
|
||||
"declaration": true,
|
||||
"sourceMap": true,
|
||||
"experimentalDecorators": true,
|
||||
"skipLibCheck": true,
|
||||
"outDir": "lib",
|
||||
"inlineSources": false,
|
||||
"strictNullChecks": false,
|
||||
"noUnusedLocals": false,
|
||||
"typeRoots": [
|
||||
"./node_modules/@types",
|
||||
"./node_modules/@microsoft"
|
||||
],
|
||||
"types": [
|
||||
"es6-promise",
|
||||
"webpack-env"
|
||||
],
|
||||
"lib": [
|
||||
"es5",
|
||||
"dom",
|
||||
"es2015.collection"
|
||||
]
|
||||
},
|
||||
"include": [
|
||||
"src/**/*.ts"
|
||||
],
|
||||
"exclude": [
|
||||
"node_modules",
|
||||
"lib"
|
||||
]
|
||||
}
|
30
samples/react-teams-message/tslint.json
Normal file
30
samples/react-teams-message/tslint.json
Normal file
@ -0,0 +1,30 @@
|
||||
{
|
||||
"extends": "@microsoft/sp-tslint-rules/base-tslint.json",
|
||||
"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-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,
|
||||
"variable-name": false,
|
||||
"whitespace": false
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user