Skip to content

921 FilePicker order of tabs and default tab #1980

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 6 commits into
base: dev
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 19 additions & 1 deletion docs/documentation/docs/controls/FilePicker.md
Original file line number Diff line number Diff line change
Expand Up @@ -107,8 +107,10 @@ The FilePicker component can be configured with the following properties:
| includePageLibraries | boolean | no | Specifies if Site Pages library to be visible on Sites tab |
| allowExternalLinks | boolean | no | Specifies if external links should be allowed. |
| checkIfFileExists | boolean | no | When using file links, this property allows the user to choose if the control should check if the link point to a file that exists or not. |
| tabOrder | FilePickerTab[]| no | Defines a custom display order for the tabs. Tabs not listed will follow their default order. |
| defaultSelectedTab | FilePickerTab | no | Sets the default selected tab. If not specified, the first visible tab is used. |

interface `IFilePickerResult`
Interface `IFilePickerResult`

Provides options for carousel buttons location.

Expand All @@ -120,4 +122,20 @@ Provides options for carousel buttons location.
| fileSize | number | Size of the result (in bytes). Set only for file upload |
| downloadFileContent | () => Promise<File> | Function allows to download file content. Returns File object. |

Enum `FilePickerTab`

Represents the available tabs in the File Picker component. Each tab corresponds to a different source from which users can select files.

| Name | Description |
|-----------------|-------------------------------------------------------|
| Recent | Displays recently used files. |
| StockImages | Shows stock image selection. |
| Web | Allows searching files from the web. |
| OrgAssets | Displays organizational assets. |
| OneDrive | Allows file selection from OneDrive. |
| Site | Enables browsing site files. |
| Upload | Provides option to upload local files. |
| Link | Lets the user add a file via a URL. |
| MultipleUpload | Supports uploading multiple files at once. |

![](https://telemetry.sharepointpnp.com/sp-dev-fx-controls-react/filePicker/FilePicker)
121 changes: 72 additions & 49 deletions src/controls/filePicker/FilePicker.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ import { StockImages } from "./StockImagesTab/StockImages";
import UploadFilePickerTab from "./UploadFilePickerTab/UploadFilePickerTab";
import MultipleUploadFilePickerTab from "./MultipleUploadFilePickerTab/MultipleUploadFilePickerTab";
import WebSearchTab from "./WebSearchTab/WebSearchTab";
import { FilePickerTab } from "./FilePickerTab";


export class FilePicker extends React.Component<
Expand Down Expand Up @@ -89,7 +90,7 @@ export class FilePicker extends React.Component<

this.setState({
organisationAssetsEnabled: orgAssetsEnabled,
selectedTab: this.getDefaultSelectedTabKey(this.props, orgAssetsEnabled),
selectedTab: this._getDefaultSelectedTabKey(this.props, orgAssetsEnabled),
});
if (!!this.props.context && !!this.props.webAbsoluteUrl) {
const { title, id } = await this.fileBrowserService.getSiteTitleAndId();
Expand Down Expand Up @@ -190,7 +191,7 @@ export class FilePicker extends React.Component<
/>
</div>
<div className={styles.tabsContainer}>
{this.state.selectedTab === "keyLink" && (
{this.state.selectedTab === FilePickerTab.Link && (
<LinkFilePickerTab
fileSearchService={this.fileSearchService}
renderCustomLinkTabContent={
Expand All @@ -201,7 +202,7 @@ export class FilePicker extends React.Component<
{...linkTabProps}
/>
)}
{this.state.selectedTab === "keyUpload" && (
{this.state.selectedTab === FilePickerTab.Upload && (
<UploadFilePickerTab
renderCustomUploadTabContent={
this.props.renderCustomUploadTabContent
Expand All @@ -210,7 +211,7 @@ export class FilePicker extends React.Component<
onChange={this._handleOnChange}
/>
)}
{this.state.selectedTab === "keyMultipleUpload" && (
{this.state.selectedTab === FilePickerTab.MultipleUpload && (
<MultipleUploadFilePickerTab
renderCustomMultipleUploadTabContent={
this.props.renderCustomMultipleUploadTabContent
Expand All @@ -219,7 +220,7 @@ export class FilePicker extends React.Component<
onChange={this._handleOnChange}
/>
)}
{this.state.selectedTab === "keySite" && (
{this.state.selectedTab === FilePickerTab.Site && (
<SiteFilePickerTab
fileBrowserService={this.fileBrowserService}
includePageLibraries={this.props.includePageLibraries}
Expand All @@ -230,37 +231,37 @@ export class FilePicker extends React.Component<
{...linkTabProps}
/>
)}
{this.state.selectedTab === "keyOrgAssets" && (
{this.state.selectedTab === FilePickerTab.OrgAssets && (
<SiteFilePickerTab
breadcrumbFirstNode={{
isCurrentItem: true,
text: strings.OrgAssetsTabLabel,
key: "keyOrgAssets",
key: FilePickerTab.OrgAssets,
}}
fileBrowserService={this.orgAssetsService}
webTitle={this.state.webTitle}
{...linkTabProps}
/>
)}
{this.state.selectedTab === "keyWeb" && (
{this.state.selectedTab === FilePickerTab.Web && (
<WebSearchTab
bingSearchService={this.fileSearchService}
{...linkTabProps}
/>
)}
{this.state.selectedTab === "keyOneDrive" && (
{this.state.selectedTab === FilePickerTab.OneDrive && (
<OneDriveFilesTab
oneDriveService={this.oneDriveService}
{...linkTabProps}
/>
)}
{this.state.selectedTab === "keyRecent" && (
{this.state.selectedTab === FilePickerTab.Recent && (
<RecentFilesTab
fileSearchService={this.fileSearchService}
{...linkTabProps}
/>
)}
{this.state.selectedTab === "keyStockImages" && (
{this.state.selectedTab === FilePickerTab.StockImages && (
<StockImages
language={
this.props.context.pageContext.cultureInfo.currentCultureName
Expand Down Expand Up @@ -294,7 +295,7 @@ export class FilePicker extends React.Component<
private _handleOpenPanel = (): void => {
this.setState({
panelOpen: true,
selectedTab: this.getDefaultSelectedTabKey(
selectedTab: this._getDefaultSelectedTabKey(
this.props,
this.state.organisationAssetsEnabled
),
Expand Down Expand Up @@ -344,29 +345,29 @@ export class FilePicker extends React.Component<
*/
private _getNavPanelOptions = (): INavLinkGroup[] => {
const addUrl = this.props.storeLastActiveTab !== false;
const links = [];
let links = [];

if (!this.props.hideRecentTab) {
links.push({
name: strings.RecentLinkLabel,
url: addUrl ? "#recent" : undefined,
icon: "Recent",
key: "keyRecent",
key: FilePickerTab.Recent,
});
}
if (!this.props.hideStockImages) {
links.push({
name: strings.StockImagesLinkLabel,
url: addUrl ? "#stockImages" : undefined,
key: "keyStockImages",
key: FilePickerTab.StockImages,
icon: "ImageSearch",
});
}
if (this.props.bingAPIKey && !this.props.hideWebSearchTab) {
links.push({
name: strings.WebSearchLinkLabel,
url: addUrl ? "#search" : undefined,
key: "keyWeb",
key: FilePickerTab.Web,
icon: "Search",
});
}
Expand All @@ -378,85 +379,107 @@ export class FilePicker extends React.Component<
name: strings.OrgAssetsLinkLabel,
url: addUrl ? "#orgAssets" : undefined,
icon: "FabricFolderConfirm",
key: "keyOrgAssets",
key: FilePickerTab.OrgAssets,
});
}
if (!this.props.hideOneDriveTab) {
links.push({
name: "OneDrive",
url: addUrl ? "#onedrive" : undefined,
key: "keyOneDrive",
key: FilePickerTab.OneDrive,
icon: "OneDrive",
});
}
if (!this.props.hideSiteFilesTab) {
links.push({
name: strings.SiteLinkLabel,
url: addUrl ? "#globe" : undefined,
key: "keySite",
key: FilePickerTab.Site,
icon: "Globe",
});
}
if (!this.props.hideLocalUploadTab) {
links.push({
name: strings.UploadLinkLabel,
url: addUrl ? "#upload" : undefined,
key: "keyUpload",
key: FilePickerTab.Upload,
icon: "System",
});
}
if (!this.props.hideLocalMultipleUploadTab) {
links.push({
name: strings.UploadLinkLabel + " " + strings.OneDriveRootFolderName,
url: addUrl ? "#Multipleupload" : undefined,
key: "keyMultipleUpload",
key: FilePickerTab.MultipleUpload,
icon: "BulkUpload",
});
}
if (!this.props.hideLinkUploadTab) {
links.push({
name: strings.FromLinkLinkLabel,
url: addUrl ? "#link" : undefined,
key: "keyLink",
key: FilePickerTab.Link,
icon: "Link",
});
}

if(this.props.tabOrder) {
links = this._getTabOrder(links);
}

const groups: INavLinkGroup[] = [{ links }];
return groups;
}

private getDefaultSelectedTabKey = (
/**
* Sorts navigation tabs based on the tabOrder prop
*/
private _getTabOrder = (links): INavLink[] => {
const sortedKeys = [
...this.props.tabOrder,
...links.map(l => l.key).filter(key => !this.props.tabOrder.includes(key)),
];

links.sort((a, b) => {
return sortedKeys.indexOf(a.key) - sortedKeys.indexOf(b.key);
});

return links;
};

/**
* Returns the default selected tab key
*/
private _getDefaultSelectedTabKey = (
props: IFilePickerProps,
orgAssetsEnabled: boolean
): string => {
if (!props.hideRecentTab) {
return "keyRecent";
}
if (!props.hideStockImages) {
return "keyStockImages";
}
if (props.bingAPIKey && !props.hideWebSearchTab) {
return "keyWeb";
}
if (!props.hideOrganisationalAssetTab && orgAssetsEnabled) {
return "keyOrgAssets";
}
if (!props.hideOneDriveTab) {
return "keyOneDrive";
}
if (!props.hideSiteFilesTab) {
return "keySite";
}
if (!props.hideLocalUploadTab) {
return "keyUpload";
}
if (!props.hideLinkUploadTab) {
return "keyLink";
}
if (!props.hideLocalMultipleUploadTab) {
return "keyMultipleUpload";
const tabsConfig = [
{ isTabVisible: !props.hideRecentTab, tabKey: FilePickerTab.Recent },
{ isTabVisible: !props.hideStockImages, tabKey: FilePickerTab.StockImages },
{ isTabVisible: props.bingAPIKey && !props.hideWebSearchTab, tabKey: FilePickerTab.Web },
{ isTabVisible: !props.hideOrganisationalAssetTab && orgAssetsEnabled, tabKey: FilePickerTab.OrgAssets },
{ isTabVisible: !props.hideOneDriveTab, tabKey: FilePickerTab.OneDrive },
{ isTabVisible: !props.hideSiteFilesTab, tabKey: FilePickerTab.Site },
{ isTabVisible: !props.hideLocalUploadTab, tabKey: FilePickerTab.Upload },
{ isTabVisible: !props.hideLinkUploadTab, tabKey: FilePickerTab.Link },
{ isTabVisible: !props.hideLocalMultipleUploadTab, tabKey: FilePickerTab.MultipleUpload }
];

const visibleTabs = tabsConfig.filter(tab => tab.isTabVisible);
const visibleTabKeys = visibleTabs.map(tab => tab.tabKey);

// If defaultSelectedTab is provided and is visible, then return tabKey
if(this.props.defaultSelectedTab && visibleTabKeys.includes(this.props.defaultSelectedTab)) {
return this.props.defaultSelectedTab;
}

// If no valid default tab is provided, find the first visible tab in the order
if (this.props.tabOrder) {
const visibleTabSet = new Set(visibleTabKeys);
return this.props.tabOrder.find(key => visibleTabSet.has(key));
} else {
return visibleTabKeys[0]; // first visible tab from default order
}
}
}
11 changes: 11 additions & 0 deletions src/controls/filePicker/FilePickerTab.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
export enum FilePickerTab {
Recent = "keyRecent",
StockImages = "keyStockImages",
Web = "keyWeb",
OrgAssets = "keyOrgAssets",
OneDrive = "keyOneDrive",
Site = "keySite",
Upload = "keyUpload",
Link = "keyLink",
MultipleUpload = "keyMultipleUpload"
}
11 changes: 11 additions & 0 deletions src/controls/filePicker/IFilePickerProps.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { IIconProps } from "@fluentui/react/lib/Icon";
import { BaseComponentContext } from '@microsoft/sp-component-base';

import { IFilePickerResult } from "./FilePicker.types";
import { FilePickerTab } from "./FilePickerTab";

export interface IFilePickerProps {
/**
Expand Down Expand Up @@ -175,4 +176,14 @@ export interface IFilePickerProps {
* Specifies if file check should be done
*/
checkIfFileExists?: boolean;
/**
* Specifies tab order
* Default [FilePickerTab.Recent, FilePickerTab.StockImages, FilePickerTab.Web, FilePickerTab.OrgAssets, FilePickerTab.OneDrive, FilePickerTab.Site, FilePickerTab.Upload, FilePickerTab.Link, FilePickerTab.MultipleUpload]
*/
tabOrder?: FilePickerTab[];
/**
* Specifies default selected tab
* One of the values from the FilePickerTab enum: Recent, StockImages, Web, OrgAssets, OneDrive, Site, Upload, Link, or MultipleUpload.
*/
defaultSelectedTab?: FilePickerTab;
}
1 change: 1 addition & 0 deletions src/controls/filePicker/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@ export * from "./FilePicker";
export * from "./FilePicker.types";
export * from "./IFilePickerProps";
export * from "./IFilePickerState";
export * from "./FilePickerTab";