Adding react-recaptch sample

This commit is contained in:
Siddharth 2019-10-09 01:04:27 +05:30
parent 04140c8eba
commit d130360b33
28 changed files with 18061 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-recaptcha/.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,12 @@
{
"@microsoft/generator-sharepoint": {
"isCreatingSolution": true,
"environment": "spo",
"version": "1.8.2",
"libraryName": "react-recaptcha",
"libraryId": "e96b3b94-3ccb-4e61-be34-e7ef7d952cbd",
"packageManager": "npm",
"isDomainIsolated": false,
"componentType": "webpart"
}
}

View File

@ -0,0 +1,74 @@
# SPFx Google reCaptcha Sample
## Summary
This is sample webpart which showcase how to implement Google reCaptcha v2 in SPFx. CAPTCHA is used to prevent bots from automatically submitting forms with SPAM or other unwanted content.
* Please refer this [link](https://www.c-sharpcorner.com/article/google-recaptcha-in-sharepoint-framework-webpartspfx/) to know 'How to build this from Scratch'
![Webpart in action](screens/WebpartInAction.gif?raw=true "Webpart in action")
## Used SharePoint Framework Version
![drop](https://img.shields.io/badge/version-1.9.1-green.svg)
## Applies to
* [SharePoint Framework](http://dev.office.com/sharepoint/docs/spfx/sharepoint-framework-overview)
* [Office 365 tenant](http://dev.office.com/sharepoint/docs/spfx/set-up-your-developer-tenant)
## Prerequisites
We would need to register our site which wants to use reCaptcha at Google. Follow below steps to get site key.
* Browse this [link](https://www.google.com/recaptcha/admin).
* Login with valid google account.
* Provide a valid site label name.
* Select reCAPTCHA v2, Select "I'm not a robot"
* Add domain name, if you are using local workbench enter localhost.
* For using it in context of SharePoint, enter your tenant url https://yourorg.sharepoint.com
* Accept terms and condition
* Submit
![Google recaptcha registration](screens/1.png?raw=true "Google recaptcha registration")
On sucessfull submission, we get site key and secret key, copy site key somewhere we would be using it later.
![Google recaptcha registration](screens/2.png?raw=true "Google recaptcha registration")
## Solution
Solution|Author(s)
--------|---------
react-recaptcha | Siddharth Vaghasia([siddh_me](https://twitter.com/siddh_me/))
## Version history
Version|Date|Comments
-------|----|--------
1.0.0|Sept 26, 2019|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 react framework in SPFx webpart
* Using [react-google-recaptcha](https://github.com/dozoisch/react-google-recaptcha) npm package in SPFx webpart
* Validate if captcha is resolved before submiting data.
<img src="https://telemetry.sharepointpnp.com/sp-dev-fx-webparts/samples/react-recaptcha" />

View File

@ -0,0 +1,18 @@
{
"$schema": "https://developer.microsoft.com/json-schemas/spfx-build/config.2.0.schema.json",
"version": "2.0",
"bundles": {
"recaptcha-web-part": {
"components": [
{
"entrypoint": "./lib/webparts/recaptcha/RecaptchaWebPart.js",
"manifest": "./src/webparts/recaptcha/RecaptchaWebPart.manifest.json"
}
]
}
},
"externals": {},
"localizedResources": {
"RecaptchaWebPartStrings": "lib/webparts/recaptcha/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-recaptcha",
"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-recaptcha-client-side-solution",
"id": "e96b3b94-3ccb-4e61-be34-e7ef7d952cbd",
"version": "1.0.0.0",
"includeClientSideAssets": true,
"isDomainIsolated": false
},
"paths": {
"zippedPackage": "solution/react-recaptcha.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-recaptcha/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);

17491
samples/react-recaptcha/package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,44 @@
{
"name": "react-recaptcha",
"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.8.2",
"@microsoft/sp-lodash-subset": "1.8.2",
"@microsoft/sp-office-ui-fabric-core": "1.8.2",
"@microsoft/sp-property-pane": "1.8.2",
"@microsoft/sp-webpart-base": "1.8.2",
"@types/es6-promise": "0.0.33",
"@types/react": "16.7.22",
"@types/react-dom": "16.8.0",
"@types/react-google-recaptcha": "^1.1.0",
"@types/webpack-env": "1.13.1",
"office-ui-fabric-react": "6.143.0",
"react": "16.7.0",
"react-async-script": "^1.1.1",
"react-dom": "16.7.0",
"react-google-recaptcha": "^2.0.1"
},
"resolutions": {
"@types/react": "16.7.22"
},
"devDependencies": {
"@microsoft/sp-build-web": "1.8.2",
"@microsoft/sp-tslint-rules": "1.8.2",
"@microsoft/sp-module-interfaces": "1.8.2",
"@microsoft/sp-webpart-workbench": "1.8.2",
"@microsoft/rush-stack-compiler-2.9": "0.7.7",
"gulp": "~3.9.1",
"@types/chai": "3.4.34",
"@types/mocha": "2.2.38",
"ajv": "~5.2.2"
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 65 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 186 KiB

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": "200835ce-2963-400e-ae18-f556484c5fba",
"alias": "RecaptchaWebPart",
"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": "recaptcha" },
"description": { "default": "This is sample webpart to showcase usage of reCaptcha in spfx webpart" },
"officeFabricIconFontName": "Page",
"properties": {
"description": "recaptcha"
}
}]
}

View File

@ -0,0 +1,60 @@
import * as React from 'react';
import * as ReactDom from 'react-dom';
import { Version } from '@microsoft/sp-core-library';
import { BaseClientSideWebPart } from '@microsoft/sp-webpart-base';
import {
IPropertyPaneConfiguration,
PropertyPaneTextField
} from '@microsoft/sp-property-pane';
import * as strings from 'RecaptchaWebPartStrings';
import Recaptcha from './components/Recaptcha';
import { IRecaptchaProps } from './components/IRecaptchaProps';
export interface IRecaptchaWebPartProps {
description: string;
}
export default class RecaptchaWebPart extends BaseClientSideWebPart<IRecaptchaWebPartProps> {
public render(): void {
const element: React.ReactElement<IRecaptchaProps > = React.createElement(
Recaptcha,
{
description: this.properties.description
}
);
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('description', {
label: strings.DescriptionFieldLabel
})
]
}
]
}
]
};
}
}

View File

@ -0,0 +1,3 @@
export interface IRecaptchaProps {
description: string;
}

View File

@ -0,0 +1,74 @@
@import '~@microsoft/sp-office-ui-fabric-core/dist/sass/SPFabricCore.scss';
.recaptcha {
.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,70 @@
import * as React from 'react';
import styles from './Recaptcha.module.scss';
import { IRecaptchaProps } from './IRecaptchaProps';
import { escape } from '@microsoft/sp-lodash-subset';
import ReCAPTCHA from 'react-google-recaptcha';
import * as ReactDom from 'react-dom';
import { TextField, MaskedTextField,PrimaryButton,MessageBar, MessageBarType } from 'office-ui-fabric-react';
export default class Recaptcha extends React.Component<IRecaptchaProps, {}> {
public captcha:any;
public _messageContainer:HTMLElement = undefined;
public render(): React.ReactElement<IRecaptchaProps> {
return (
<div className={ styles.recaptcha }>
<p>
<TextField label="Enter your name" styles={{ fieldGroup: { width: 300 } }} />
</p>
<ReCAPTCHA ref={ (el) => { this.captcha = el; } }
sitekey="6LeZV7oUAAAAALiIfCUnnrlXE0fYrcyvM9JHVN72"
onChange={this.onChange} />
<p>
<div id="messageContainer" ref={(elm) => { this._messageContainer = elm; }}>
</div>
</p>
<PrimaryButton text="Submit" onClick={() => this.buttonClicked()} />
</div>
);
}
public buttonClicked(): void {
if(this.captcha.getValue())
{
ReactDom.unmountComponentAtNode(this._messageContainer);
const element2 = React.createElement(
MessageBar,
{
messageBarType:MessageBarType.success,
isMultiline:false,
dismissButtonAriaLabel:"Close"
},
"You data has been saved sucessfully"
);
//const camContainer = document.getElementById("camContainer")
ReactDom.render(element2, this._messageContainer);
}
else{
const element2 = React.createElement(
MessageBar,
{
messageBarType:MessageBarType.error,
isMultiline:false,
dismissButtonAriaLabel:"Close"
},
"Please select captcha."
);
//const camContainer = document.getElementById("camContainer")
ReactDom.render(element2, this._messageContainer);
}
}
public onChange(value){
console.log("Captcha value:", value);
}
}

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 IRecaptchaWebPartStrings {
PropertyPaneDescription: string;
BasicGroupName: string;
DescriptionFieldLabel: string;
}
declare module 'RecaptchaWebPartStrings' {
const strings: IRecaptchaWebPartStrings;
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
}
}