Merge pull request #1283 from Harshagracy/master
This commit is contained in:
commit
1760ce33b2
|
@ -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": {
|
||||
"version": "1.10.0",
|
||||
"libraryName": "save-email-to-sharepoint",
|
||||
"libraryId": "a1464bb8-773a-438c-a425-b5fc2a5a86a4",
|
||||
"environment": "spo",
|
||||
"packageManager": "npm",
|
||||
"isCreatingSolution": true,
|
||||
"isDomainIsolated": false,
|
||||
"componentType": "webpart"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,85 @@
|
|||
---
|
||||
page_type: sample
|
||||
products:
|
||||
- office-sp
|
||||
languages:
|
||||
- javascript
|
||||
- typescript
|
||||
extensions:
|
||||
contentType: samples
|
||||
technologies:
|
||||
- SharePoint Framework
|
||||
platforms:
|
||||
- react
|
||||
createdDate: 5/15/2020 12:00:00 AM
|
||||
---
|
||||
# Save Outlook email to SharePoint Document Library Add-in
|
||||
|
||||
## Summary
|
||||
|
||||
This Add-in helps the user to save current selected email to SharePoint document Library.
|
||||
![Save outlook email to SharePoint Library](./assets/saveEmailToSharePoint.gif)
|
||||
|
||||
## Features and usage
|
||||
|
||||
In Outlook web, select an email and select more options. Select 'More actions' at the top of the message. Scroll to the bottom and select **Save Email to SharePoint** Add-in. The add-in loads the taskpane that list's the sites user has access. Once the user selects the site, it loads the list of document libraries that are present in that site. After selecting a library, the user can save the email by clicking **Save** button. Once it is saved, a link will be generated to view the email preview. The email will be saved in `.eml` format.
|
||||
|
||||
## Used SharePoint Framework Version
|
||||
|
||||
![1.10.0](https://img.shields.io/badge/version-1.10.0-green.svg)
|
||||
|
||||
## Applies to
|
||||
|
||||
* [SharePoint Framework](https:/dev.office.com/sharepoint)
|
||||
* [Office 365 tenant](https://dev.office.com/sharepoint/docs/spfx/set-up-your-development-environment)
|
||||
|
||||
## Solution
|
||||
|
||||
Solution|Author(s)
|
||||
--------|---------
|
||||
save-email-to-sharepoint-client-side-solution | [Harsha Vardhini](https://twitter.com/harshagracy)
|
||||
|
||||
## Version history
|
||||
|
||||
Version|Date|Comments
|
||||
-------|----|--------
|
||||
1.0|May 15, 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 bundle --ship`
|
||||
* `gulp package-solution --ship`
|
||||
* Deploy the `save-email-to-sharepoint.sppkg` to SharePoint App Catalog
|
||||
|
||||
## Graph API approval
|
||||
|
||||
* Move to the SharePoint tenant administrative UIs located at https://tenant-admin.sharepoint.com
|
||||
* Move to API management under the Advance left menu option to see the currently pending permission requests. Notice that the request for Mail.ReadWrite permission for in Graph API is pending for approval.
|
||||
* Select the pending permission row and choose Approve from the toolbar.
|
||||
|
||||
## Publish Office Add-ins using Centralized Deployment via the Office 365 admin center
|
||||
|
||||
* For deployment in your tenant, Please refer this article - https://docs.microsoft.com/en-us/microsoft-365/admin/manage/manage-deployment-of-add-ins?view=o365-worldwide
|
||||
|
||||
## Personally deploy in your outlook web app
|
||||
|
||||
Before deploying tenant wide, you can use the below steps to test it for your outlook web app.
|
||||
* In Outlook web, select an email and select more options
|
||||
* Select **More actions** at the top of the message.
|
||||
* Go to the bottom of the list and select **Get Add-ins**.
|
||||
* On the **Add-ins for Outlook** page, select the **My add-ins**.
|
||||
* Scroll to the bottom to **Custom Add-ins**
|
||||
* Select **Custom Add-ins from a file**. Upload the manifest file `e6083c02-3280-4430-a877-22cbc6251d21_outlookManifest.xml` from the `OfficeAddin` folder.
|
||||
* Click +**Install** in the warning window.
|
||||
* Now you can use the Add-in for your outlook web login.
|
||||
|
||||
<img src="https://telemetry.sharepointpnp.com/sp-dev-fx-webparts/samples/react-office-add-in-save-email-to-sharepoint" />
|
Binary file not shown.
After Width: | Height: | Size: 1.5 MiB |
|
@ -0,0 +1,18 @@
|
|||
{
|
||||
"$schema": "https://developer.microsoft.com/json-schemas/spfx-build/config.2.0.schema.json",
|
||||
"version": "2.0",
|
||||
"bundles": {
|
||||
"save-email-to-share-point-web-part": {
|
||||
"components": [
|
||||
{
|
||||
"entrypoint": "./lib/webparts/saveEmailToSharePoint/SaveEmailToSharePointWebPart.js",
|
||||
"manifest": "./src/webparts/saveEmailToSharePoint/SaveEmailToSharePointWebPart.manifest.json"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"externals": {},
|
||||
"localizedResources": {
|
||||
"SaveEmailToSharePointWebPartStrings": "lib/webparts/saveEmailToSharePoint/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": "save-email-to-sharepoint",
|
||||
"accessKey": "<!-- ACCESS KEY -->"
|
||||
}
|
|
@ -0,0 +1,24 @@
|
|||
{
|
||||
"$schema": "https://developer.microsoft.com/json-schemas/spfx-build/package-solution.schema.json",
|
||||
"solution": {
|
||||
"name": "save-email-to-sharepoint-client-side-solution",
|
||||
"id": "a1464bb8-773a-438c-a425-b5fc2a5a86a4",
|
||||
"version": "1.0.0.0",
|
||||
"includeClientSideAssets": true,
|
||||
"skipFeatureDeployment": true,
|
||||
"isDomainIsolated": false,
|
||||
"webApiPermissionRequests": [
|
||||
{
|
||||
"resource": "Microsoft Graph",
|
||||
"scope": "Mail.ReadBasic"
|
||||
},
|
||||
{
|
||||
"resource": "Microsoft Graph",
|
||||
"scope": "Mail.Read"
|
||||
}
|
||||
]
|
||||
},
|
||||
"paths": {
|
||||
"zippedPackage": "solution/save-email-to-sharepoint.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'));
|
|
@ -0,0 +1,91 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||
<OfficeApp xmlns="http://schemas.microsoft.com/office/appforoffice/1.1"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:bt="http://schemas.microsoft.com/office/officeappbasictypes/1.0"
|
||||
xmlns:mailappor="http://schemas.microsoft.com/office/mailappversionoverrides/1.0"
|
||||
xsi:type="MailApp">
|
||||
<Id>e6083c02-3280-4430-a877-22cbc6251d21</Id>
|
||||
<Version>1.0.0.0</Version>
|
||||
<ProviderName>Save Email Provider</ProviderName>
|
||||
<DefaultLocale>en-US</DefaultLocale>
|
||||
<DisplayName DefaultValue="Save Email to SharePoint"/>
|
||||
<Description DefaultValue="A template to get started with a Save Email as file in SharePoint Outlook addin."/>
|
||||
<IconUrl DefaultValue="https://spoprod-a.akamaihd.net/files/fabric/assets/item-types/32_1.5x/email.png"/>
|
||||
<HighResolutionIconUrl DefaultValue="https://cdn.graph.office.net/prod/media/shared/addin-icon.png"/>
|
||||
<SupportUrl DefaultValue="https://localhost:4321/help"/>
|
||||
<AppDomains>
|
||||
<AppDomain>https://login.microsoftonline.com</AppDomain>
|
||||
<AppDomain>https://login.windows.net</AppDomain>
|
||||
</AppDomains>
|
||||
<Hosts>
|
||||
<Host Name="Mailbox" />
|
||||
</Hosts>
|
||||
<Requirements>
|
||||
<Sets>
|
||||
<Set Name="Mailbox" MinVersion="1.4" />
|
||||
<Set Name="SharePointHostedAddin" MinVersion="1.1" />
|
||||
</Sets>
|
||||
</Requirements>
|
||||
<FormSettings>
|
||||
<Form xsi:type="ItemRead">
|
||||
<DesktopSettings>
|
||||
<SourceLocation DefaultValue="https://_SharePointTenantUrl_/_layouts/15/outlookhostedapp.aspx?componentId=e6083c02-3280-4430-a877-22cbc6251d21&isConfigureMode=true"/>
|
||||
<RequestedHeight>250</RequestedHeight>
|
||||
</DesktopSettings>
|
||||
</Form>
|
||||
</FormSettings>
|
||||
<Permissions>ReadWriteMailbox</Permissions>
|
||||
<Rule xsi:type="RuleCollection" Mode="Or">
|
||||
<Rule xsi:type="ItemIs" ItemType="Message" FormType="Read" />
|
||||
</Rule>
|
||||
<DisableEntityHighlighting>false</DisableEntityHighlighting>
|
||||
<VersionOverrides xmlns="http://schemas.microsoft.com/office/mailappversionoverrides" xsi:type="VersionOverridesV1_0">
|
||||
<VersionOverrides xmlns="http://schemas.microsoft.com/office/mailappversionoverrides/1.1" xsi:type="VersionOverridesV1_1">
|
||||
<Hosts>
|
||||
<Host xsi:type="MailHost">
|
||||
<DesktopFormFactor>
|
||||
<ExtensionPoint xsi:type="MessageReadCommandSurface">
|
||||
<OfficeTab id="TabDefault">
|
||||
<Group id="msgReadGroup">
|
||||
<Label resid="GroupLabel" />
|
||||
<Control xsi:type="Button" id="msgReadOpenPaneButton">
|
||||
<Label resid="TaskpaneButton.Label" />
|
||||
<Supertip>
|
||||
<Title resid="TaskpaneButton.Label" />
|
||||
<Description resid="TaskpaneButton.Tooltip" />
|
||||
</Supertip>
|
||||
<Icon>
|
||||
<bt:Image size="16" resid="Icon.16x16" />
|
||||
<bt:Image size="32" resid="Icon.32x32" />
|
||||
<bt:Image size="80" resid="Icon.80x80" />
|
||||
</Icon>
|
||||
<Action xsi:type="ShowTaskpane">
|
||||
<SourceLocation resid="Taskpane.Url" />
|
||||
</Action>
|
||||
</Control>
|
||||
</Group>
|
||||
</OfficeTab>
|
||||
</ExtensionPoint>
|
||||
</DesktopFormFactor>
|
||||
</Host>
|
||||
</Hosts>
|
||||
<Resources>
|
||||
<bt:Images>
|
||||
<bt:Image id="Icon.16x16" DefaultValue="https://cdn.graph.office.net/prod/media/shared/addin-icon.png"/>
|
||||
<bt:Image id="Icon.32x32" DefaultValue="https://cdn.graph.office.net/prod/media/shared/addin-icon.png"/>
|
||||
<bt:Image id="Icon.80x80" DefaultValue="https://cdn.graph.office.net/prod/media/shared/addin-icon.png"/>
|
||||
</bt:Images>
|
||||
<bt:Urls>
|
||||
<bt:Url id="Taskpane.Url" DefaultValue="https://_SharePointTenantUrl_/_layouts/15/outlookhostedapp.aspx?componentId=e6083c02-3280-4430-a877-22cbc6251d21&isConfigureMode=true" />
|
||||
</bt:Urls>
|
||||
<bt:ShortStrings>
|
||||
<bt:String id="GroupLabel" DefaultValue="Add-in groupLabel"/>
|
||||
<bt:String id="TaskpaneButton.Label" DefaultValue="Show Taskpane"/>
|
||||
</bt:ShortStrings>
|
||||
<bt:LongStrings>
|
||||
<bt:String id="TaskpaneButton.Tooltip" DefaultValue="Opens taskpane."/>
|
||||
</bt:LongStrings>
|
||||
</Resources>
|
||||
</VersionOverrides>
|
||||
</VersionOverrides>
|
||||
</OfficeApp>
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,44 @@
|
|||
{
|
||||
"name": "save-email-to-sharepoint",
|
||||
"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-plusbeta",
|
||||
"@microsoft/sp-lodash-subset": "1.10.0-plusbeta",
|
||||
"@microsoft/sp-office-ui-fabric-core": "1.10.0-plusbeta",
|
||||
"@microsoft/sp-property-pane": "1.10.0-plusbeta",
|
||||
"@microsoft/sp-webpart-base": "1.10.0-plusbeta",
|
||||
"@pnp/sp": "^2.0.4",
|
||||
"@types/es6-promise": "0.0.33",
|
||||
"@types/office-js": "^1.0.97",
|
||||
"@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-plusbeta",
|
||||
"@microsoft/sp-tslint-rules": "1.10.0-plusbeta",
|
||||
"@microsoft/sp-module-interfaces": "1.10.0-plusbeta",
|
||||
"@microsoft/sp-webpart-workbench": "1.10.0-plusbeta",
|
||||
"@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,27 @@
|
|||
{
|
||||
"$schema": "https://developer.microsoft.com/json-schemas/spfx/client-side-web-part-manifest.schema.json",
|
||||
"id": "e6083c02-3280-4430-a877-22cbc6251d21",
|
||||
"alias": "SaveEmailToSharePointWebPart",
|
||||
"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": "SaveEmailToSharePoint" },
|
||||
"description": { "default": "Save your Email to sharepoint from the outlook add-in web" },
|
||||
"officeFabricIconFontName": "Page",
|
||||
"properties": {
|
||||
"description": "SaveEmailToSharePoint"
|
||||
}
|
||||
}]
|
||||
}
|
|
@ -0,0 +1,64 @@
|
|||
import * as React from 'react';
|
||||
import * as ReactDom from 'react-dom';
|
||||
import { Version } from '@microsoft/sp-core-library';
|
||||
import {
|
||||
IPropertyPaneConfiguration,
|
||||
PropertyPaneTextField
|
||||
} from '@microsoft/sp-property-pane';
|
||||
import { BaseClientSideWebPart, WebPartContext } from '@microsoft/sp-webpart-base';
|
||||
import { sp } from "@pnp/sp/presets/all";
|
||||
import * as strings from 'SaveEmailToSharePointWebPartStrings';
|
||||
import SaveEmailToSharePoint from './components/SaveEmailToSharePoint';
|
||||
import { ISaveEmailToSharePointProps } from './components/ISaveEmailToSharePointProps';
|
||||
|
||||
export interface ISaveEmailToSharePointWebPartProps {
|
||||
description: string;
|
||||
context: WebPartContext;
|
||||
}
|
||||
|
||||
export default class SaveEmailToSharePointWebPart extends BaseClientSideWebPart <ISaveEmailToSharePointWebPartProps> {
|
||||
protected onInit(): Promise<void> {
|
||||
return super.onInit().then(_ => {
|
||||
sp.setup({
|
||||
spfxContext: this.context
|
||||
});
|
||||
});
|
||||
}
|
||||
public render(): void {
|
||||
const element: React.ReactElement<ISaveEmailToSharePointProps> = React.createElement(
|
||||
SaveEmailToSharePoint,
|
||||
{
|
||||
description: this.properties.description,
|
||||
context: this.context
|
||||
}
|
||||
);
|
||||
|
||||
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: [
|
||||
{
|
||||
groups: [
|
||||
{
|
||||
groupFields: [
|
||||
PropertyPaneTextField('description', {
|
||||
label: strings.DescriptionFieldLabel
|
||||
})
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
};
|
||||
}
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
import { WebPartContext } from "@microsoft/sp-webpart-base";
|
||||
|
||||
export interface ISaveEmailToSharePointProps {
|
||||
description: string;
|
||||
context: WebPartContext;
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
import {SPRest} from '@pnp/sp';
|
||||
import "@pnp/sp/webs";
|
||||
import "@pnp/sp/items/list";
|
||||
import "@pnp/sp/lists";
|
||||
import "@pnp/sp/sites";
|
||||
import "@pnp/sp/search";
|
||||
export const sp= new SPRest();
|
|
@ -0,0 +1,81 @@
|
|||
@import '~office-ui-fabric-react/dist/sass/References.scss';
|
||||
|
||||
.saveEmailToSharePoint {
|
||||
.container {
|
||||
@include ms-Grid;
|
||||
}
|
||||
|
||||
.errMsg,
|
||||
.successMsg {
|
||||
@include ms-Grid-col;
|
||||
margin-top: 5px !important;
|
||||
right: 2px;
|
||||
}
|
||||
|
||||
.iconStyle {
|
||||
margin-right: 8px;
|
||||
}
|
||||
|
||||
.row {
|
||||
margin-left: 5px;
|
||||
}
|
||||
|
||||
.column {
|
||||
@include ms-Grid-col;
|
||||
padding-left: 0px;
|
||||
@include ms-lg10;
|
||||
@include ms-xl8;
|
||||
@include ms-xlPush2;
|
||||
@include ms-lgPush1;
|
||||
}
|
||||
|
||||
.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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
:global {
|
||||
.btnSave {
|
||||
margin-top: 5px;
|
||||
}
|
||||
|
||||
.btnCancel {
|
||||
margin-top: 5px;
|
||||
margin-left: 5px;
|
||||
}
|
||||
|
||||
.ms-Dropdown-caretDownWrapper {
|
||||
right: 16px;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,200 @@
|
|||
import * as React from 'react';
|
||||
import styles from './SaveEmailToSharePoint.module.scss';
|
||||
import { ISaveEmailToSharePointProps } from './ISaveEmailToSharePointProps';
|
||||
import { SearchResults } from "@pnp/sp/search";
|
||||
import { Icon, Dropdown, IDropdownOption, IDropdownStyles, PrimaryButton, Label, IDropdownProps, Link, MessageBar, MessageBarType, MessageBarButton } from 'office-ui-fabric-react';
|
||||
import Services from './Services/Services';
|
||||
import * as strings from 'SaveEmailToSharePointWebPartStrings';
|
||||
|
||||
|
||||
const dropdownStyles: Partial<IDropdownStyles> = { dropdown: { width: 300 } };
|
||||
interface SaveEmailToSharePointState {
|
||||
allSites: any;
|
||||
selectedSite: any;
|
||||
allLibraries: any;
|
||||
selectedLibrary: any;
|
||||
savedLink: string;
|
||||
rootURL: string;
|
||||
errMsg: string;
|
||||
}
|
||||
export default class SaveEmailToSharePoint extends React.Component<ISaveEmailToSharePointProps, SaveEmailToSharePointState> {
|
||||
private services = new Services();
|
||||
constructor(props: ISaveEmailToSharePointProps, state: SaveEmailToSharePointState) {
|
||||
super(props);
|
||||
this.state = {
|
||||
allSites: null,
|
||||
selectedSite: null,
|
||||
allLibraries: null,
|
||||
selectedLibrary: null,
|
||||
savedLink: '',
|
||||
rootURL: '',
|
||||
errMsg: ''
|
||||
};
|
||||
}
|
||||
public componentWillMount() {
|
||||
this.getAllSites();
|
||||
this.getRootURL();
|
||||
}
|
||||
|
||||
public getRootURL = () => {
|
||||
this.services.getRootSiteURL().then((rootURL) => {
|
||||
this.setState({
|
||||
rootURL: rootURL
|
||||
});
|
||||
});
|
||||
}
|
||||
private saveToLibrary = (file) => {
|
||||
let filename = Office.context.mailbox.item.subject + ".eml";
|
||||
this.services.saveFileToSP(this.state.selectedSite.key, this.state.selectedLibrary.key, filename, file).then((result) => {
|
||||
console.log(result.data.ServerRelativeUrl);
|
||||
this.setState({
|
||||
savedLink: this.state.rootURL + result.data.ServerRelativeUrl + "?web=1",
|
||||
errMsg:''
|
||||
});
|
||||
}).catch((err) => {
|
||||
this.setState({
|
||||
errMsg: this.parseErr(err.message),
|
||||
savedLink:''
|
||||
});
|
||||
});
|
||||
}
|
||||
public getAllSites = () => {
|
||||
this.services.getSiteNames().then((allSiteResults: SearchResults) => {
|
||||
console.log(allSiteResults.PrimarySearchResults);
|
||||
let allsite = [];
|
||||
allSiteResults.PrimarySearchResults.forEach(element => {
|
||||
let siteValue = { key: element.Path, text: element.Title };
|
||||
allsite.push(siteValue);
|
||||
});
|
||||
this.setState({
|
||||
allSites: allsite
|
||||
});
|
||||
});
|
||||
}
|
||||
public getCurrentEmailContent = () => {
|
||||
let id = Office.context.mailbox.item.itemId;
|
||||
this.services.getEmailContent(this.props.context, id).then((response: any) => {
|
||||
this.saveToLibrary(response);
|
||||
}).catch((err) => {
|
||||
this.setState({
|
||||
errMsg: "Graph API error: " + this.parseErr(err.message),
|
||||
savedLink:''
|
||||
});
|
||||
});
|
||||
}
|
||||
public parseErr = (msg:string) => {
|
||||
return JSON.parse(msg.substring(msg.indexOf('"message"')+10,msg.length-2)).value;
|
||||
}
|
||||
public OnSelectSite = (event: React.FormEvent<HTMLDivElement>, item: IDropdownOption) => {
|
||||
this.services.getAllDocumentLibary(item.key.toString()).then((libraries) => {
|
||||
if (libraries.length) {
|
||||
let allLib = [];
|
||||
libraries.forEach(element => {
|
||||
let library = { key: element.ServerRelativeUrl, text: element.Title };
|
||||
allLib.push(library);
|
||||
});
|
||||
this.setState({
|
||||
selectedSite: item,
|
||||
allLibraries: allLib
|
||||
});
|
||||
} else {
|
||||
this.setState({
|
||||
selectedSite: item,
|
||||
savedLink: '',
|
||||
errMsg: ''
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
public OnSelectLibrary = (event: React.FormEvent<HTMLDivElement>, item: IDropdownOption) => {
|
||||
this.setState({
|
||||
selectedLibrary: item,
|
||||
savedLink: ''
|
||||
});
|
||||
}
|
||||
public render(): React.ReactElement<ISaveEmailToSharePointProps> {
|
||||
return (
|
||||
<div className={styles.saveEmailToSharePoint} >
|
||||
<div className={styles.row}>
|
||||
{this.state.allSites ? <Dropdown
|
||||
label={strings.SiteLabel}
|
||||
selectedKey={this.state.selectedSite ? this.state.selectedSite.key : undefined}
|
||||
onChange={this.OnSelectSite}
|
||||
placeholder={strings.SitePlaceHolder}
|
||||
options={this.state.allSites}
|
||||
styles={dropdownStyles}
|
||||
className={styles.column}
|
||||
onRenderPlaceholder={this.onRenderforSite}
|
||||
/> : null}
|
||||
</div>
|
||||
<div className={styles.row}>
|
||||
{this.state.allLibraries ? <Dropdown
|
||||
label={strings.LibraryLabel}
|
||||
selectedKey={this.state.selectedLibrary ? this.state.selectedLibrary.key : undefined}
|
||||
onChange={this.OnSelectLibrary}
|
||||
placeholder={strings.LibraryPlaceHolder}
|
||||
options={this.state.allLibraries}
|
||||
styles={dropdownStyles}
|
||||
className={styles.column + " ms-fadeIn200"}
|
||||
onRenderPlaceholder={this.onRenderforLib}
|
||||
/> : null}
|
||||
</div>
|
||||
<div className={styles.row}>
|
||||
<PrimaryButton
|
||||
text={strings.Save}
|
||||
disabled={this.state.selectedLibrary ? false : true}
|
||||
className={styles.column + " btnSave"}
|
||||
onClick={this.getCurrentEmailContent} />
|
||||
|
||||
<PrimaryButton
|
||||
text={strings.Cancel}
|
||||
className={styles.column + " btnCancel"}
|
||||
onClick={() => { Office.context.ui.closeContainer(); }} />
|
||||
</div>
|
||||
<div className={styles.row}>
|
||||
{this.state.savedLink.length ?
|
||||
<MessageBar
|
||||
messageBarType={MessageBarType.success}
|
||||
isMultiline={true}
|
||||
onDismiss={null}
|
||||
className={styles.successMsg}
|
||||
dismissButtonAriaLabel="Close"
|
||||
actions={
|
||||
<div>
|
||||
<MessageBarButton onClick={()=>window.open(this.state.savedLink,'_blank')}>OK</MessageBarButton>
|
||||
</div>
|
||||
}>
|
||||
{strings.PreviewMessage.replace("{libName}", this.state.selectedLibrary.text)}
|
||||
</MessageBar>
|
||||
: null}
|
||||
{this.state.errMsg.length ? <MessageBar
|
||||
messageBarType={MessageBarType.error}
|
||||
isMultiline={true}
|
||||
onDismiss={null}
|
||||
className={styles.errMsg}
|
||||
dismissButtonAriaLabel="Close">
|
||||
{this.state.errMsg}
|
||||
</MessageBar>
|
||||
: null}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
public onRenderforLib = (props: IDropdownProps): JSX.Element => {
|
||||
return (
|
||||
<React.Fragment>
|
||||
<Icon iconName="DocLibrary" className={styles.iconStyle} />
|
||||
<span >{props.label}</span>
|
||||
</React.Fragment>
|
||||
);
|
||||
}
|
||||
public onRenderforSite = (props: IDropdownProps): JSX.Element => {
|
||||
return (
|
||||
<React.Fragment>
|
||||
<Icon iconName="Website" className={styles.iconStyle} />
|
||||
<span >{props.label}</span>
|
||||
</React.Fragment>
|
||||
);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,40 @@
|
|||
import { sp } from '../SPPreset';
|
||||
import { Web } from '@pnp/sp/webs';
|
||||
import { SearchResults } from '@pnp/sp/search';
|
||||
import { WebPartContext } from '@microsoft/sp-webpart-base';
|
||||
import { MSGraphClient } from "@microsoft/sp-http";
|
||||
|
||||
export default class Services {
|
||||
public async getSiteNames(): Promise<SearchResults> {
|
||||
const allSiteResults: SearchResults = await sp.search({
|
||||
Querytext: "contentclass:STS_Site contentclass:STS_Web",
|
||||
EnableInterleaving: true,
|
||||
RowLimit: 100
|
||||
});
|
||||
return allSiteResults;
|
||||
}
|
||||
public getRootSiteURL(): Promise<string> {
|
||||
return sp.web.get().then((data) => {
|
||||
return data.ResourcePath.DecodedUrl;
|
||||
});
|
||||
}
|
||||
public saveFileToSP(SiteURL: string, serverRelativeURL: string, filename: string, file): Promise<any> {
|
||||
let web = Web(SiteURL);
|
||||
return web.getFolderByServerRelativeUrl(serverRelativeURL).files.add(filename, file, true).then((result) => {
|
||||
return result;
|
||||
});
|
||||
}
|
||||
public getEmailContent(context: WebPartContext, id: string): Promise<any> {
|
||||
return context.msGraphClientFactory.getClient().then((client: MSGraphClient): Promise< void> => {
|
||||
return client.api('/me/messages/' + id + '/$value').version('v1.0').responseType('blob').get().then((response: any) => {
|
||||
return response;
|
||||
});
|
||||
});
|
||||
}
|
||||
public getAllDocumentLibary(absoluteURL: string): Promise<any[]> {
|
||||
return sp.site.getDocumentLibraries(absoluteURL).then((libraries: any[]) => {
|
||||
return libraries;
|
||||
});
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
define([], function () {
|
||||
return {
|
||||
"PropertyPaneDescription": "Description",
|
||||
"BasicGroupName": "Group Name",
|
||||
"DescriptionFieldLabel": "Description Field",
|
||||
"SiteLabel": "Select a site",
|
||||
"SitePlaceHolder": "Select a site",
|
||||
"LibraryLabel": "Select a Library",
|
||||
"LibraryPlaceHolder": "Select a Library",
|
||||
"PreviewMessage":"The selected email is saved in the {libName} Library. Select 'OK' to preview the saved email.",
|
||||
"Save": "Save",
|
||||
"Cancel": "Cancel"
|
||||
}
|
||||
});
|
|
@ -0,0 +1,17 @@
|
|||
declare interface ISaveEmailToSharePointWebPartStrings {
|
||||
PropertyPaneDescription: string;
|
||||
BasicGroupName: string;
|
||||
DescriptionFieldLabel: string;
|
||||
SiteLabel:string;
|
||||
SitePlaceHolder: string;
|
||||
LibraryLabel: string;
|
||||
LibraryPlaceHolder: string;
|
||||
PreviewMessage: string;
|
||||
Save: string;
|
||||
Cancel: string;
|
||||
}
|
||||
|
||||
declare module 'SaveEmailToSharePointWebPartStrings' {
|
||||
const strings: ISaveEmailToSharePointWebPartStrings;
|
||||
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