Merge pull request #1550 from sudharsank/react-quick-poll

This commit is contained in:
Hugo Bernier 2020-10-18 18:28:44 -04:00 committed by GitHub
commit 04d41005dd
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 2290 additions and 1734 deletions

View File

@ -2,11 +2,11 @@
"@microsoft/generator-sharepoint": {
"isCreatingSolution": true,
"environment": "spo",
"version": "1.10.0",
"version": "1.11.0",
"libraryName": "react-simple-poll",
"libraryId": "890ced10-dacc-4d0d-b9df-355a289980b3",
"packageManager": "npm",
"isDomainIsolated": false,
"componentType": "webpart"
}
}
}

View File

@ -1,6 +1,7 @@
# React Quick Poll
## Summary
> This component is developed for the users who really need to create a **_Poll_** within a minute and with less maintenance. **_'QuickPoll'_** list will be created automatically to store the user response.
> Following are some of the features of this component.
* **_Easy_** to setup with most of the configurations are optional.
@ -22,7 +23,7 @@
* **_Start Date_** - Date when the end user can start seeing the poll question.
* **_End Date_** - Last day of the poll question visible to the end user.
3. **_Success Message_** - Message to be displayed to the user after successful submission. It is optional, if not provided the default message '**Thank you for your submission**' will be displayed.
3. **_Success Message_** - Message to be displayed to the user after a successful submission. It is optional, if not provided the default message '**Thank you for your submission**' will be displayed.
4. **_Response Message_** - Message to be displayed to the user with the user response, once the user has submitted. It is optional, if not provided the default message '**You voted for: ~User Response~**' will be displayed below the chart.
@ -36,33 +37,37 @@
* Make sure the **Multi Choice** option is chosen wisely, do not change once the user started to response to the poll.
## Preview
![Advanced-Comments-Box](./assets/react-quick-poll.gif)
![React-Quick-Poll](./assets/react-quick-poll.gif)
## Used SharePoint Framework Version
![drop](https://img.shields.io/badge/version-GA-green.svg)
![SPFx 1.11](https://img.shields.io/badge/version-1.11-green.svg)
## Applies to
* [SharePoint Framework](https://docs.microsoft.com/sharepoint/dev/spfx/sharepoint-framework-overview)
* [Office 365 tenant](https://docs.microsoft.com/sharepoint/dev/spfx/set-up-your-development-environment)
* [SharePoint Framework](https:/dev.office.com/sharepoint)
* [Office 365 tenant](https://dev.office.com/sharepoint/docs/spfx/set-up-your-development-environment)
## Prerequisites
> **@microsoft/generator-sharepoint - 1.10.0**
> **@microsoft/generator-sharepoint - 1.11.0**
## Solution
Solution|Author(s)
--------|---------
react-quick-poll | Sudharsan K.([@sudharsank](https://twitter.com/sudharsank), [Know More](http://windowssharepointserver.blogspot.com/))
react-quick-poll | Sudharsan K.([@sudharsank](https://twitter.com/sudharsank), [Know More](https://spknowledge.com/))
## Version history
Version|Date|Comments
-------|----|--------
1.0.0.1|Feb 24 2020|Initial release
2.0.0.0|Oct 17 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
@ -71,26 +76,27 @@ Version|Date|Comments
- in the command line run:
- `npm install`
- `gulp bundle --ship && gulp package-solution --ship`
- Add the .sppkg file to the app catalog and add the **'_Quick Poll_'** web part to the page.
- Add the `.sppkg` file to the app catalog and add the **'_Quick Poll_'** web part to the page.
## Features
- Used [PnP Property Pane Controls](https://sharepoint.github.io/sp-dev-fx-property-controls/) to create the property pane controls
* [PropertyFieldToggleWithCallout](https://sharepoint.github.io/sp-dev-fx-property-controls/controls/PropertyFieldToggleWithCallout/)
* [PropertyFieldCollectionData](https://sharepoint.github.io/sp-dev-fx-property-controls/controls/PropertyFieldCollectionData/)
* [PropertyFieldChoiceGroupWithCallout](https://sharepoint.github.io/sp-dev-fx-property-controls/controls/PropertyFieldChoiceGroupWithCallout/)
* PropertyPaneTextField (From base property controls)
- Used [PnP Reusable REact Controls](https://sharepoint.github.io/sp-dev-fx-controls-react/)
- Used [PnP Reusable React Controls](https://sharepoint.github.io/sp-dev-fx-controls-react/)
* [Placeholder](https://sharepoint.github.io/sp-dev-fx-controls-react/controls/Placeholder/)
* [ChartControl](https://sharepoint.github.io/sp-dev-fx-controls-react/controls/ChartControl/)
- Used few styles and controls (Text, MessageBar, ProgressIndicator, PrimaryButton, ChoiceGroup, List, Checkbox) from [Office UI Fabric](https://developer.microsoft.com/en-us/fabric)
- Used [PnP](https://pnp.github.io/pnpjs/) for communication with SharePoint.
- Used [Moment.js](https://momentjs.com/) for datetime formatting.
#### Local Mode
### Local Mode
This solution doesn't work on local mode.
#### SharePoint Mode
### SharePoint Mode
If you want to try on a real environment, open:
[O365 Workbench](https://your-domain.sharepoint.com/_layouts/15/workbench.aspx)
<img src="https://telemetry.sharepointpnp.com/sp-dev-fx-webparts/samples/react-quick-poll" />

View File

@ -3,9 +3,16 @@
"solution": {
"name": "React Quick Poll",
"id": "890ced10-dacc-4d0d-b9df-355a289980b3",
"version": "1.0.0.1",
"version": "2.0.0.0",
"includeClientSideAssets": true,
"isDomainIsolated": false
"isDomainIsolated": false,
"developer": {
"name": "Sudharsan K.",
"privacyUrl": "",
"termsOfUseUrl": "",
"websiteUrl": "https://spknowledge.com/",
"mpnId": "000000"
}
},
"paths": {
"zippedPackage": "solution/react-quick-poll.sppkg"

File diff suppressed because it is too large Load Diff

View File

@ -12,20 +12,17 @@
"test": "gulp test"
},
"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",
"@microsoft/sp-core-library": "1.11.0",
"@microsoft/sp-lodash-subset": "1.11.0",
"@microsoft/sp-office-ui-fabric-core": "1.11.0",
"@microsoft/sp-property-pane": "1.11.0",
"@microsoft/sp-webpart-base": "1.11.0",
"@pnp/polyfill-ie11": "^2.0.1-5",
"@pnp/sp": "^2.0.2",
"@pnp/spfx-controls-react": "^1.16.0",
"@pnp/spfx-property-controls": "^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",
"moment": "^2.24.0",
"office-ui-fabric-react": "6.189.2",
"office-ui-fabric-react": "6.214.0",
"react": "16.8.5",
"react-dom": "16.8.5"
},
@ -33,14 +30,14 @@
"@types/react": "16.8.8"
},
"devDependencies": {
"@microsoft/sp-build-web": "1.10.0",
"@microsoft/sp-tslint-rules": "1.10.0",
"@microsoft/sp-module-interfaces": "1.10.0",
"@microsoft/sp-webpart-workbench": "1.10.0",
"@microsoft/rush-stack-compiler-3.3": "0.3.5",
"gulp": "~3.9.1",
"@microsoft/sp-build-web": "1.11.0",
"@microsoft/sp-module-interfaces": "1.11.0",
"@microsoft/sp-tslint-rules": "1.11.0",
"@microsoft/sp-webpart-workbench": "1.11.0",
"@types/chai": "3.4.34",
"@types/mocha": "2.2.38",
"ajv": "~5.2.2"
"ajv": "~5.2.2",
"gulp": "~3.9.1"
}
}

View File

@ -2,8 +2,8 @@ import * as React from 'react';
import * as ReactDom from 'react-dom';
import { Version, ServiceScope } from '@microsoft/sp-core-library';
import {
IPropertyPaneConfiguration,
PropertyPaneTextField,
IPropertyPaneConfiguration,
PropertyPaneTextField,
} from '@microsoft/sp-property-pane';
import { BaseClientSideWebPart } from '@microsoft/sp-webpart-base';
import { CalloutTriggers } from '@pnp/spfx-property-controls/lib/PropertyFieldHeader';
@ -11,6 +11,7 @@ import { PropertyFieldToggleWithCallout } from '@pnp/spfx-property-controls/lib/
import { PropertyFieldChoiceGroupWithCallout } from '@pnp/spfx-property-controls/lib/PropertyFieldChoiceGroupWithCallout';
import { PropertyFieldCollectionData, CustomCollectionFieldType } from '@pnp/spfx-property-controls/lib/PropertyFieldCollectionData';
import { DateTimePicker, DateConvention, TimeConvention } from '@pnp/spfx-controls-react/lib/DateTimePicker';
import "@pnp/polyfill-ie11";
import { sp } from "@pnp/sp/presets/all";
import * as strings from 'SimplePollWebPartStrings';
import SimplePoll from './components/SimplePoll';
@ -21,262 +22,265 @@ import { ChartType } from '@pnp/spfx-controls-react/lib/ChartControl';
export interface ISimplePollWebPartProps {
pollQuestions: any[];
MsgAfterSubmission: string;
BtnSubmitVoteText: string;
chartType: ChartType;
ResponseMsgToUser: string;
pollBasedOnDate: boolean;
NoPollMsg: string;
pollQuestions: any[];
MsgAfterSubmission: string;
BtnSubmitVoteText: string;
chartType: ChartType;
ResponseMsgToUser: string;
pollBasedOnDate: boolean;
NoPollMsg: string;
}
export default class SimplePollWebPart extends BaseClientSideWebPart<ISimplePollWebPartProps> {
private helper: SPHelper = null;
private userinfo: IUserInfo = null;
protected async onInit(): Promise<void> {
await super.onInit();
sp.setup(this.context);
this.helper = new SPHelper();
this.userinfo = await this.helper.getCurrentUserInfo();
}
private helper: SPHelper = null;
private userinfo: IUserInfo = null;
protected async onInit(): Promise<void> {
await super.onInit();
sp.setup({
ie11: true,
spfxContext: this.context
});
this.helper = new SPHelper();
this.userinfo = await this.helper.getCurrentUserInfo();
}
public render(): void {
const element: React.ReactElement<ISimplePollProps> = React.createElement(
SimplePoll,
{
pollQuestions: this.properties.pollQuestions,
SuccessfullVoteSubmissionMsg: this.properties.MsgAfterSubmission,
ResponseMsgToUser: this.properties.ResponseMsgToUser,
BtnSubmitVoteText: this.properties.BtnSubmitVoteText,
chartType: this.properties.chartType ? this.properties.chartType : ChartType.Doughnut,
pollBasedOnDate: this.properties.pollBasedOnDate,
NoPollMsg: this.properties.NoPollMsg,
currentUserInfo: this.userinfo,
openPropertyPane: this.openPropertyPane
}
);
ReactDom.render(element, this.domElement);
}
protected get disableReactivePropertyChanges() {
return false;
}
protected onDispose(): void {
ReactDom.unmountComponentAtNode(this.domElement);
}
protected get dataVersion(): Version {
return Version.parse('1.0');
}
private openPropertyPane = (): void => {
this.context.propertyPane.open();
}
protected getPropertyPaneConfiguration(): IPropertyPaneConfiguration {
return {
pages: [
{
header: {
description: strings.PropertyPaneDescription
},
groups: [
public render(): void {
const element: React.ReactElement<ISimplePollProps> = React.createElement(
SimplePoll,
{
groupName: strings.BasicGroupName,
groupFields: [
PropertyFieldToggleWithCallout('pollBasedOnDate', {
calloutTrigger: CalloutTriggers.Hover,
key: 'pollBasedOnDateFieldId',
label: strings.PollDateLabel,
calloutContent: React.createElement('div', {}, strings.PollDateCalloutText),
onText: 'Yes',
offText: 'No',
checked: this.properties.pollBasedOnDate
}),
PropertyFieldCollectionData("pollQuestions", {
key: "pollQuestions",
label: strings.PollQuestionsLabel,
panelHeader: strings.PollQuestionsPanelHeader,
manageBtnLabel: strings.PollQuestionsManageButton,
enableSorting: true,
value: this.properties.pollQuestions,
fields: [
{
id: "QTitle",
title: strings.Q_Title_Title,
type: CustomCollectionFieldType.custom,
required: true,
onCustomRender: (field, value, onUpdate, item, itemId) => {
return (
React.createElement("div", null,
React.createElement("textarea",
{
style: { width: "250px", height: "70px" },
placeholder: strings.Q_Title_Placeholder,
key: itemId,
value: value,
onChange: (event: React.FormEvent<HTMLTextAreaElement>) => {
onUpdate(field.id, event.currentTarget.value);
},
})
)
);
}
},
{
id: "QOptions",
title: strings.Q_Options_Title,
type: CustomCollectionFieldType.custom,
required: true,
onCustomRender: (field, value, onUpdate, item, itemId) => {
return (
React.createElement("div", null,
React.createElement("textarea",
{
style: { width: "250px", height: "70px" },
placeholder: strings.Q_Options_Placeholder,
key: itemId,
value: value,
onChange: (event: React.FormEvent<HTMLTextAreaElement>) => {
onUpdate(field.id, event.currentTarget.value);
},
})
)
);
}
},
{
id: "QMultiChoice",
title: strings.MultiChoice_Title,
type: CustomCollectionFieldType.boolean,
defaultValue: false
},
{
id: "QStartDate",
title: strings.Q_StartDate_Title,
type: CustomCollectionFieldType.custom,
required: false,
onCustomRender: (field, value, onUpdate, item, itemId) => {
return (
React.createElement(DateTimePicker, {
key: itemId,
showLabels: false,
dateConvention: DateConvention.Date,
showGoToToday: true,
showMonthPickerAsOverlay: true,
value: value ? new Date(value) : null,
disabled: !this.properties.pollBasedOnDate,
onChange: (date: Date) => {
onUpdate(field.id, date);
}
})
);
}
},
{
id: "QEndDate",
title: strings.Q_EndDate_Title,
type: CustomCollectionFieldType.custom,
required: false,
onCustomRender: (field, value, onUpdate, item, itemId) => {
return (
React.createElement(DateTimePicker, {
key: itemId,
showLabels: false,
dateConvention: DateConvention.Date,
showGoToToday: true,
showMonthPickerAsOverlay: true,
value: value ? new Date(value) : null,
disabled: !this.properties.pollBasedOnDate,
onChange: (date: Date) => {
onUpdate(field.id, date);
}
})
);
}
}
],
disabled: false
}),
PropertyPaneTextField('MsgAfterSubmission', {
label: strings.MsgAfterSubmissionLabel,
description: strings.MsgAfterSubmissionDescription,
maxLength: 150,
multiline: true,
rows: 3,
resizable: false,
placeholder: strings.MsgAfterSubmissionPlaceholder,
value: this.properties.MsgAfterSubmission
}),
PropertyPaneTextField('ResponseMsgToUser', {
label: strings.ResponseMsgToUserLabel,
description: strings.ResponseMsgToUserDescription,
maxLength: 150,
multiline: true,
rows: 3,
resizable: false,
placeholder: strings.ResponseMsgToUserPlaceholder,
value: this.properties.ResponseMsgToUser
}),
PropertyPaneTextField('BtnSubmitVoteText', {
label: strings.BtnSumbitVoteLabel,
description: strings.BtnSumbitVoteDescription,
maxLength: 50,
multiline: false,
resizable: false,
placeholder: strings.BtnSumbitVotePlaceholder,
value: this.properties.BtnSubmitVoteText
}),
PropertyPaneTextField('NoPollMsg', {
label: strings.NoPollMsgLabel,
description: strings.NoPollMsgDescription,
maxLength: 150,
multiline: true,
rows: 3,
resizable: false,
placeholder: strings.NoPollMsgPlaceholder,
value: this.properties.NoPollMsg
}),
PropertyFieldChoiceGroupWithCallout('chartType', {
calloutContent: React.createElement('div', {}, strings.ChartFieldCalloutText),
calloutTrigger: CalloutTriggers.Hover,
key: 'choice_charttype',
label: strings.ChartFieldLabel,
options: [
{
key: 'pie',
text: 'Pie',
checked: this.properties.chartType === ChartType.Pie,
iconProps: { officeFabricIconFontName: 'PieSingle' }
}, {
key: 'doughnut',
text: 'Doughnut',
checked: this.properties.chartType === ChartType.Doughnut,
iconProps: { officeFabricIconFontName: 'DonutChart' }
}, {
key: 'bar',
text: 'Bar',
checked: this.properties.chartType === ChartType.Bar,
iconProps: { officeFabricIconFontName: 'BarChartVertical' }
}, {
key: 'horizontalBar',
text: 'Horizontal Bar',
checked: this.properties.chartType === ChartType.HorizontalBar,
iconProps: { officeFabricIconFontName: 'BarChartHorizontal' }
}, {
key: 'line',
text: 'Line',
checked: this.properties.chartType === ChartType.Line,
iconProps: { officeFabricIconFontName: 'LineChart' }
}]
})
]
pollQuestions: this.properties.pollQuestions,
SuccessfullVoteSubmissionMsg: this.properties.MsgAfterSubmission,
ResponseMsgToUser: this.properties.ResponseMsgToUser,
BtnSubmitVoteText: this.properties.BtnSubmitVoteText,
chartType: this.properties.chartType ? this.properties.chartType : ChartType.Doughnut,
pollBasedOnDate: this.properties.pollBasedOnDate,
NoPollMsg: this.properties.NoPollMsg,
currentUserInfo: this.userinfo,
openPropertyPane: this.openPropertyPane
}
]
}
]
};
}
);
ReactDom.render(element, this.domElement);
}
protected get disableReactivePropertyChanges() {
return false;
}
protected onDispose(): void {
ReactDom.unmountComponentAtNode(this.domElement);
}
protected get dataVersion(): Version {
return Version.parse('1.0');
}
private openPropertyPane = (): void => {
this.context.propertyPane.open();
}
protected getPropertyPaneConfiguration(): IPropertyPaneConfiguration {
return {
pages: [
{
header: {
description: strings.PropertyPaneDescription
},
groups: [
{
groupName: strings.BasicGroupName,
groupFields: [
PropertyFieldToggleWithCallout('pollBasedOnDate', {
calloutTrigger: CalloutTriggers.Hover,
key: 'pollBasedOnDateFieldId',
label: strings.PollDateLabel,
calloutContent: React.createElement('div', {}, strings.PollDateCalloutText),
onText: 'Yes',
offText: 'No',
checked: this.properties.pollBasedOnDate
}),
PropertyFieldCollectionData("pollQuestions", {
key: "pollQuestions",
label: strings.PollQuestionsLabel,
panelHeader: strings.PollQuestionsPanelHeader,
manageBtnLabel: strings.PollQuestionsManageButton,
enableSorting: true,
value: this.properties.pollQuestions,
fields: [
{
id: "QTitle",
title: strings.Q_Title_Title,
type: CustomCollectionFieldType.custom,
required: true,
onCustomRender: (field, value, onUpdate, item, itemId) => {
return (
React.createElement("div", null,
React.createElement("textarea",
{
style: { width: "220px", height: "70px" },
placeholder: strings.Q_Title_Placeholder,
key: itemId,
value: value,
onChange: (event: React.FormEvent<HTMLTextAreaElement>) => {
onUpdate(field.id, event.currentTarget.value);
},
})
)
);
}
},
{
id: "QOptions",
title: strings.Q_Options_Title,
type: CustomCollectionFieldType.custom,
required: true,
onCustomRender: (field, value, onUpdate, item, itemId) => {
return (
React.createElement("div", null,
React.createElement("textarea",
{
style: { width: "220px", height: "70px" },
placeholder: strings.Q_Options_Placeholder,
key: itemId,
value: value,
onChange: (event: React.FormEvent<HTMLTextAreaElement>) => {
onUpdate(field.id, event.currentTarget.value);
},
})
)
);
}
},
{
id: "QMultiChoice",
title: strings.MultiChoice_Title,
type: CustomCollectionFieldType.boolean,
defaultValue: false
},
{
id: "QStartDate",
title: strings.Q_StartDate_Title,
type: CustomCollectionFieldType.custom,
required: false,
onCustomRender: (field, value, onUpdate, item, itemId) => {
return (
React.createElement(DateTimePicker, {
key: itemId,
showLabels: false,
dateConvention: DateConvention.Date,
showGoToToday: true,
showMonthPickerAsOverlay: true,
value: value ? new Date(value) : null,
disabled: !this.properties.pollBasedOnDate,
onChange: (date: Date) => {
onUpdate(field.id, date);
}
})
);
}
},
{
id: "QEndDate",
title: strings.Q_EndDate_Title,
type: CustomCollectionFieldType.custom,
required: false,
onCustomRender: (field, value, onUpdate, item, itemId) => {
return (
React.createElement(DateTimePicker, {
key: itemId,
showLabels: false,
dateConvention: DateConvention.Date,
showGoToToday: true,
showMonthPickerAsOverlay: true,
value: value ? new Date(value) : null,
disabled: !this.properties.pollBasedOnDate,
onChange: (date: Date) => {
onUpdate(field.id, date);
}
})
);
}
}
],
disabled: false
}),
PropertyPaneTextField('MsgAfterSubmission', {
label: strings.MsgAfterSubmissionLabel,
description: strings.MsgAfterSubmissionDescription,
maxLength: 150,
multiline: true,
rows: 3,
resizable: false,
placeholder: strings.MsgAfterSubmissionPlaceholder,
value: this.properties.MsgAfterSubmission
}),
PropertyPaneTextField('ResponseMsgToUser', {
label: strings.ResponseMsgToUserLabel,
description: strings.ResponseMsgToUserDescription,
maxLength: 150,
multiline: true,
rows: 3,
resizable: false,
placeholder: strings.ResponseMsgToUserPlaceholder,
value: this.properties.ResponseMsgToUser
}),
PropertyPaneTextField('BtnSubmitVoteText', {
label: strings.BtnSumbitVoteLabel,
description: strings.BtnSumbitVoteDescription,
maxLength: 50,
multiline: false,
resizable: false,
placeholder: strings.BtnSumbitVotePlaceholder,
value: this.properties.BtnSubmitVoteText
}),
PropertyPaneTextField('NoPollMsg', {
label: strings.NoPollMsgLabel,
description: strings.NoPollMsgDescription,
maxLength: 150,
multiline: true,
rows: 3,
resizable: false,
placeholder: strings.NoPollMsgPlaceholder,
value: this.properties.NoPollMsg
}),
PropertyFieldChoiceGroupWithCallout('chartType', {
calloutContent: React.createElement('div', {}, strings.ChartFieldCalloutText),
calloutTrigger: CalloutTriggers.Hover,
key: 'choice_charttype',
label: strings.ChartFieldLabel,
options: [
{
key: 'pie',
text: 'Pie',
checked: this.properties.chartType === ChartType.Pie,
iconProps: { officeFabricIconFontName: 'PieSingle' }
}, {
key: 'doughnut',
text: 'Doughnut',
checked: this.properties.chartType === ChartType.Doughnut,
iconProps: { officeFabricIconFontName: 'DonutChart' }
}, {
key: 'bar',
text: 'Bar',
checked: this.properties.chartType === ChartType.Bar,
iconProps: { officeFabricIconFontName: 'BarChartVertical' }
}, {
key: 'horizontalBar',
text: 'Horizontal Bar',
checked: this.properties.chartType === ChartType.HorizontalBar,
iconProps: { officeFabricIconFontName: 'BarChartHorizontal' }
}, {
key: 'line',
text: 'Line',
checked: this.properties.chartType === ChartType.Line,
iconProps: { officeFabricIconFontName: 'LineChart' }
}]
})
]
}
]
}
]
};
}
}

View File

@ -6,96 +6,101 @@ import { IOptionsContainerProps } from './IOptionsContainerProps';
import * as _ from 'lodash';
export interface IOptionsContainerState {
selChoices?: string[];
selChoices?: string[];
}
export default class OptionsContainer extends React.Component<IOptionsContainerProps, IOptionsContainerState> {
constructor(props: IOptionsContainerProps) {
super(props);
this.state = {
selChoices: []
};
}
constructor(props: IOptionsContainerProps) {
super(props);
this.state = {
selChoices: []
};
}
public render(): JSX.Element {
const { disabled, selectedKey, label, options, onChange, multiSelect } = this.props;
return (
<div>
{multiSelect ? (
<div style={{ paddingTop: "15px" }}>
<List items={this.getOptions()} onRenderCell={this._onRenderCell} />
</div>
) : (
<ChoiceGroup disabled={disabled}
selectedKey={this._getSelectedKey()}
options={this.onRenderChoiceOptions()} required={true} label=""
onChange={this._onChange}
/>
)
public render(): JSX.Element {
const { disabled, selectedKey, label, options, onChange, multiSelect } = this.props;
return (
<div>
{multiSelect ? (
<div style={{ paddingTop: "15px" }}>
<List items={this.getOptions()} onRenderCell={this._onRenderCell} />
</div>
) : (
<ChoiceGroup disabled={disabled}
selectedKey={this._getSelectedKey()}
options={this.onRenderChoiceOptions()} required={true} label=""
onChange={this._onChange}
/>
)
}
</div>
);
}
private getOptions = (): string[] => {
let tempChoices: string[] = [];
if (this.props.options.indexOf(',') >= 0) {
let tmpChoices = this.props.options.split(',');
tmpChoices.map(choice => {
if (choice && choice.trim().length > 0) tempChoices.push(choice);
});
} else tempChoices.push(this.props.options);
return tempChoices;
}
private _onRenderCell = (item: any, index: number | undefined): JSX.Element => {
if (item && item.length > 0) {
return (
<div style={{ marginBottom: "15px" }}>
<Checkbox label={item} onChange={this._makeChangeHandler(item)} />
</div>
);
}
</div>
);
}
private getOptions = (): string[] => {
let tempChoices: string[] = [];
if (this.props.options.indexOf(',') >= 0) {
tempChoices = this.props.options.split(',');
} else tempChoices.push(this.props.options);
return tempChoices;
}
private _onRenderCell = (item: any, index: number | undefined): JSX.Element => {
return (
<div style={{ marginBottom: "15px" }}>
<Checkbox label={item} onChange={this._makeChangeHandler(item)} />
</div>
);
}
private onRenderChoiceOptions(): IChoiceGroupOption[] {
let choices: IChoiceGroupOption[] = [];
let tempChoices: string[] = this.getOptions();
if (tempChoices.length > 0) {
tempChoices.map((choice: string) => {
choices.push({
key: choice.trim(),
text: choice.trim()
});
});
} else {
choices.push({
key: '0',
text: "Sorry, no choices found",
disabled: true,
});
}
return choices;
}
private _getSelectedKey = (): string => {
return this.props.selectedKey();
}
private _onChange = (ev: React.FormEvent<HTMLInputElement>, option: any): void => {
this.props.onChange(ev, option, false);
}
private _makeChangeHandler = (item: string) => {
return (ev: any, checked: boolean) => this._onCheckboxChange(ev, checked, item);
}
private _onCheckboxChange = (ev: any, isChecked: boolean, item: string) => {
let finalSel: string[] = this.state.selChoices;
if (finalSel.length > 0) {
if (isChecked) {
finalSel.push(item);
} else finalSel = _.filter(finalSel, (o) => { return o !== item; });
} else {
if (isChecked) finalSel.push(item);
private onRenderChoiceOptions(): IChoiceGroupOption[] {
let choices: IChoiceGroupOption[] = [];
let tempChoices: string[] = this.getOptions();
if (tempChoices.length > 0) {
tempChoices.map((choice: string) => {
choices.push({
key: choice.trim(),
text: choice.trim()
});
});
} else {
choices.push({
key: '0',
text: "Sorry, no choices found",
disabled: true,
});
}
return choices;
}
private _getSelectedKey = (): string => {
return this.props.selectedKey();
}
private _onChange = (ev: React.FormEvent<HTMLInputElement>, option: any): void => {
this.props.onChange(ev, option, false);
}
private _makeChangeHandler = (item: string) => {
return (ev: any, checked: boolean) => this._onCheckboxChange(ev, checked, item);
}
private _onCheckboxChange = (ev: any, isChecked: boolean, item: string) => {
let finalSel: string[] = this.state.selChoices;
if (finalSel.length > 0) {
if (isChecked) {
finalSel.push(item);
} else finalSel = _.filter(finalSel, (o) => { return o !== item; });
} else {
if (isChecked) finalSel.push(item);
}
this.setState({ selChoices: finalSel });
this.props.onChange(ev, { key: finalSel }, true);
}
this.setState({ selChoices: finalSel });
this.props.onChange(ev, { key: finalSel }, true);
}
}

View File

@ -29,7 +29,8 @@
]
},
"include": [
"src/**/*.ts"
"src/**/*.ts",
"src/**/*.tsx"
],
"exclude": [
"node_modules",

View File

@ -0,0 +1,344 @@
# Upgrade project react-simple-poll to v1.11.0
Date: 10/16/2020
## Findings
Following is the list of steps required to upgrade your project to SharePoint Framework version 1.11.0. [Summary](#Summary) of the modifications is included at the end of the report.
### FN001001 @microsoft/sp-core-library | Required
Upgrade SharePoint Framework dependency package @microsoft/sp-core-library
Execute the following command:
```sh
npm i -SE @microsoft/sp-core-library@1.11.0
```
File: [./package.json](./package.json)
### FN001002 @microsoft/sp-lodash-subset | Required
Upgrade SharePoint Framework dependency package @microsoft/sp-lodash-subset
Execute the following command:
```sh
npm i -SE @microsoft/sp-lodash-subset@1.11.0
```
File: [./package.json](./package.json)
### FN001003 @microsoft/sp-office-ui-fabric-core | Required
Upgrade SharePoint Framework dependency package @microsoft/sp-office-ui-fabric-core
Execute the following command:
```sh
npm i -SE @microsoft/sp-office-ui-fabric-core@1.11.0
```
File: [./package.json](./package.json)
### FN001004 @microsoft/sp-webpart-base | Required
Upgrade SharePoint Framework dependency package @microsoft/sp-webpart-base
Execute the following command:
```sh
npm i -SE @microsoft/sp-webpart-base@1.11.0
```
File: [./package.json](./package.json)
### FN001005 @types/react | Required
Remove SharePoint Framework dependency package @types/react
Execute the following command:
```sh
npm un -S @types/react
```
File: [./package.json](./package.json)
### FN001006 @types/react-dom | Required
Remove SharePoint Framework dependency package @types/react-dom
Execute the following command:
```sh
npm un -S @types/react-dom
```
File: [./package.json](./package.json)
### FN001007 @types/webpack-env | Required
Remove SharePoint Framework dependency package @types/webpack-env
Execute the following command:
```sh
npm un -S @types/webpack-env
```
File: [./package.json](./package.json)
### FN001010 @types/es6-promise | Required
Remove SharePoint Framework dependency package @types/es6-promise
Execute the following command:
```sh
npm un -S @types/es6-promise
```
File: [./package.json](./package.json)
### FN001021 @microsoft/sp-property-pane | Required
Upgrade SharePoint Framework dependency package @microsoft/sp-property-pane
Execute the following command:
```sh
npm i -SE @microsoft/sp-property-pane@1.11.0
```
File: [./package.json](./package.json)
### FN001022 office-ui-fabric-react | Required
Upgrade SharePoint Framework dependency package office-ui-fabric-react
Execute the following command:
```sh
npm i -SE office-ui-fabric-react@6.214.0
```
File: [./package.json](./package.json)
### FN002001 @microsoft/sp-build-web | Required
Upgrade SharePoint Framework dev dependency package @microsoft/sp-build-web
Execute the following command:
```sh
npm i -DE @microsoft/sp-build-web@1.11.0
```
File: [./package.json](./package.json)
### FN002002 @microsoft/sp-module-interfaces | Required
Upgrade SharePoint Framework dev dependency package @microsoft/sp-module-interfaces
Execute the following command:
```sh
npm i -DE @microsoft/sp-module-interfaces@1.11.0
```
File: [./package.json](./package.json)
### FN002003 @microsoft/sp-webpart-workbench | Required
Upgrade SharePoint Framework dev dependency package @microsoft/sp-webpart-workbench
Execute the following command:
```sh
npm i -DE @microsoft/sp-webpart-workbench@1.11.0
```
File: [./package.json](./package.json)
### FN002009 @microsoft/sp-tslint-rules | Required
Upgrade SharePoint Framework dev dependency package @microsoft/sp-tslint-rules
Execute the following command:
```sh
npm i -DE @microsoft/sp-tslint-rules@1.11.0
```
File: [./package.json](./package.json)
### FN002013 @types/webpack-env | Required
Install SharePoint Framework dev dependency package @types/webpack-env
Execute the following command:
```sh
npm i -DE @types/webpack-env@1.13.1
```
File: [./package.json](./package.json)
### FN002014 @types/es6-promise | Required
Install SharePoint Framework dev dependency package @types/es6-promise
Execute the following command:
```sh
npm i -DE @types/es6-promise@0.0.33
```
File: [./package.json](./package.json)
### FN002015 @types/react | Required
Install SharePoint Framework dev dependency package @types/react
Execute the following command:
```sh
npm i -DE @types/react@16.8.8
```
File: [./package.json](./package.json)
### FN002016 @types/react-dom | Required
Install SharePoint Framework dev dependency package @types/react-dom
Execute the following command:
```sh
npm i -DE @types/react-dom@16.8.3
```
File: [./package.json](./package.json)
### FN006004 package-solution.json developer | Optional
In package-solution.json add developer section
In file [./config/package-solution.json](./config/package-solution.json) update the code as follows:
```json
{
"solution": {
"developer": {
"name": "Contoso",
"privacyUrl": "https://contoso.com/privacy",
"termsOfUseUrl": "https://contoso.com/terms-of-use",
"websiteUrl": "https://contoso.com/my-app",
"mpnId": "000000"
}
}
}
```
File: [./config/package-solution.json](./config/package-solution.json)
### FN010001 .yo-rc.json version | Recommended
Update version in .yo-rc.json
In file [./.yo-rc.json](./.yo-rc.json) update the code as follows:
```json
{
"@microsoft/generator-sharepoint": {
"version": "1.11.0"
}
}
```
File: [./.yo-rc.json](./.yo-rc.json)
### FN012012 tsconfig.json include property | Required
Update tsconfig.json include property
In file [./tsconfig.json](./tsconfig.json) update the code as follows:
```json
{
"include": [
"src/**/*.tsx"
]
}
```
File: [./tsconfig.json](./tsconfig.json)
### FN017001 Run npm dedupe | Optional
If, after upgrading npm packages, when building the project you have errors similar to: "error TS2345: Argument of type 'SPHttpClientConfiguration' is not assignable to parameter of type 'SPHttpClientConfiguration'", try running 'npm dedupe' to cleanup npm packages.
Execute the following command:
```sh
npm dedupe
```
File: [./package.json](./package.json)
## Summary
### Execute script
```sh
npm i -SE @microsoft/sp-core-library@1.11.0 @microsoft/sp-lodash-subset@1.11.0 @microsoft/sp-office-ui-fabric-core@1.11.0 @microsoft/sp-webpart-base@1.11.0 @microsoft/sp-property-pane@1.11.0 office-ui-fabric-react@6.214.0
npm i -DE @microsoft/sp-build-web@1.11.0 @microsoft/sp-module-interfaces@1.11.0 @microsoft/sp-webpart-workbench@1.11.0 @microsoft/sp-tslint-rules@1.11.0 @types/webpack-env@1.13.1 @types/es6-promise@0.0.33 @types/react@16.8.8 @types/react-dom@16.8.3
npm un -S @types/react @types/react-dom @types/webpack-env @types/es6-promise
npm dedupe
```
### Modify files
#### [./config/package-solution.json](./config/package-solution.json)
In package-solution.json add developer section:
```json
{
"solution": {
"developer": {
"name": "Contoso",
"privacyUrl": "https://contoso.com/privacy",
"termsOfUseUrl": "https://contoso.com/terms-of-use",
"websiteUrl": "https://contoso.com/my-app",
"mpnId": "000000"
}
}
}
```
#### [./.yo-rc.json](./.yo-rc.json)
Update version in .yo-rc.json:
```json
{
"@microsoft/generator-sharepoint": {
"version": "1.11.0"
}
}
```
#### [./tsconfig.json](./tsconfig.json)
Update tsconfig.json include property:
```json
{
"include": [
"src/**/*.tsx"
]
}
```