Update SPFx

This commit is contained in:
AriGunawan 2022-05-23 00:17:10 +07:00
parent 39ea25afc2
commit c2a2ec7ffd
24 changed files with 40269 additions and 9992 deletions

View File

@ -9,6 +9,7 @@ node_modules
# Build generated files
dist
lib
release
solution
temp
*.sppkg

View File

@ -0,0 +1,16 @@
!dist
config
gulpfile.js
release
src
temp
tsconfig.json
tslint.json
*.log
.yo-rc.json
.vscode

View File

@ -1,11 +1,16 @@
{
"@microsoft/generator-sharepoint": {
"plusBeta": false,
"isCreatingSolution": true,
"environment": "spo",
"version": "1.6.0",
"version": "1.14.0",
"libraryName": "image-gallery",
"libraryId": "876cbbe8-6974-4676-9da3-5c190ac8164f",
"libraryId": "e55194cd-8581-401c-b4fc-06169480813f",
"environment": "spo",
"packageManager": "npm",
"solutionName": "image-gallery",
"solutionShortDescription": "image-gallery description",
"skipFeatureDeployment": true,
"isDomainIsolated": false,
"componentType": "webpart"
}
}
}

View File

@ -1,35 +1,37 @@
# Filterable Image Gallery
## Summary
This sample describes an SPFx application which implements an image gallery with taxonomy base filtering and typed search. This application also implements pagination.
![Filterable Image Gallery web part built on the SharePoint Framework using React](./assets/image-gallery.gif)
## Used SharePoint Framework Version
![drop](https://img.shields.io/badge/version-1.6.0-green.svg)
## Compatibility
![SPFx 1.14](https://img.shields.io/badge/SPFx-1.14-green.svg)
![Node.js v14 | v12](https://img.shields.io/badge/Node.js-v14%20%7C%20v12-green.svg)
![Compatible with SharePoint Online](https://img.shields.io/badge/SharePoint%20Online-Compatible-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)
* [Microsoft 365 tenant](https://docs.microsoft.com/sharepoint/dev/spfx/set-up-your-development-environment)
## Solution
Solution|Author(s)
--------|---------
react-image-gallery | Ejaz Hussain
react-image-gallery | [Ejaz Hussain](https://github.com/ejazhussain) ([@EjazHussain_](https://twitter.com/EjazHussain_))
react-image-gallery | [Ari Gunawan](https://github.com/AriGunawan) ([@arigunawan3023](https://twitter.com/arigunawan3023))
## Version history
Version|Date|Comments
-------|----|--------
1.0|March 01, 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.**
---
1.1|May 23, 2022|Update SPFx version, update README, and fix minor issues
## Minimal Path to Awesome
@ -39,12 +41,13 @@ Version|Date|Comments
- `gulp serve`
- Create a Department Term set with associated child terms, for example, HR, Information Services, Sales, Marketing
- Create a Departments Term set with associated child terms, for example, HR, Information Services, Sales, Marketing
- Create an Image Library and add some sample images
- Tag each image with Department Metadata Column
- Also fill in Title field for each image, this is require for typed search functionality
## Features
Here are the main features for this application
- Taxonomy-based filtering
@ -52,4 +55,30 @@ Here are the main features for this application
- Right-side popup panel
- Server-side pagination using REST API
## Help
We do not support samples, but 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're having issues building the solution, please run [spfx doctor](https://pnp.github.io/cli-microsoft365/cmd/spfx/spfx-doctor/) from within the solution folder to diagnose incompatibility issues with your environment.
You can try looking at [issues related to this sample](https://github.com/pnp/sp-dev-fx-webparts/issues?q=label%3A%22sample%3A%20react-image-gallery%22) to see if anybody else is having the same issues.
You can also try looking at [discussions related to this sample](https://github.com/pnp/sp-dev-fx-webparts/discussions?discussions_q=react-image-gallery) and see what the community is saying.
If you encounter any issues 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%2Csample%3A%20react-image-gallery&template=bug-report.yml&sample=react-image-gallery&authors=@arigunawan%20@ejazhussain&title=react-image-gallery%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%3Aquestion%2Csample%3A%20react-image-gallery&template=question.yml&sample=react-image-gallery&authors=@arigunawan%20@ejazhussain&title=react-image-gallery%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%3Aenhancement%2Csample%3A%20react-image-gallery&template=suggestion.yml&sample=react-image-gallery&authors=@arigunawan%20@ejazhussain&title=react-image-gallery%20-%20).
## 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.**
<img src="https://telemetry.sharepointpnp.com/sp-dev-fx-webparts/samples/react-image-gallery" />

View File

@ -1,6 +1,6 @@
{
"$schema": "https://developer.microsoft.com/json-schemas/spfx-build/deploy-azure-storage.schema.json",
"workingDir": "./temp/deploy/",
"workingDir": "./release/assets/",
"account": "<!-- STORAGE ACCOUNT NAME -->",
"container": "image-gallery",
"accessKey": "<!-- ACCESS KEY -->"

View File

@ -3,9 +3,36 @@
"solution": {
"name": "image-gallery-client-side-solution",
"id": "876cbbe8-6974-4676-9da3-5c190ac8164f",
"version": "1.0.0.0",
"version": "1.1.0.0",
"includeClientSideAssets": true,
"skipFeatureDeployment": true
"skipFeatureDeployment": true,
"isDomainIsolated": false,
"developer": {
"name": "",
"websiteUrl": "",
"privacyUrl": "",
"termsOfUseUrl": "",
"mpnId": "Undefined-1.14.0"
},
"metadata": {
"shortDescription": {
"default": "image-gallery description"
},
"longDescription": {
"default": "image-gallery description"
},
"screenshotPaths": [],
"videoUrl": "",
"categories": []
},
"features": [
{
"title": "image-gallery Feature",
"description": "The feature that activates elements of the image-gallery solution.",
"id": "afeca86e-a632-48ce-a9eb-b5a4a3e94d85",
"version": "1.0.0.0"
}
]
},
"paths": {
"zippedPackage": "solution/image-gallery.sppkg"

View File

@ -2,9 +2,5 @@
"$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/"
}
"initialPage": "https://enter-your-SharePoint-site/_layouts/workbench.aspx"
}

View File

@ -1,7 +1,16 @@
'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);
var getTasks = build.rig.getTasks;
build.rig.getTasks = function () {
var result = getTasks.call(build.rig);
result.set('serve', result.get('serve-deprecated'));
return result;
};
build.initialize(require('gulp'));

File diff suppressed because it is too large Load Diff

23532
samples/react-image-gallery/package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

View File

@ -2,41 +2,33 @@
"name": "react-image-gallery",
"version": "0.0.1",
"private": true,
"engines": {
"node": ">=0.10.0"
},
"main": "lib/index.js",
"scripts": {
"build": "gulp bundle",
"clean": "gulp clean",
"test": "gulp test"
},
"dependencies": {
"@microsoft/sp-core-library": "1.6.0",
"@microsoft/sp-lodash-subset": "1.6.0",
"@microsoft/sp-office-ui-fabric-core": "1.6.0",
"@microsoft/sp-webpart-base": "1.6.0",
"@pnp/common": "^1.2.7",
"@pnp/graph": "^1.2.7",
"@pnp/logging": "^1.2.7",
"@pnp/odata": "^1.2.7",
"@pnp/sp": "^1.2.7",
"@pnp/spfx-controls-react": "1.11.0",
"@types/es6-promise": "0.0.33",
"@types/react": "15.6.6",
"@types/react-dom": "15.5.6",
"@types/webpack-env": "1.13.1",
"react": "15.6.2",
"react-dom": "15.6.2",
"react-js-pagination": "^3.0.2"
"@microsoft/sp-core-library": "1.14.0",
"@microsoft/sp-lodash-subset": "1.14.0",
"@microsoft/sp-office-ui-fabric-core": "1.14.0",
"@microsoft/sp-property-pane": "1.14.0",
"@microsoft/sp-webpart-base": "1.14.0",
"@pnp/spfx-controls-react": "^3.7.2",
"office-ui-fabric-react": "7.174.1",
"react": "16.13.1",
"react-dom": "16.13.1",
"react-js-pagination": "^3.0.3"
},
"devDependencies": {
"@microsoft/sp-build-web": "1.6.0",
"@microsoft/sp-module-interfaces": "1.6.0",
"@microsoft/sp-webpart-workbench": "1.6.0",
"tslint-microsoft-contrib": "~5.0.0",
"gulp": "~3.9.1",
"@types/chai": "3.4.34",
"@types/mocha": "2.2.38",
"ajv": "~5.2.2"
"@types/react": "16.9.51",
"@types/react-dom": "16.9.8",
"@microsoft/sp-build-web": "1.14.0",
"@microsoft/sp-tslint-rules": "1.14.0",
"@microsoft/sp-module-interfaces": "1.14.0",
"@microsoft/rush-stack-compiler-3.9": "0.4.47",
"gulp": "~4.0.2",
"ajv": "~5.2.2",
"@types/webpack-env": "1.13.1"
}
}

View File

@ -1,147 +1,94 @@
import { SPHttpClient, SPHttpClientResponse, ISPHttpClientOptions } from '@microsoft/sp-http';
import { reject } from 'lodash';
import { IListService, IImage } from '../Interfaces';
import { sp, spODataEntityArray, Item } from "@pnp/sp";
import Constants from '../Common/constants';
import { stringIsNullOrEmpty } from '@pnp/common';
import { SPHttpClient } from "@microsoft/sp-http";
import { IListService } from "../Interfaces";
export class ListService implements IListService {
private spHttpClient: SPHttpClient;
private spHttpClient: SPHttpClient;
constructor(spHttpClient?: SPHttpClient) {
this.spHttpClient = spHttpClient;
}
constructor(spHttpClient?: SPHttpClient) {
this.spHttpClient = spHttpClient;
public async readItems(url: string): Promise<any> {
try {
const response = await this.spHttpClient.get(
url,
SPHttpClient.configurations.v1,
{
headers: {
Accept: "application/json;odata=nometadata",
"odata-version": "",
},
}
);
const items: any = await response.json();
let result = {};
if (items.value.length) {
result = {
items: items.value,
nextLink: items["odata.nextLink"],
};
} else {
result = null;
}
return result;
} catch (error) {
return error;
}
public async readItems(url: string): Promise<any> {
try {
// return new Promise<any>(async (resolve) => {
const response = await this.spHttpClient.get(url, SPHttpClient.configurations.v1,
{
headers: {
'Accept': 'application/json;odata=nometadata',
'odata-version': ''
}
});
// this.spHttpClient.get(url, SPHttpClient.configurations.v1,
// {
// headers: {
// 'Accept': 'application/json;odata=nometadata',
// 'odata-version': ''
// }
// }).then((response: SPHttpClientResponse): Promise<{ value: number }> => {
// return response.json();
// }).then((response: { value: number }): void => {
const items: any = await response.json();
let result = {};
if (items.value.length) {
// resolve(response.value);
// });
result = {
items: items.value,
nextLink: items["odata.nextLink"]
}
}
else {
result = null;
}
return result;
// });
}
public async getListItemsCount(url: string): Promise<any> {
try {
const response = await this.spHttpClient.get(
url,
SPHttpClient.configurations.v1,
{
headers: {
Accept: "application/json;odata=nometadata",
"odata-version": "",
},
}
catch (error) {
return error;
}
);
const result: any = await response.json();
// return new Promise<any>(async (resolve) => {
// this.spHttpClient.get(url, SPHttpClient.configurations.v1,
// {
// headers: {
// 'Accept': 'application/json;odata=nometadata',
// 'odata-version': ''
// }
// }).then((response: SPHttpClientResponse): Promise<{ value: number }> => {
// return response.json();
// }).then((response: { value: number }): void => {
// resolve(response.value);
// });
// });
return result.value;
} catch (error) {
return error;
}
public async getListItemsCount(url: string): Promise<any> {
try {
const response = await this.spHttpClient.get(url, SPHttpClient.configurations.v1,
{
headers: {
'Accept': 'application/json;odata=nometadata',
'odata-version': ''
}
});
const result: any = await response.json();
return result.value;
}
catch (error) {
return error;
}
// return new Promise<any>(async (resolve) => {
// this.spHttpClient.get(url, SPHttpClient.configurations.v1,
// {
// headers: {
// 'Accept': 'application/json;odata=nometadata',
// 'odata-version': ''
// }
// }).then((response: SPHttpClientResponse): Promise<{ value: number }> => {
// return response.json();
// }).then((response: { value: number }): void => {
// resolve(response.value);
// });
// });
}
// return new Promise<any>(async (resolve) => {
// this.spHttpClient.get(url, SPHttpClient.configurations.v1,
// {
// headers: {
// 'Accept': 'application/json;odata=nometadata',
// 'odata-version': ''
// }
// }).then((response: SPHttpClientResponse): Promise<{ value: number }> => {
// return response.json();
// }).then((response: { value: number }): void => {
// resolve(response.value);
// });
// });
}
}

View File

@ -12,15 +12,18 @@
// 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", "TeamsPersonalApp", "TeamsTab", "SharePointFullPage"],
"supportsThemeVariants": true,
"preconfiguredEntries": [{
"groupId": "5c03119e-3074-46fd-976b-c60198311f70", // Other
"group": { "default": "Other" },
"title": { "default": "imageGallery" },
"description": { "default": "imageGallery description" },
"officeFabricIconFontName": "Page",
"title": { "default": "React Image Gallery" },
"description": { "default": "React component that shows image gallery from a list" },
"officeFabricIconFontName": "PhotoCollection",
"properties": {
"description": "imageGallery"
"description": "imageGallery",
"pageSize": 5
}
}]
}

View File

@ -2,17 +2,16 @@ import * as React from 'react';
import * as ReactDom from 'react-dom';
import { Version } from '@microsoft/sp-core-library';
import {
BaseClientSideWebPart,
IPropertyPaneConfiguration,
PropertyPaneTextField,
PropertyPaneSlider
} from '@microsoft/sp-webpart-base';
} from '@microsoft/sp-property-pane';
import { BaseClientSideWebPart } from '@microsoft/sp-webpart-base';
import * as strings from 'ImageGalleryWebPartStrings';
import ImageGallery from './components/ImageGallery';
import { IImageGalleryProps } from './components/IImageGalleryProps';
import ConfigureWebPart from './components/ConfigureWebPart/ConfigureWebPart';
import { sp } from '@pnp/sp';
import { ListService } from '../../Services/ListService';
export interface IImageGalleryWebPartProps {
@ -22,17 +21,12 @@ export interface IImageGalleryWebPartProps {
}
export default class ImageGalleryWebPart extends BaseClientSideWebPart<IImageGalleryWebPartProps> {
private listService: ListService
private listService: ListService;
protected async onInit(): Promise<void> {
const _ = await super.onInit();
this.listService = new ListService(this.context.spHttpClient);
sp.setup({
spfxContext: this.context
});
}
public render(): void {
@ -43,17 +37,15 @@ export default class ImageGalleryWebPart extends BaseClientSideWebPart<IImageGal
// }
// );
let element: any;
if (this.properties.imageLibrary && this.properties.pageSize) {
element = React.createElement<IImageGalleryProps>(
ImageGallery,
{
listName: this.properties.imageLibrary,
context: this.context,
siteUrl: this.context.pageContext.site.absoluteUrl,
siteUrl: this.context.pageContext.web.absoluteUrl,
pageSize: this.properties.pageSize
}
@ -72,7 +64,6 @@ export default class ImageGalleryWebPart extends BaseClientSideWebPart<IImageGal
);
}
ReactDom.render(element, this.domElement);
}
@ -83,6 +74,7 @@ export default class ImageGalleryWebPart extends BaseClientSideWebPart<IImageGal
protected get dataVersion(): Version {
return Version.parse('1.0');
}
protected get disableReactivePropertyChanges(): boolean {
return true;
}
@ -91,7 +83,6 @@ export default class ImageGalleryWebPart extends BaseClientSideWebPart<IImageGal
return {
pages: [
{
groups: [
{
groupName: strings.BasicGroupName,

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

View File

@ -1,21 +1,17 @@
import * as React from 'react';
import { IWebPartContext } from '@microsoft/sp-webpart-base';
import { WebPartContext } from '@microsoft/sp-webpart-base';
import { MessageBar, MessageBarType } from 'office-ui-fabric-react/lib/MessageBar';
import { PrimaryButton } from 'office-ui-fabric-react/lib/Button';
import styles from './ConfigureWebPart.module.scss';
export interface IConfigureWebPartProps {
webPartContext: IWebPartContext;
webPartContext: WebPartContext;
title: string;
description?: string;
buttonText?: string;
}
const ConfigureWebPart: React.SFC<IConfigureWebPartProps> = (props) => {
const ConfigureWebPart: React.FunctionComponent<IConfigureWebPartProps> = (props) => {
const {
webPartContext,
title,

View File

@ -4,10 +4,10 @@ export interface IImageGalleryState {
showPanel: boolean;
selectedImage?: IImage;
showLoader: boolean;
itemsNotFoundMessage?: string,
sQuery?: string,
dQuery?: string
itemsNotFound?: boolean,
itemsNotFoundMessage?: string;
sQuery?: string;
dQuery?: string;
itemsNotFound?: boolean;
itemCount?: number;
pageSize?: number;
currentPage?: number;

View File

@ -179,4 +179,9 @@
background-color: #fff;
border: 1px solid rgba(0, 0, 0, .125);
}
}
.filterContainer {
display: flex;
justify-content: space-between;
}

View File

@ -1,26 +1,19 @@
import * as React from 'react';
import styles from './ImageGallery.module.scss';
import { IImageGalleryProps } from './IImageGalleryProps';
import { escape } from '@microsoft/sp-lodash-subset';
import { css, classNamesFunction, IStyleFunction } from '@uifabric/utilities/lib';
import { css } from '@uifabric/utilities/lib';
import { TaxonomyPicker, IPickerTerms } from "@pnp/spfx-controls-react/lib/TaxonomyPicker";
import { TextField } from 'office-ui-fabric-react/lib/TextField';
import { IListService, IImage } from '../../../Interfaces';
import { ListService } from '../../../Services/ListService';
import { Panel, PanelType } from 'office-ui-fabric-react/lib/Panel';
import { objectDefinedNotNull, stringIsNullOrEmpty } from '@pnp/common';
import { Label } from 'office-ui-fabric-react/lib/Label';
import { Spinner, SpinnerSize } from 'office-ui-fabric-react/lib/Spinner';
import { Icon } from 'office-ui-fabric-react/lib/Icon';
import { MessageBar, MessageBarType } from 'office-ui-fabric-react/lib/MessageBar';
import { SPHttpClient, SPHttpClientResponse } from '@microsoft/sp-http';
import { Button } from 'office-ui-fabric-react/lib/Button';
import { PrimaryButton } from 'office-ui-fabric-react/lib/Button';
import { IImageGalleryState } from './IImageGalleryState';
export default class ImageGallery extends React.Component<IImageGalleryProps, IImageGalleryState> {
private _spService: IListService;
private selectQuery: string[] = [];
private expandQuery: string[] = [];
@ -41,10 +34,7 @@ export default class ImageGallery extends React.Component<IImageGalleryProps, II
pageSize: this.props.pageSize,
currentPage: 1,
nextLink: "",
}
};
this._onTaxPickerChange = this._onTaxPickerChange.bind(this);
this._onClickNext = this._onClickNext.bind(this);
@ -52,17 +42,12 @@ export default class ImageGallery extends React.Component<IImageGalleryProps, II
this._onImageClick = this._onImageClick.bind(this);
this._onSearchChange = this._onSearchChange.bind(this);
this._spService = new ListService(this.props.context.spHttpClient);
}
public async componentDidMount() {
//Get Images from the library
let value = await this._spService.getListItemsCount(`${this.props.siteUrl}/_api/web/lists/GetByTitle('${this.props.listName}')/ItemCount`);
this.setState({
itemCount: value
@ -83,17 +68,16 @@ export default class ImageGallery extends React.Component<IImageGalleryProps, II
});
let response = await this._spService.readItems(url);
if (objectDefinedNotNull(response)) {
if (objectDefinedNotNull(response.nextLink)) {
if (response) {
if (response.nextLink) {
this.urlCollection.push(response.nextLink);
}
this.setState({
showLoader: false,
items: response.items,
status: `Showing items ${(this.state.currentPage - 1) * this.props.pageSize + 1} - ${((this.state.currentPage - 1) * this.props.pageSize) + response.items.length} of ${this.state.itemCount}`
});
}
else {
this.setState({
@ -102,12 +86,10 @@ export default class ImageGallery extends React.Component<IImageGalleryProps, II
status: "",
itemsNotFound: true
});
}
}
private async _onClickNext() {
this.setState({
currentPage: this.state.currentPage + 1,
showLoader: true
@ -115,12 +97,13 @@ export default class ImageGallery extends React.Component<IImageGalleryProps, II
let url = this.urlCollection[this.urlCollection.length - 1];
this._readItems(url);
}
private async _onClickPrevious() {
let url = "";
if (this.urlCollection.length > 1) {
this.setState({
currentPage: this.state.currentPage - 1
})
});
this.urlCollection.pop();
url = this.urlCollection[this.urlCollection.length - 1];
@ -143,8 +126,6 @@ export default class ImageGallery extends React.Component<IImageGalleryProps, II
});
}
private buildQueryParams(taxQuery?: string, searchQuery?: string): string {
this.selectQuery = [];
this.expandQuery = [];
@ -179,33 +160,30 @@ export default class ImageGallery extends React.Component<IImageGalleryProps, II
return queryParam + selectColumns + filterColumns;
}
private buildFilterQuery(taxQuery: string, searchQuery: string) {
let result: string = "";
if (!stringIsNullOrEmpty(taxQuery) && stringIsNullOrEmpty(searchQuery)) {
if (!taxQuery && searchQuery) {
result = `TaxCatchAll/Term eq '${taxQuery}'`;
}
if (stringIsNullOrEmpty(taxQuery) && !stringIsNullOrEmpty(searchQuery)) {
if (taxQuery && !searchQuery) {
result = `startswith(Title,'${searchQuery}')`;
}
if (!stringIsNullOrEmpty(taxQuery) && !stringIsNullOrEmpty(searchQuery)) {
if (!taxQuery && !searchQuery) {
result = `(TaxCatchAll/Term eq '${taxQuery}') and (startswith(Title,'${searchQuery}'))`;
}
if (stringIsNullOrEmpty(taxQuery) && stringIsNullOrEmpty(searchQuery)) {
if (taxQuery && searchQuery) {
result = "";
}
return result;
}
private async _onTaxPickerChange(terms: IPickerTerms) {
private async _onTaxPickerChange(terms: IPickerTerms) {
this.urlCollection = [];
let query = "";
@ -225,9 +203,9 @@ export default class ImageGallery extends React.Component<IImageGalleryProps, II
let url = `${this.props.siteUrl}/_api/web/lists/GetByTitle('${this.props.listName}')/items/${queryParam}`;
this.urlCollection.push(url);
this._readItems(url);
}
private async _onSearchChange(query: any) {
private async _onSearchChange(event: any, query: any) {
this.urlCollection = [];
this.setState({
sQuery: query
@ -235,12 +213,10 @@ export default class ImageGallery extends React.Component<IImageGalleryProps, II
let queryParam = this.buildQueryParamsTotalFilteredItems(this.state.dQuery, query);
let response = await this._spService.readItems(`${this.props.siteUrl}/_api/web/lists/GetByTitle('${this.props.listName}')/items/${queryParam}`);
if (objectDefinedNotNull(response)) {
if (response) {
this.setState({
itemCount: response.items.length
});
}
else {
this.setState({
@ -248,12 +224,12 @@ export default class ImageGallery extends React.Component<IImageGalleryProps, II
});
}
queryParam = this.buildQueryParams(this.state.dQuery, query);
let url = `${this.props.siteUrl}/_api/web/lists/GetByTitle('${this.props.listName}')/items/${queryParam}`;
this.urlCollection.push(url);
this._readItems(url);
}
private _onImageClick(selectedImage: any): void {
this.setState({
selectedImage,
@ -263,7 +239,6 @@ export default class ImageGallery extends React.Component<IImageGalleryProps, II
}
public render(): React.ReactElement<IImageGalleryProps> {
const spinnerStyles = props => ({
circle: [
{
@ -279,13 +254,11 @@ export default class ImageGallery extends React.Component<IImageGalleryProps, II
]
});
let result = [];
let tagList;
if (this.state.items.length) {
result = this.state.items.map((item, index) => {
return (
<div key={index} className={css(styles.column, styles.mslg3)} onClick={() => this._onImageClick(item)}>
@ -295,27 +268,27 @@ export default class ImageGallery extends React.Component<IImageGalleryProps, II
<figcaption>{item.Title}</figcaption>
</div>
</div>
)
);
});
}
if (objectDefinedNotNull(this.state.selectedImage.Department)) {
if (this.state.selectedImage.Department) {
tagList = this.state.selectedImage.Department.map((tag: any, index) => {
return <li className={styles.listGroupItem} key={index}> <Icon iconName="Tag" className={styles.msIconTag} /> {tag.Label}</li>;
});
}
return (
<div className={styles.imageGallery}>
<div className={styles.container} dir="ltr">
<div className={css(styles.row, styles.header)}>
<div className={css(styles.column, styles.mslg12, styles.pageTitle)}>
<h1>Image Gallery <small> Filterable</small></h1></div>
</div>
<div className={css(styles.row, styles.filters)}>
<div className={css(styles.column, styles.mslg12, styles.panel)}>
<div className={styles.panelBody}>
<div className={css(styles.column, styles.mslg3, styles.filter)}>
<div className={styles.filterContainer}>
<div>
<TaxonomyPicker
allowMultipleSelections={false}
termsetNameOrID="Departments"
@ -325,10 +298,9 @@ export default class ImageGallery extends React.Component<IImageGalleryProps, II
onChange={this._onTaxPickerChange}
isTermSetSelectable={false}
/>
</div>
<div className={css(styles.column, styles.mslg3, "ms-u-lgPush6", styles.searchBox)}>
<TextField label="Search" className={styles.searchBoxInputField} placeholder="Enter search term" onChanged={this._onSearchChange} />
<div>
<TextField label="Search" className={styles.searchBoxInputField} placeholder="Enter search term" onChange={this._onSearchChange} />
</div>
</div>
</div>
@ -336,15 +308,12 @@ export default class ImageGallery extends React.Component<IImageGalleryProps, II
<div className={css(styles.row)}>
<div className={css(styles.column, styles.mslg12, styles.panel)}>
<div className={styles.panelBody}>
{
this.state.showLoader
? <Spinner size={SpinnerSize.large} label="loading..." className={css(styles.loader)} getStyles={spinnerStyles} />
? <Spinner size={SpinnerSize.large} label="loading..." className={css(styles.loader)} styles={spinnerStyles} />
: ""
}
<div className={css(styles.row, styles.mainContent)}>
{result.length > 0 ? result : ""}
{!result.length && this.state.itemsNotFound ? <MessageBar
messageBarType={MessageBarType.warning}
@ -375,7 +344,6 @@ export default class ImageGallery extends React.Component<IImageGalleryProps, II
</div>
</div>
</Panel>
</div>
</div>
</div>
@ -386,10 +354,10 @@ export default class ImageGallery extends React.Component<IImageGalleryProps, II
<div className={styles.status}>{this.state.status}</div>
<ul className={styles.pager}>
<li>
<Button disabled={((this.state.currentPage - 1) * this.props.pageSize + 1) <= 1} onClick={this._onClickPrevious}>Previous</Button>
<PrimaryButton disabled={((this.state.currentPage - 1) * this.props.pageSize + 1) <= 1} onClick={this._onClickPrevious}>Previous</PrimaryButton>
</li>
<li>
<Button disabled={((this.state.currentPage - 1) * this.props.pageSize) + this.state.items.length >= this.state.itemCount} onClick={this._onClickNext}>Next</Button>
<PrimaryButton disabled={((this.state.currentPage - 1) * this.props.pageSize) + this.state.items.length >= this.state.itemCount} onClick={this._onClickNext}>Next</PrimaryButton>
</li>
</ul>
@ -399,5 +367,4 @@ export default class ImageGallery extends React.Component<IImageGalleryProps, II
</div>
);
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 542 B

View File

@ -1,4 +1,5 @@
{
"extends": "./node_modules/@microsoft/rush-stack-compiler-3.9/includes/tsconfig-web.json",
"compilerOptions": {
"target": "es5",
"forceConsistentCasingInFileNames": true,
@ -10,25 +11,25 @@
"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"
"es2015.collection",
"es2015.promise"
]
},
"include": [
"src/**/*.ts"
],
"exclude": [
"node_modules",
"lib"
"src/**/*.ts",
"src/**/*.tsx"
]
}

View File

@ -1,7 +1,5 @@
{
"rulesDirectory": [
"tslint-microsoft-contrib"
],
"extends": "./node_modules/@microsoft/sp-tslint-rules/base-tslint.json",
"rules": {
"class-name": false,
"export-name": false,
@ -19,7 +17,6 @@
"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,