@pnp/spfx-property-controls
Version:
Reusable property pane controls for SharePoint Framework solutions
298 lines • 17.1 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const tslib_1 = require("tslib");
const React = tslib_1.__importStar(require("react"));
const WebSearchTab_types_1 = require("./WebSearchTab.types");
const react_1 = require("@fluentui/react");
const GeneralHelper_1 = require("../../../../helpers/GeneralHelper");
const WebSearchTab_module_scss_1 = tslib_1.__importDefault(require("./WebSearchTab.module.scss"));
const strings = tslib_1.__importStar(require("PropertyControlStrings"));
/**
* Renders search suggestions and performs seach queries
*/
class WebSearchTab extends React.Component {
constructor(props) {
super(props);
this._listElem = undefined;
this._onSelectionChanged = () => {
// Get the selected item
const selectedItems = this._selection.getSelection();
const filePickerResult = this.state.filePickerResult;
let selectedFileResult = null;
if (selectedItems && selectedItems.length > 0) {
//Get the selected key
const selectedItem = selectedItems[0];
//Brute force approach to making sure all URLs are loading over HTTPS
// even if it breaks the page.
const selectedUrl = selectedItem.contentUrl.replace('http://', 'https://');
selectedFileResult = {
fileAbsoluteUrl: selectedUrl,
fileName: GeneralHelper_1.GeneralHelper.getFileNameFromUrl(selectedUrl),
fileNameWithoutExtension: GeneralHelper_1.GeneralHelper.getFileNameWithoutExtension(selectedUrl),
downloadFileContent: () => {
return this.props.bingSearchService.downloadBingContent(selectedUrl, GeneralHelper_1.GeneralHelper.getFileNameFromUrl(selectedUrl));
},
};
}
// If clicked on already selected file -> deselect it
if (filePickerResult &&
selectedFileResult &&
filePickerResult.fileAbsoluteUrl === selectedFileResult.fileAbsoluteUrl) {
this._selection.setAllSelected(false);
selectedFileResult = null;
}
// Save the selected file
this.setState({
filePickerResult: selectedFileResult,
});
if (this._listElem) {
// Force the list to update to show the selection check
this._listElem.forceUpdate();
}
};
/**
* Renders the returned search results
*/
this._renderSearchResults = () => {
const { results } = this.state;
// If there are no results, tell 'em.
if (results === undefined || results.length < 1) {
return (React.createElement(react_1.Label, { className: WebSearchTab_module_scss_1.default.noResultLabel }, strings.NoResultsBadEnglish));
}
return (React.createElement(react_1.FocusZone, null,
React.createElement(react_1.SelectionZone, { selection: this._selection, onItemInvoked: (item) => {
if (item)
this._selection.setKeySelected(item.key, true, true);
} },
React.createElement(react_1.List, { ref: this._linkElement, className: WebSearchTab_module_scss_1.default.bingGrildList, items: this.state.results, getItemCountForPage: this._getItemCountForPage, getPageHeight: this._getPageHeight, renderedWindowsAhead: 4, onRenderCell: this._onRenderSearchResultsCell }))));
};
/**
* Show an individual search result item
*/
this._onRenderSearchResultsCell = (item, index) => {
const { query } = this.state;
let isSelected = false;
if (this._selection && index !== undefined) {
isSelected = this._selection.isIndexSelected(index);
}
// The logic for calculating the thumbnail dimensions is not quite the same as the out-of-the-box file picker,
// but it'll have to do.
// Find the aspect ratio of the picture
const ratio = item.width / item.height;
// Fit the height to the desired row height
const thumbnailHeight = Math.min(this._rowHeight, item.height);
// Resize the picture with the same aspect ratio
const thumbnailWidth = thumbnailHeight * ratio;
const searchResultAltText = strings.SearchResultAlt.replace('{0}', query);
return (React.createElement("div", { className: WebSearchTab_module_scss_1.default.bingGridListCell, style: {
width: 100 / this._columnCount + '%',
} },
React.createElement("div", { "aria-label": searchResultAltText, className: (0, react_1.css)(WebSearchTab_module_scss_1.default.bingTile, isSelected ? WebSearchTab_module_scss_1.default.isSelected : undefined), "data-is-focusable": true, "data-selection-index": index, style: {
width: `${thumbnailWidth}px`,
height: `${thumbnailHeight}px`,
} },
React.createElement("div", { className: WebSearchTab_module_scss_1.default.bingTileContent, "data-selection-invoke": true },
React.createElement(react_1.Image, { src: item.thumbnailUrl, className: WebSearchTab_module_scss_1.default.bingTileThumbnail, alt: searchResultAltText, width: thumbnailWidth, height: thumbnailHeight }),
React.createElement("div", { className: WebSearchTab_module_scss_1.default.bingTileFrame }),
React.createElement("div", { className: WebSearchTab_module_scss_1.default.bingTileCheckCircle, role: 'checkbox', "aria-checked": isSelected, "data-item-index": index, "data-selection-toggle": true, "data-automationid": 'CheckCircle' },
React.createElement(react_1.Check, { checked: isSelected })),
React.createElement("div", { className: WebSearchTab_module_scss_1.default.bingTileNamePlate },
React.createElement(react_1.Link, { href: item.contentUrl, target: '_blank', "aria-label": strings.SearchResultAriaLabel }, item.displayUrl))))));
};
/**
* Renders suggestions when there aren't any queries
*/
this._renderSearchSuggestions = () => {
const suggestions = this.props.suggestions !== undefined
? this.props.suggestions
: WebSearchTab_types_1.DEFAULT_SUGGESTIONS;
return (React.createElement(react_1.FocusZone, null,
React.createElement(react_1.List, { className: WebSearchTab_module_scss_1.default.filePickerFolderCardGrid, items: suggestions, getItemCountForPage: this._getItemCountForPage, getPageHeight: this._getPageHeight, renderedWindowsAhead: 4, onRenderCell: this._onRenderSuggestionCell })));
};
/**
* Gets search results from Bing
*/
this._getSearchResults = () => tslib_1.__awaiter(this, void 0, void 0, function* () {
// Do nothing
if (this.state.query === undefined || !this.props.bingSearchService) {
return;
}
// Show a loading indicator + remove selection
this.setState({
filePickerResult: null,
isLoading: true,
});
const searchParams = {
aspect: this.state.aspect,
size: this.state.size,
license: this.state.license,
query: this.state.query,
};
const searchResults = yield this.props.bingSearchService.executeBingSearch(searchParams);
// If the results were obtained
if (searchResults) {
// Set the items so that the selection zone can keep track of them
this._selection.setItems(searchResults, true);
}
// Save results and stop loading indicator
this.setState({
isLoading: false,
results: searchResults,
});
});
/**
* Calculates how many items there should be in the page
*/
this._getItemCountForPage = (itemIndex, surfaceRect) => {
if (itemIndex === 0) {
this._columnCount = Math.ceil(surfaceRect.width / WebSearchTab_types_1.MAX_ROW_HEIGHT);
this._columnWidth = Math.floor(surfaceRect.width / this._columnCount);
this._rowHeight = this._columnWidth;
}
return this._columnCount * WebSearchTab_types_1.ROWS_PER_PAGE;
};
/**
* Gets the height of a list "page"
*/
this._getPageHeight = () => {
return this._rowHeight * WebSearchTab_types_1.ROWS_PER_PAGE;
};
/**
* Renders a cell for search suggestions
*/
this._onRenderSuggestionCell = (item, index) => {
return (React.createElement("div", { className: WebSearchTab_module_scss_1.default.filePickerFolderCardTile, "data-is-focusable": true, style: {
width: 100 / this._columnCount + '%',
} },
React.createElement("div", { className: WebSearchTab_module_scss_1.default.filePickerFolderCardSizer },
React.createElement("div", { className: WebSearchTab_module_scss_1.default.filePickerFolderCardPadder },
React.createElement(react_1.Image, { src: item.backgroundUrl, className: WebSearchTab_module_scss_1.default.filePickerFolderCardImage, imageFit: react_1.ImageFit.cover }),
React.createElement(react_1.DefaultButton, { className: WebSearchTab_module_scss_1.default.filePickerFolderCardLabel, onClick: (_event) => this._handleSearch(item.topic) }, item.topic)))));
};
/**
* Renders the search box
*/
this._renderSearchBox = () => {
const { query } = this.state;
const hasQuery = query !== undefined;
const license = this.state.license ? this.state.license : 'All';
return (React.createElement("div", { className: WebSearchTab_module_scss_1.default.searchBoxContainer },
React.createElement("div", { className: WebSearchTab_module_scss_1.default.searchBoxMedium },
React.createElement("div", { className: WebSearchTab_module_scss_1.default.searchBox },
React.createElement(react_1.SearchBox, { placeholder: strings.SearchBoxPlaceholder, value: query, onSearch: (newQuery) => this._handleSearch(newQuery) }))),
React.createElement(react_1.Label, null, strings.PoweredByBing),
hasQuery && (React.createElement("div", { className: WebSearchTab_module_scss_1.default.dropdownContainer },
React.createElement(react_1.Dropdown, { className: WebSearchTab_module_scss_1.default.filterDropdown, onRenderPlaceHolder: (props) => this._renderFilterPlaceholder(props), selectedKey: this.state.size, options: [
{ key: 'All', text: strings.SizeOptionAll },
{ key: 'Small', text: strings.SizeOptionSmall },
{ key: 'Medium', text: strings.SizeOptionMedium },
{ key: 'Large', text: strings.SizeOptionLarge },
{ key: 'Wallpaper', text: strings.SizeOptionExtraLarge },
], onChanged: (option, index) => this._handleChangeSize(option) }),
React.createElement(react_1.Dropdown, { className: WebSearchTab_module_scss_1.default.filterDropdown, onRenderPlaceHolder: (props) => this._renderFilterPlaceholder(props), selectedKey: this.state.aspect, options: [
{ key: 'All', text: strings.LayoutOptionAll },
{ key: 'Square', text: strings.LayoutOptionSquare },
{ key: 'Wide', text: strings.LayoutOptionWide },
{ key: 'Tall', text: strings.LayoutOptionTall },
], onChanged: (option, index) => this._handleChangeLayout(option) }),
React.createElement(react_1.Dropdown, { className: WebSearchTab_module_scss_1.default.filterDropdown, onRenderPlaceHolder: (props) => this._renderFilterPlaceholder(props), selectedKey: license, options: [
{ key: 'All', text: strings.LicenseOptionAll },
{ key: 'Any', text: strings.LicenseOptionAny },
], onChanged: (option, index) => this._handleChangeLicense(option) })))));
};
/**
* Handles when a user changes the size drop down.
* Resubmits search query
*/
this._handleChangeSize = (option) => {
this.setState({
size: option.key,
}, () => this._getSearchResults());
};
/**
* Handles when user selects a new layout from the drop down.
* Resubmits search query.
*/
this._handleChangeLayout = (option) => {
this.setState({
aspect: option.key,
}, () => this._getSearchResults());
};
/**
* Handles when a user changes the license from the drop down
* Resubits search query
*/
this._handleChangeLicense = (option) => {
this.setState({
license: option.key,
}, () => this._getSearchResults());
};
/**
* Renders the drop down placeholders
*/
this._renderFilterPlaceholder = (props) => {
// return <span>{props.placeholder}</span>;
return React.createElement("span", null, "Pick the value");
};
/**
* Handles when user triggers search query
*/
this._handleSearch = (newQuery) => {
this.setState({
query: newQuery,
}, () => this._getSearchResults());
};
/**
* Handles when user closes search pane
*/
this._handleClose = () => {
this.props.onClose();
};
/**
* Handes when user saves selection
* Calls property pane file picker's save function
*/
this._handleSave = () => {
this.props.onSave(this.state.filePickerResult);
};
/**
* Creates a reference to the list
*/
this._linkElement = (e) => {
this._listElem = e;
};
this._selection = new react_1.Selection({
selectionMode: react_1.SelectionMode.single,
onSelectionChanged: this._onSelectionChanged,
});
this.state = {
isLoading: false,
results: undefined,
filePickerResult: null,
};
}
/**
* Render the tab
*/
render() {
const { query, results } = this.state;
return (React.createElement("div", { className: WebSearchTab_module_scss_1.default.tabContainer },
React.createElement("div", { className: WebSearchTab_module_scss_1.default.tabHeaderContainer },
React.createElement("h2", { className: WebSearchTab_module_scss_1.default.tabHeader }, strings.WebSearchLinkLabel)),
this.props.bingSearchService && this._renderSearchBox(),
React.createElement("div", { className: (0, react_1.css)(WebSearchTab_module_scss_1.default.tab, WebSearchTab_module_scss_1.default.tabOffset) },
!query && this._renderSearchSuggestions(),
query && results && this._renderSearchResults()),
React.createElement("div", { className: WebSearchTab_module_scss_1.default.actionButtonsContainer },
this.state.results && this.state.license === 'Any' && (React.createElement(react_1.MessageBar, null, strings.CreativeCommonsMessage)),
React.createElement(react_1.Label, { className: WebSearchTab_module_scss_1.default.copyrightLabel },
strings.CopyrightWarning,
"\u00A0\u00A0",
React.createElement(react_1.Link, { target: '_blank', href: strings.CopyrightUrl }, strings.LearnMoreLink)),
React.createElement("div", { className: WebSearchTab_module_scss_1.default.actionButtons },
React.createElement(react_1.PrimaryButton, { disabled: !this.state.filePickerResult, className: WebSearchTab_module_scss_1.default.actionButton, onClick: () => this._handleSave() }, strings.OpenButtonLabel),
React.createElement(react_1.DefaultButton, { onClick: () => this._handleClose(), className: WebSearchTab_module_scss_1.default.actionButton }, strings.CancelButtonLabel)))));
}
}
exports.default = WebSearchTab;
//# sourceMappingURL=WebSearchTab.js.map