react-zpl-viewer sample (#1140)

* Initial Commit

* Fixed file select and updated ReadME

* updated ReadME
This commit is contained in:
Zach 2020-03-09 13:57:48 -04:00 committed by GitHub
parent 7f7756e8ca
commit 3a7a3746ff
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
33 changed files with 19286 additions and 0 deletions

View 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-zpl-viewer/.gitignore vendored Normal file
View 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

View File

@ -0,0 +1,5 @@
{
"recommendations": [
"msjsdiag.debugger-for-chrome"
]
}

View File

@ -0,0 +1,43 @@
{
/**
* Install Chrome Debugger Extension for Visual Studio Code to debug your components with the
* Chrome browser: https://aka.ms/spfx-debugger-extensions
*/
"version": "0.2.0",
"configurations": [{
"name": "Local workbench",
"type": "chrome",
"request": "launch",
"url": "https://localhost:4321/temp/workbench.html",
"webRoot": "${workspaceRoot}",
"sourceMaps": true,
"sourceMapPathOverrides": {
"webpack:///.././src/*": "${webRoot}/src/*",
"webpack:///../../../src/*": "${webRoot}/src/*",
"webpack:///../../../../src/*": "${webRoot}/src/*",
"webpack:///../../../../../src/*": "${webRoot}/src/*"
},
"runtimeArgs": [
"--remote-debugging-port=9222"
]
},
{
"name": "Hosted workbench",
"type": "chrome",
"request": "launch",
"url": "https://enter-your-SharePoint-site/_layouts/workbench.aspx",
"webRoot": "${workspaceRoot}",
"sourceMaps": true,
"sourceMapPathOverrides": {
"webpack:///.././src/*": "${webRoot}/src/*",
"webpack:///../../../src/*": "${webRoot}/src/*",
"webpack:///../../../../src/*": "${webRoot}/src/*",
"webpack:///../../../../../src/*": "${webRoot}/src/*"
},
"runtimeArgs": [
"--remote-debugging-port=9222",
"-incognito"
]
}
]
}

View File

@ -0,0 +1,13 @@
// Place your settings in this file to overwrite default and user settings.
{
// Configure glob patterns for excluding files and folders in the file explorer.
"files.exclude": {
"**/.git": true,
"**/.DS_Store": true,
"**/bower_components": true,
"**/coverage": true,
"**/lib-amd": true,
"src/**/*.scss.ts": true
},
"typescript.tsdk": ".\\node_modules\\typescript\\lib"
}

View File

@ -0,0 +1,12 @@
{
"@microsoft/generator-sharepoint": {
"isCreatingSolution": true,
"environment": "spo",
"version": "1.9.1",
"libraryName": "react-zpl-viewer",
"libraryId": "f9e943cb-495d-4cd3-bd6c-73c4071cef3d",
"packageManager": "npm",
"isDomainIsolated": false,
"componentType": "webpart"
}
}

View File

@ -0,0 +1,52 @@
# react-zpl-viewer
## Summary
This webpart will allow a user to select a text file contatining zpl which is used to generate an image using the [labelary web service](http://labelary.com/service.html) to render the zpl and return the image.
![Preview](./assets/preview.gif)
## Used SharePoint Framework Version
![drop](https://img.shields.io/badge/version-1.9.1-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)
--------|---------
react-zpl-viewer | Zach Roberts [spodev](https://spodev.com)
## Version history
Version|Date|Comments
-------|----|--------
1.0|Feburary 13, 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 --nobrowser`
* Browse to the workbench `https://yourtenant.sharepoint.com/sites/yoursite/_layout/15/workbench.aspx` and add the webpart
## Features
This webpart allows a user to select a text file containing zpl which then the contents of the selected file are read and the user is also able to configure the size of the label they would like to see in the render. When the user clicks the show label button the label is generated using an online server to render the image.
* [PnP SPFx React Controls - File Selector](https://sharepoint.github.io/sp-dev-fx-controls-react/)
* [PnP JS - Read Contents of a file](https://pnp.github.io/pnpjs/)
<img src="https://telemetry.sharepointpnp.com/sp-dev-fx-webparts/samples/react-zpl-viewer" />

Binary file not shown.

After

Width:  |  Height:  |  Size: 755 KiB

View File

@ -0,0 +1,19 @@
{
"$schema": "https://developer.microsoft.com/json-schemas/spfx-build/config.2.0.schema.json",
"version": "2.0",
"bundles": {
"react-zpl-viewer-web-part": {
"components": [
{
"entrypoint": "./lib/webparts/reactZplViewer/ReactZplViewerWebPart.js",
"manifest": "./src/webparts/reactZplViewer/ReactZplViewerWebPart.manifest.json"
}
]
}
},
"externals": {},
"localizedResources": {
"ReactZplViewerWebPartStrings": "lib/webparts/reactZplViewer/loc/{locale}.js",
"ControlStrings": "node_modules/@pnp/spfx-controls-react/lib/loc/{locale}.js"
}
}

View File

@ -0,0 +1,4 @@
{
"$schema": "https://developer.microsoft.com/json-schemas/spfx-build/copy-assets.schema.json",
"deployCdnPath": "temp/deploy"
}

View File

@ -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-zpl-viewer",
"accessKey": "<!-- ACCESS KEY -->"
}

View File

@ -0,0 +1,13 @@
{
"$schema": "https://developer.microsoft.com/json-schemas/spfx-build/package-solution.schema.json",
"solution": {
"name": "react-zpl-viewer-client-side-solution",
"id": "f9e943cb-495d-4cd3-bd6c-73c4071cef3d",
"version": "1.0.0.0",
"includeClientSideAssets": true,
"isDomainIsolated": false
},
"paths": {
"zippedPackage": "solution/react-zpl-viewer.sppkg"
}
}

View 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/"
}
}

View 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-zpl-viewer/gulpfile.js vendored Normal file
View File

@ -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);

18571
samples/react-zpl-viewer/package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,44 @@
{
"name": "react-zpl-viewer",
"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.9.1",
"@microsoft/sp-lodash-subset": "1.9.1",
"@microsoft/sp-office-ui-fabric-core": "1.9.1",
"@microsoft/sp-webpart-base": "1.9.1",
"@pnp/graph": "^2.0.2",
"@pnp/sp": "^2.0.2",
"@pnp/spfx-controls-react": "1.16.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.9.1",
"@microsoft/sp-tslint-rules": "1.9.1",
"@microsoft/sp-module-interfaces": "1.9.1",
"@microsoft/sp-webpart-workbench": "1.9.1",
"@microsoft/rush-stack-compiler-2.9": "0.7.16",
"gulp": "~3.9.1",
"@types/chai": "3.4.34",
"@types/mocha": "2.2.38",
"ajv": "~5.2.2"
}
}

View File

@ -0,0 +1 @@
// A file is required to be in the root of the /src directory by the TypeScript compiler

View File

@ -0,0 +1,27 @@
{
"$schema": "https://developer.microsoft.com/json-schemas/spfx/client-side-web-part-manifest.schema.json",
"id": "1a208af5-4772-423b-8f62-96e3739abd99",
"alias": "ReactZplViewerWebPart",
"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": "react-zpl-viewer" },
"description": { "default": "react-zpl-viewer description" },
"officeFabricIconFontName": "Page",
"properties": {
"description": "react-zpl-viewer"
}
}]
}

View File

@ -0,0 +1,73 @@
import * as React from 'react';
import * as ReactDom from 'react-dom';
import { Version } from '@microsoft/sp-core-library';
import {
BaseClientSideWebPart,
IPropertyPaneConfiguration,
PropertyPaneTextField,
WebPartContext
} from '@microsoft/sp-webpart-base';
import * as strings from 'ReactZplViewerWebPartStrings';
import { ReactZplViewer, IReactZplViewerProps } from './components/main';
import { sp } from '@pnp/sp';
export interface IReactZplViewerWebPartProps {
description: string;
title: string;
context: WebPartContext;
}
export default class ReactZplViewerWebPart extends BaseClientSideWebPart<IReactZplViewerWebPartProps> {
public render(): void {
const element: React.ReactElement<IReactZplViewerProps > = React.createElement(
ReactZplViewer,
{
description: this.properties.description,
title: this.properties.title,
context: this.context
}
);
ReactDom.render(element, this.domElement);
}
public onInit(): Promise<void> {
return super.onInit().then(_ => {
sp.setup({
spfxContext: this.context
});
});
}
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('title', {
label: 'Title',
value: 'ZPL Viewer'
})
]
}
]
}
]
};
}
}

View File

@ -0,0 +1 @@
export * from './main';

View File

@ -0,0 +1,5 @@
export interface labelImage {
url?: string;
width?: string;
height?: string;
}

View File

@ -0,0 +1,7 @@
import { WebPartContext } from "@microsoft/sp-webpart-base";
export interface IReactZplViewerProps {
description: string;
title: string;
context: WebPartContext;
}

View File

@ -0,0 +1,11 @@
import { IFilePickerResult } from "@pnp/spfx-controls-react/lib/FilePicker";
import {labelImage} from './IReactLabelImage';
export interface IReactZplViewerState {
selectedFile?: IFilePickerResult;
showSelectedFile?: boolean;
zpl?: string;
width?: number;
height?: number;
labelImage?: labelImage;
}

View File

@ -0,0 +1,84 @@
@import '~office-ui-fabric-react/dist/sass/References.scss';
.reactZplViewer {
.imgBackground {
background-color: lightgray;
text-align: center;
}
.imgLabel {
padding: 20px;
}
.container {
max-width: 700px;
margin: 0px auto;
box-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.2), 0 25px 50px 0 rgba(0, 0, 0, 0.1);
}
.row {
@include ms-Grid-row;
@include ms-fontColor-white;
background-color: $ms-color-themeDark;
padding: 20px;
}
.column {
@include ms-Grid-col;
@include ms-lg10;
@include ms-xl8;
@include ms-xlPush2;
@include ms-lgPush1;
}
.title {
@include ms-font-xl;
@include ms-fontColor-white;
}
.subTitle {
@include ms-font-l;
@include ms-fontColor-white;
}
.description {
@include ms-font-l;
@include ms-fontColor-white;
}
.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;
}
}
}

View File

@ -0,0 +1,129 @@
import * as React from 'react';
import styles from './ReactZplViewer.module.scss';
import { IReactZplViewerProps } from './IReactZplViewerProps';
import { escape } from '@microsoft/sp-lodash-subset';
import { FilePicker, IFilePickerResult } from '@pnp/spfx-controls-react/lib/FilePicker';
import { IReactZplViewerState } from './IReactZplViewerState';
import { TextField, Text, PrimaryButton, Label, Dropdown, Slider } from 'office-ui-fabric-react';
import { sp } from '@pnp/sp';
import "@pnp/sp/webs";
import "@pnp/sp/files";
import "@pnp/sp/folders";
const baseUrl: string = 'http://api.labelary.com/v1/printers/8dpmm/labels/';
export class ReactZplViewer extends React.Component<IReactZplViewerProps, IReactZplViewerState> {
constructor(props: IReactZplViewerProps) {
super(props);
this.state = {
selectedFile: null,
showSelectedFile: false,
zpl: "",
labelImage: {
url: null,
height: null,
width: null
}
};
}
public render(): React.ReactElement<IReactZplViewerProps> {
return (
<div className={ styles.reactZplViewer }>
<h1>ZPL Viewer</h1>
<div className={"ms-Grid"}>
<div className={"ms-Grid-row"}>
<div className={"ms-Grid-col"}>
{this.state.showSelectedFile == true ?
<Text>{this.state.selectedFile.fileName}</Text>
: <div>No File Selected</div>
}
</div>
<div className={"ms-Grid-col"}>
<FilePicker
accepts={[".txt"]}
onSave={this._getFile}
onChanged={this._getFile}
context={this.props.context}
buttonLabel="Select File"
hideLinkUploadTab={true}
hideLocalUploadTab={true}
hideOneDriveTab={true}
hideOrganisationalAssetTab={true}
hideRecentTab={true}
/>
</div>
</div>
<div className={"ms-Grid-row"}>
<Label>Label Size:</Label>
<Slider
label="Width:"
min={1}
max={10}
showValue={true}
onChange={(value: number) => this.setState({width: value})}
/>
<Slider
label="Height:"
min={1}
max={10}
showValue={true}
onChange={(value: number) => this.setState({height: value})}
/>
</div>
<div className={"ms-Grid-row"}>
<PrimaryButton
text="Show Label"
onClick={this._showLabel}
disabled={!this.state.showSelectedFile}
/>
</div>
<div className={"ms-Grid-row"}>
{this.state.labelImage.url !== null ?
<div className={styles.imgBackground} >
<img width={this.state.labelImage.width+'00px'} height={this.state.labelImage.height+'00px'} className={styles.imgLabel} src={this.state.labelImage.url} alt="ZPL Label" />
</div>
: <div></div>
}
</div>
</div>
</div>
);
}
private _getFile = (filePickerResult: IFilePickerResult): void => {
this.setState({
selectedFile: filePickerResult,
showSelectedFile: true
}, () => {
this._getZpl();
});
}
private _getZpl = (): void => {
const relativeURL: string = this.state.selectedFile.fileAbsoluteUrl.split("com").pop();
sp.web.getFileByServerRelativeUrl(relativeURL).getText().then(zpl => {
this.setState({
zpl: zpl
});
});
}
private _showLabel = (): void => {
const imageUrl: string = baseUrl + `${this.state.width}x${this.state.height}/0/${this.state.zpl}`;
const imageWidth: string = this.state.width.toString();
const imageHeight: string = this.state.height.toString();
this.setState({
labelImage: {
url: imageUrl,
width: imageWidth,
height: imageHeight
},
});
}
}

View File

@ -0,0 +1,2 @@
export * from './ReactZplViewer';
export * from './IReactZplViewerProps';

View File

@ -0,0 +1,7 @@
define([], function() {
return {
"PropertyPaneDescription": "Description",
"BasicGroupName": "Group Name",
"DescriptionFieldLabel": "Description Field"
}
});

View File

@ -0,0 +1,10 @@
declare interface IReactZplViewerWebPartStrings {
PropertyPaneDescription: string;
BasicGroupName: string;
DescriptionFieldLabel: string;
}
declare module 'ReactZplViewerWebPartStrings' {
const strings: IReactZplViewerWebPartStrings;
export = strings;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

View File

@ -0,0 +1,38 @@
{
"extends": "./node_modules/@microsoft/rush-stack-compiler-2.9/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"
]
}

View 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
}
}