Skip to content

Commit 609c7ca

Browse files
author
Piotr Siatka
committed
Switch from string to IFIleResult for FilePicker selection.
Fix bugs. Refactor WebSearch.
1 parent 3f849e7 commit 609c7ca

24 files changed

+196
-161
lines changed

src/common/utilities/GeneralHelper.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -241,6 +241,15 @@ export class GeneralHelper {
241241
return parseFloat((bytes / Math.pow(k, i)).toFixed(dm)) + ' ' + strings.SizeUnit[i];
242242
}
243243

244+
public static getFileNameWithoutExtension(itemUrl : string) {
245+
const tokens = itemUrl.split("/");
246+
const fileNameWithExtension = tokens[tokens.length - 1];
247+
const fileNameTokens = fileNameWithExtension.split(".");
248+
const fileName = fileNameTokens[fileNameTokens.length - 1];
249+
250+
return fileName;
251+
}
252+
244253
private static _getEncodedChar(c): string {
245254
const o = {
246255
"<": "&lt;",

src/controls/filePicker/FilePicker.tsx

Lines changed: 22 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import { FileBrowserService } from '../../services/FileBrowserService';
2424
import { OneDriveFilesTab } from './OneDriveFilesTab';
2525
import { OneDriveService } from '../../services/OneDriveService';
2626
import { OrgAssetsService } from '../../services/OrgAssetsService';
27+
import { IFilePickerResult } from './FilePicker.types';
2728

2829
export class FilePicker extends React.Component<IFilePickerProps, IFilePickerState> {
2930
private fileBrowserService: FileBrowserService;
@@ -60,6 +61,13 @@ export class FilePicker extends React.Component<IFilePickerProps, IFilePickerSta
6061
// If no acceptable file type was passed, and we're expecting images, set the default image filter
6162
const accepts: string = this.props.accepts;
6263

64+
const linkTabProps = {
65+
accepts: accepts,
66+
context: this.props.webPartContext,
67+
onClose: () => this._handleClosePanel(),
68+
onSave: (value: IFilePickerResult) => { this._handleSave(value) }
69+
}
70+
6371
return (
6472
<div >
6573
<Label required={this.props.required}>{this.props.label}</Label>
@@ -92,29 +100,20 @@ export class FilePicker extends React.Component<IFilePickerProps, IFilePickerSta
92100
this.state.selectedTab === "keyLink" &&
93101
<LinkFilePickerTab
94102
allowExternalTenantLinks={true}
95-
accepts={accepts}
96-
context={this.props.webPartContext}
97-
onClose={() => this._handleClosePanel()}
98-
onSave={(value: string) => this._handleSave(value)}
103+
{...linkTabProps}
99104
/>
100105
}
101106
{
102107
this.state.selectedTab === "keyUpload" &&
103108
<UploadFilePickerTab
104-
context={this.props.webPartContext}
105-
accepts={accepts}
106-
onClose={() => this._handleClosePanel()}
107-
onSave={(value: string) => this._handleSave(value)}
109+
{...linkTabProps}
108110
/>
109111
}
110112
{
111113
this.state.selectedTab === "keySite" &&
112114
<SiteFilePickerTab
113115
fileBrowserService={this.fileBrowserService}
114-
context={this.props.webPartContext}
115-
accepts={accepts}
116-
onClose={() => this._handleClosePanel()}
117-
onSave={(value: string) => this._handleSave(value)}
116+
{...linkTabProps}
118117
/>
119118
}
120119
{
@@ -126,38 +125,27 @@ export class FilePicker extends React.Component<IFilePickerProps, IFilePickerSta
126125
key: "keyOrgAssets"
127126
}}
128127
fileBrowserService={this.orgAssetsService}
129-
context={this.props.webPartContext}
130-
accepts={accepts}
131-
onClose={() => this._handleClosePanel()}
132-
onSave={(value: string) => this._handleSave(value)}
128+
{...linkTabProps}
133129
/>
134130
}
135131
{
136132
this.state.selectedTab === "keyWeb" &&
137133
<WebSearchTab
138-
context={this.props.webPartContext}
139-
accepts={accepts}
140-
onClose={() => this._handleClosePanel()}
141-
onSave={(value: string) => this._handleSave(value)}
134+
bingAPIKey={this.props.bingAPIKey}
135+
{...linkTabProps}
142136
/>
143137
}
144138
{
145139
this.state.selectedTab === "keyOneDrive" &&
146140
<OneDriveFilesTab
147141
oneDriveService={this.oneDriveService}
148-
context={this.props.webPartContext}
149-
accepts={accepts}
150-
onClose={() => this._handleClosePanel()}
151-
onSave={(value: string) => this._handleSave(value)}
142+
{...linkTabProps}
152143
/>
153144
}
154145
{
155146
this.state.selectedTab === "keyRecent" &&
156147
<RecentFilesTab
157-
context={this.props.webPartContext}
158-
accepts={accepts}
159-
onClose={() => this._handleClosePanel()}
160-
onSave={(value: string) => this._handleSave(value)}
148+
{...linkTabProps}
161149
/>
162150
}
163151

@@ -196,8 +184,8 @@ export class FilePicker extends React.Component<IFilePickerProps, IFilePickerSta
196184
/**
197185
* On save action
198186
*/
199-
private _handleSave = (image: string) => {
200-
this.props.onChanged(image);
187+
private _handleSave = (filePickerResult: IFilePickerResult) => {
188+
this.props.onChanged(filePickerResult);
201189
this.setState({
202190
panelOpen: false
203191
});
@@ -210,6 +198,9 @@ export class FilePicker extends React.Component<IFilePickerProps, IFilePickerSta
210198
this.setState({ selectedTab: item.key });
211199
}
212200

201+
/**
202+
* Prepares navigation panel options
203+
*/
213204
private _getNavPanelOptions = () => {
214205
let links = [];
215206

@@ -221,7 +212,7 @@ export class FilePicker extends React.Component<IFilePickerProps, IFilePickerSta
221212
key: 'keyRecent',
222213
});
223214
}
224-
if (!this.props.hideWebSearchTab) {
215+
if (this.props.bingAPIKey && !this.props.hideWebSearchTab) {
225216
links.push({
226217
name: strings.WebSearchLinkLabel,
227218
url: '#search',

src/controls/filePicker/FilePicker.types.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,12 @@ import { WebPartContext } from "@microsoft/sp-webpart-base";
33
export interface IFilePickerTab {
44
context: WebPartContext;
55
accepts: string;
6-
onSave: (value: string) => void;
6+
onSave: (value: IFilePickerResult) => void;
77
onClose: () => void;
88
}
9+
10+
export interface IFilePickerResult {
11+
fileTitle: string;
12+
fileAbsoluteUrl: string;
13+
file: File;
14+
}

src/controls/filePicker/IFilePickerProps.ts

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { WebPartContext } from "@microsoft/sp-webpart-base";
2+
import { IFilePickerResult } from "./FilePicker.types";
23

34
export interface IFilePickerProps {
45
/**
@@ -11,20 +12,25 @@ export interface IFilePickerProps {
1112
buttonLabel: string;
1213

1314
/**
14-
* Content of the file. TODO: change to bytes?
15+
* Content of the file.
1516
*/
16-
value: string;
17+
filePickerResult: IFilePickerResult;
1718

1819
/**
1920
* Handler when the file has been selected
2021
*/
21-
onSave:(value:string)=>void;
22+
onSave:(filePickerResult: IFilePickerResult)=>void;
2223

2324
/**
24-
* File extensions to be displayed. TODO: Change to string[] ?
25+
* File extensions to be displayed.
2526
*/
2627
accepts?: string;
2728

29+
/**
30+
* Used to execute WebSearch.
31+
*/
32+
bingAPIKey?: string;
33+
2834
webPartContext: WebPartContext;
2935
/**
3036
* Specifies if the picker button is disabled
@@ -40,5 +46,5 @@ export interface IFilePickerProps {
4046
hideLinkUploadTab?: boolean;
4147

4248
required?: boolean;
43-
onChanged: (value: string) => void;
49+
onChanged: (filePickerResult: IFilePickerResult) => void;
4450
}
Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
1+
import { IFilePickerResult } from "../FilePicker.types";
2+
13
export interface ILinkFilePickerTabState {
2-
fileUrl?: string;
4+
filePickerResult?: IFilePickerResult;
35
isValid: boolean;
46
}

src/controls/filePicker/LinkFilePickerTab/LinkFilePickerTab.tsx

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import { FetchClient } from "@pnp/common";
1616
// Localized strings
1717
import * as strings from 'ControlStrings';
1818
import { GeneralHelper } from '../../../Utilities';
19+
import { IFilePickerResult } from '../FilePicker.types';
1920

2021
export default class LinkFilePickerTab extends React.Component<ILinkFilePickerTabProps, ILinkFilePickerTabState> {
2122
constructor(props: ILinkFilePickerTabProps) {
@@ -24,7 +25,7 @@ export default class LinkFilePickerTab extends React.Component<ILinkFilePickerTa
2425
}
2526

2627
public render(): React.ReactElement<ILinkFilePickerTabProps> {
27-
28+
const fileUrl = this.state.filePickerResult ? this.state.filePickerResult.fileAbsoluteUrl : null;
2829
return (
2930
<div className={styles.tabContainer}>
3031
<div className={styles.tabHeaderContainer}>
@@ -47,7 +48,7 @@ export default class LinkFilePickerTab extends React.Component<ILinkFilePickerTa
4748
validateOnFocusIn={false}
4849
validateOnFocusOut={false}
4950
validateOnLoad={true}
50-
value={this.state.fileUrl}
51+
value={fileUrl}
5152
onChanged={(_event: React.FormEvent<HTMLInputElement | HTMLTextAreaElement>, newValue?: string) => this._handleChange(newValue)}
5253
/>
5354
</div>
@@ -66,9 +67,14 @@ export default class LinkFilePickerTab extends React.Component<ILinkFilePickerTa
6667
/**
6768
* Called as user types in a new value
6869
*/
69-
private _handleChange = (newValue?: string) => {
70+
private _handleChange = (fileUrl?: string) => {
71+
const filePickerResult: IFilePickerResult = {
72+
file: null,
73+
fileAbsoluteUrl: fileUrl,
74+
fileTitle: GeneralHelper.getFileNameWithoutExtension(fileUrl)
75+
}
7076
this.setState({
71-
fileUrl: newValue
77+
filePickerResult
7278
});
7379
}
7480

@@ -131,7 +137,7 @@ export default class LinkFilePickerTab extends React.Component<ILinkFilePickerTa
131137
* Handles when user saves
132138
*/
133139
private _handleSave = () => {
134-
this.props.onSave(encodeURI(this.state.fileUrl));
140+
this.props.onSave(this.state.filePickerResult);
135141
}
136142

137143
/**

src/controls/filePicker/OneDriveFilesTab/IOneDriveFilesTabState.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
import { OneDriveFilesBreadcrumbItem } from "./OneDriveFilesTab.types";
2+
import { IFilePickerResult } from "../FilePicker.types";
23

34
export interface IOneDriveFilesTabState {
4-
fileUrl?: string;
5+
filePickerResult: IFilePickerResult;
56
libraryAbsolutePath: string;
67
libraryTitle: string;
78
folderPath: string;

src/controls/filePicker/OneDriveFilesTab/OneDriveFilesTab.tsx

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,14 @@ import * as strings from 'ControlStrings';
1414
import { mergeStyles } from 'office-ui-fabric-react/lib/Styling';
1515
import { css } from 'office-ui-fabric-react/lib/Utilities';
1616
import { Link } from 'office-ui-fabric-react/lib/Link';
17+
import { IFilePickerResult } from '../FilePicker.types';
1718

1819
export class OneDriveFilesTab extends React.Component<IOneDriveFilesTabProps, IOneDriveFilesTabState> {
1920
constructor(props: IOneDriveFilesTabProps) {
2021
super(props);
2122

2223
this.state = {
24+
filePickerResult: null,
2325
libraryAbsolutePath: undefined,
2426
libraryTitle: strings.DocumentLibraries,
2527
folderPath: undefined,
@@ -72,7 +74,7 @@ export class OneDriveFilesTab extends React.Component<IOneDriveFilesTabProps, IO
7274
<div className={styles.tabFiles}>
7375
{this.state.libraryAbsolutePath !== undefined &&
7476
<FileBrowser
75-
onChange={(fileUrl: string) => this._handleSelectionChange(fileUrl)}
77+
onChange={(filePickerResult: IFilePickerResult) => this._handleSelectionChange(filePickerResult)}
7678
onOpenFolder={(folder: IFile) => this._handleOpenFolder(folder, true)}
7779
fileBrowserService={this.props.oneDriveService}
7880
libraryName={this.state.libraryTitle}
@@ -82,7 +84,7 @@ export class OneDriveFilesTab extends React.Component<IOneDriveFilesTabProps, IO
8284
<div className={styles.actionButtonsContainer}>
8385
<div className={styles.actionButtons}>
8486
<PrimaryButton
85-
disabled={!this.state.fileUrl}
87+
disabled={!this.state.filePickerResult}
8688
onClick={() => this._handleSave()} className={styles.actionButton}>{strings.OpenButtonLabel}</PrimaryButton>
8789
<DefaultButton onClick={() => this._handleClose()} className={styles.actionButton}>{strings.CancelButtonLabel}</DefaultButton>
8890
</div>
@@ -125,24 +127,24 @@ export class OneDriveFilesTab extends React.Component<IOneDriveFilesTabProps, IO
125127

126128
this.setState({
127129
breadcrumbItems,
128-
fileUrl: undefined
130+
filePickerResult: undefined
129131
});
130132
}
131133

132134
/**
133135
* Is called when user selects a different file
134136
*/
135-
private _handleSelectionChange = (imageUrl: string) => {
137+
private _handleSelectionChange = (filePickerResult: IFilePickerResult) => {
136138
this.setState({
137-
fileUrl: imageUrl
139+
filePickerResult
138140
});
139141
}
140142

141143
/**
142144
* Called when user saves
143145
*/
144146
private _handleSave = () => {
145-
this.props.onSave(encodeURI(this.state.fileUrl));
147+
this.props.onSave(this.state.filePickerResult);
146148
}
147149

148150
/**
Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
import { IRecentFile } from ".";
2+
import { IFilePickerResult } from "../FilePicker.types";
23

34
export interface IRecentFilesTabState {
45
results: IRecentFile[];
56
isLoading: boolean;
6-
fileUrl?: string;
7+
filePickerResult: IFilePickerResult;
78
}

0 commit comments

Comments
 (0)