[react-search-refiners] Replaced string based properties by @pnp PropertyFieldCollectionData controls (#704)

* * Migrated to SPFx 1.7.0
* Fixed sort feature
* Added a sample TypeScript function to demonstrate NLP processing for the search query
* Miscelleanous improvements

* * Fixed wrong ids and dependencies

* * Updated README

* * Replaced JSOM taxonomy methods by the @pnp/sp-taxonomy counterparts + refactored refiners translation logic
* Updated the filter panel to close on click out
* Updgraded to @pnp 1.2.6
* Added a event listeners for hash change when the search box in bound to the 'URL fragment' SPFx builtin data source property so you can now build predefined filters with '#'.
* Fix suggestions panel position to be absolute

* * Quick fix on the search box

* * Added a default query option (related to https://github.com/SharePoint/sp-dev-fx-webparts/issues/556)

* * Added the ability to search by clicking on the search box icon

* * Replaced 'refiners' property by a property collection.

* * Replaced the 'sortList' WP property by a collection data control from PnP.

* * Replaced 'sortableFields' by a collection data pnp control.
This commit is contained in:
Franck Cornu 2018-12-03 14:58:46 -05:00 committed by Mikael Svenson
parent 845e7d618c
commit d9fefb7bd4
18 changed files with 270 additions and 154 deletions

View File

@ -0,0 +1,6 @@
interface IRefinerConfiguration {
refinerName: string;
displayValue: string;
}
export default IRefinerConfiguration;

View File

@ -0,0 +1,9 @@
export interface ISortFieldConfiguration {
sortField: string;
sortDirection: ISortFieldDirection;
}
export enum ISortFieldDirection {
Ascending = 1,
Descending= 2
}

View File

@ -0,0 +1,6 @@
interface ISortableFieldConfiguration {
sortField: string;
displayValue: string;
}
export default ISortableFieldConfiguration;

View File

@ -1,4 +1,5 @@
import { ISearchResults, IRefinementFilter } from '../../models/ISearchResult';
import { Sort } from '@pnp/sp';
interface ISearchService {
@ -25,7 +26,7 @@ interface ISearchService {
/**
* The sort order of the results
*/
sortList?: string;
sortList?: Sort[];
/**
* Indicates wheter or not the query rules should be applied in the query

View File

@ -21,7 +21,7 @@ class SearchService implements ISearchService {
private _selectedProperties: string[];
private _queryTemplate: string;
private _resultSourceId: string;
private _sortList: string;
private _sortList: Sort[];
private _enableQueryRules: boolean;
public get resultsCount(): number { return this._resultsCount; }
@ -36,8 +36,8 @@ class SearchService implements ISearchService {
public set resultSourceId(value: string) { this._resultSourceId = value; }
public get resultSourceId(): string { return this._resultSourceId; }
public set sortList(value: string) { this._sortList = value; }
public get sortList(): string { return this._sortList; }
public set sortList(value: Sort[]) { this._sortList = value; }
public get sortList(): Sort[] { return this._sortList; }
public set enableQueryRules(value: boolean) { this._enableQueryRules = value; }
public get enableQueryRules(): boolean { return this._enableQueryRules; }
@ -91,35 +91,7 @@ class SearchService implements ISearchService {
searchQuery.RowLimit = this._resultsCount ? this._resultsCount : 50;
searchQuery.SelectProperties = this._selectedProperties;
searchQuery.TrimDuplicates = false;
let sortList: Sort[] = [
{
Property: 'Created',
Direction: SortDirection.Descending
},
{
Property: 'Size',
Direction: SortDirection.Ascending
}
];
if (this._sortList) {
let sortDirections = this._sortList.split(',');
sortList = sortDirections.map(sorter => {
let sort = sorter.split(':');
let s: Sort = { Property: sort[0].trim(), Direction: SortDirection.Descending };
if (sort.indexOf('[') !== -1) {
s.Direction = SortDirection.FQLFormula;
}
else if (sort.length > 1) {
let direction = sort[1].trim().toLocaleLowerCase();
s.Direction = direction === "ascending" ? SortDirection.Ascending : SortDirection.Descending;
}
return s;
});
}
searchQuery.SortList = sortList;
searchQuery.SortList = this._sortList ? this._sortList : [];
if (refiners) {
// Get the refiners order specified in the property pane

View File

@ -1,5 +1,8 @@
import ResultsLayoutOption from '../../models/ResultsLayoutOption';
import { DynamicProperty } from '@microsoft/sp-component-base';
import IRefinerConfiguration from '../../models/IRefinerConfiguration';
import { ISortFieldConfiguration } from '../../models/ISortFieldConfiguration';
import ISortableFieldConfiguration from '../../models/ISortableFieldConfiguration';
export interface ISearchResultsWebPartProps {
queryKeywords: DynamicProperty<string>;
@ -7,12 +10,12 @@ export interface ISearchResultsWebPartProps {
useDefaultSearchQuery: boolean;
queryTemplate: string;
resultSourceId: string;
sortList: string;
sortList: ISortFieldConfiguration[];
enableQueryRules: boolean;
maxResultsCount: number;
selectedProperties: string;
refiners: string;
sortableFields: string;
refiners: IRefinerConfiguration[];
sortableFields: ISortableFieldConfiguration[];
showPaging: boolean;
showResultsCount: boolean;
showBlank: boolean;

View File

@ -26,7 +26,26 @@
"properties": {
"queryKeywords": "",
"queryTemplate": "{searchTerms} Path:{Site}",
"refiners": "Created:\"Created Date\",Size:\"Size of the file\"",
"sortList": [
{
"sortField": "Created",
"sortDirection": 1
},
{
"sortField": "Size",
"sortDirection": 2
}
],
"refiners": [
{
"refinerName": "Created",
"displayValue": "Created Date"
},
{
"refinerName": "Size",
"displayValue": "Size of the file"
}
],
"selectedProperties": "Title,Path,Created,Filename,SiteLogo,PreviewUrl,PictureThumbnailURL,ServerRedirectedPreviewURL,ServerRedirectedURL,HitHighlightedSummary,FileType,contentclass,ServerRedirectedEmbedURL,DefaultEncodingURL",
"enableQueryRules": false,
"maxResultsCount": 10,

View File

@ -16,7 +16,6 @@ import {
IPropertyPaneChoiceGroupOption,
PropertyPaneChoiceGroup,
PropertyPaneCheckbox,
} from '@microsoft/sp-webpart-base';
import * as strings from 'SearchResultsWebPartStrings';
import SearchResultsContainer from './components/SearchResultsContainer/SearchResultsContainer';
@ -34,7 +33,10 @@ import TaxonomyService from '../../services/TaxonomyService/TaxonomyService';
import MockTaxonomyService from '../../services/TaxonomyService/MockTaxonomyService';
import ISearchResultsContainerProps from './components/SearchResultsContainer/ISearchResultsContainerProps';
import { Placeholder, IPlaceholderProps } from '@pnp/spfx-controls-react/lib/Placeholder';
import { PropertyFieldCollectionData, CustomCollectionFieldType } from '@pnp/spfx-property-controls/lib/PropertyFieldCollectionData';
import { SPHttpClientResponse, SPHttpClient } from '@microsoft/sp-http';
import { SortDirection, Sort } from '@pnp/sp';
import { ISortFieldConfiguration, ISortFieldDirection } from '../../models/ISortFieldConfiguration';
const LOG_SOURCE: string = '[SearchResultsWebPart_{0}]';
@ -51,18 +53,12 @@ export default class SearchResultsWebPart extends BaseClientSideWebPart<ISearchR
*/
private _templateContentToDisplay: string;
constructor() {
super();
this._parseFieldListString = this._parseFieldListString.bind(this);
}
public async render(): Promise<void> {
// Configure the provider before the query according to our needs
this._searchService.resultsCount = this.properties.maxResultsCount;
this._searchService.queryTemplate = await this.replaceQueryVariables(this.properties.queryTemplate);
this._searchService.resultSourceId = this.properties.resultSourceId;
this._searchService.sortList = this.properties.sortList;
this._searchService.sortList = this._convertToSortList(this.properties.sortList);
this._searchService.enableQueryRules = this.properties.enableQueryRules;
// Determine the template content to display
@ -112,11 +108,11 @@ export default class SearchResultsWebPart extends BaseClientSideWebPart<ISearchR
queryKeywords: queryKeywords,
maxResultsCount: this.properties.maxResultsCount,
resultSourceId: this.properties.resultSourceId,
sortList: this.properties.sortList,
sortList: this._convertToSortList(this.properties.sortList),
enableQueryRules: this.properties.enableQueryRules,
selectedProperties: this.properties.selectedProperties ? this.properties.selectedProperties.replace(/\s|,+$/g, '').split(',') : [],
refiners: this._parseFieldListString(this.properties.refiners),
sortableFields: this._parseFieldListString(this.properties.sortableFields),
refiners: this.properties.refiners,
sortableFields: this.properties.sortableFields,
showPaging: this.properties.showPaging,
showResultsCount: this.properties.showResultsCount,
showBlank: this.properties.showBlank,
@ -156,6 +152,8 @@ export default class SearchResultsWebPart extends BaseClientSideWebPart<ISearchR
protected async onInit(): Promise<void> {
this.initializeRequiredProperties();
if (Environment.type === EnvironmentType.Local) {
this._searchService = new MockSearchService();
this._taxonomyService = new MockTaxonomyService();
@ -177,6 +175,32 @@ export default class SearchResultsWebPart extends BaseClientSideWebPart<ISearchR
return super.onInit();
}
private _convertToSortList(sortList: ISortFieldConfiguration[]): Sort[] {
return sortList.map(e => {
let direction;
switch (e.sortDirection) {
case ISortFieldDirection.Ascending:
direction = SortDirection.Ascending;
break;
case ISortFieldDirection.Descending:
direction = SortDirection.Descending;
break;
default:
direction = SortDirection.Ascending;
break;
}
return {
Property: e.sortField,
Direction: direction
} as Sort;
});
}
protected onDispose(): void {
ReactDom.unmountComponentAtNode(this.domElement);
}
@ -185,6 +209,37 @@ export default class SearchResultsWebPart extends BaseClientSideWebPart<ISearchR
return Version.parse('1.0');
}
/**
* Initializes the Web Part required properties if there are not present in the manifest (i.e. during an update scenario)
*/
private initializeRequiredProperties() {
this.properties.queryTemplate = this.properties.queryTemplate ? this.properties.queryTemplate : "{searchTerms} Path:{Site}";
this.properties.refiners = Array.isArray(this.properties.refiners) ? this.properties.refiners : [
{
refinerName: "Created",
displayValue: "Created Date"
},
{
refinerName: "Size",
displayValue: "Size of the file"
}
];
this.properties.sortList = Array.isArray(this.properties.sortList) ? this.properties.sortList : [
{
sortField: "Created",
sortDirection: ISortFieldDirection.Ascending
},
{
sortField: "Size",
sortDirection: ISortFieldDirection.Descending
}
];
this.properties.sortableFields = Array.isArray(this.properties.sortableFields) ? this.properties.sortableFields : [];
this.properties.selectedProperties = this.properties.selectedProperties ? this.properties.selectedProperties : "Title,Path,Created,Filename,SiteLogo,PreviewUrl,PictureThumbnailURL,ServerRedirectedPreviewURL,ServerRedirectedURL,HitHighlightedSummary,FileType,contentclass,ServerRedirectedEmbedURL,DefaultEncodingURL";
this.properties.maxResultsCount = this.properties.maxResultsCount ? this.properties.maxResultsCount : 10;
}
protected getPropertyPaneConfiguration(): IPropertyPaneConfiguration {
return {
@ -300,39 +355,6 @@ export default class SearchResultsWebPart extends BaseClientSideWebPart<ISearchR
return '';
}
/**
* Parses a list of Fields from the property pane value by extracting the managed property and its label.
* @param rawValue the raw value of the refiner
*/
private _parseFieldListString(rawValue: string): { [key: string]: string } {
let returnValues = {};
if(!rawValue) { return returnValues; }
// Get each configuration
let refinerKeyValuePair = rawValue.split(',');
if (refinerKeyValuePair.length > 0) {
refinerKeyValuePair.map((e) => {
const refinerValues = e.split(':');
switch (refinerValues.length) {
case 1:
// Take the same name as the refiner managed property
returnValues[refinerValues[0]] = refinerValues[0];
break;
case 2:
// Trim quotes if present
returnValues[refinerValues[0]] = refinerValues[1].replace(/^'(.*)'$/, '$1');
break;
}
});
}
return returnValues;
}
/**
* Get the correct results template content according to the property pane current configuration
* @returns the template content as a string
@ -495,21 +517,60 @@ export default class SearchResultsWebPart extends BaseClientSideWebPart<ISearchR
onGetErrorMessage: this.validateSourceId.bind(this),
deferredValidationTime: 300
}),
PropertyPaneTextField('sortList', {
label: strings.Sort.SortList,
description: strings.Sort.SortListDescription,
multiline: false,
resizable: true,
PropertyFieldCollectionData('sortList', {
manageBtnLabel: strings.ConfigureBtnLabel,
key: 'sortList',
panelHeader: strings.Sort.SortPropertyPaneFieldLabel,
panelDescription: strings.Sort.SortListDescription,
label: strings.Sort.SortPropertyPaneFieldLabel,
value: this.properties.sortList,
deferredValidationTime: 300
fields: [
{
id: 'sortField',
title: "Field name",
type: CustomCollectionFieldType.string,
required: true,
placeholder: '\"Created\", \"Size\", etc.'
},
{
id: 'sortDirection',
title: "Direction",
type: CustomCollectionFieldType.dropdown,
required: true,
options: [
{
key: ISortFieldDirection.Ascending,
text: strings.Sort.SortDirectionAscendingLabel
},
{
key: ISortFieldDirection.Descending,
text: strings.Sort.SortDirectionDescendingLabel
}
]
}
]
}),
PropertyPaneTextField('sortableFields', {
label: strings.SortableFieldsLabel,
description: strings.SortableFieldsDescription,
multiline: true,
resizable: true,
PropertyFieldCollectionData('sortableFields', {
manageBtnLabel: strings.ConfigureBtnLabel,
key: 'sortableFields',
panelHeader: strings.Sort.SortableFieldsPropertyPaneField,
panelDescription: strings.Sort.SortableFieldsDescription,
label: strings.Sort.SortableFieldsPropertyPaneField,
value: this.properties.sortableFields,
deferredValidationTime: 300,
fields: [
{
id: 'sortField',
title: strings.Sort.SortableFieldManagedPropertyField,
type: CustomCollectionFieldType.string,
placeholder: '\"Created\", \"Size\", etc.',
required: true
},
{
id: 'displayValue',
title: strings.Sort.SortableFieldDisplayValueField,
type: CustomCollectionFieldType.string
}
]
}),
PropertyPaneToggle('enableQueryRules', {
label: strings.EnableQueryRulesLabel,
@ -523,13 +584,26 @@ export default class SearchResultsWebPart extends BaseClientSideWebPart<ISearchR
value: this.properties.selectedProperties,
deferredValidationTime: 300
}),
PropertyPaneTextField('refiners', {
label: strings.RefinersFieldLabel,
description: strings.RefinersFieldDescription,
multiline: true,
resizable: true,
PropertyFieldCollectionData('refiners', {
manageBtnLabel: strings.ConfigureBtnLabel,
key: 'refiners',
panelHeader: strings.Refiners.RefinersFieldLabel,
panelDescription: strings.Refiners.RefinersFieldDescription,
label: strings.Refiners.RefinersFieldLabel,
value: this.properties.refiners,
deferredValidationTime: 300,
fields: [
{
id: 'refinerName',
title: strings.Refiners.RefinerManagedPropertyField,
type: CustomCollectionFieldType.string,
placeholder: '\"RefinableStringXXX\", etc.'
},
{
id: 'displayValue',
title: strings.Refiners.RefinerDisplayValueField,
type: CustomCollectionFieldType.string
}
]
}),
PropertyPaneSlider('maxResultsCount', {
label: strings.MaxResultsCount,

View File

@ -48,9 +48,14 @@ export default class FilterPanel extends React.Component<IFilterPanelProps, IFil
// Initialize the Office UI grouped list
this.props.availableFilters.map((filter, i) => {
// Get group name
let groupName = filter.FilterName;
const configuredFilter = this.props.refinersConfiguration.filter(e => { return e.refinerName === filter.FilterName;});
groupName = configuredFilter.length > 0 && configuredFilter[0].displayValue ? configuredFilter[0].displayValue : groupName;
groups.push({
key: i.toString(),
name: this.props.refinersConfiguration[filter.FilterName],
name: groupName,
count: 1,
startIndex: i,
isDropEnabled: true,

View File

@ -1,9 +1,10 @@
import { IRefinementResult } from '../../../../models/ISearchResult';
import RefinementFilterOperationCallback from '../../../../models/RefinementValueOperationCallback';
import IRefinerConfiguration from '../../../../models/IRefinerConfiguration';
interface IFilterPanelProps {
availableFilters: IRefinementResult[];
refinersConfiguration: { [key: string]: string };
refinersConfiguration: IRefinerConfiguration[];
onUpdateFilters: RefinementFilterOperationCallback;
resetSelectedFilters: boolean;
}

View File

@ -3,6 +3,9 @@ import ITaxonomyService from '../../../../services/TaxonomyService/ITaxonomyServ
import { DisplayMode } from '@microsoft/sp-core-library';
import TemplateService from '../../../../services/TemplateService/TemplateService';
import { WebPartContext } from '@microsoft/sp-webpart-base';
import IRefinerConfiguration from '../../../../models/IRefinerConfiguration';
import { Sort } from '@pnp/sp';
import ISortableFieldConfiguration from '../../../../models/ISortableFieldConfiguration';
interface ISearchResultsContainerProps {
@ -39,7 +42,7 @@ interface ISearchResultsContainerProps {
/**
* The sort order of the results
*/
sortList: string;
sortList: Sort[];
/**
* Enable SharePoint query rules
@ -54,12 +57,12 @@ interface ISearchResultsContainerProps {
/**
* The managed properties used as refiners for the query
*/
refiners: { [key: string]: string };
refiners: IRefinerConfiguration[];
/**
* The managed properties used as sortable fields for the query
*/
sortableFields: { [key: string]: string };
sortableFields: ISortableFieldConfiguration[];
/**
* Show the paging control

View File

@ -179,7 +179,7 @@ export default class SearchResultsContainer extends React.Component<ISearchConta
this.props.searchService.selectedProperties = this.props.selectedProperties;
const refinerManagedProperties = Object.keys(this.props.refiners).join(',');
const refinerManagedProperties = this.props.refiners.map(e => { return e.refinerName ;}).join(',');
const searchResults = await this.props.searchService.search(this.props.queryKeywords, refinerManagedProperties, this.state.selectedFilters, this.state.currentPage);
const localizedFilters = await this._getLocalizedFilters(searchResults.RefinementResults);
@ -245,10 +245,10 @@ export default class SearchResultsContainer extends React.Component<ISearchConta
this.props.searchService.selectedProperties = nextProps.selectedProperties;
const refinerManagedProperties = Object.keys(nextProps.refiners).join(',');
const refinerManagedProperties = nextProps.refiners.map(e => { return e.refinerName ;}).join(',');
// Reset sortlist
this.props.searchService.sortList = this.props.sortList;
this.props.searchService.sortList = nextProps.sortList;
// We reset the page number and refinement filters
const searchResults = await this.props.searchService.search(nextProps.queryKeywords, refinerManagedProperties, [], 1);
@ -322,7 +322,7 @@ export default class SearchResultsContainer extends React.Component<ISearchConta
areResultsLoading: true,
});
const refinerManagedProperties = Object.keys(this.props.refiners).join(',');
const refinerManagedProperties = this.props.refiners.map(e => { return e.refinerName ;}).join(',');
const searchResults = await
this.props.searchService.search(this.props.queryKeywords, refinerManagedProperties, newFilters, 1);
@ -353,9 +353,9 @@ export default class SearchResultsContainer extends React.Component<ISearchConta
errorMessage:null
});
const refinerManagedProperties = Object.keys(this.props.refiners).join(',');
const refinerManagedProperties = this.props.refiners.map(e => { return e.refinerName ;}).join(',');
this.props.searchService.sortList = `${sortField}:${SortDirection[sortDirection].toLocaleLowerCase()}`;
this.props.searchService.sortList = [{Property: sortField, Direction: sortDirection}];
try
{
@ -391,7 +391,7 @@ export default class SearchResultsContainer extends React.Component<ISearchConta
areResultsLoading: true,
});
const refinerManagedProperties = Object.keys(this.props.refiners).join(',');
const refinerManagedProperties = this.props.refiners.map(e => { return e.refinerName ;}).join(',');
const searchResults = await this.props.searchService.search(this.props.queryKeywords, refinerManagedProperties, this.state.selectedFilters, pageNumber);

View File

@ -30,6 +30,11 @@
color: "[theme: themePrimary, default: #005a9e]";
}
&__sortDropdown {
min-width: 135px;
max-width: 200px;
}
&__sortResultBtn {
color: "[theme: themePrimary]";
}

View File

@ -1,8 +1,9 @@
import UpdateSortOperationCallback from '../../../../models/UpdateSortOperationCallback';
import { SortDirection } from "@pnp/sp";
import ISortableFieldConfiguration from '../../../../models/ISortableFieldConfiguration';
interface ISortPanelProps {
sortableFieldsConfiguration: { [key: string]: string };
sortableFieldsConfiguration: ISortableFieldConfiguration[];
onUpdateSort: UpdateSortOperationCallback;
sortDirection?:SortDirection;
sortField?:string;

View File

@ -4,7 +4,7 @@ import ISortPanelState from './ISortP
import { Dropdown, IDropdownOption } from 'office-ui-fabric-react/lib/Dropdown';
import * as strings from 'SearchResultsWebPartStrings';
import { ActionButton } from 'office-ui-fabric-react/lib/Button';
import { SortDirection } from "@pnp/sp";
import { SortDirection } from '@pnp/sp';
import styles from '../SearchResultsWebPart.module.scss';
export default class SortPanel extends React.Component<ISortPanelProps, ISortPanelState> {
@ -17,14 +17,13 @@ export default class SortPanel extends React.Component<ISortPanelProps, ISortPan
sortField:this.props.sortField ? this.props.sortField : null
};
this._getSortableFieldCount = this._getSortableFieldCount.bind(this);
this._setSortDirection = this._setSortDirection.bind(this);
this._getDropdownOptions = this._getDropdownOptions.bind(this);
this._onChangedSelectedField = this._onChangedSelectedField.bind(this);
}
public render(): React.ReactElement<ISortPanelProps> {
if (this._getSortableFieldCount() === 0) return <span />;
if (this.props.sortableFieldsConfiguration.length === 0) return <span />;
const dropdownOptions: IDropdownOption[] = this._getDropdownOptions();
@ -42,6 +41,7 @@ export default class SortPanel extends React.Component<ISortPanelProps, ISortPan
}}
/>
<Dropdown
className={ styles.searchWp__sortDropdown }
placeHolder={strings.Sort.SortPanelSortFieldPlaceHolder}
ariaLabel={strings.Sort.SortPanelSortFieldAria}
onChanged={this._onChangedSelectedField}
@ -52,14 +52,6 @@ export default class SortPanel extends React.Component<ISortPanelProps, ISortPan
);
}
private _getSortableFieldCount() {
if(!this.props.sortableFieldsConfiguration) return 0;
return Object.keys(this.props.sortableFieldsConfiguration).filter(value => {
return value;
}).length;
}
private _setSortDirection() {
let sortDirection;
@ -86,14 +78,16 @@ export default class SortPanel extends React.Component<ISortPanelProps, ISortPan
}
private _getDropdownOptions():IDropdownOption[] {
let dropdownOptions:IDropdownOption[] = [];
const sortableFields = Object.keys(this.props.sortableFieldsConfiguration);
sortableFields.forEach((fieldKey) => {
//Strip " from start and end of the display name if present
const fieldDisplayName = this.props.sortableFieldsConfiguration[fieldKey].replace(/^\"+|\"+$/g, '');
dropdownOptions.push({ key: fieldKey, text: fieldDisplayName});
let dropdownOptions:IDropdownOption[] = [];
this.props.sortableFieldsConfiguration.map(e => {
dropdownOptions.push({
key: e.sortField,
text: e.displayValue
});
});
return dropdownOptions;
}

View File

@ -8,12 +8,8 @@ define([], function() {
"LoadingMessage": "Results are loading, please wait...",
"MaxResultsCount": "Number of items to retrieve per page",
"NoResultMessage": "There are no results to show",
"RefinersFieldLabel": "Refiners",
"SortableFieldsLabel": "Sortable fields",
"FilterPanelTitle": "Available filters",
"SortPanelTitle":"Sort",
"FilterResultsButtonLabel": "Filters",
"SortResultsButtonLabel":"Sort",
"SelectedFiltersLabel": "Selected filters:",
"RemoveAllFiltersLabel": "Remove all filters",
"ShowPagingLabel": "Show paging",
@ -31,8 +27,6 @@ define([], function() {
"InvalidResultSourceIdMessage": "Invalid identifier",
"EnableQueryRulesLabel": "Enable query rules",
"StylingSettingsGroupName": "Styling options",
"RefinersFieldDescription": "Specifies managed properties used as refiners (ordered comma-separated list). You can specify the label by using the following format <Managed Property Name>:\"My friendly name\".",
"SortableFieldsDescription": "Specifies sortable properties used by the sort panel (ordered comma-separated list). You can specify the label by using the following format <Managed Property Name>:\"My friendly name\".",
"SelectedPropertiesFieldDescription": "Speficies the properties to retrieve from the search results.",
"SearchQueryKeywordsFieldDescription": "Use pre-defined search query keywords to retrieve a static set of results.",
"CountMessageLong": "<b>{0}</b> results for '<em>{1}</em>'",
@ -54,8 +48,10 @@ define([], function() {
"PromotedResultsLabel": "Promoted result(s)",
"PanelCloseButtonAria":"Close",
"Sort": {
"SortList": "Initial sort order",
"SortListDescription": "Specify initial sort order in a comma separated list on the format <Managed Property Name>:ascending/descending (default:Created:descending,Size:ascending).",
"SortableFieldsPropertyPaneField": "Sortable properties",
"SortableFieldsDescription": "Specifies sortable properties that users can use in the UI. Only one property can be used at a time for sorting and will override the search order specified in the WP if exists.",
"SortPropertyPaneFieldLabel": "Sort order",
"SortListDescription": "Specify the sort order for the search results. This will only applied when no manual filters have been set (i.e. sortable fields)",
"SortDirectionAscendingLabel":"Ascending",
"SortDirectionDescendingLabel":"Descending",
"SortErrorMessage":"Invalid search property (Check if the managed property is sortable).",
@ -63,10 +59,19 @@ define([], function() {
"SortPanelSortFieldAria":"Select a field",
"SortPanelSortFieldPlaceHolder":"Select a field",
"SortPanelSortDirectionLabel":"Sort Direction",
"SortableFieldManagedPropertyField": "Sort managed property",
"SortableFieldDisplayValueField": "Field name to display"
},
"Refiners": {
"RefinersFieldLabel": "Refiners",
"RefinerManagedPropertyField": "Filter managed property",
"RefinerDisplayValueField": "Filter name to display",
"RefinersFieldDescription": "Specifies managed properties used as refiners. If there are no values for a filter property, it won't appear in the panel.",
},
"TermNotFound": "(Term with ID '{0}' not found)",
"UseDefaultSearchQueryKeywordsFieldLabel": "Use a default search query",
"DefaultSearchQueryKeywordsFieldLabel": "Default search query",
"DefaultSearchQueryKeywordsFieldDescription": "This query will be used when the data source value is still empty."
"DefaultSearchQueryKeywordsFieldDescription": "This query will be used when the data source value is still empty.",
"ConfigureBtnLabel": "Configure"
}
});

View File

@ -8,12 +8,8 @@ define([], function() {
"LoadingMessage": "Les résultats sont en cours de chargement, veuillez patienter...",
"MaxResultsCount": "Nombre de résulats à récupérer par page",
"NoResultMessage": "Il n'y a aucun résultat à afficher.",
"RefinersFieldLabel": "Filtres",
"SortableFieldsLabel": "Triables",
"FilterPanelTitle": "Filtres disponibles",
"SortPanelTitle":"Trier",
"FilterResultsButtonLabel": "Filtrer",
"SortResultsButtonLabel":"Trier",
"SelectedFiltersLabel": "Filtre(s) appliqué(s):",
"RemoveAllFiltersLabel": "Supprimer tous les filtres",
"ShowPagingLabel": "Afficher la pagination",
@ -31,8 +27,6 @@ define([], function() {
"InvalidResultSourceIdMessage": "Identifiant invalide",
"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). Vous pouvez spécifier un label personnalisé en utilisant le format suivant <Nom de la propriété gérée>:\"Nom convivial\".",
"SortableFieldsDescription": "Propriétés gerées à utiliser comme triables (liste ordonnée séparée par une virgule). Vous pouvez spécifier un label personnalisé en utilisant le format suivant <Nom de la propriété gérée>:\"Nom convivial\".",
"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.",
"CountMessageLong": "<b>{0}</b> résultats pour '<em>{1}</em>'",
@ -54,8 +48,10 @@ define([], function() {
"PromotedResultsLabel": "Résultat(s) promu(s)",
"PanelCloseButtonAria":"Proche",
"Sort": {
"SortList": "Ordre de tri",
"SortListDescription": "Spécifiez l'ordre de tri dans une liste séparée par des virgules au format <Nom de la propriété gérée>:ascending/descending (par défaut:Created:descending,Size:ascending).",
"SortableFieldsPropertyPaneField":"Propriétés triables",
"SortableFieldsDescription": "Propriétés à utiliser pour permettre aux utilisateurs de trier les résultats depuis l'interface. Le tri ne peut être porter que sur une seule propriété à la fois et surpasse le tri par défaut des résulats si existant.",
"SortPropertyPaneFieldLabel":"Ordre de tri",
"SortListDescription": "Spécifiez l'ordre de tri des résultats de recherche. Ceux-ci ne s'appliqueront que si aucun champ de tri n'a été configurée pour ce Web Part (i.e propriétés triables)",
"SortDirectionAscendingLabel":"Ascendant",
"SortDirectionDescendingLabel":"Descendant",
"SortErrorMessage":"Propriété de recherche non valide (Vérifiez si la propriété managée est triable).",
@ -63,10 +59,19 @@ define([], function() {
"SortPanelSortFieldAria":"Sélectionner un champ",
"SortPanelSortFieldPlaceHolder":"Sélectionner un champ",
"SortPanelSortDirectionLabel":"Direction de tri",
"SortableFieldManagedPropertyField": "Propriété gérée de tri",
"SortableFieldDisplayValueField": "Intitulé du champ à afficher"
},
"Refiners": {
"RefinersFieldLabel": "Filtres",
"RefinersFieldDescription": "Configurez ici les propriétés gerées à utiliser comme filtres. Si il n'existe pas de valeurs pour le filtre spécifié, il n'apparaîtra pas dans le panneau.",
"RefinerManagedPropertyField": "Propriété gérée de filtre",
"RefinerDisplayValueField": "Intitulé du filtre à afficher",
},
"TermNotFound": "(Terme avec l'ID '{0}' non trouvé)",
"UseDefaultSearchQueryKeywordsFieldLabel": "Utiliser une requête initiale",
"DefaultSearchQueryKeywordsFieldLabel": "Requête de recherche par défaut",
"DefaultSearchQueryKeywordsFieldDescription": "Cette requête sera utilisée par défault dans le cas où la valeur de la source de données est encore vide."
"DefaultSearchQueryKeywordsFieldDescription": "Cette requête sera utilisée par défault dans le cas où la valeur de la source de données est encore vide.",
"ConfigureBtnLabel": "Configurer"
}
});

View File

@ -9,14 +9,10 @@ declare interface ISearchResultsWebPartStrings {
LoadingMessage: string;
MaxResultsCount: string;
NoResultMessage: string;
RefinersFieldLabel: string;
SortableFieldsLabel: string;
RefinersFieldDescription: string;
SortableFieldsDescription: string;
FilterPanelTitle: string;
SortPanelTitle: string;
FilterResultsButtonLabel: string;
SortResultsButtonLabel:string;
SelectedFiltersLabel: string;
RemoveAllFiltersLabel: string;
ShowPagingLabel: string;
@ -52,8 +48,9 @@ declare interface ISearchResultsWebPartStrings {
HandlebarsHelpersDescription: string;
PromotedResultsLabel: string;
PanelCloseButtonAria:string;
ConfigureBtnLabel: string;
Sort: {
SortList: string;
SortPropertyPaneFieldLabel
SortListDescription: string;
SortDirectionAscendingLabel:string;
SortDirectionDescendingLabel:string;
@ -62,6 +59,16 @@ declare interface ISearchResultsWebPartStrings {
SortPanelSortFieldAria:string;
SortPanelSortFieldPlaceHolder:string;
SortPanelSortDirectionLabel:string;
SortableFieldsPropertyPaneField: string;
SortableFieldsDescription: string;
SortableFieldManagedPropertyField: string;
SortableFieldDisplayValueField: string;
},
Refiners: {
RefinersFieldLabel: string;
RefinersFieldDescription: string;
RefinerManagedPropertyField: string;
RefinerDisplayValueField: string;
},
TermNotFound: string;
UseDefaultSearchQueryKeywordsFieldLabel: string;