Merge pull request #1214 from zachroberts8668/zroberts8668

Added react-personal-greeting
This commit is contained in:
Hugo Bernier 2020-04-15 00:20:41 -04:00 committed by GitHub
commit 7fa7639c5f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
31 changed files with 29142 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

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,26 @@
{
"@pnp/generator-spfx": {
"framework": "react",
"pnpFramework": "reactjs.plus",
"pnp-libraries": [
"msgraph",
"@pnp/pnpjs",
"rush@3.3"
],
"pnp-ci": "no-devops",
"pnp-vetting": [],
"spfxenv": "spo",
"pnp-testing": []
},
"@microsoft/generator-sharepoint": {
"environment": "spo",
"framework": "react",
"isCreatingSolution": true,
"version": "1.10.0",
"libraryName": "react-personal-greeting",
"libraryId": "5e7ea24d-fccc-4d96-a56c-488564d9c61c",
"packageManager": "npm",
"isDomainIsolated": false,
"componentType": "webpart"
}
}

View File

@ -0,0 +1,62 @@
# react-personal-greeting
## Summary
The web part pulls in the current user's name and displays it on the page. The greeting text before the name is customizable through the property pane. Additionally the position of the greeting and color of the text can be adjusted through the property pane as well.
![picture of the web part in action](assets/react-personal-greeting.gif)
## 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)
* [PnP SPFx Controls](https://sharepoint.github.io/sp-dev-fx-controls-react)
* [PnP SPFx Property Controls](https://sharepoint.github.io/sp-dev-fx-property-controls)
## Prerequisites
## Solution
Solution|Author(s)
--------|---------
react-personal-greeting|Zach Roberts - [SPODev](https://spodev.com)
## Version history
Version|Date|Comments
-------|----|--------
1.0|April 14, 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 build`
* `gulp bundle --ship`
* `gulp package-solution --ship`
* add the webpart to your tenant app store
* add the app to a SharePoint site and then add the webpart to the page
## Features
This Web Part illustrates the following concepts on top of the SharePoint Framework:
* Using the SPFx context to gather the current user's display name.
* Adjusting the styles of the component in the webpart using the props adjusted through the property pane.
* PnP SPFx Placeholder - This component allows you to have a placeholder visble under certain conditions if your web parts requires some setup.
* PnP SPFx Color Picker - This component adds an awesome color picker to the property pane, great for adjusting colors in your webpart.
<img src="https://telemetry.sharepointpnp.com/sp-dev-fx-webparts/samples/react-personal-greeting" />

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 MiB

View File

@ -0,0 +1,20 @@
{
"$schema": "https://developer.microsoft.com/json-schemas/spfx-build/config.2.0.schema.json",
"version": "2.0",
"bundles": {
"personal-greeting-web-part": {
"components": [
{
"entrypoint": "./lib/webparts/personalGreeting/PersonalGreetingWebPart.js",
"manifest": "./src/webparts/personalGreeting/PersonalGreetingWebPart.manifest.json"
}
]
}
},
"externals": {},
"localizedResources": {
"PersonalGreetingWebPartStrings": "lib/webparts/personalGreeting/loc/{locale}.js",
"PropertyControlStrings": "node_modules/@pnp/spfx-property-controls/lib/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-personal-greeting",
"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-personal-greeting-client-side-solution",
"id": "5e7ea24d-fccc-4d96-a56c-488564d9c61c",
"version": "1.0.0.0",
"includeClientSideAssets": true,
"isDomainIsolated": false
},
"paths": {
"zippedPackage": "solution/react-personal-greeting.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 -->"
}

View File

@ -0,0 +1,29 @@
'use strict';
// check if gulp dist was called
if (process.argv.indexOf('dist') !== -1) {
// add ship options to command call
process.argv.push('--ship');
}
const path = require('path');
const gulp = require('gulp');
const build = require('@microsoft/sp-build-web');
const gulpSequence = require('gulp-sequence');
build.addSuppression(`Warning - [sass] The local CSS class 'ms-Grid' is not camelCase and will not be type-safe.`);
// Create clean distrubution package
gulp.task('dist', gulpSequence('clean', 'bundle', 'package-solution'));
// Create clean development package
gulp.task('dev', gulpSequence('clean', 'bundle', 'package-solution'));
/**
* Custom Framework Specific gulp tasks
*/
build.initialize(gulp);

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,49 @@
{
"name": "react-personal-greeting",
"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",
"preversion": "node ./tools/pre-version.js",
"postversion": "gulp dist"
},
"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/pnpjs": "^2.0.3",
"@pnp/spfx-controls-react": "1.17.0",
"@pnp/spfx-property-controls": "1.17.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/microsoft-graph-types": "^1.12.0",
"@microsoft/rush-stack-compiler-3.3": "0.3.5",
"@microsoft/sp-build-web": "1.10.0",
"@microsoft/sp-module-interfaces": "1.10.0",
"@microsoft/sp-tslint-rules": "1.10.0",
"@microsoft/sp-webpart-workbench": "1.10.0",
"@types/chai": "3.4.34",
"@types/mocha": "2.2.38",
"ajv": "~5.2.2",
"gulp": "~3.9.1",
"gulp-sequence": "1.0.0"
}
}

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": "c1627244-55ce-4a32-97a0-cb278d5d7a61",
"alias": "PersonalGreetingWebPart",
"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": "Personal Greeting" },
"description": { "default": "Personal Greeting description" },
"officeFabricIconFontName": "Page",
"properties": {
"description": "Personal Greeting"
}
}]
}

View File

@ -0,0 +1,94 @@
import * as React from 'react';
import * as ReactDom from 'react-dom';
import { Version } from '@microsoft/sp-core-library';
import {
IPropertyPaneConfiguration,
PropertyPaneTextField,
PropertyPaneDropdown
} from '@microsoft/sp-property-pane';
import { BaseClientSideWebPart, WebPartContext } from '@microsoft/sp-webpart-base';
import * as strings from 'PersonalGreetingWebPartStrings';
import PersonalGreeting from './components/PersonalGreeting';
import { IPersonalGreetingProps } from './components/IPersonalGreetingProps';
import { PropertyFieldColorPicker, PropertyFieldColorPickerStyle } from '@pnp/spfx-property-controls/lib/PropertyFieldColorPicker';
export interface IPersonalGreetingWebPartProps {
greetingText: string;
context: WebPartContext;
position: string;
textColor: string;
}
export default class PersonalGreetingWebPart extends BaseClientSideWebPart <IPersonalGreetingWebPartProps> {
public render(): void {
const element: React.ReactElement<IPersonalGreetingProps> = React.createElement(
PersonalGreeting,
{
greetingText: this.properties.greetingText,
context: this.context,
position: this.properties.position,
textColor: this.properties.textColor
}
);
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: 'Use the fields below to configure the webpart. The placeholder will be removed once text has been entered into the "Greeting Text" field.'
},
groups: [
{
groupName: 'Settings',
groupFields: [
PropertyPaneTextField('greetingText', {
label: 'Greeting Text',
}),
PropertyPaneDropdown('position', {
label: 'Text Position',
selectedKey: 'left',
options: [{
key: 'left',
text: 'left'
},
{
key: 'center',
text: 'center'
},
{
key: 'right',
text: 'right'
}
]
}),
PropertyFieldColorPicker('textColor', {
label: 'Text Color',
properties: this.properties,
onPropertyChange: this.onPropertyPaneFieldChanged,
selectedColor: this.properties.textColor,
style: PropertyFieldColorPickerStyle.Full,
key: 'textColor'
})
]
}
]
}
]
};
}
}

View File

@ -0,0 +1,9 @@
import { WebPartContext } from "@microsoft/sp-webpart-base";
export interface IPersonalGreetingProps {
greetingText: string;
context: WebPartContext;
position: string;
textColor: string;
}

View File

@ -0,0 +1,13 @@
@import '~office-ui-fabric-react/dist/sass/References.scss';
.personalGreeting {
.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);
}
.title {
font-size: x-large;
font-weight: 375;
}
}

View File

@ -0,0 +1,33 @@
import * as React from 'react';
import styles from './PersonalGreeting.module.scss';
import { IPersonalGreetingProps } from './IPersonalGreetingProps';
import { escape } from '@microsoft/sp-lodash-subset';
import { CommandBar, ICommandBarItemProps } from 'office-ui-fabric-react/lib/CommandBar';
import { Placeholder } from "@pnp/spfx-controls-react/lib/Placeholder";
export default class PersonalGreeting extends React.Component<IPersonalGreetingProps, {}> {
public render(): React.ReactElement<IPersonalGreetingProps> {
const custstyles = {
'text-align': this.props.position,
'color': this.props.textColor
} as React.CSSProperties;
return (
<div className={ styles.personalGreeting }>
{this.props.greetingText == null ?
<Placeholder iconName='Edit' iconText='Configure the web part' description='Please configure the web part' buttonLabel='Configure' onConfigure={this._onConfigure} />
: <div className={ styles.title } style={custstyles}>{this.props.greetingText} {this.props.context.pageContext.user.displayName}</div>
// : <h2>{this.props.greetingText} {this.props.context.pageContext.user.displayName} </h2>
}
</div>
);
}
private _onConfigure = (): void => {
this.props.context.propertyPane.open();
}
}

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 IPersonalGreetingWebPartStrings {
PropertyPaneDescription: string;
BasicGroupName: string;
DescriptionFieldLabel: string;
}
declare module 'PersonalGreetingWebPartStrings' {
const strings: IPersonalGreetingWebPartStrings;
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,64 @@
/**
* This script updates the package-solution version analogue to the
* the package.json file.
*/
if (process.env.npm_package_version === undefined) {
throw 'Package version cannot be evaluated';
}
// define path to package-solution file
const solution = './config/package-solution.json',
teams = './teams/manifest.json';
// require filesystem instance
const fs = require('fs');
// get next automated package version from process variable
const nextPkgVersion = process.env.npm_package_version;
// make sure next build version match
const nextVersion = nextPkgVersion.indexOf('-') === -1 ?
nextPkgVersion : nextPkgVersion.split('-')[0];
// Update version in SPFx package-solution if exists
if (fs.existsSync(solution)) {
// read package-solution file
const solutionFileContent = fs.readFileSync(solution, 'UTF-8');
// parse file as json
const solutionContents = JSON.parse(solutionFileContent);
// set property of version to next version
solutionContents.solution.version = nextVersion + '.0';
// save file
fs.writeFileSync(
solution,
// convert file back to proper json
JSON.stringify(solutionContents, null, 2),
'UTF-8');
}
// Update version in teams manifest if exists
if (fs.existsSync(teams)) {
// read package-solution file
const teamsManifestContent = fs.readFileSync(teams, 'UTF-8');
// parse file as json
const teamsContent = JSON.parse(teamsManifestContent);
// set property of version to next version
teamsContent.version = nextVersion;
// save file
fs.writeFileSync(
teams,
// convert file back to proper json
JSON.stringify(teamsContent, null, 2),
'UTF-8');
}

View File

@ -0,0 +1,39 @@
{
"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"
],
"esModuleInterop": true
},
"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
}
}

File diff suppressed because it is too large Load Diff