[react-search-refiners] Added SearchBox WP + "Result Source Id" and "Enable Query Rules" parameters (#413)
* Added the react-search-refiners folder * Updated pagination + format date for DateTime filters * Added grouped list in the filter panel + fixed some bugs * Added custom scrollbar style * Added a placeholder when the Web Part is not configured * Cleaned code * Miscellaneous fixes before PR. * Added Web Part sample images * Updated images * Adde the link to the associated blog post. * Replaced toggle by checkbox + added query template parameter. * react-search-refiners: CSS fixes * Quick fix * Updated the panel position to the left + added an overlay between each search operation to notify the user * [react-search-refiners] Updated the screenshots + npm packages * Synced the remote branch from the upstream to merge things correctly * [react-search-refiners] Removed useless files generated by the upstream merge * [react-search-refiners] Removed remaining useless files * [react-search-refiners] Added a search box and a result source Id + enable query rules parameters * [react-search-refiners] Added field descriptions * [react-search-refiners] Updated the README file + solution demo animation
This commit is contained in:
parent
e704708b02
commit
f421c5cd3b
|
@ -29,6 +29,7 @@ Version|Date|Comments
|
|||
-------|----|--------
|
||||
1.0 | October 17, 2017 | Initial release
|
||||
1.1 | January 03, 2018 | Improvements and updating to SPFx drop 1.4
|
||||
1.2 | February 12, 2018 | Added a search box Web Part + Added a "Result Source Id" and "Enable Query Rules" parameters.
|
||||
|
||||
## 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.**
|
||||
|
|
|
@ -5,15 +5,24 @@
|
|||
"search-web-part": {
|
||||
"components": [
|
||||
{
|
||||
"entrypoint": "./lib/webparts/search/SearchWebPart.js",
|
||||
"manifest": "./src/webparts/search/SearchWebPart.manifest.json"
|
||||
"entrypoint": "./lib/webparts/searchResults/SearchResultsWebPart.js",
|
||||
"manifest": "./src/webparts/searchResults/SearchResultsWebPart.manifest.json"
|
||||
}
|
||||
]
|
||||
},
|
||||
"search-box-web-part": {
|
||||
"components": [
|
||||
{
|
||||
"entrypoint": "./lib/webparts/searchBox/SearchBoxWebPart.js",
|
||||
"manifest": "./src/webparts/searchBox/SearchBoxWebPart.manifest.json"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"externals": {},
|
||||
"localizedResources": {
|
||||
"SearchWebPartStrings": "lib/webparts/search/loc/{locale}.js",
|
||||
"PropertyControlStrings": "./node_modules/@pnp/spfx-property-controls/lib/loc/{locale}.js"
|
||||
"SearchWebPartStrings": "lib/webparts/searchResults/loc/{locale}.js",
|
||||
"PropertyControlStrings": "./node_modules/@pnp/spfx-property-controls/lib/loc/{locale}.js",
|
||||
"SearchBoxWebPartStrings": "lib/webparts/searchBox/loc/{locale}.js"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
{
|
||||
"$schema": "https://dev.office.com/json-schemas/spfx-build/package-solution.schema.json",
|
||||
"solution": {
|
||||
"name": "PnP - Search and Refiners Web Part",
|
||||
"name": "PnP - Search Web Parts",
|
||||
"id": "890affef-33e0-4d72-bd72-36399e02143b",
|
||||
"version": "1.1.0.0",
|
||||
"version": "1.1.0.1",
|
||||
"includeClientSideAssets": true
|
||||
},
|
||||
"paths": {
|
||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 2.7 MiB After Width: | Height: | Size: 11 MiB |
File diff suppressed because it is too large
Load Diff
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "react-search-refiners",
|
||||
"version": "0.0.1",
|
||||
"version": "0.0.2",
|
||||
"private": true,
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
|
@ -14,8 +14,8 @@
|
|||
"@microsoft/sp-core-library": "~1.4.0",
|
||||
"@microsoft/sp-lodash-subset": "~1.4.0",
|
||||
"@microsoft/sp-webpart-base": "~1.4.0",
|
||||
"@pnp/spfx-controls-react": "^1.1.2",
|
||||
"@pnp/spfx-property-controls": "^1.2.0",
|
||||
"@pnp/spfx-controls-react": "1.2.1",
|
||||
"@pnp/spfx-property-controls": "1.3.0",
|
||||
"@types/react": "15.6.6",
|
||||
"@types/react-addons-shallow-compare": "0.14.17",
|
||||
"@types/react-addons-test-utils": "0.14.15",
|
||||
|
@ -30,7 +30,8 @@
|
|||
"react-custom-scrollbars": "4.1.2",
|
||||
"react-dom": "15.6.2",
|
||||
"react-js-pagination": "3.0.0",
|
||||
"sp-pnp-js": "3.0.3"
|
||||
"sp-pnp-js": "3.0.3",
|
||||
"@microsoft/sp-office-ui-fabric-core": "~1.4.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@microsoft/sp-build-web": "~1.4.0",
|
||||
|
@ -38,6 +39,7 @@
|
|||
"@microsoft/sp-webpart-workbench": "~1.4.0",
|
||||
"gulp": "~3.9.1",
|
||||
"@types/chai": ">=3.4.34 <3.6.0",
|
||||
"@types/mocha": ">=2.2.33 <2.6.0"
|
||||
"@types/mocha": ">=2.2.33 <2.6.0",
|
||||
"ajv": "~5.2.2"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,6 +17,16 @@ interface ISearchDataProvider {
|
|||
*/
|
||||
queryTemplate?: string;
|
||||
|
||||
/**
|
||||
* The SharePoint result source id to target
|
||||
*/
|
||||
resultSourceId?: string;
|
||||
|
||||
/**
|
||||
* Indicates wheter or not the query rules should be applied in the query
|
||||
*/
|
||||
enableQueryRules?: boolean;
|
||||
|
||||
/**
|
||||
* Perfoms a search query.
|
||||
* @returns ISearchResults object. Use the "RelevantResults" property to acces results proeprties (returned as key/value pair object => item.[<Managed property name>])
|
||||
|
|
|
@ -17,6 +17,8 @@ class SearchDataProvider implements ISearchDataProvider {
|
|||
private _appSearchSettings: SearchQuery;
|
||||
private _selectedProperties: string[];
|
||||
private _queryTemplate: string;
|
||||
private _resultSourceId: string;
|
||||
private _enableQueryRules: boolean;
|
||||
|
||||
public get resultsCount(): number { return this._resultsCount; }
|
||||
public set resultsCount(value: number) { this._resultsCount = value; }
|
||||
|
@ -27,6 +29,12 @@ class SearchDataProvider implements ISearchDataProvider {
|
|||
public set queryTemplate(value: string) { this._queryTemplate = value; }
|
||||
public get queryTemplate(): string { return this._queryTemplate; }
|
||||
|
||||
public set resultSourceId(value: string) { this._resultSourceId = value; }
|
||||
public get resultSourceId(): string { return this._resultSourceId; }
|
||||
|
||||
public set enableQueryRules(value: boolean) { this._enableQueryRules = value; }
|
||||
public get enableQueryRules(): boolean { return this._enableQueryRules; }
|
||||
|
||||
public constructor(webPartContext: IWebPartContext) {
|
||||
this._context = webPartContext;
|
||||
|
||||
|
@ -63,9 +71,16 @@ class SearchDataProvider implements ISearchDataProvider {
|
|||
searchQuery.ClientType = "ContentSearchRegular";
|
||||
searchQuery.Querytext = query;
|
||||
|
||||
// To be able to use search query variable according to the current context
|
||||
// http://www.techmikael.com/2015/07/sharepoint-rest-do-support-query.html
|
||||
searchQuery.QueryTemplate = this._queryTemplate;
|
||||
// Disable query rules by default if not specified
|
||||
searchQuery.EnableQueryRules = this._enableQueryRules ? this._enableQueryRules : false;
|
||||
|
||||
if (this._resultSourceId) {
|
||||
searchQuery.SourceId = this._resultSourceId;
|
||||
} else {
|
||||
// To be able to use search query variable according to the current context
|
||||
// http://www.techmikael.com/2015/07/sharepoint-rest-do-support-query.html
|
||||
searchQuery.QueryTemplate = this._queryTemplate;
|
||||
}
|
||||
|
||||
searchQuery.RowLimit = this._resultsCount ? this._resultsCount : 50;
|
||||
searchQuery.SelectProperties = this._selectedProperties;
|
||||
|
@ -159,7 +174,7 @@ class SearchDataProvider implements ISearchDataProvider {
|
|||
let values: IRefinementValue[] = [];
|
||||
refiner.Entries.map((item) => {
|
||||
values.push({
|
||||
RefinementCount: item.RefinementCount,
|
||||
RefinementCount: parseInt(item.RefinementCount, 10),
|
||||
RefinementName: this._formatDate(item.RefinementName), // This value will appear in the selected filter bar
|
||||
RefinementToken: item.RefinementToken,
|
||||
RefinementValue: this._formatDate(item.RefinementValue), // This value will appear in the filter panel
|
||||
|
|
|
@ -0,0 +1,29 @@
|
|||
{
|
||||
"$schema": "https://dev.office.com/json-schemas/spfx/client-side-web-part-manifest.schema.json",
|
||||
"id": "096b96cc-8a44-41fa-9b4d-c0ab2ab2a779",
|
||||
"alias": "SearchBoxWebPart",
|
||||
"componentType": "WebPart",
|
||||
|
||||
// The "*" signifies that the version should be taken from the package.json
|
||||
"version": "*",
|
||||
"manifestVersion": 2,
|
||||
|
||||
// If true, the component can only be installed on sites where Custom Script is allowed.
|
||||
// Components that allow authors to embed arbitrary script code should set this to true.
|
||||
// https://support.office.com/en-us/article/Turn-scripting-capabilities-on-or-off-1f2c515f-5d7e-448a-9fd7-835da935584f
|
||||
"requiresCustomScript": false,
|
||||
|
||||
"preconfiguredEntries": [{
|
||||
"groupId": "5c03119e-3074-46fd-976b-c60198311f70", // Other
|
||||
"group": {
|
||||
"default": "PnP"
|
||||
},
|
||||
"title": {
|
||||
"default": "Search Box" , "fr-fr": "Boîte de recherche"
|
||||
},
|
||||
"description": { "default": "Allows users to enter query keywords", "fr-fr": "Permets aux utilisateurs d'entrer des mots clés de recherche." },
|
||||
"officeFabricIconFontName": "Search",
|
||||
"properties": {
|
||||
}
|
||||
}]
|
||||
}
|
|
@ -0,0 +1,39 @@
|
|||
import * as React from 'react';
|
||||
import * as ReactDom from 'react-dom';
|
||||
import { Version } from '@microsoft/sp-core-library';
|
||||
import {
|
||||
BaseClientSideWebPart,
|
||||
IPropertyPaneConfiguration,
|
||||
PropertyPaneTextField
|
||||
} from '@microsoft/sp-webpart-base';
|
||||
|
||||
import * as strings from 'SearchBoxWebPartStrings';
|
||||
import SearchBox from './components/SearchBoxContainer';
|
||||
import { ISearchBoxProps } from './components/ISearchBoxContainerProps';
|
||||
|
||||
export interface ISearchBoxWebPartProps {
|
||||
}
|
||||
|
||||
export default class SearchBoxWebPart extends BaseClientSideWebPart<ISearchBoxWebPartProps> {
|
||||
|
||||
public render(): void {
|
||||
const element: React.ReactElement<ISearchBoxProps > = React.createElement(
|
||||
SearchBox, { });
|
||||
|
||||
ReactDom.render(element, this.domElement);
|
||||
}
|
||||
|
||||
protected get dataVersion(): Version {
|
||||
return Version.parse('1.0');
|
||||
}
|
||||
|
||||
protected getPropertyPaneConfiguration(): IPropertyPaneConfiguration {
|
||||
return {
|
||||
pages: [
|
||||
{
|
||||
groups: []
|
||||
}
|
||||
]
|
||||
};
|
||||
}
|
||||
}
|
|
@ -0,0 +1,2 @@
|
|||
export interface ISearchBoxProps {
|
||||
}
|
|
@ -0,0 +1,36 @@
|
|||
import * as React from 'react';
|
||||
import { ISearchBoxProps } from './ISearchBoxContainerProps';
|
||||
import { escape } from '@microsoft/sp-lodash-subset';
|
||||
import { SearchBox } from "office-ui-fabric-react/lib/SearchBox";
|
||||
import { Text } from "@microsoft/sp-core-library";
|
||||
import * as strings from 'SearchBoxWebPartStrings';
|
||||
|
||||
export default class SearchBoxContainer extends React.Component<ISearchBoxProps, {}> {
|
||||
|
||||
public constructor() {
|
||||
super();
|
||||
|
||||
this.onSearch = this.onSearch.bind(this);
|
||||
}
|
||||
|
||||
public render(): React.ReactElement<ISearchBoxProps> {
|
||||
return (
|
||||
<SearchBox
|
||||
onSearch={ this.onSearch }
|
||||
placeholder={ strings.SearchInputPlaceholder }
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handler when a user enters new keywords
|
||||
* @param queryText The query text entered by the user
|
||||
*/
|
||||
public onSearch(queryText: string) {
|
||||
const url = new URLSearchParams();
|
||||
url.append("k", queryText);
|
||||
|
||||
// The data parameter wil be caught by the search results WP
|
||||
history.pushState({ k: queryText}, '', Text.format("#{0}", url.toString()));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
define([], function() {
|
||||
return {
|
||||
"SearchInputPlaceholder": "Enter your search terms..."
|
||||
}
|
||||
});
|
|
@ -0,0 +1,5 @@
|
|||
define([], function() {
|
||||
return {
|
||||
"SearchInputPlaceholder": "Entrez vos termes de recherche..."
|
||||
}
|
||||
});
|
|
@ -0,0 +1,8 @@
|
|||
declare interface ISearchBoxWebPartStrings {
|
||||
SearchInputPlaceholder: string;
|
||||
}
|
||||
|
||||
declare module 'SearchBoxWebPartStrings' {
|
||||
const strings: ISearchBoxWebPartStrings;
|
||||
export = strings;
|
||||
}
|
|
@ -1,10 +1,13 @@
|
|||
export interface ISearchWebPartProps {
|
||||
export interface ISearchResultsWebPartProps {
|
||||
queryKeywords: string;
|
||||
queryTemplate: string;
|
||||
resultSourceId: string;
|
||||
enableQueryRules: boolean;
|
||||
maxResultsCount: number;
|
||||
selectedProperties: string;
|
||||
refiners: string;
|
||||
showPaging: boolean;
|
||||
showFileIcon: boolean;
|
||||
showCreatedDate: boolean;
|
||||
useSearchBoxQuery: boolean;
|
||||
}
|
|
@ -17,17 +17,19 @@
|
|||
"default": "PnP"
|
||||
},
|
||||
"title": {
|
||||
"default": "Search with Refiners"
|
||||
"default": "Search Results with Refiners", "fr-fr": "Résulats de recherche avec filtres"
|
||||
},
|
||||
"description": {
|
||||
"default": "Displays search results with customizable dynamic refiners"
|
||||
"default": "Displays search results with customizable dynamic refiners",
|
||||
"fr-fr": "Affiche des résulats de recherche avec filtres personnalisables"
|
||||
},
|
||||
"officeFabricIconFontName": "Search",
|
||||
"officeFabricIconFontName": "SearchAndApps",
|
||||
"properties": {
|
||||
"queryKeywords": "",
|
||||
"queryTemplate": "{searchTerms} Path:{Site}",
|
||||
"refiners": "Created",
|
||||
"selectedProperties": "Title,Path,Created,Filename,SiteLogo,PreviewUrl,PictureThumbnailURL,ServerRedirectedPreviewURL",
|
||||
"enableQueryRules": false,
|
||||
"maxResultsCount": 10,
|
||||
"showFileIcon": true,
|
||||
"showCreatedDate": true
|
|
@ -10,18 +10,21 @@ import {
|
|||
} from '@microsoft/sp-webpart-base';
|
||||
import { Environment, EnvironmentType } from '@microsoft/sp-core-library';
|
||||
import * as strings from 'SearchWebPartStrings';
|
||||
import SearchContainer from "./components/SearchContainer/SearchContainer";
|
||||
import ISearchContainerProps from "./components/SearchContainer/ISearchContainerProps";
|
||||
import { ISearchWebPartProps } from './ISearchWebPartProps';
|
||||
import SearchContainer from "./components/SearchResultsContainer/SearchResultsContainer";
|
||||
import ISearchContainerProps from "./components/SearchResultsContainer/ISearchResultsContainerProps";
|
||||
import { ISearchResultsWebPartProps } from './ISearchResultsWebPartProps';
|
||||
import ISearchDataProvider from "../dataProviders/ISearchDataProvider";
|
||||
import MockSearchDataProvider from "../dataProviders/MockSearchDataProvider";
|
||||
import SearchDataProvider from "../dataProviders/SearchDataProvider";
|
||||
import * as moment from "moment";
|
||||
import { Placeholder, IPlaceholderProps } from "@pnp/spfx-controls-react/lib/Placeholder";
|
||||
import { PropertyPaneCheckbox } from '@microsoft/sp-webpart-base/lib/propertyPane/propertyPaneFields/propertyPaneCheckBox/PropertyPaneCheckbox';
|
||||
import { PropertyPaneHorizontalRule } from '@microsoft/sp-webpart-base/lib/propertyPane/propertyPaneFields/propertyPaneHorizontalRule/PropertyPaneHorizontalRule';
|
||||
|
||||
export default class SearchWebPart extends BaseClientSideWebPart<ISearchWebPartProps> {
|
||||
export default class SearchWebPart extends BaseClientSideWebPart<ISearchResultsWebPartProps> {
|
||||
|
||||
private _dataProvider: ISearchDataProvider;
|
||||
private _useResultSource: boolean;
|
||||
|
||||
/**
|
||||
* Override the base onInit() implementation to get the persisted properties to initialize data provider.
|
||||
|
@ -38,11 +41,17 @@ export default class SearchWebPart extends BaseClientSideWebPart<ISearchWebPartP
|
|||
this._dataProvider = new SearchDataProvider(this.context);
|
||||
}
|
||||
|
||||
// Register an handler to catch search box queries
|
||||
this.bindPushStateEvent();
|
||||
|
||||
this._useResultSource = false;
|
||||
|
||||
return super.onInit();
|
||||
}
|
||||
|
||||
protected get disableReactivePropertyChanges(): boolean {
|
||||
return true;
|
||||
// Set this to true if you don't want the reactive behavior.
|
||||
return false;
|
||||
}
|
||||
|
||||
public render(): void {
|
||||
|
@ -52,6 +61,8 @@ export default class SearchWebPart extends BaseClientSideWebPart<ISearchWebPartP
|
|||
// Configure the provider before the query according to our needs
|
||||
this._dataProvider.resultsCount = this.properties.maxResultsCount;
|
||||
this._dataProvider.queryTemplate = this.properties.queryTemplate;
|
||||
this._dataProvider.resultSourceId = this.properties.resultSourceId;
|
||||
this._dataProvider.enableQueryRules = this.properties.enableQueryRules;
|
||||
|
||||
const searchContainer: React.ReactElement<ISearchContainerProps> = React.createElement(
|
||||
SearchContainer,
|
||||
|
@ -59,6 +70,8 @@ export default class SearchWebPart extends BaseClientSideWebPart<ISearchWebPartP
|
|||
searchDataProvider: this._dataProvider,
|
||||
queryKeywords: this.properties.queryKeywords,
|
||||
maxResultsCount: this.properties.maxResultsCount,
|
||||
resultSourceId: this.properties.resultSourceId,
|
||||
enableQueryRules: this.properties.enableQueryRules,
|
||||
selectedProperties: this.properties.selectedProperties ? this.properties.selectedProperties.replace(/\s|,+$/g, '').split(",") : [],
|
||||
refiners: this.properties.refiners,
|
||||
showPaging: this.properties.showPaging,
|
||||
|
@ -78,10 +91,9 @@ export default class SearchWebPart extends BaseClientSideWebPart<ISearchWebPartP
|
|||
}
|
||||
);
|
||||
|
||||
renderElement = this.properties.queryKeywords ? searchContainer : placeholder;
|
||||
renderElement = (this.properties.queryKeywords && !this.properties.useSearchBoxQuery) || this.properties.useSearchBoxQuery ? searchContainer : placeholder;
|
||||
|
||||
ReactDom.render(renderElement, this.domElement);
|
||||
|
||||
}
|
||||
|
||||
protected get dataVersion(): Version {
|
||||
|
@ -96,32 +108,55 @@ export default class SearchWebPart extends BaseClientSideWebPart<ISearchWebPartP
|
|||
{
|
||||
groupName: strings.SearchSettingsGroupName,
|
||||
groupFields: [
|
||||
PropertyPaneCheckbox("useSearchBoxQuery", {
|
||||
checked: false,
|
||||
text: strings.UseSearchBoxQueryLabel,
|
||||
}),
|
||||
PropertyPaneTextField('queryKeywords', {
|
||||
label: strings.SearchQueryKeywordsFieldLabel,
|
||||
description: strings.SearchQueryKeywordsFieldDescription,
|
||||
value: this.properties.queryKeywords,
|
||||
multiline: true,
|
||||
resizable: true,
|
||||
placeholder: strings.SearchQueryPlaceHolderText,
|
||||
onGetErrorMessage: this._validateEmptyField.bind(this)
|
||||
onGetErrorMessage: this._validateEmptyField.bind(this),
|
||||
deferredValidationTime: 500,
|
||||
disabled: this.properties.useSearchBoxQuery
|
||||
}),
|
||||
PropertyPaneTextField('queryTemplate', {
|
||||
label: strings.QueryTemplateFieldLabel,
|
||||
value: this.properties.queryTemplate,
|
||||
multiline: true,
|
||||
resizable: true,
|
||||
placeholder: strings.SearchQueryPlaceHolderText
|
||||
placeholder: strings.SearchQueryPlaceHolderText,
|
||||
deferredValidationTime: 300,
|
||||
disabled: this._useResultSource,
|
||||
}),
|
||||
PropertyPaneTextField('resultSourceId', {
|
||||
label: strings.ResultSourceIdLabel,
|
||||
multiline: false,
|
||||
onGetErrorMessage: this.validateSourceId.bind(this),
|
||||
deferredValidationTime: 300
|
||||
}),
|
||||
PropertyPaneToggle('enableQueryRules', {
|
||||
label: strings.EnableQueryRulesLabel,
|
||||
checked: this.properties.enableQueryRules,
|
||||
}),
|
||||
PropertyPaneTextField('selectedProperties', {
|
||||
label: strings.SelectedPropertiesFieldLabel,
|
||||
description: strings.SelectedPropertiesFieldDescription,
|
||||
multiline: true,
|
||||
resizable: true,
|
||||
value: this.properties.selectedProperties,
|
||||
deferredValidationTime: 300
|
||||
}),
|
||||
PropertyPaneTextField('refiners', {
|
||||
label: strings.RefinersFieldLabel,
|
||||
description: strings.RefinersFieldDescription,
|
||||
multiline: true,
|
||||
resizable: true,
|
||||
value: this.properties.refiners
|
||||
value: this.properties.refiners,
|
||||
deferredValidationTime: 300
|
||||
}),
|
||||
PropertyPaneSlider("maxResultsCount", {
|
||||
label: strings.MaxResultsCount,
|
||||
|
@ -130,7 +165,12 @@ export default class SearchWebPart extends BaseClientSideWebPart<ISearchWebPartP
|
|||
showValue: true,
|
||||
step: 1,
|
||||
value: 50,
|
||||
}),
|
||||
})
|
||||
]
|
||||
},
|
||||
{
|
||||
groupName: strings.StylingSettingsGroupName,
|
||||
groupFields: [
|
||||
PropertyPaneToggle("showPaging", {
|
||||
label: strings.ShowPagingLabel,
|
||||
checked: this.properties.showPaging,
|
||||
|
@ -142,7 +182,7 @@ export default class SearchWebPart extends BaseClientSideWebPart<ISearchWebPartP
|
|||
PropertyPaneToggle("showCreatedDate", {
|
||||
label: strings.ShowCreatedDateLabel,
|
||||
checked: this.properties.showCreatedDate,
|
||||
}),
|
||||
})
|
||||
]
|
||||
}
|
||||
]
|
||||
|
@ -166,4 +206,44 @@ export default class SearchWebPart extends BaseClientSideWebPart<ISearchWebPartP
|
|||
|
||||
return "";
|
||||
}
|
||||
|
||||
private bindPushStateEvent() {
|
||||
|
||||
// Original source: https://www.eliostruyf.com/check-page-mode-from-within-spfx-extensions
|
||||
|
||||
const _pushState = () => {
|
||||
const _defaultPushState = history.pushState;
|
||||
const _self = this;
|
||||
return function (data: any, title: string, url?: string | null) {
|
||||
|
||||
const currentUrl = new URLSearchParams(url);
|
||||
// We need to call the in context of the component
|
||||
// The "k" parameter is set by the search box component
|
||||
if (_self.properties.useSearchBoxQuery) {
|
||||
_self.properties.queryKeywords = data.k;
|
||||
_self.render();
|
||||
}
|
||||
// Call the original function with the provided arguments
|
||||
// This context is necessary for the context of the history change
|
||||
return _defaultPushState.apply(this, [data, title, url]);
|
||||
};
|
||||
};
|
||||
|
||||
history.pushState = _pushState();
|
||||
}
|
||||
|
||||
private validateSourceId(value: string): string {
|
||||
if(value.length > 0) {
|
||||
if (!/^(\{){0,1}[0-9a-fA-F]{8}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{12}(\}){0,1}$/.test(value)) {
|
||||
this._useResultSource = false;
|
||||
return strings.InvalidResultSourceIdMessage;
|
||||
} else {
|
||||
this._useResultSource = true;
|
||||
}
|
||||
} else {
|
||||
this._useResultSource = false;
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
}
|
|
@ -10,7 +10,7 @@ import { IRefinementResult, IRefinementValue, IRefinementFilter } from "../../..
|
|||
import { Link } from 'office-ui-fabric-react/lib/Link';
|
||||
import { Label } from 'office-ui-fabric-react/lib/Label';
|
||||
import { Text } from "@microsoft/sp-core-library";
|
||||
import "../SearchWebPart.scss";
|
||||
import "../SearchResultsWebPart.scss";
|
||||
import * as update from "immutability-helper";
|
||||
import {
|
||||
GroupedList,
|
|
@ -1,9 +1,11 @@
|
|||
import ISearchDataProvider from "../../../dataProviders/ISearchDataProvider";
|
||||
|
||||
interface ISearchContainerProps {
|
||||
interface ISearchResultsContainerProps {
|
||||
searchDataProvider: ISearchDataProvider;
|
||||
queryKeywords: string;
|
||||
maxResultsCount: number;
|
||||
resultSourceId: string;
|
||||
enableQueryRules: boolean;
|
||||
selectedProperties: string[];
|
||||
refiners: string;
|
||||
showPaging: boolean;
|
||||
|
@ -11,4 +13,4 @@ interface ISearchContainerProps {
|
|||
showCreatedDate: boolean;
|
||||
}
|
||||
|
||||
export default ISearchContainerProps;
|
||||
export default ISearchResultsContainerProps;
|
|
@ -1,6 +1,6 @@
|
|||
import { ISearchResults, IRefinementFilter, IRefinementResult } from "../../../models/ISearchResult";
|
||||
|
||||
interface ISearchContainerState {
|
||||
interface ISearchResultsContainerState {
|
||||
|
||||
/**
|
||||
* The current search results to display
|
||||
|
@ -48,4 +48,4 @@ interface ISearchContainerState {
|
|||
lastQuery: string;
|
||||
}
|
||||
|
||||
export default ISearchContainerState;
|
||||
export default ISearchResultsContainerState;
|
|
@ -1,18 +1,19 @@
|
|||
import * as React from "react";
|
||||
import ISearchContainerProps from "./ISearchContainerProps";
|
||||
import ISearchContainerState from "./ISearchContainerState";
|
||||
import ISearchContainerProps from "./ISearchResultsContainerProps";
|
||||
import ISearchContainerState from "./ISearchResultsContainerState";
|
||||
import { MessageBar, MessageBarType } from "office-ui-fabric-react/lib/MessageBar";
|
||||
import { Spinner, SpinnerSize } from "office-ui-fabric-react/lib/Spinner";
|
||||
import { Logger, LogLevel } from "sp-pnp-js";
|
||||
import * as strings from "SearchWebPartStrings";
|
||||
import { ISearchResults, IRefinementFilter } from "../../../models/ISearchResult";
|
||||
import TilesList from "../TilesList/TilesList";
|
||||
import "../SearchWebPart.scss";
|
||||
import "../SearchResultsWebPart.scss";
|
||||
import FilterPanel from "../FilterPanel/FilterPanel";
|
||||
import Paging from "../Paging/Paging";
|
||||
import { Overlay } from "office-ui-fabric-react/lib/Overlay";
|
||||
import { UrlQueryParameterCollection } from "@microsoft/sp-core-library";
|
||||
|
||||
export default class SearchContainer extends React.Component<ISearchContainerProps, ISearchContainerState> {
|
||||
export default class SearchResultsContainer extends React.Component<ISearchContainerProps, ISearchContainerState> {
|
||||
|
||||
public constructor(props) {
|
||||
super(props);
|
||||
|
@ -96,6 +97,7 @@ export default class SearchContainer extends React.Component<ISearchContainerPro
|
|||
}
|
||||
|
||||
public async componentDidMount() {
|
||||
|
||||
try {
|
||||
|
||||
this.setState({
|
||||
|
@ -139,7 +141,10 @@ export default class SearchContainer extends React.Component<ISearchContainerPro
|
|||
|| this.props.maxResultsCount !== nextProps.maxResultsCount
|
||||
|| this.state.lastQuery !== query
|
||||
|| this.props.showFileIcon !== nextProps.showFileIcon
|
||||
|| this.props.showCreatedDate !== nextProps.showCreatedDate ) {
|
||||
|| this.props.resultSourceId !== nextProps.resultSourceId
|
||||
|| this.props.showCreatedDate !== nextProps.showCreatedDate
|
||||
|| this.props.queryKeywords !== nextProps.queryKeywords
|
||||
|| this.props.enableQueryRules !== nextProps.enableQueryRules) {
|
||||
|
||||
try {
|
||||
// Clear selected filters on a new query or new refiners
|
|
@ -12,7 +12,7 @@ import {
|
|||
import { ImageFit } from 'office-ui-fabric-react/lib/Image';
|
||||
import * as moment from "moment";
|
||||
import { isEmpty } from '@microsoft/sp-lodash-subset';
|
||||
import "../SearchWebPart.scss";
|
||||
import "../SearchResultsWebPart.scss";
|
||||
|
||||
const PREVIEW_IMAGE_WIDTH: number = 204;
|
||||
const PREVIEW_IMAGE_HEIGHT: number = 111;
|
|
@ -3,7 +3,7 @@ import ITilesListViewProps from "./ITilesListViewProps";
|
|||
import { List } from 'office-ui-fabric-react/lib/List';
|
||||
import Tile from "./Tile";
|
||||
import { IRectangle } from "office-ui-fabric-react/lib/Utilities";
|
||||
import "../SearchWebPart.scss";
|
||||
import "../SearchResultsWebPart.scss";
|
||||
|
||||
const ROWS_PER_PAGE = 3;
|
||||
const MAX_ROW_HEIGHT = 300;
|
|
@ -22,6 +22,15 @@ define([], function() {
|
|||
"PlaceHolderEditLabel": "Edit",
|
||||
"PlaceHolderConfigureBtnLabel": "Configure",
|
||||
"PlaceHolderIconText": "Search Results Web Part with Refinements",
|
||||
"PlaceHolderDescription": "This component displays search results with paging and customizable refinement panel"
|
||||
"PlaceHolderDescription": "This component displays search results with paging and customizable refinement panel",
|
||||
"ResultSourceIdLabel": "Result Source Identifier",
|
||||
"InvalidResultSourceIdMessage": "Invalid identifier",
|
||||
"UseSearchBoxQueryLabel": "Use search box query",
|
||||
"EnableQueryRulesLabel": "Enable query rules",
|
||||
"StylingSettingsGroupName": "Styling options",
|
||||
"RefinersFieldDescription": "Specifies managed properties used as refiners (ordered comma-separated list).",
|
||||
"SelectedPropertiesFieldDescription": "Speficies the properties to retrieve from the search results.",
|
||||
"SearchQueryKeywordsFieldDescription": "Use pre-defined search query keywords to retrieve a static set of results."
|
||||
|
||||
}
|
||||
});
|
|
@ -22,6 +22,14 @@ define([], function() {
|
|||
"PlaceHolderEditLabel": "Éditer",
|
||||
"PlaceHolderConfigureBtnLabel": "Configurer",
|
||||
"PlaceHolderIconText": "Web Part de recherche avec affinements",
|
||||
"PlaceHolderDescription": "Ce composant affiche une liste de résulats de recherche avec pagination et des filtres configurables"
|
||||
"PlaceHolderDescription": "Ce composant affiche une liste de résulats de recherche avec pagination et des filtres configurables",
|
||||
"ResultSourceIdLabel": "Identifiant de l'origine de résultats",
|
||||
"InvalidResultSourceIdMessage": "Identifiant invalide",
|
||||
"UseSearchBoxQueryLabel": "Utiliser la requête de la boîte de recherche",
|
||||
"EnableQueryRulesLabel": "Activer les règles de requête",
|
||||
"StylingSettingsGroupName": "Options d'affichage",
|
||||
"RefinersFieldDescription": "Propriétés gerées à utiliser comme filtres (liste ordonnée séparée par une virgule)",
|
||||
"SelectedPropertiesFieldDescription": "Propriétés à récupérer des résulats de recherche.",
|
||||
"SearchQueryKeywordsFieldDescription": "Utilisez une requête de recherche prédéfinie pour obtenir un ensemble de résultats statique."
|
||||
}
|
||||
});
|
|
@ -1,12 +1,15 @@
|
|||
declare interface ISearchWebPartStrings {
|
||||
SearchSettingsGroupName: string;
|
||||
SearchQueryKeywordsFieldLabel: string;
|
||||
SearchQueryKeywordsFieldDescription: string;
|
||||
QueryTemplateFieldLabel: string;
|
||||
SelectedPropertiesFieldLabel: string;
|
||||
SelectedPropertiesFieldDescription: string;
|
||||
LoadingMessage: string;
|
||||
MaxResultsCount: string;
|
||||
NoResultMessage: string;
|
||||
RefinersFieldLabel: string;
|
||||
RefinersFieldDescription: string;
|
||||
FilterPanelTitle: string;
|
||||
FilterResultsButtonLabel: string;
|
||||
SelectedFiltersLabel: string;
|
||||
|
@ -22,6 +25,11 @@ declare interface ISearchWebPartStrings {
|
|||
PlaceHolderConfigureBtnLabel: string;
|
||||
PlaceHolderIconText: string;
|
||||
PlaceHolderDescription: string;
|
||||
ResultSourceIdLabel: string;
|
||||
InvalidResultSourceIdMessage: string;
|
||||
UseSearchBoxQueryLabel: string;
|
||||
EnableQueryRulesLabel: string;
|
||||
StylingSettingsGroupName: string;
|
||||
}
|
||||
|
||||
declare module 'SearchWebPartStrings' {
|
Loading…
Reference in New Issue