Update readme

This commit is contained in:
Ari Gunawan 2021-09-26 21:54:22 +07:00
parent f24f863d27
commit 902bce7ca5
13 changed files with 577 additions and 10 deletions

View File

@ -0,0 +1,6 @@
{
"$schema": "https://raw.githubusercontent.com/s-KaiNet/spfx-fast-serve/master/schema/config.latest.schema.json",
"cli": {
"isLibraryComponent": false
}
}

View File

@ -0,0 +1,24 @@
/*
* User webpack settings file. You can add your own settings here.
* Changes from this file will be merged into the base webpack configuration file.
* This file will not be overwritten by the subsequent spfx-fast-serve calls.
*/
// you can add your project related webpack configuration here, it will be merged using webpack-merge module
// i.e. plugins: [new webpack.Plugin()]
const webpackConfig = {
}
// for even more fine-grained control, you can apply custom webpack settings using below function
const transformConfig = function (initialWebpackConfig) {
// transform the initial webpack config here, i.e.
// initialWebpackConfig.plugins.push(new webpack.Plugin()); etc.
return initialWebpackConfig;
}
module.exports = {
webpackConfig,
transformConfig
}

View File

@ -0,0 +1,104 @@
{
"bundles": {
"react-query-example-web-part": {
"dependencies": [
{
"componentId": "f9e737b7-f0df-4597-ba8c-3060f82380db",
"componentName": "@microsoft/sp-property-pane",
"componentVersion": "1.12.1",
"isDirectDependency": true
},
{
"componentId": "1c6c9123-7aac-41f3-a376-3caea41ed83f",
"componentName": "@microsoft/sp-loader",
"componentVersion": "1.12.1",
"isDirectDependency": false
},
{
"componentId": "8217e442-8ed3-41fd-957d-b112e841286a",
"componentName": "@ms/sp-telemetry",
"componentVersion": "0.19.2",
"isDirectDependency": false
},
{
"componentId": "e40f8203-b39d-425a-a957-714852e33b79",
"componentName": "@microsoft/sp-dynamic-data",
"componentVersion": "1.12.1",
"isDirectDependency": false
},
{
"componentId": "73e1dc6c-8441-42cc-ad47-4bd3659f8a3a",
"componentName": "@microsoft/sp-lodash-subset",
"componentVersion": "1.12.1",
"isDirectDependency": false
},
{
"componentId": "7263c7d0-1d6a-45ec-8d85-d4d1d234171b",
"componentName": "@microsoft/sp-core-library",
"componentVersion": "1.12.1",
"isDirectDependency": false
},
{
"componentId": "01c4df03-e775-48cb-aa14-171ee5199a15",
"componentName": "tslib",
"componentVersion": "1.10.0",
"isDirectDependency": false
},
{
"componentId": "2e09fb9b-13bb-48f2-859f-97d6fff71176",
"componentName": "@ms/odsp-core-bundle",
"componentVersion": "1.1.13",
"isDirectDependency": false
},
{
"componentId": "78359e4b-07c2-43c6-8d0b-d060b4d577e8",
"componentName": "@microsoft/sp-diagnostics",
"componentVersion": "1.12.1",
"isDirectDependency": false
},
{
"componentId": "1c4541f7-5c31-41aa-9fa8-fbc9dc14c0a8",
"componentName": "@microsoft/sp-page-context",
"componentVersion": "1.12.1",
"isDirectDependency": false
},
{
"componentId": "229b8d08-79f3-438b-8c21-4613fc877abd",
"componentName": "@microsoft/load-themed-styles",
"componentVersion": "0.1.2",
"isDirectDependency": false
},
{
"componentId": "c07208f0-ea3b-4c1a-9965-ac1b825211a6",
"componentName": "@microsoft/sp-http",
"componentVersion": "1.12.1",
"isDirectDependency": false
},
{
"componentId": "0d910c1c-13b9-4e1c-9aa4-b008c5e42d7d",
"componentName": "react",
"componentVersion": "16.9.0",
"isDirectDependency": false
},
{
"componentId": "aa0a46ec-1505-43cd-a44a-93f3a5aa460a",
"componentName": "react-dom",
"componentVersion": "16.9.0",
"isDirectDependency": false
},
{
"componentId": "974a7777-0990-4136-8fa6-95d80114c2e0",
"componentName": "@microsoft/sp-webpart-base",
"componentVersion": "1.12.1",
"isDirectDependency": true
},
{
"componentId": "467dc675-7cc5-4709-8aac-78e3b71bd2f6",
"componentName": "@microsoft/sp-component-base",
"componentVersion": "1.12.1",
"isDirectDependency": false
}
]
}
}
}

View File

@ -0,0 +1,114 @@
{
"id": "b59e6ef1-0904-45d4-a778-290a67738172",
"alias": "ReactQueryExampleWebPart",
"componentType": "WebPart",
"version": "0.0.1",
"manifestVersion": 2,
"requiresCustomScript": false,
"supportedHosts": [
"SharePointWebPart"
],
"preconfiguredEntries": [
{
"groupId": "5c03119e-3074-46fd-976b-c60198311f70",
"group": {
"default": "Other"
},
"title": {
"default": "ReactQueryExample"
},
"description": {
"default": "ReactQueryExample description"
},
"officeFabricIconFontName": "Page",
"properties": {
"description": "ReactQueryExample"
}
}
],
"loaderConfig": {
"internalModuleBaseUrls": [
"<!-- PATH TO CDN -->"
],
"entryModuleId": "react-query-example-web-part",
"scriptResources": {
"react-query-example-web-part": {
"type": "path",
"path": "react-query-example-web-part.js"
},
"@microsoft/sp-property-pane": {
"type": "component",
"id": "f9e737b7-f0df-4597-ba8c-3060f82380db",
"version": "1.12.1"
},
"@microsoft/sp-lodash-subset": {
"type": "component",
"id": "73e1dc6c-8441-42cc-ad47-4bd3659f8a3a",
"version": "1.12.1"
},
"@microsoft/sp-core-library": {
"type": "component",
"id": "7263c7d0-1d6a-45ec-8d85-d4d1d234171b",
"version": "1.12.1"
},
"@microsoft/sp-webpart-base": {
"type": "component",
"id": "974a7777-0990-4136-8fa6-95d80114c2e0",
"version": "1.12.1"
},
"react": {
"type": "component",
"id": "0d910c1c-13b9-4e1c-9aa4-b008c5e42d7d",
"version": "16.9.0"
},
"react-dom": {
"type": "component",
"id": "aa0a46ec-1505-43cd-a44a-93f3a5aa460a",
"version": "16.9.0"
},
"ReactQueryExampleWebPartStrings": {
"type": "path",
"path": "ReactQueryExampleWebPartStrings_en-us.js"
},
"@microsoft/sp-http": {
"type": "component",
"id": "c07208f0-ea3b-4c1a-9965-ac1b825211a6",
"version": "1.12.1"
},
"PropertyControlStrings": {
"type": "localizedPath",
"paths": {
"bg-BG": "PropertyControlStrings_bg-bg.js",
"ca-ES": "PropertyControlStrings_ca-es.js",
"da-DK": "PropertyControlStrings_da-dk.js",
"de-DE": "PropertyControlStrings_de-de.js",
"el-GR": "PropertyControlStrings_el-gr.js",
"en-US": "PropertyControlStrings_en-us.js",
"es-ES": "PropertyControlStrings_es-es.js",
"et-EE": "PropertyControlStrings_et-ee.js",
"fi-FI": "PropertyControlStrings_fi-fi.js",
"fr-FR": "PropertyControlStrings_fr-fr.js",
"it-IT": "PropertyControlStrings_it-it.js",
"ja-JP": "PropertyControlStrings_ja-jp.js",
"lt-LT": "PropertyControlStrings_lt-lt.js",
"lv-LV": "PropertyControlStrings_lv-lv.js",
"nb-NO": "PropertyControlStrings_nb-no.js",
"nl-NL": "PropertyControlStrings_nl-nl.js",
"no": "PropertyControlStrings_no.js",
"pl-PL": "PropertyControlStrings_pl-pl.js",
"pt-PT": "PropertyControlStrings_pt-pt.js",
"ro-RO": "PropertyControlStrings_ro-ro.js",
"ru-RU": "PropertyControlStrings_ru-ru.js",
"sk-SK": "PropertyControlStrings_sk-sk.js",
"sr-Latn-RS": "PropertyControlStrings_sr-latn-rs.js",
"sv-SE": "PropertyControlStrings_sv-se.js",
"tr-TR": "PropertyControlStrings_tr-tr.js",
"vi-VN": "PropertyControlStrings_vi-vn.js",
"zh-CN": "PropertyControlStrings_zh-cn.js",
"zh-TW": "PropertyControlStrings_zh-tw.js"
},
"defaultPath": "PropertyControlStrings_en-us.js"
}
}
}
}

View File

@ -0,0 +1,101 @@
import { sp } from '@pnp/sp';
import { format } from 'date-fns';
import {
DetailsList,
DetailsListLayoutMode,
SelectionMode,
} from 'office-ui-fabric-react/lib/DetailsList';
import { Spinner } from 'office-ui-fabric-react/lib/Spinner';
import * as React from 'react';
import { FunctionComponent, useEffect, useState } from 'react';
import { IDisplayItemsProps } from './IDisplayItemsProps';
export const DisplayItems: FunctionComponent<IDisplayItemsProps> = (
props: IDisplayItemsProps
) => {
const [items, setItems] = useState([]);
const [isLoading, setIsLoading] = useState(true);
const columns = [
{
key: 'id',
name: 'ID',
fieldName: 'id',
minWidth: 50,
maxWidth: 50,
isResizable: true,
},
{
key: 'title',
name: 'Title',
fieldName: 'title',
minWidth: 250,
isResizable: true,
},
{
key: 'editor',
name: 'Modified By',
fieldName: 'editor',
minWidth: 200,
isResizable: true,
},
{
key: 'modified',
name: 'Last Modified',
fieldName: 'modified',
minWidth: 200,
isResizable: true,
},
];
useEffect(() => {
if (!props.isNeedRefreshData) return;
setIsLoading(true);
const fetchData = async () => {
const result = await sp.web.lists
.getById(props.listId)
.items.expand('Editor')
.select('ID', 'Title', 'Modified', 'Editor/Title')
.orderBy('Modified', false)
.get();
setItems(
result.map((item) => ({
id: item.ID,
title: item.Title,
editor: item.Editor.Title,
modified: format(new Date(item.Modified), 'kk:mm PPP'),
}))
);
setIsLoading(false);
props.updateIsNeedRefreshData(false);
};
fetchData();
}, [props.isNeedRefreshData]);
function handleItemInvoked(item: any, index: number) {
props.setSelectedItem(item);
}
if (isLoading) {
return (
<div>
<Spinner label='Loading data...' />
</div>
);
}
return (
<DetailsList
items={items}
columns={columns}
setKey='set'
layoutMode={DetailsListLayoutMode.justified}
ariaLabelForSelectionColumn='Toggle selection'
ariaLabelForSelectAllCheckbox='Toggle selection for all items'
checkButtonAriaLabel='select row'
onItemInvoked={handleItemInvoked}
selectionMode={SelectionMode.none}
/>
);
};

View File

@ -0,0 +1,6 @@
export interface IDisplayItemsProps {
listId: string;
isNeedRefreshData: boolean;
updateIsNeedRefreshData: (value: boolean) => void;
setSelectedItem: (selectedItem: any) => void;
}

View File

@ -0,0 +1,29 @@
.form {
padding: 28px;
margin-bottom: 28px;
border-radius: 2px;
background-clip: padding-box;
-webkit-box-shadow: 0 1.6px 3.6px 0 #00000021, 0 0.3px 0.9px 0 #0000001c;
box-shadow: 0 1.6px 3.6px 0 #00000021, 0 0.3px 0.9px 0 #0000001c;
position: relative;
width: 50%;
@media (max-width: 600px) {
width: 100%;
}
.title {
display: block;
font-size: 24px;
margin-bottom: 15px;
}
.buttonsContainer {
text-align: right;
margin-top: 20px;
button:not(:last-child) {
margin-right: 10px;
}
}
}

View File

@ -0,0 +1,13 @@
// This file is automatically generated.
// Please do not change this file!
/* tslint:disable */
/* eslint-disable */
interface CssExports {
'buttonsContainer': string;
'form': string;
'title': string;
}
const cssExports: CssExports;
export default cssExports;

View File

@ -0,0 +1,125 @@
import { sp } from '@pnp/sp';
import { format } from 'date-fns';
import {
DetailsList,
DetailsListLayoutMode,
} from 'office-ui-fabric-react/lib/DetailsList';
import { Label } from 'office-ui-fabric-react/lib/Label';
import { Spinner } from 'office-ui-fabric-react/lib/Spinner';
import * as React from 'react';
import { FunctionComponent, useEffect, useRef, useState } from 'react';
import { IFormProps } from './IFormProps';
import styles from './Form.module.scss';
import { ITextField, TextField } from 'office-ui-fabric-react/lib/TextField';
import {
DefaultButton,
PrimaryButton,
} from 'office-ui-fabric-react/lib/Button';
export const Form: FunctionComponent<IFormProps> = (props: IFormProps) => {
const [isLoading, setIsLoading] = useState(false);
const [isNew, setIsNew] = useState(true);
const [title, setTitle] = useState('');
let titleEl: ITextField;
useEffect(() => {
if (!props.selectedItem) {
setTitle('');
setIsNew(true);
return;
}
setIsNew(false);
setTitle(props.selectedItem.title);
titleEl.focus();
}, [props.selectedItem]);
async function addItem() {
setIsLoading(true);
await sp.web.lists.getById(props.listId).items.add({ Title: title });
props.updateIsNeedRefreshData(true);
setTitle('');
setIsLoading(false);
}
async function editItem() {
setIsLoading(true);
await sp.web.lists
.getById(props.listId)
.items.getById(props.selectedItem.id)
.update({ Title: title });
props.updateIsNeedRefreshData(true);
props.setSelectedItem(null);
setIsNew(true);
setIsLoading(false);
}
async function handleClickSave() {
if (isNew) {
await addItem();
} else {
await editItem();
}
}
async function handleClickDelete() {
await sp.web.lists
.getById(props.listId)
.items.getById(props.selectedItem.id)
.delete();
props.updateIsNeedRefreshData(true);
props.setSelectedItem(null);
setIsNew(true);
setIsLoading(false);
}
async function handleClickCancel() {
if (isNew) {
setTitle('');
} else {
props.setSelectedItem(null);
}
}
return (
<div className={styles.form}>
<span className={styles.title}>
{isNew ? 'Add' : 'Edit'} Item
{props.selectedItem ? ` (ID: ${props.selectedItem.id})` : ''}
</span>
<TextField
label='Title'
value={title}
onChange={(event, newValue) => setTitle(newValue)}
onKeyPress={(event) => {
if (event.key === 'Enter') handleClickSave();
}}
disabled={isLoading}
componentRef={el => titleEl = el}
/>
<div className={styles.buttonsContainer}>
{!isNew && (
<PrimaryButton
text='Delete'
onClick={handleClickDelete}
allowDisabledFocus
disabled={isLoading}
/>
)}
<PrimaryButton
text='Save'
onClick={handleClickSave}
allowDisabledFocus
disabled={isLoading}
/>
<DefaultButton
text='Cancel'
onClick={handleClickCancel}
allowDisabledFocus
disabled={isLoading}
/>
</div>
</div>
);
};

View File

@ -0,0 +1,6 @@
export interface IFormProps {
listId: string;
updateIsNeedRefreshData: (value: boolean) => void;
selectedItem: any;
setSelectedItem: (selectedItem: any) => void;
}

View File

@ -0,0 +1,20 @@
// This file is automatically generated.
// Please do not change this file!
/* tslint:disable */
/* eslint-disable */
interface CssExports {
'button': string;
'column': string;
'container': string;
'description': string;
'label': string;
'ms-Grid': string;
'reactQueryExample': string;
'row': string;
'subTitle': string;
'title': string;
}
const cssExports: CssExports;
export default cssExports;

View File

@ -23,33 +23,38 @@ Sample Web Parts illustrating performing SharePoint CRUD operations in React, An
![Sample To do SharePoint Framework Client-Side Web Part built using Angular and ngOfficeUIFabric](./assets/preview.png)
## Used SharePoint Framework Version
![drop](https://img.shields.io/badge/drop-1.6.0-green.svg)
## Compatibility
![SPFx 1.12.1](https://img.shields.io/badge/SPFx-1.12.1-green.svg)
![Node.js LTS v14 | LTS v12 | LTS v10](https://img.shields.io/badge/Node.js-LTS%20v14%20%7C%20LTS%20v12%20%7C%20LTS%20v10-green.svg)
![SharePoint Online](https://img.shields.io/badge/SharePoint-Online-yellow.svg)
![Teams N/A: Untested with Microsoft Teams](https://img.shields.io/badge/Teams-N%2FA-lightgrey.svg "Untested with Microsoft Teams")
![Workbench Hosted](https://img.shields.io/badge/Workbench-Hosted-green.svg)
## Applies to
* [SharePoint Framework Developer Preview](https://docs.microsoft.com/sharepoint/dev/spfx/sharepoint-framework-overview)
* [Office 365 developer tenant](https://docs.microsoft.com/sharepoint/dev/spfx/set-up-your-developer-tenant)
* [SharePoint Framework](https://docs.microsoft.com/sharepoint/dev/spfx/sharepoint-framework-overview)
* [Microsoft 365 tenant](https://docs.microsoft.com/sharepoint/dev/spfx/set-up-your-development-environment)
## Solution
Solution|Author(s)
--------|---------
sharepoint-crud|Waldek Mastykarz (MVP, Rencore, @waldekm), Gautam Sheth (SharePoint Consultant, RapidCircle)
sharepoint-crud|Waldek Mastykarz (MVP, Rencore, @waldekm)
sharepoint-crud|Gautam Sheth (SharePoint Consultant, RapidCircle)
sharepoint-crud|[Ari Gunawan](https://github.com/AriGunawan) ([@AriGunawan3023](https://twitter.com/AriGunawan3023))
## Version history
Version|Date|Comments
-------|----|--------
1.4|September 26, 2021|Updated to SPFx 1.12.1
1.3|November 1, 2018|Updated to SPFx 1.6.0
1.2|March 30, 2018|Updated to SPFx 1.4.1
1.1|March 9, 2017|Updated to SPFx GA
1.0|September 16, 2016|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.**
---
## Prerequisites
## Minimal Path to Awesome
@ -95,4 +100,18 @@ This sample illustrates the following concepts on top of the SharePoint Framewor
- configuring global request headers and overriding them for specific requests
- sorting and selecting top n items from a list using the fluent API
## 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.**
## Help
We do not support samples, but we this community is always willing to help, and we want to improve these samples. We use GitHub to track issues, which makes it easy for community members to volunteer their time and help resolve issues.
If you encounter any issues while using this sample, [create a new issue](https://github.com/pnp/sp-dev-fx-webparts/issues/new?assignees=&labels=Needs%3A+Triage+%3Amag%3A%2Ctype%3Abug-suspected&template=bug-report.yml&sample=sharepoint-crud&authors=@waldekmastykarz%20@AriGunawan&title=sharepoint-crud%20-%20).
For questions regarding this sample, [create a new question](https://github.com/pnp/sp-dev-fx-webparts/issues/new?assignees=&labels=Needs%3A+Triage+%3Amag%3A%2Ctype%3Abug-suspected&template=question.yml&sample=sharepoint-crud&authors=@waldekmastykarz%20@AriGunawan&title=sharepoint-crud%20-%20).
Finally, if you have an idea for improvement, [make a suggestion](https://github.com/pnp/sp-dev-fx-webparts/issues/new?assignees=&labels=Needs%3A+Triage+%3Amag%3A%2Ctype%3Abug-suspected&template=suggestion.yml&sample=sharepoint-crud&authors=@waldekmastykarz%20@AriGunawan&title=sharepoint-crud%20-%20).
<img src="https://telemetry.sharepointpnp.com/sp-dev-fx-webparts/samples/sharepoint-crud" />

View File

@ -3,7 +3,7 @@
"solution": {
"name": "sharepoint-crud-client-side-solution",
"id": "1409e8a2-1ce4-4888-87f8-1dc377b6b62e",
"version": "1.7.0.0",
"version": "1.4.0.0",
"includeClientSideAssets": true,
"skipFeatureDeployment": true,
"isDomainIsolated": false,