diff --git a/docs/documentation/docs/controls/FilePicker.md b/docs/documentation/docs/controls/FilePicker.md index 81b19ea63..aa036b862 100644 --- a/docs/documentation/docs/controls/FilePicker.md +++ b/docs/documentation/docs/controls/FilePicker.md @@ -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. @@ -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) diff --git a/src/controls/filePicker/FilePicker.tsx b/src/controls/filePicker/FilePicker.tsx index 32b78215e..0859c53e4 100644 --- a/src/controls/filePicker/FilePicker.tsx +++ b/src/controls/filePicker/FilePicker.tsx @@ -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< @@ -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(); @@ -190,7 +191,7 @@ export class FilePicker extends React.Component< />
- {this.state.selectedTab === "keyLink" && ( + {this.state.selectedTab === FilePickerTab.Link && ( )} - {this.state.selectedTab === "keyUpload" && ( + {this.state.selectedTab === FilePickerTab.Upload && ( )} - {this.state.selectedTab === "keyMultipleUpload" && ( + {this.state.selectedTab === FilePickerTab.MultipleUpload && ( )} - {this.state.selectedTab === "keySite" && ( + {this.state.selectedTab === FilePickerTab.Site && ( )} - {this.state.selectedTab === "keyOrgAssets" && ( + {this.state.selectedTab === FilePickerTab.OrgAssets && ( )} - {this.state.selectedTab === "keyWeb" && ( + {this.state.selectedTab === FilePickerTab.Web && ( )} - {this.state.selectedTab === "keyOneDrive" && ( + {this.state.selectedTab === FilePickerTab.OneDrive && ( )} - {this.state.selectedTab === "keyRecent" && ( + {this.state.selectedTab === FilePickerTab.Recent && ( )} - {this.state.selectedTab === "keyStockImages" && ( + {this.state.selectedTab === FilePickerTab.StockImages && ( { this.setState({ panelOpen: true, - selectedTab: this.getDefaultSelectedTabKey( + selectedTab: this._getDefaultSelectedTabKey( this.props, this.state.organisationAssetsEnabled ), @@ -344,21 +345,21 @@ 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", }); } @@ -366,7 +367,7 @@ export class FilePicker extends React.Component< links.push({ name: strings.WebSearchLinkLabel, url: addUrl ? "#search" : undefined, - key: "keyWeb", + key: FilePickerTab.Web, icon: "Search", }); } @@ -378,14 +379,14 @@ 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", }); } @@ -393,7 +394,7 @@ export class FilePicker extends React.Component< links.push({ name: strings.SiteLinkLabel, url: addUrl ? "#globe" : undefined, - key: "keySite", + key: FilePickerTab.Site, icon: "Globe", }); } @@ -401,7 +402,7 @@ export class FilePicker extends React.Component< links.push({ name: strings.UploadLinkLabel, url: addUrl ? "#upload" : undefined, - key: "keyUpload", + key: FilePickerTab.Upload, icon: "System", }); } @@ -409,7 +410,7 @@ export class FilePicker extends React.Component< links.push({ name: strings.UploadLinkLabel + " " + strings.OneDriveRootFolderName, url: addUrl ? "#Multipleupload" : undefined, - key: "keyMultipleUpload", + key: FilePickerTab.MultipleUpload, icon: "BulkUpload", }); } @@ -417,46 +418,68 @@ export class FilePicker extends React.Component< 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 + } } } diff --git a/src/controls/filePicker/FilePickerTab.ts b/src/controls/filePicker/FilePickerTab.ts new file mode 100644 index 000000000..9094e9bbf --- /dev/null +++ b/src/controls/filePicker/FilePickerTab.ts @@ -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" +} diff --git a/src/controls/filePicker/IFilePickerProps.ts b/src/controls/filePicker/IFilePickerProps.ts index 903c850fc..64a567f4d 100644 --- a/src/controls/filePicker/IFilePickerProps.ts +++ b/src/controls/filePicker/IFilePickerProps.ts @@ -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 { /** @@ -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; } diff --git a/src/controls/filePicker/index.ts b/src/controls/filePicker/index.ts index 64d58e192..b484b2be8 100644 --- a/src/controls/filePicker/index.ts +++ b/src/controls/filePicker/index.ts @@ -2,3 +2,4 @@ export * from "./FilePicker"; export * from "./FilePicker.types"; export * from "./IFilePickerProps"; export * from "./IFilePickerState"; +export * from "./FilePickerTab";