Skip to content

Commit d1de207

Browse files
committed
Merge branch 'v2-dev' into ravichandran-blog-v2-dev
2 parents 62f3185 + 8965c86 commit d1de207

File tree

14 files changed

+196
-27
lines changed

14 files changed

+196
-27
lines changed

CHANGELOG.JSON

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,20 @@
11
{
22
"versions": [
3+
{
4+
"version": "2.9.0",
5+
"changes": {
6+
"new": [],
7+
"enhancements": [
8+
"`FilePicker`: spanish translation for Stock Images labels [#946](https://github.com/pnp/sp-dev-fx-controls-react/pull/946)",
9+
"`FilePicker`: Add support for a defaultFolderAbsolutePath prop [#947](https://github.com/pnp/sp-dev-fx-controls-react/pull/947)"
10+
],
11+
"fixes": []
12+
},
13+
"contributions": [
14+
"[Ketill Antoníus Ágústsson](https://github.com/Katli95)",
15+
"[Sergio Ortega Martín](https://github.com/sortegamartin)"
16+
]
17+
},
318
{
419
"version": "2.8.0",
520
"changes": {

docs/documentation/docs/controls/FilePicker.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,8 @@ The FilePicker component can be configured with the following properties:
7575
| label | string | no | Specifies the text describing the file picker. |
7676
| buttonLabel | string | no | Specifies the label of the file picker button. |
7777
| buttonIcon | string | no | In case it is provided the file picker will be rendered as an action button. |
78-
buttonIconProps | IIconProps | no | In case it is provided the file picker will be rendered as an Icon the and all can define Properties for Icon |
78+
| buttonIconProps | IIconProps | no | In case it is provided the file picker will be rendered as an Icon the and all can define Properties for Icon |
79+
| defaultFolderAbsolutePath | string | no | Optional string parameter to set a default active folder/library for the SiteFilesTab. E.g. `"https://contoso.sharepoint.com/teams/siteName/documentLibrary/Folder 1/SubFolder 1"` |
7980
| onSave | (filePickerResult: IFilePickerResult[]) => void | yes | Handler when the file has been selected and picker has been closed. |
8081
| onChange | (filePickerResult: IFilePickerResult[]) => void | no | Handler when the file selection has been changed. |
8182
| onCancel | () => void | no | Handler when file picker has been cancelled. |

package-lock.json

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "@pnp/spfx-controls-react",
33
"description": "Reusable React controls for SharePoint Framework solutions",
4-
"version": "2.8.0",
4+
"version": "2.9.0",
55
"engines": {
66
"node": ">=10"
77
},

src/controls/filePicker/FilePicker.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -214,6 +214,7 @@ export class FilePicker extends React.Component<
214214
<SiteFilePickerTab
215215
fileBrowserService={this.fileBrowserService}
216216
includePageLibraries={this.props.includePageLibraries}
217+
defaultFolderAbsolutePath={this.props.defaultFolderAbsolutePath}
217218
{...linkTabProps}
218219
/>
219220
)}

src/controls/filePicker/FilePicker.types.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
import { WebPartContext } from "@microsoft/sp-webpart-base";
22
import { IBreadcrumbItem } from "office-ui-fabric-react/lib/Breadcrumb";
3-
import { IFile, ILibrary } from "../../services/FileBrowserService.types";
3+
import { IFile, IFolder, ILibrary } from "../../services/FileBrowserService.types";
44
import { ExtensionContext } from "@microsoft/sp-extension-base";
55

66
export interface FilePickerBreadcrumbItem extends IBreadcrumbItem {
77
libraryData?: ILibrary;
8-
folderData?: IFile;
8+
folderData?: IFolder;
99
}
1010

1111
export interface IFilePickerTab {

src/controls/filePicker/IFilePickerProps.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -157,4 +157,9 @@ export interface IFilePickerProps {
157157
* Specifies if Site Pages library to be visible on Sites tab
158158
*/
159159
includePageLibraries?: boolean;
160+
161+
/**
162+
* Specifies a default folder to be active in the Site Files tab
163+
*/
164+
defaultFolderAbsolutePath?: string;
160165
}

src/controls/filePicker/SiteFilePickerTab/ISiteFilePickerTabProps.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,5 +10,10 @@ export interface ISiteFilePickerTabProps extends IFilePickerTab {
1010
*/
1111
breadcrumbFirstNode?: IBreadcrumbItem;
1212

13+
/**
14+
* Specifies a default folder to be active in the Site Files tab
15+
*/
16+
defaultFolderAbsolutePath?: string;
17+
1318
includePageLibraries?: boolean;
1419
}

src/controls/filePicker/SiteFilePickerTab/SiteFilePickerTab.tsx

Lines changed: 124 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,46 +1,153 @@
11
import * as React from 'react';
22
import findIndex from 'lodash/findIndex';
33
import { ISiteFilePickerTabProps } from './ISiteFilePickerTabProps';
4-
import {ISiteFilePickerTabState } from './ISiteFilePickerTabState';
4+
import { ISiteFilePickerTabState } from './ISiteFilePickerTabState';
55
import { DocumentLibraryBrowser } from '../controls/DocumentLibraryBrowser/DocumentLibraryBrowser';
66
import { FileBrowser } from '../controls/FileBrowser/FileBrowser';
77
import { PrimaryButton, DefaultButton } from 'office-ui-fabric-react/lib/components/Button';
88
import { Breadcrumb, IBreadcrumbItem } from 'office-ui-fabric-react/lib/Breadcrumb';
9-
import { IFile, ILibrary } from '../../../services/FileBrowserService.types';
9+
import { IFile, IFolder, ILibrary } from '../../../services/FileBrowserService.types';
1010
import { Link } from 'office-ui-fabric-react/lib/Link';
1111
import { IFilePickerResult, FilePickerBreadcrumbItem } from '../FilePicker.types';
1212

13+
import { SPWeb } from "@microsoft/sp-page-context";
14+
1315
import styles from './SiteFilePickerTab.module.scss';
1416
import * as strings from 'ControlStrings';
1517
import { urlCombine } from '../../../common/utilities';
18+
import { cloneDeep } from '@microsoft/sp-lodash-subset';
1619

1720
export default class SiteFilePickerTab extends React.Component<ISiteFilePickerTabProps, ISiteFilePickerTabState> {
21+
private _defaultLibraryNamePromise: Promise<void | string> = Promise.resolve();
22+
1823
constructor(props: ISiteFilePickerTabProps) {
1924
super(props);
2025

2126
// Add current site to the breadcrumb or the provided node
22-
const breadcrumbSiteNode: FilePickerBreadcrumbItem = this.props.breadcrumbFirstNode ? this.props. breadcrumbFirstNode : {
23-
isCurrentItem: true,
27+
const breadcrumbSiteNode: FilePickerBreadcrumbItem = this.props.breadcrumbFirstNode ? this.props.breadcrumbFirstNode : {
28+
isCurrentItem: false,
2429
text: props.context.pageContext.web.title,
25-
key: props.context.pageContext.web.id.toString()
30+
key: props.context.pageContext.web.id.toString(),
31+
onClick: (ev, itm) => { this.onBreadcrumpItemClick(itm); }
2632
};
27-
breadcrumbSiteNode.onClick = () => { this.onBreadcrumpItemClick(breadcrumbSiteNode); };
33+
34+
let breadcrumbItems: FilePickerBreadcrumbItem[] = [breadcrumbSiteNode];
35+
36+
let { folderAbsPath = undefined, libraryServRelUrl = undefined, folderServRelPath = undefined, folderBreadcrumbs = [] } = props.defaultFolderAbsolutePath
37+
? this._parseInitialLocationState(
38+
props.defaultFolderAbsolutePath,
39+
props.context.pageContext.web
40+
)
41+
: {};
42+
43+
breadcrumbItems.push(...folderBreadcrumbs);
44+
45+
breadcrumbItems[breadcrumbItems.length - 1].isCurrentItem = true;
2846

2947
this.state = {
3048
filePickerResult: null,
31-
libraryAbsolutePath: undefined,
32-
libraryUrl: urlCombine(props.context.pageContext.web.serverRelativeUrl, '/Shared%20Documents'),
33-
libraryPath: undefined,
49+
libraryAbsolutePath: folderAbsPath || undefined,
50+
libraryUrl: libraryServRelUrl || urlCombine(props.context.pageContext.web.serverRelativeUrl, '/Shared%20Documents'),
51+
libraryPath: folderServRelPath,
3452
folderName: strings.DocumentLibraries,
35-
breadcrumbItems: [breadcrumbSiteNode]
53+
breadcrumbItems
3654
};
3755
}
3856

57+
private _parseInitialLocationState(folderAbsPath: string, { serverRelativeUrl: webServRelUrl, absoluteUrl: webAbsUrl }: SPWeb) {
58+
// folderAbsPath: "https://tenant.sharepoint.com/teams/Test/DocLib/Folder"
59+
60+
// folderServRelPath: "/teams/Test/DocLib/Folder"
61+
let folderServRelPath = folderAbsPath && folderAbsPath.substr(folderAbsPath.indexOf(webServRelUrl));
62+
63+
// folderWebRelPath: "/DocLib/Folder"
64+
let folderWebRelPath = folderServRelPath && folderServRelPath.substr(webServRelUrl.length);
65+
let libInternalName = folderWebRelPath && folderWebRelPath.substring(1, Math.max(folderWebRelPath.indexOf("/", 2), 0) || undefined);
66+
67+
// libraryServRelUrl: "/teams/Test/DocLib/"
68+
let libraryServRelUrl = urlCombine(webServRelUrl, libInternalName);
69+
70+
let tenantUrl = folderAbsPath.substring(0, folderAbsPath.indexOf(webServRelUrl));
71+
let folderBreadcrumbs: FilePickerBreadcrumbItem[] = this.parseBreadcrumbsFromPaths(
72+
libraryServRelUrl,
73+
folderServRelPath,
74+
folderWebRelPath,
75+
webAbsUrl,
76+
tenantUrl,
77+
libInternalName
78+
);
79+
80+
return { libraryServRelUrl, folderServRelPath, folderAbsPath, folderBreadcrumbs };
81+
}
82+
83+
private parseBreadcrumbsFromPaths(
84+
libraryServRelUrl: string,
85+
folderServRelPath: string,
86+
folderWebRelPath: string,
87+
webAbsUrl: string,
88+
tenantUrl: string,
89+
libInternalName: string
90+
) {
91+
this._defaultLibraryNamePromise = this.props.fileBrowserService.getLibraryNameByInternalName(libInternalName);
92+
let folderBreadcrumbs: FilePickerBreadcrumbItem[] = [];
93+
folderBreadcrumbs.push({
94+
isCurrentItem: false,
95+
text: libInternalName,
96+
key: libraryServRelUrl,
97+
libraryData: {
98+
serverRelativeUrl: libraryServRelUrl,
99+
absoluteUrl: urlCombine(webAbsUrl, libInternalName),
100+
title: libInternalName
101+
},
102+
onClick: (ev, itm) => { this.onBreadcrumpItemClick(itm); }
103+
});
104+
105+
if (folderServRelPath != libraryServRelUrl) {
106+
let folderLibRelPath = folderWebRelPath.substring(libInternalName.length + 2);
107+
let breadcrumbFolderServRelPath = libraryServRelUrl;
108+
109+
let crumbs: FilePickerBreadcrumbItem[] = folderLibRelPath.split("/").map((currFolderName => {
110+
breadcrumbFolderServRelPath += `/${currFolderName}`;
111+
return {
112+
isCurrentItem: false,
113+
text: currFolderName,
114+
key: urlCombine(tenantUrl, breadcrumbFolderServRelPath),
115+
folderData: {
116+
name: currFolderName,
117+
absoluteUrl: urlCombine(tenantUrl, breadcrumbFolderServRelPath),
118+
serverRelativeUrl: breadcrumbFolderServRelPath,
119+
},
120+
onClick: (ev, itm) => { this.onBreadcrumpItemClick(itm); }
121+
};
122+
}));
123+
124+
folderBreadcrumbs.push(...crumbs);
125+
}
126+
return folderBreadcrumbs;
127+
}
128+
129+
public componentDidMount(): void {
130+
this._defaultLibraryNamePromise.then(docLibName => {
131+
if (docLibName) {
132+
let updatedBCItems = cloneDeep(this.state.breadcrumbItems);
133+
updatedBCItems.forEach(crumb => {
134+
if (crumb.libraryData) {
135+
crumb.text = docLibName;
136+
crumb.libraryData.title = docLibName;
137+
}
138+
});
139+
this.setState({ breadcrumbItems: updatedBCItems });
140+
}
141+
}).catch((err) => {
142+
console.log("[SiteFilePicker] Failed To Fetch defaultLibraryName, defaulting to internal name");
143+
});
144+
}
145+
39146
public render(): React.ReactElement<ISiteFilePickerTabProps> {
40147
return (
41-
<div className={styles.tabContainer}>
148+
<div className={styles.tabContainer} >
42149
<div className={styles.tabHeaderContainer}>
43-
<Breadcrumb items={this.state.breadcrumbItems} /*onRenderItem={this.renderBreadcrumbItem}*/ className={styles.breadcrumbNav}/>
150+
<Breadcrumb items={this.state.breadcrumbItems} /*onRenderItem={this.renderBreadcrumbItem}*/ className={styles.breadcrumbNav} />
44151
</div>
45152
<div className={styles.tabFiles}>
46153
{this.state.libraryAbsolutePath === undefined &&
@@ -142,7 +249,7 @@ export default class SiteFilePickerTab extends React.Component<ISiteFilePickerTa
142249
/**
143250
* Triggered when user opens a file folder
144251
*/
145-
private _handleOpenFolder = (folder: IFile, addBreadcrumbNode: boolean) => {
252+
private _handleOpenFolder = (folder: IFolder, addBreadcrumbNode: boolean) => {
146253
const { breadcrumbItems } = this.state;
147254

148255
if (addBreadcrumbNode) {
@@ -151,9 +258,9 @@ export default class SiteFilePickerTab extends React.Component<ISiteFilePickerTa
151258
folderData: folder,
152259
isCurrentItem: true,
153260
text: folder.name,
154-
key: folder.absoluteUrl
261+
key: folder.absoluteUrl,
262+
onClick: (ev, itm) => { this.onBreadcrumpItemClick(itm); }
155263
};
156-
breadcrumbNode.onClick = () => { this.onBreadcrumpItemClick(breadcrumbNode); };
157264
breadcrumbItems.push(breadcrumbNode);
158265
}
159266

@@ -177,9 +284,9 @@ export default class SiteFilePickerTab extends React.Component<ISiteFilePickerTa
177284
libraryData: library,
178285
isCurrentItem: true,
179286
text: library.title,
180-
key: library.serverRelativeUrl
287+
key: library.serverRelativeUrl,
288+
onClick: (ev, itm) => { this.onBreadcrumpItemClick(itm); }
181289
};
182-
breadcrumbNode.onClick = () => { this.onBreadcrumpItemClick(breadcrumbNode); };
183290
breadcrumbItems.push(breadcrumbNode);
184291
}
185292
this.setState({

src/loc/es-es.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -310,6 +310,8 @@ define([], () => {
310310
"UploadImageHeader": "Subir imagen",
311311
"UploadLinkLabel": "Subir",
312312
"WebSearchLinkLabel": "Búsqueda web",
313+
"StockImagesLinkLabel": "Imágenes de stock",
314+
"StockImagesHeader": "Imágenes de stock",
313315
"Yes": "Sí",
314316
"SelectedLabel": "Seleccionado",
315317
"SelectIcon": "Seleccionar icono"

0 commit comments

Comments
 (0)