React visio javascript APIs web part sample (#606)
* Add new project files * Add office-js package * update strings * add Visio service - still missing types * Embed visio file * remove non required package * move import of officejs to web part file * remove fixed width * use delegate functions to pass values to component * Display links on right panel * Update property description and web part icon * add comment * load document when url is provided * Add readme * Fixed broken image
This commit is contained in:
parent
b5ab9513fe
commit
db70df922c
|
@ -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,11 @@
|
|||
{
|
||||
"@microsoft/generator-sharepoint": {
|
||||
"isCreatingSolution": true,
|
||||
"environment": "spo",
|
||||
"version": "1.5.1",
|
||||
"libraryName": "react-visio",
|
||||
"libraryId": "0ad401f1-b158-4626-8e71-cf27b1f4848d",
|
||||
"packageManager": "npm",
|
||||
"componentType": "webpart"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,55 @@
|
|||
# React Visio Embed
|
||||
|
||||
## Summary
|
||||
|
||||
This sample shows how the [Visio JavaScript APIs](https://dev.office.com/reference/add-ins/visio/visio-javascript-reference-overview) can be used within a web part. For sample purposes, this web part will display the name and the hyperlinks of a Visio shape when the user selects it.
|
||||
|
||||
To test the web part, upload the sample file provided to a SharePoint document library. Then open the file on the Visio web client and copy the Url from the browser. Add that url on the web part properties field and the EmbeddedSession will start and display the diagram.
|
||||
|
||||
![Demo](./assets/Preview.PNG)
|
||||
|
||||
## Used SharePoint Framework Version
|
||||
|
||||
![drop](https://img.shields.io/badge/drop-1.5.1-green.svg)
|
||||
|
||||
## Applies to
|
||||
|
||||
* [SharePoint Framework](https:/dev.office.com/sharepoint)
|
||||
* [Visio JavaScript APIs](https://dev.office.com/reference/add-ins/visio/visio-javascript-reference-overview)
|
||||
|
||||
## Prerequisites
|
||||
|
||||
* Office 365 subscription with SharePoint Online licence
|
||||
* SharePoint Framework [development environment](https://dev.office.com/sharepoint/docs/spfx/set-up-your-development-environment) already set up.
|
||||
|
||||
## Solution
|
||||
|
||||
Solution|Author(s)
|
||||
--------|---------
|
||||
react-visio|Joel Rodrigues
|
||||
|
||||
## Version history
|
||||
|
||||
Version|Date|Comments
|
||||
-------|----|--------
|
||||
1.0|August 23, 2018|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`
|
||||
|
||||
## Features
|
||||
|
||||
This Web Part illustrates the following concepts on top of the SharePoint Framework:
|
||||
|
||||
* Using the Visio JavaScript APIs to embed a diagram on a page
|
||||
* Using the Visio JavaScript APIs to interact with the Visio diagram and data available
|
Binary file not shown.
Binary file not shown.
After Width: | Height: | Size: 25 KiB |
|
@ -0,0 +1,23 @@
|
|||
{
|
||||
"$schema": "https://developer.microsoft.com/json-schemas/spfx-build/config.2.0.schema.json",
|
||||
"version": "2.0",
|
||||
"bundles": {
|
||||
"visio-sample-web-part": {
|
||||
"components": [
|
||||
{
|
||||
"entrypoint": "./lib/webparts/visioSample/VisioSampleWebPart.js",
|
||||
"manifest": "./src/webparts/visioSample/VisioSampleWebPart.manifest.json"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"externals": {
|
||||
"officejs": {
|
||||
"path": "https://appsforoffice.microsoft.com/embedded/1.0/visio-web-embedded.js",
|
||||
"globalName": "officejs"
|
||||
}
|
||||
},
|
||||
"localizedResources": {
|
||||
"VisioSampleWebPartStrings": "lib/webparts/visioSample/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-visio",
|
||||
"accessKey": "<!-- ACCESS KEY -->"
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
{
|
||||
"$schema": "https://developer.microsoft.com/json-schemas/spfx-build/package-solution.schema.json",
|
||||
"solution": {
|
||||
"name": "react-visio-client-side-solution",
|
||||
"id": "0ad401f1-b158-4626-8e71-cf27b1f4848d",
|
||||
"version": "1.0.0.0",
|
||||
"includeClientSideAssets": true,
|
||||
"skipFeatureDeployment": true
|
||||
},
|
||||
"paths": {
|
||||
"zippedPackage": "solution/react-visio.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,45 @@
|
|||
{
|
||||
"$schema": "https://developer.microsoft.com/json-schemas/core-build/tslint.schema.json",
|
||||
// Display errors as warnings
|
||||
"displayAsWarning": true,
|
||||
// The TSLint task may have been configured with several custom lint rules
|
||||
// before this config file is read (for example lint rules from the tslint-microsoft-contrib
|
||||
// project). If true, this flag will deactivate any of these rules.
|
||||
"removeExistingRules": true,
|
||||
// When true, the TSLint task is configured with some default TSLint "rules.":
|
||||
"useDefaultConfigAsBase": false,
|
||||
// Since removeExistingRules=true and useDefaultConfigAsBase=false, there will be no lint rules
|
||||
// which are active, other than the list of rules below.
|
||||
"lintConfig": {
|
||||
// Opt-in to Lint rules which help to eliminate bugs in JavaScript
|
||||
"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-case": true,
|
||||
"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,
|
||||
"valid-typeof": true,
|
||||
"variable-name": false,
|
||||
"whitespace": false
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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 gulp = require('gulp');
|
||||
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(gulp);
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,35 @@
|
|||
{
|
||||
"name": "react-visio",
|
||||
"version": "0.0.1",
|
||||
"private": true,
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
},
|
||||
"scripts": {
|
||||
"build": "gulp bundle",
|
||||
"clean": "gulp clean",
|
||||
"test": "gulp test"
|
||||
},
|
||||
"dependencies": {
|
||||
"@microsoft/sp-core-library": "1.5.1",
|
||||
"@microsoft/sp-lodash-subset": "1.5.1",
|
||||
"@microsoft/sp-office-ui-fabric-core": "1.5.1",
|
||||
"@microsoft/sp-webpart-base": "1.5.1",
|
||||
"@types/es6-promise": "0.0.33",
|
||||
"@types/office-js": "0.0.101",
|
||||
"@types/react": "15.6.6",
|
||||
"@types/react-dom": "15.5.6",
|
||||
"@types/webpack-env": "1.13.1",
|
||||
"react": "15.6.2",
|
||||
"react-dom": "15.6.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@microsoft/sp-build-web": "1.5.1",
|
||||
"@microsoft/sp-module-interfaces": "1.5.1",
|
||||
"@microsoft/sp-webpart-workbench": "1.5.1",
|
||||
"@types/chai": "3.4.34",
|
||||
"@types/mocha": "2.2.38",
|
||||
"ajv": "~5.2.2",
|
||||
"gulp": "~3.9.1"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,350 @@
|
|||
|
||||
import { find } from '@microsoft/sp-lodash-subset';
|
||||
import { IWebPartContext } from '@microsoft/sp-webpart-base';
|
||||
|
||||
export class VisioService {
|
||||
|
||||
private _webPartContext: IWebPartContext;
|
||||
|
||||
private _url = "";
|
||||
/**
|
||||
* gets the url of the Visio document to embed
|
||||
* @returns a string with the document url
|
||||
*/
|
||||
get url(): string {
|
||||
return this._url;
|
||||
}
|
||||
/**
|
||||
* sets the url of the Visio document to embed
|
||||
* @param url the url of the document
|
||||
*/
|
||||
set url(url: string) {
|
||||
// apis are enabled for EmbedView action only
|
||||
url = url.replace("action=view", "action=embedview");
|
||||
url = url.replace("action=interactivepreview", "action=embedview");
|
||||
url = url.replace("action=default", "action=embedview");
|
||||
url = url.replace("action=edit", "action=embedview");
|
||||
|
||||
this._url = url;
|
||||
}
|
||||
|
||||
private _session: OfficeExtension.EmbeddedSession = null;
|
||||
private _shapes: Visio.Shape[] = [];
|
||||
private _selectedShape: Visio.Shape;
|
||||
|
||||
private _documentLoadComplete = false;
|
||||
private _pageLoadComplete = false;
|
||||
/**
|
||||
* gets a pre-loaded collection of relevant shapes from the diagram
|
||||
*/
|
||||
public get shapes(): Visio.Shape[] {
|
||||
return this._shapes;
|
||||
}
|
||||
|
||||
// delegate functions passed from the react component
|
||||
public onSelectionChanged: (selectedShape: Visio.Shape) => void;
|
||||
public getAllShapes: (shapes: Visio.Shape[]) => void;
|
||||
|
||||
/**
|
||||
* class constructor
|
||||
* @param webPartContext the context of the web part
|
||||
*/
|
||||
constructor(webPartContext: IWebPartContext) {
|
||||
// set web part context
|
||||
this._webPartContext = webPartContext;
|
||||
}
|
||||
|
||||
/**
|
||||
* initialize session by embedding the Visio diagram on the page
|
||||
* @returns returns a promise
|
||||
*/
|
||||
private async _init(): Promise<any> {
|
||||
// initialize communication between the developer frame and the Visio Online frame
|
||||
this._session = new OfficeExtension.EmbeddedSession(
|
||||
this._url, {
|
||||
id: "embed-iframe",
|
||||
container: document.getElementById("iframeHost"),
|
||||
width: "100%",
|
||||
height: "600px"
|
||||
}
|
||||
);
|
||||
await this._session.init();
|
||||
console.log("Session successfully initialized");
|
||||
}
|
||||
|
||||
/**
|
||||
* function to add custom event handlers
|
||||
* @returns returns a promise
|
||||
*/
|
||||
private _addCustomEventHandlers = async (): Promise<any> => {
|
||||
|
||||
try {
|
||||
await Visio.run(this._session, async (context: Visio.RequestContext) => {
|
||||
var doc: Visio.Document = context.document;
|
||||
|
||||
// on document load complete
|
||||
const onDocumentLoadCompleteEventResult: OfficeExtension.EventHandlerResult<Visio.DocumentLoadCompleteEventArgs> =
|
||||
doc.onDocumentLoadComplete.add(
|
||||
this._onDocumentLoadComplete
|
||||
);
|
||||
// on page load complete
|
||||
const onPageLoadCompleteEventResult: OfficeExtension.EventHandlerResult<Visio.PageLoadCompleteEventArgs> =
|
||||
doc.onPageLoadComplete.add(
|
||||
this._onPageLoadComplete
|
||||
);
|
||||
// on selection changed
|
||||
const onSelectionChangedEventResult: OfficeExtension.EventHandlerResult<Visio.SelectionChangedEventArgs> =
|
||||
doc.onSelectionChanged.add(
|
||||
this._onSelectionChanged
|
||||
);
|
||||
|
||||
await context.sync();
|
||||
console.log("Document Load Complete handler attached");
|
||||
});
|
||||
} catch (error) {
|
||||
this.logError(error);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* method executed after a on document load complete event is triggered
|
||||
* @param args event arguments
|
||||
* @returns returns a promise
|
||||
*/
|
||||
private _onDocumentLoadComplete = async (args: Visio.DocumentLoadCompleteEventArgs): Promise<void> => {
|
||||
|
||||
// only execute if not executed yet
|
||||
if (!this._documentLoadComplete) {
|
||||
|
||||
try {
|
||||
console.log("Document Loaded Event: " + JSON.stringify(args));
|
||||
|
||||
// set internal flag to prevent event from running again if triggered twice
|
||||
this._documentLoadComplete = true;
|
||||
|
||||
await Visio.run(this._session, async (context: Visio.RequestContext) => {
|
||||
var doc: Visio.Document = context.document;
|
||||
// disable Hyperlinks on embed diagram
|
||||
doc.view.disableHyperlinks = true;
|
||||
// hide diagram boundary on embed diagram
|
||||
doc.view.hideDiagramBoundary = true;
|
||||
|
||||
await context.sync();
|
||||
});
|
||||
|
||||
|
||||
} catch (error) {
|
||||
this.logError(error);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* method executed after a on page load event is triggered
|
||||
* @param args event arguments
|
||||
* @returns returns a promise
|
||||
*/
|
||||
private _onPageLoadComplete = async (args: Visio.PageLoadCompleteEventArgs): Promise<void> => {
|
||||
|
||||
// only execute if not executed yet
|
||||
if (!this._pageLoadComplete) {
|
||||
|
||||
try {
|
||||
console.log("Page Loaded Event: " + JSON.stringify(args));
|
||||
|
||||
// set internal flag to prevent event from running again if triggered twice
|
||||
this._pageLoadComplete = true;
|
||||
|
||||
// get all relevant shapes and populate the class variable
|
||||
this._shapes = await this._getAllShapes();
|
||||
|
||||
// call delegate function from the react component
|
||||
this.getAllShapes(this._shapes);
|
||||
|
||||
} catch (error) {
|
||||
this.logError(error);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* method executed after a on selection change event is triggered
|
||||
* @param args event arguments
|
||||
* @returns returns a promise
|
||||
*/
|
||||
private _onSelectionChanged = async (args: Visio.SelectionChangedEventArgs): Promise<void> => {
|
||||
|
||||
try {
|
||||
console.log("Selection Changed Event " + JSON.stringify(args));
|
||||
|
||||
if (args.shapeNames.length > 0 && this._shapes && this._shapes.length > 0) {
|
||||
|
||||
// get name of selected item
|
||||
const selectedShapeText: string = args.shapeNames[0];
|
||||
|
||||
// find selected shape on the list of pre-loaded shapes
|
||||
this._selectedShape = find(this._shapes,
|
||||
s => s.name === selectedShapeText
|
||||
);
|
||||
|
||||
// call delegate function from the react component
|
||||
this.onSelectionChanged(this._selectedShape);
|
||||
|
||||
} else {
|
||||
// shape was deselected
|
||||
this._selectedShape = null;
|
||||
}
|
||||
} catch (error) {
|
||||
this.logError(error);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* select a shape on the visio diagram
|
||||
* @param name the name of the shape to select
|
||||
*/
|
||||
public selectShape = async (name: string): Promise<void> => {
|
||||
|
||||
try {
|
||||
|
||||
// find the correct shape from the pre-loaded list of shapes
|
||||
// check the ShapeData item with the 'Name' key
|
||||
const shape: Visio.Shape = find(this._shapes,
|
||||
s => (find(s.shapeDataItems.items, i => i.label === "Name").value === name)
|
||||
);
|
||||
|
||||
// only select shape if not the currently selected one
|
||||
if (this._selectedShape === null
|
||||
|| this._selectedShape === undefined
|
||||
|| (this._selectedShape && this._selectedShape.name !== shape.name)) {
|
||||
|
||||
await Visio.run(this._session, async (context: Visio.RequestContext) => {
|
||||
const page: Visio.Page = context.document.getActivePage();
|
||||
const shapesCollection: Visio.ShapeCollection = page.shapes;
|
||||
shapesCollection.load();
|
||||
await context.sync();
|
||||
|
||||
const diagramShape: Visio.Shape = shapesCollection.getItem(shape.name);
|
||||
// select shape on diagram
|
||||
diagramShape.select = true;
|
||||
|
||||
await context.sync();
|
||||
console.log(`Selected shape '${shape.name}' in diagram`);
|
||||
this._selectedShape = shape;
|
||||
});
|
||||
} else {
|
||||
console.log(`Shape '${shape.name}' is already selected in diagram`);
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
this.logError(error);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* get all shapes from page
|
||||
* @returns returns a promise
|
||||
*/
|
||||
private _getAllShapes = async (): Promise<Visio.Shape[]> => {
|
||||
|
||||
console.log("Getting all shapes");
|
||||
|
||||
try {
|
||||
let shapes: Visio.Shape[];
|
||||
|
||||
await Visio.run(this._session, async (context: Visio.RequestContext) => {
|
||||
const page: Visio.Page = context.document.getActivePage();
|
||||
const shapesCollection: Visio.ShapeCollection = page.shapes;
|
||||
shapesCollection.load();
|
||||
await context.sync();
|
||||
|
||||
// load all required properties for each shape
|
||||
for (let i: number = 0; i < shapesCollection.items.length; i++) {
|
||||
shapesCollection.items[i].shapeDataItems.load();
|
||||
shapesCollection.items[i].hyperlinks.load();
|
||||
}
|
||||
await context.sync();
|
||||
|
||||
shapes = shapesCollection.items;
|
||||
|
||||
return shapes;
|
||||
});
|
||||
|
||||
return shapes;
|
||||
} catch (error) {
|
||||
this.logError(error);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* initializes the embed session and attaches event handlers
|
||||
* this is the function that should be called to start the session
|
||||
* @param docUrl embed url of the document
|
||||
* @returns returns a promise
|
||||
*/
|
||||
public load = async (docUrl: string): Promise<void> => {
|
||||
console.log("Start loading Visio data");
|
||||
|
||||
try {
|
||||
|
||||
// sets the url, modifying it if required - uses set method to re-use logic
|
||||
this.url = docUrl;
|
||||
|
||||
// init
|
||||
await this._init();
|
||||
|
||||
// add custom onDocumentLoadComplete event handler
|
||||
await this._addCustomEventHandlers();
|
||||
|
||||
// trigger document and page loaded event handlers after 3 seconds in case Visio fails to trigger them
|
||||
// this is randomly happening on chrome, but seems to always fail on IE...
|
||||
setTimeout(() => {
|
||||
this._onDocumentLoadComplete(null);
|
||||
this._onPageLoadComplete(null);
|
||||
}, 3000);
|
||||
|
||||
} catch (error) {
|
||||
this.logError(error);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* generate embed url for a document
|
||||
* @param docId the list item ID of the target document
|
||||
*/
|
||||
private generateEmbedUrl = async (itemProperties: any): Promise<string> => {
|
||||
let url: string = "";
|
||||
|
||||
try {
|
||||
// check if data was returned
|
||||
if (itemProperties) {
|
||||
// generate required URL
|
||||
const siteUrl: string = this._webPartContext.pageContext.site.absoluteUrl;
|
||||
const sourceDoc: string = encodeURIComponent(itemProperties.File.ContentTag.split(",")[0]);
|
||||
const fileName: string = encodeURIComponent(itemProperties.File.Name);
|
||||
|
||||
if (siteUrl && sourceDoc && fileName) {
|
||||
url = `${siteUrl}/_layouts/15/Doc.aspx?sourcedoc=${sourceDoc}&file=${fileName}&action=default`;
|
||||
}
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
}
|
||||
|
||||
return url;
|
||||
}
|
||||
|
||||
/**
|
||||
* log error
|
||||
* @param error error object
|
||||
*/
|
||||
private logError = (error: any): void => {
|
||||
console.error("Error");
|
||||
if (error instanceof OfficeExtension.Error) {
|
||||
console.error("Debug info: ", JSON.stringify(error.debugInfo));
|
||||
} else {
|
||||
console.error(error);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
export * from "./VisioService";
|
|
@ -0,0 +1,25 @@
|
|||
{
|
||||
"$schema": "https://developer.microsoft.com/json-schemas/spfx/client-side-web-part-manifest.schema.json",
|
||||
"id": "79648d46-3e2b-41ec-a290-52bf757f806f",
|
||||
"alias": "VisioSampleWebPart",
|
||||
"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,
|
||||
|
||||
"preconfiguredEntries": [{
|
||||
"groupId": "5c03119e-3074-46fd-976b-c60198311f70", // Other
|
||||
"group": { "default": "Other" },
|
||||
"title": { "default": "Visio Embed Sample" },
|
||||
"description": { "default": "Sample web part using Visio API" },
|
||||
"officeFabricIconFontName": "VisioDiagram",
|
||||
"properties": {
|
||||
}
|
||||
}]
|
||||
}
|
|
@ -0,0 +1,74 @@
|
|||
import * as React from 'react';
|
||||
import * as ReactDom from 'react-dom';
|
||||
import { Version, Environment, EnvironmentType } from '@microsoft/sp-core-library';
|
||||
import {
|
||||
BaseClientSideWebPart,
|
||||
IPropertyPaneConfiguration,
|
||||
PropertyPaneTextField
|
||||
} from '@microsoft/sp-webpart-base';
|
||||
|
||||
import 'officejs';
|
||||
import * as strings from 'VisioSampleWebPartStrings';
|
||||
import { VisioSample, IVisioSampleProps } from './components/visioSample';
|
||||
import { VisioService } from "../../shared/services";
|
||||
|
||||
export interface IVisioSampleWebPartProps {
|
||||
documentUrl: string;
|
||||
}
|
||||
|
||||
export default class VisioSampleWebPart extends BaseClientSideWebPart<IVisioSampleWebPartProps> {
|
||||
|
||||
private _visioService: VisioService;
|
||||
|
||||
public onInit(): Promise<void> {
|
||||
if (DEBUG && Environment.type === EnvironmentType.Local) {
|
||||
console.log("Mock data service not implemented yet");
|
||||
} else {
|
||||
this._visioService = new VisioService(this.context);
|
||||
}
|
||||
|
||||
return super.onInit();
|
||||
}
|
||||
|
||||
public render(): void {
|
||||
const element: React.ReactElement<IVisioSampleProps > = React.createElement(
|
||||
VisioSample,
|
||||
{
|
||||
visioService: this._visioService,
|
||||
documentUrl: this.properties.documentUrl
|
||||
}
|
||||
);
|
||||
|
||||
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('documentUrl', {
|
||||
label: strings.DocumentUrlLabel
|
||||
})
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
};
|
||||
}
|
||||
}
|
|
@ -0,0 +1,2 @@
|
|||
@import '~@microsoft/sp-office-ui-fabric-core/dist/sass/SPFabricCore.scss';
|
||||
.hyperlink {}
|
|
@ -0,0 +1,14 @@
|
|||
import * as React from 'react';
|
||||
import styles from '../visioSample/VisioSample.module.scss';
|
||||
import { IHyperlinkProps } from '.';
|
||||
|
||||
export class Hyperlink extends React.Component<IHyperlinkProps, {}> {
|
||||
|
||||
|
||||
public render(): React.ReactElement<IHyperlinkProps> {
|
||||
return (
|
||||
<a href={this.props.properties.address} target="_blank">{this.props.properties.description}</a>
|
||||
|
||||
);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
export interface IHyperlinkProps {
|
||||
properties: Visio.Hyperlink;
|
||||
}
|
|
@ -0,0 +1,2 @@
|
|||
export * from "./Hyperlink";
|
||||
export * from "./IHyperlinkProps";
|
|
@ -0,0 +1,62 @@
|
|||
import * as React from 'react';
|
||||
import styles from '../visioSample/VisioSample.module.scss';
|
||||
import { IVisioSampleProps, IVisioSampleState } from '../visioSample';
|
||||
|
||||
export class VisioSample extends React.Component<IVisioSampleProps, IVisioSampleState> {
|
||||
|
||||
constructor(props: IVisioSampleProps) {
|
||||
super(props);
|
||||
|
||||
// set delegate functions that will be used to pass the values from the Visio service to the component
|
||||
this.props.visioService.onSelectionChanged = this._onSelectionChanged;
|
||||
this.props.visioService.getAllShapes = this._getAllShapes;
|
||||
|
||||
this.state = {
|
||||
selectedShape: null
|
||||
};
|
||||
}
|
||||
|
||||
public render(): React.ReactElement<IVisioSampleProps> {
|
||||
return (
|
||||
<div className={styles.visioSample}>
|
||||
<div id='iframeHost' className={styles.iframeHost}></div>
|
||||
<div className={styles.detailsPanel}>
|
||||
{this.state.selectedShape &&
|
||||
<h2>{this.state.selectedShape.name}</h2>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
public componentDidMount() {
|
||||
if (this.props.documentUrl) {
|
||||
this.props.visioService.load(this.props.documentUrl);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* method executed after a on selection change event is triggered
|
||||
* @param selectedShape the shape selected by the user on the Visio diagram
|
||||
*/
|
||||
private _onSelectionChanged = (selectedShape: Visio.Shape): void => {
|
||||
|
||||
console.log("Selected shape: ", selectedShape);
|
||||
console.log("Selected shape name: ", selectedShape.name);
|
||||
|
||||
this.setState({
|
||||
selectedShape: selectedShape
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* method executed after the collection of shapes is retrieved - after Visio diagram page load
|
||||
* @param shapes the collection of shapes on the Visio diagram
|
||||
*/
|
||||
private _getAllShapes = (shapes: Visio.Shape[]): void => {
|
||||
|
||||
console.log("Shapes: ", shapes);
|
||||
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
import { VisioService } from "../../../../shared/services";
|
||||
|
||||
export interface IVisioSampleProps {
|
||||
visioService: VisioService;
|
||||
documentUrl: string;
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
export interface IVisioSampleState {
|
||||
selectedShape: Visio.Shape;
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
@import '~@microsoft/sp-office-ui-fabric-core/dist/sass/SPFabricCore.scss';
|
||||
.visioSample {
|
||||
/* layout */
|
||||
display: flex;
|
||||
height: 600px;
|
||||
.iframeHost {
|
||||
flex: 3;
|
||||
}
|
||||
.detailsPanel {
|
||||
flex: 1;
|
||||
padding: 20px;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,78 @@
|
|||
import * as React from 'react';
|
||||
import styles from '../hyperlink/VisioSample.module.scss';
|
||||
import { IVisioSampleProps, IVisioSampleState } from '.';
|
||||
import { Hyperlink } from '../hyperlink';
|
||||
|
||||
export class VisioSample extends React.Component<IVisioSampleProps, IVisioSampleState> {
|
||||
|
||||
constructor(props: IVisioSampleProps) {
|
||||
super(props);
|
||||
|
||||
// set delegate functions that will be used to pass the values from the Visio service to the component
|
||||
this.props.visioService.onSelectionChanged = this._onSelectionChanged;
|
||||
this.props.visioService.getAllShapes = this._getAllShapes;
|
||||
|
||||
this.state = {
|
||||
selectedShape: null
|
||||
};
|
||||
}
|
||||
|
||||
public render(): React.ReactElement<IVisioSampleProps> {
|
||||
return (
|
||||
<div className={styles.visioSample}>
|
||||
<div id='iframeHost' className={styles.iframeHost}></div>
|
||||
<div className={styles.detailsPanel}>
|
||||
{this.state.selectedShape &&
|
||||
<div>
|
||||
<h2>{this.state.selectedShape.name}</h2>
|
||||
<div>
|
||||
{this.state.selectedShape.hyperlinks.items.length > 0 &&
|
||||
this.state.selectedShape.hyperlinks.items.map(
|
||||
hyperlinkProps => <Hyperlink properties={hyperlinkProps}></Hyperlink>
|
||||
)
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
public componentDidMount() {
|
||||
if (this.props.documentUrl) {
|
||||
this.props.visioService.load(this.props.documentUrl);
|
||||
}
|
||||
}
|
||||
|
||||
public async componentDidUpdate(prevProps: IVisioSampleProps) {
|
||||
if (this.props.documentUrl && this.props.documentUrl !== prevProps.documentUrl) {
|
||||
this.props.visioService.load(this.props.documentUrl);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* method executed after a on selection change event is triggered
|
||||
* @param selectedShape the shape selected by the user on the Visio diagram
|
||||
*/
|
||||
private _onSelectionChanged = (selectedShape: Visio.Shape): void => {
|
||||
|
||||
console.log("Selected shape: ", selectedShape);
|
||||
console.log("Selected shape name: ", selectedShape.name);
|
||||
|
||||
this.setState({
|
||||
selectedShape: selectedShape
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* method executed after the collection of shapes is retrieved - after Visio diagram page load
|
||||
* @param shapes the collection of shapes on the Visio diagram
|
||||
*/
|
||||
private _getAllShapes = (shapes: Visio.Shape[]): void => {
|
||||
|
||||
console.log("Shapes: ", shapes);
|
||||
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
export * from "./VisioSample";
|
||||
export * from "./IVisioSampleProps";
|
||||
export * from "./IVisioSampleState";
|
|
@ -0,0 +1,7 @@
|
|||
define([], function() {
|
||||
return {
|
||||
"PropertyPaneDescription": "Web part configuration",
|
||||
"BasicGroupName": "Document",
|
||||
"DocumentUrlLabel": "Visio Document Url - open document on web client and copy url from browser"
|
||||
}
|
||||
});
|
|
@ -0,0 +1,10 @@
|
|||
declare interface IVisioSampleWebPartStrings {
|
||||
PropertyPaneDescription: string;
|
||||
BasicGroupName: string;
|
||||
DocumentUrlLabel: string;
|
||||
}
|
||||
|
||||
declare module 'VisioSampleWebPartStrings' {
|
||||
const strings: IVisioSampleWebPartStrings;
|
||||
export = strings;
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
{
|
||||
"compilerOptions": {
|
||||
"target": "es5",
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"module": "esnext",
|
||||
"moduleResolution": "node",
|
||||
"jsx": "react",
|
||||
"declaration": true,
|
||||
"sourceMap": true,
|
||||
"experimentalDecorators": true,
|
||||
"skipLibCheck": true,
|
||||
"typeRoots": [
|
||||
"./node_modules/@types",
|
||||
"./node_modules/@microsoft"
|
||||
],
|
||||
"types": [
|
||||
"es6-promise",
|
||||
"webpack-env",
|
||||
"office-js"
|
||||
],
|
||||
"lib": [
|
||||
"es5",
|
||||
"dom",
|
||||
"es2015.collection"
|
||||
]
|
||||
}
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
{
|
||||
"rulesDirectory": "./config"
|
||||
}
|
Loading…
Reference in New Issue