Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit a9c8c1d

Browse files
author
Alex Terentiev
committedSep 14, 2022
form customizer demo
1 parent 3d596ca commit a9c8c1d

24 files changed

+63179
-0
lines changed
 

‎form-customizer/.eslintrc.js

+352
Large diffs are not rendered by default.

‎form-customizer/.gitignore

+34
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
# Logs
2+
logs
3+
*.log
4+
npm-debug.log*
5+
6+
# Dependency directories
7+
node_modules
8+
9+
# Build generated files
10+
dist
11+
lib
12+
release
13+
solution
14+
temp
15+
*.sppkg
16+
.heft
17+
18+
# Coverage directory used by tools like istanbul
19+
coverage
20+
21+
# OSX
22+
.DS_Store
23+
24+
# Visual Studio files
25+
.ntvs_analysis.dat
26+
.vs
27+
bin
28+
obj
29+
30+
# Resx Generated Code
31+
*.resx.ts
32+
33+
# Styles Generated Code
34+
*.scss.ts

‎form-customizer/.npmignore

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
!dist
2+
config
3+
4+
gulpfile.js
5+
6+
release
7+
src
8+
temp
9+
10+
tsconfig.json
11+
tslint.json
12+
13+
*.log
14+
15+
.yo-rc.json
16+
.vscode

‎form-customizer/.vscode/launch.json

+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
{
2+
"version": "0.2.0",
3+
"configurations": [
4+
{
5+
"name": "Hosted workbench",
6+
"type": "pwa-chrome",
7+
"request": "launch",
8+
"url": "https://enter-your-SharePoint-site/_layouts/workbench.aspx",
9+
"webRoot": "${workspaceRoot}",
10+
"sourceMaps": true,
11+
"sourceMapPathOverrides": {
12+
"webpack:///.././src/*": "${webRoot}/src/*",
13+
"webpack:///../../../src/*": "${webRoot}/src/*",
14+
"webpack:///../../../../src/*": "${webRoot}/src/*",
15+
"webpack:///../../../../../src/*": "${webRoot}/src/*"
16+
},
17+
"runtimeArgs": [
18+
"--remote-debugging-port=9222",
19+
"-incognito"
20+
]
21+
}
22+
]
23+
}

‎form-customizer/.vscode/settings.json

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
// Place your settings in this file to overwrite default and user settings.
2+
{
3+
// Configure glob patterns for excluding files and folders in the file explorer.
4+
"files.exclude": {
5+
"**/.git": true,
6+
"**/.DS_Store": true,
7+
"**/bower_components": true,
8+
"**/coverage": true,
9+
"**/lib-amd": true,
10+
"src/**/*.scss.ts": true
11+
},
12+
"typescript.tsdk": ".\\node_modules\\typescript\\lib"
13+
}

‎form-customizer/.yo-rc.json

+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
{
2+
"@microsoft/generator-sharepoint": {
3+
"plusBeta": true,
4+
"isCreatingSolution": true,
5+
"nodeVersion": "16.14.2",
6+
"version": "1.16.0-beta.1",
7+
"libraryName": "form-customizer",
8+
"libraryId": "45924751-bffc-4749-a420-396c4b6bd4ea",
9+
"environment": "spo",
10+
"packageManager": "npm",
11+
"solutionName": "form-customizer",
12+
"solutionShortDescription": "form-customizer description",
13+
"skipFeatureDeployment": true,
14+
"isDomainIsolated": false,
15+
"componentType": "extension",
16+
"extensionType": "FormCustomizer"
17+
}
18+
}

‎form-customizer/ApplyCustomizer.ps1

+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
2+
3+
Connect-PnPOnline `
4+
-Url "https://yourtenant.sharepoint.com/sites/your-site" `
5+
-Interactive
6+
$contentTypes = Get-PnPContentType -List "Your List"
7+
$ct = $contentTypes[0]
8+
$ct.NewFormClientSideComponentId = "f41d8732-2612-4442-823a-a649cd9b9997"
9+
$ct.Update($false)

‎form-customizer/README.md

+73
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
# form-customizer
2+
3+
## Summary
4+
5+
Short summary on functionality and used technologies.
6+
7+
[picture of the solution in action, if possible]
8+
9+
## Used SharePoint Framework Version
10+
11+
![version](https://img.shields.io/badge/version-1.13-green.svg)
12+
13+
## Applies to
14+
15+
- [SharePoint Framework](https://aka.ms/spfx)
16+
- [Microsoft 365 tenant](https://docs.microsoft.com/en-us/sharepoint/dev/spfx/set-up-your-developer-tenant)
17+
18+
> Get your own free development tenant by subscribing to [Microsoft 365 developer program](http://aka.ms/o365devprogram)
19+
20+
## Prerequisites
21+
22+
> Any special pre-requisites?
23+
24+
## Solution
25+
26+
| Solution | Author(s) |
27+
| ----------- | ------------------------------------------------------- |
28+
| folder name | Author details (name, company, twitter alias with link) |
29+
30+
## Version history
31+
32+
| Version | Date | Comments |
33+
| ------- | ---------------- | --------------- |
34+
| 1.1 | March 10, 2021 | Update comment |
35+
| 1.0 | January 29, 2021 | Initial release |
36+
37+
## Disclaimer
38+
39+
**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.**
40+
41+
---
42+
43+
## Minimal Path to Awesome
44+
45+
- Clone this repository
46+
- Ensure that you are at the solution folder
47+
- in the command-line run:
48+
- **npm install**
49+
- **gulp serve**
50+
51+
> Include any additional steps as needed.
52+
53+
## Features
54+
55+
Description of the extension that expands upon high-level summary above.
56+
57+
This extension illustrates the following concepts:
58+
59+
- topic 1
60+
- topic 2
61+
- topic 3
62+
63+
> Notice that better pictures and documentation will increase the sample usage and the value you are providing for others. Thanks for your submissions advance.
64+
65+
> Share your web part with others through Microsoft 365 Patterns and Practices program to get visibility and exposure. More details on the community, open-source projects and other activities from http://aka.ms/m365pnp.
66+
67+
## References
68+
69+
- [Getting started with SharePoint Framework](https://docs.microsoft.com/en-us/sharepoint/dev/spfx/set-up-your-developer-tenant)
70+
- [Building for Microsoft teams](https://docs.microsoft.com/en-us/sharepoint/dev/spfx/build-for-teams-overview)
71+
- [Use Microsoft Graph in your solution](https://docs.microsoft.com/en-us/sharepoint/dev/spfx/web-parts/get-started/using-microsoft-graph-apis)
72+
- [Publish SharePoint Framework applications to the Marketplace](https://docs.microsoft.com/en-us/sharepoint/dev/spfx/publish-to-marketplace-overview)
73+
- [Microsoft 365 Patterns and Practices](https://aka.ms/m365pnp) - Guidance, tooling, samples and open-source controls for your Microsoft 365 development

‎form-customizer/config/config.json

+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
{
2+
"$schema": "https://developer.microsoft.com/json-schemas/spfx-build/config.2.0.schema.json",
3+
"version": "2.0",
4+
"bundles": {
5+
"form-customizer-demo-form-customizer": {
6+
"components": [
7+
{
8+
"entrypoint": "./lib/extensions/formCustomizerDemo/FormCustomizerDemoFormCustomizer.js",
9+
"manifest": "./src/extensions/formCustomizerDemo/FormCustomizerDemoFormCustomizer.manifest.json"
10+
}
11+
]
12+
}
13+
},
14+
"externals": {},
15+
"localizedResources": {
16+
"FormCustomizerDemoFormCustomizerStrings": "lib/extensions/formCustomizerDemo/loc/{locale}.js",
17+
"ControlStrings": "node_modules/@pnp/spfx-controls-react/lib/loc/{locale}.js"
18+
}
19+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
{
2+
"$schema": "https://developer.microsoft.com/json-schemas/spfx-build/deploy-azure-storage.schema.json",
3+
"workingDir": "./release/assets/",
4+
"account": "<!-- STORAGE ACCOUNT NAME -->",
5+
"container": "form-customizer",
6+
"accessKey": "<!-- ACCESS KEY -->"
7+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
{
2+
"$schema": "https://developer.microsoft.com/json-schemas/spfx-build/package-solution.schema.json",
3+
"solution": {
4+
"name": "form-customizer-client-side-solution",
5+
"id": "45924751-bffc-4749-a420-396c4b6bd4ea",
6+
"version": "1.0.0.0",
7+
"includeClientSideAssets": true,
8+
"skipFeatureDeployment": true,
9+
"isDomainIsolated": false,
10+
"developer": {
11+
"name": "",
12+
"websiteUrl": "",
13+
"privacyUrl": "",
14+
"termsOfUseUrl": "",
15+
"mpnId": "Undefined-1.16.0-beta.1"
16+
},
17+
"metadata": {
18+
"shortDescription": {
19+
"default": "form-customizer description"
20+
},
21+
"longDescription": {
22+
"default": "form-customizer description"
23+
},
24+
"screenshotPaths": [],
25+
"videoUrl": "",
26+
"categories": []
27+
},
28+
"features": [
29+
{
30+
"title": "form-customizer Feature",
31+
"description": "The feature that activates elements of the form-customizer solution.",
32+
"id": "3e10c720-d2d7-4ce7-9813-961706323ef7",
33+
"version": "1.0.0.0"
34+
}
35+
]
36+
},
37+
"paths": {
38+
"zippedPackage": "solution/form-customizer.sppkg"
39+
}
40+
}

‎form-customizer/config/serve.json

+53
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
{
2+
"$schema": "https://developer.microsoft.com/json-schemas/spfx-build/spfx-serve.schema.json",
3+
"port": 4321,
4+
"https": true,
5+
"serveConfigurations": {
6+
"default": {
7+
"pageUrl": "https://aterentiev.sharepoint.com/sites/FormCustomizerDemos/_layouts/15/SPListForm.aspx",
8+
"formCustomizer": {
9+
"componentId": "f41d8732-2612-4442-823a-a649cd9b9997",
10+
"PageType": 8,
11+
"RootFolder": "/sites/FormCustomizerDemos/Lists/Basic%20Demo",
12+
"properties": {
13+
"sampleText": "Value"
14+
}
15+
}
16+
},
17+
"formCustomizerDemo_NewForm": {
18+
"pageUrl": "https://contoso.sharepoint.com/sites/mySite/_layouts/15/SPListForm.aspx",
19+
"formCustomizer": {
20+
"componentId": "f41d8732-2612-4442-823a-a649cd9b9997",
21+
"PageType": 8,
22+
"RootFolder": "/sites/mySite/Lists/MyList",
23+
"properties": {
24+
"sampleText": "Value"
25+
}
26+
}
27+
},
28+
"formCustomizerDemo_EditForm": {
29+
"pageUrl": "https://contoso.sharepoint.com/sites/mySite/_layouts/15/SPListForm.aspx",
30+
"formCustomizer": {
31+
"componentId": "f41d8732-2612-4442-823a-a649cd9b9997",
32+
"PageType": 6,
33+
"RootFolder": "/sites/mySite/Lists/MyList",
34+
"ID": 1,
35+
"properties": {
36+
"sampleText": "Value"
37+
}
38+
}
39+
},
40+
"formCustomizerDemo_ViewForm": {
41+
"pageUrl": "https://contoso.sharepoint.com/sites/mySite/_layouts/15/SPListForm.aspx",
42+
"formCustomizer": {
43+
"componentId": "f41d8732-2612-4442-823a-a649cd9b9997",
44+
"PageType": 4,
45+
"RootFolder": "/sites/mySite/Lists/MyList",
46+
"ID": 1,
47+
"properties": {
48+
"sampleText": "Value"
49+
}
50+
}
51+
}
52+
}
53+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
{
2+
"$schema": "https://developer.microsoft.com/json-schemas/spfx-build/write-manifests.schema.json",
3+
"cdnBasePath": "<!-- PATH TO CDN -->"
4+
}

‎form-customizer/gulpfile.js

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
'use strict';
2+
3+
const build = require('@microsoft/sp-build-web');
4+
5+
build.addSuppression(`Warning - [sass] The local CSS class 'ms-Grid' is not camelCase and will not be type-safe.`);
6+
7+
var getTasks = build.rig.getTasks;
8+
build.rig.getTasks = function () {
9+
var result = getTasks.call(build.rig);
10+
11+
result.set('serve', result.get('serve-deprecated'));
12+
13+
return result;
14+
};
15+
16+
build.initialize(require('gulp'));

‎form-customizer/package-lock.json

+62,282
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎form-customizer/package.json

+41
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
{
2+
"name": "form-customizer",
3+
"version": "0.0.1",
4+
"private": true,
5+
"main": "lib/index.js",
6+
"engines": {
7+
"node": ">=16.13.0 <17.0.0"
8+
},
9+
"scripts": {
10+
"build": "gulp bundle",
11+
"clean": "gulp clean",
12+
"test": "gulp test"
13+
},
14+
"dependencies": {
15+
"@microsoft/decorators": "1.16.0-beta.1",
16+
"@microsoft/sp-core-library": "1.16.0-beta.1",
17+
"@microsoft/sp-listview-extensibility": "1.16.0-beta.1",
18+
"@microsoft/sp-lodash-subset": "1.16.0-beta.1",
19+
"@microsoft/sp-office-ui-fabric-core": "1.16.0-beta.1",
20+
"@pnp/spfx-controls-react": "3.10.0",
21+
"office-ui-fabric-react": "7.192.0",
22+
"react": "16.13.1",
23+
"react-dom": "16.13.1",
24+
"tslib": "2.3.1"
25+
},
26+
"devDependencies": {
27+
"@microsoft/eslint-config-spfx": "1.16.0-beta.1",
28+
"@microsoft/eslint-plugin-spfx": "1.16.0-beta.1",
29+
"@microsoft/rush-stack-compiler-4.5": "0.2.2",
30+
"@microsoft/sp-build-web": "1.16.0-beta.1",
31+
"@microsoft/sp-module-interfaces": "1.16.0-beta.1",
32+
"@rushstack/eslint-config": "2.5.1",
33+
"@types/react": "16.9.51",
34+
"@types/react-dom": "16.9.8",
35+
"@types/webpack-env": "~1.15.2",
36+
"ajv": "^6.12.5",
37+
"eslint-plugin-react-hooks": "4.3.0",
38+
"gulp": "4.0.2",
39+
"typescript": "4.5.5"
40+
}
41+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
{
2+
"$schema": "https://developer.microsoft.com/json-schemas/spfx/client-side-extension-manifest.schema.json",
3+
4+
"id": "f41d8732-2612-4442-823a-a649cd9b9997",
5+
"alias": "FormCustomizerDemoFormCustomizer",
6+
"componentType": "Extension",
7+
"extensionType": "FormCustomizer",
8+
9+
// The "*" signifies that the version should be taken from the package.json
10+
"version": "*",
11+
"manifestVersion": 2,
12+
13+
// If true, the component can only be installed on sites where Custom Script is allowed.
14+
// Components that allow authors to embed arbitrary script code should set this to true.
15+
// https://support.office.com/en-us/article/Turn-scripting-capabilities-on-or-off-1f2c515f-5d7e-448a-9fd7-835da935584f
16+
"requiresCustomScript": false
17+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
import * as React from 'react';
2+
import * as ReactDOM from 'react-dom';
3+
4+
import { Log } from '@microsoft/sp-core-library';
5+
import {
6+
BaseFormCustomizer
7+
} from '@microsoft/sp-listview-extensibility';
8+
9+
import FormCustomizerDemo, { IFormCustomizerDemoProps } from './components/FormCustomizerDemo';
10+
11+
/**
12+
* If your form customizer uses the ClientSideComponentProperties JSON input,
13+
* it will be deserialized into the BaseExtension.properties object.
14+
* You can define an interface to describe it.
15+
*/
16+
export interface IFormCustomizerDemoFormCustomizerProperties {
17+
// This is an example; replace with your own property
18+
sampleText?: string;
19+
}
20+
21+
const LOG_SOURCE: string = 'FormCustomizerDemoFormCustomizer';
22+
23+
export default class FormCustomizerDemoFormCustomizer
24+
extends BaseFormCustomizer<IFormCustomizerDemoFormCustomizerProperties> {
25+
26+
public onInit(): Promise<void> {
27+
// Add your custom initialization to this method. The framework will wait
28+
// for the returned promise to resolve before rendering the form.
29+
Log.info(LOG_SOURCE, 'Activated FormCustomizerDemoFormCustomizer with properties:');
30+
Log.info(LOG_SOURCE, JSON.stringify(this.properties, undefined, 2));
31+
return Promise.resolve();
32+
}
33+
34+
public render(): void {
35+
// Use this method to perform your custom rendering.
36+
37+
const formCustomizerDemo: React.ReactElement<{}> =
38+
React.createElement(FormCustomizerDemo, {
39+
context: this.context,
40+
displayMode: this.displayMode,
41+
onSave: this._onSave,
42+
onClose: this._onClose
43+
} as IFormCustomizerDemoProps);
44+
45+
ReactDOM.render(formCustomizerDemo, this.domElement);
46+
}
47+
48+
private _onSave = (): void => {
49+
// You MUST call this.formSaved() after you save the form.
50+
this.formSaved();
51+
}
52+
53+
private _onClose = (): void => {
54+
// You MUST call this.formClosed() after you close the form.
55+
this.formClosed();
56+
}
57+
58+
public onDispose(): void {
59+
// This method should be used to free any resources that were allocated during rendering.
60+
ReactDOM.unmountComponentAtNode(this.domElement);
61+
super.onDispose();
62+
}
63+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
.formCustomizerDemo {
2+
background-color: "[theme:white, default:#ffffff]";
3+
color: "[theme:themePrimary, default:#0078d4]";
4+
padding: 0.5rem;
5+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
import * as React from 'react';
2+
import { Log, FormDisplayMode } from '@microsoft/sp-core-library';
3+
import { FormCustomizerContext } from '@microsoft/sp-listview-extensibility';
4+
import { DynamicForm } from '@pnp/spfx-controls-react/lib/DynamicForm';
5+
6+
import styles from './FormCustomizerDemo.module.scss';
7+
8+
export interface IFormCustomizerDemoProps {
9+
context: FormCustomizerContext;
10+
displayMode: FormDisplayMode;
11+
onSave: () => void;
12+
onClose: () => void;
13+
}
14+
15+
const LOG_SOURCE: string = 'FormCustomizerDemo';
16+
17+
export default class FormCustomizerDemo extends React.Component<IFormCustomizerDemoProps, {}> {
18+
public componentDidMount(): void {
19+
Log.info(LOG_SOURCE, 'React Element: FormCustomizerDemo mounted');
20+
}
21+
22+
public componentWillUnmount(): void {
23+
Log.info(LOG_SOURCE, 'React Element: FormCustomizerDemo unmounted');
24+
}
25+
26+
public render(): React.ReactElement<{}> {
27+
if (this.props.displayMode === FormDisplayMode.Display) {
28+
return <div>Not supported</div>;
29+
}
30+
return <div className={styles.formCustomizerDemo}>
31+
<DynamicForm
32+
context={this.props.context as any} // eslint-disable-line @typescript-eslint/no-explicit-any
33+
listId={this.props.context.list.guid.toString()}
34+
listItemId={this.props.context.itemId}
35+
onSubmitted={this.props.onSave}
36+
onCancelled={this.props.onClose}
37+
/>
38+
</div>;
39+
}
40+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
define([], function() {
2+
return {
3+
"Save": "Save",
4+
"Cancel": "Cancel",
5+
"Close": "Close"
6+
}
7+
});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
declare interface IFormCustomizerDemoFormCustomizerStrings {
2+
Save: string;
3+
Cancel: string;
4+
Close: string;
5+
}
6+
7+
declare module 'FormCustomizerDemoFormCustomizerStrings' {
8+
const strings: IFormCustomizerDemoFormCustomizerStrings;
9+
export = strings;
10+
}

‎form-customizer/src/index.ts

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

‎form-customizer/tsconfig.json

+36
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
{
2+
"extends": "./node_modules/@microsoft/rush-stack-compiler-4.5/includes/tsconfig-web.json",
3+
"compilerOptions": {
4+
"target": "es5",
5+
"forceConsistentCasingInFileNames": true,
6+
"module": "esnext",
7+
"moduleResolution": "node",
8+
"jsx": "react",
9+
"declaration": true,
10+
"sourceMap": true,
11+
"experimentalDecorators": true,
12+
"skipLibCheck": true,
13+
"outDir": "lib",
14+
"inlineSources": false,
15+
"strictNullChecks": false,
16+
"noImplicitAny": true,
17+
18+
"typeRoots": [
19+
"./node_modules/@types",
20+
"./node_modules/@microsoft"
21+
],
22+
"types": [
23+
"webpack-env"
24+
],
25+
"lib": [
26+
"es5",
27+
"dom",
28+
"es2015.collection",
29+
"es2015.promise"
30+
]
31+
},
32+
"include": [
33+
"src/**/*.ts",
34+
"src/**/*.tsx"
35+
]
36+
}

0 commit comments

Comments
 (0)
Please sign in to comment.