Merge pull request #1293 from siddharth-vaghasia/react-teams-message
This commit is contained in:
commit
52c5c06b3d
|
@ -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,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"
|
||||
}
|
||||
}
|
|
@ -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" />
|
Binary file not shown.
After Width: | Height: | Size: 944 KiB |
Binary file not shown.
After Width: | Height: | Size: 48 KiB |
|
@ -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"
|
||||
}
|
||||
}
|
|
@ -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 -->"
|
||||
}
|
|
@ -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"
|
||||
}
|
||||
|
||||
}
|
|
@ -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/"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
{
|
||||
"$schema": "https://developer.microsoft.com/json-schemas/spfx-build/write-manifests.schema.json",
|
||||
"cdnBasePath": "<!-- PATH TO CDN -->"
|
||||
}
|
|
@ -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'));
|
File diff suppressed because it is too large
Load Diff
|
@ -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"
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
define([], function() {
|
||||
return {
|
||||
"PropertyPaneDescription": "Description",
|
||||
"BasicGroupName": "Group Name",
|
||||
"DescriptionFieldLabel": "Description Field"
|
||||
}
|
||||
});
|
|
@ -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 |
|
@ -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"
|
||||
]
|
||||
}
|
|
@ -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…
Reference in New Issue