Skip to content

Commit

Permalink
fix of #1011
Browse files Browse the repository at this point in the history
  • Loading branch information
AJIXuMuK committed Sep 18, 2021
1 parent f3b11dc commit 70fb2ab
Show file tree
Hide file tree
Showing 5 changed files with 165 additions and 54 deletions.
37 changes: 37 additions & 0 deletions src/common/utilities/GeneralHelper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -360,3 +360,40 @@ export const toRelativeUrl = (absoluteUrl: string): string => {

return absoluteUrl.replace(/^(?:\/\/|[^/]+)*\//, '/');
};

export function sortString(a: string, b: string, isDesc: boolean): number {
const aProp = (a || '').toLowerCase();
const bProp = (b || '').toLowerCase();

if (aProp < bProp) {
return isDesc ? 1 : -1;
}
else if (aProp > bProp) {
return isDesc ? -1 : 1;
}

return 0;
}

export function sortDate(a: string | number | Date, b: string | number | Date, isDesc: boolean): number {
const aTime = dateToNumber(a);
const bTime = dateToNumber(b);

return isDesc ? bTime - aTime : aTime - bTime;
}

export function dateToNumber(date: string | number | Date): number {
if (typeof date === 'number') {
return date;
}

let dateObj: Date;
if (typeof date === 'string') {
dateObj = new Date(date);
}
else {
dateObj = date;
}

return dateObj.getTime();
}
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ export class OneDriveFilesTab extends React.Component<IOneDriveFilesTabProps, IO
const oneDriveFolderData: IFile = {
isFolder: true,
modified: null,
modifiedDate: null,
absoluteUrl: libraryAbsolutePath,
name: libraryTitle,
fileIcon: "",
Expand Down
133 changes: 86 additions & 47 deletions src/controls/filePicker/controls/FileBrowser/FileBrowser.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import * as React from 'react';
import { IFile, FilesQueryResult } from '../../../../services/FileBrowserService.types';
import { GeneralHelper } from '../../../../common/utilities/GeneralHelper';
import { GeneralHelper, sortDate, sortString } from '../../../../common/utilities/GeneralHelper';
import { LoadingState } from './IFileBrowserState';
import { TilesList } from '../TilesList/TilesList';
import { IFilePickerResult } from '../../FilePicker.types';
Expand Down Expand Up @@ -59,7 +59,7 @@ export class FileBrowser extends React.Component<IFileBrowserProps, IFileBrowser
{
key: 'column2',
name: strings.NameField,
fieldName: 'fileLeafRef',
fieldName: 'name',
minWidth: 210,
isRowHeader: true,
isResizable: true,
Expand All @@ -81,11 +81,11 @@ export class FileBrowser extends React.Component<IFileBrowserProps, IFileBrowser
{
key: 'column3',
name: strings.ModifiedField,
fieldName: 'dateModifiedValue',
fieldName: 'modified',
minWidth: 120,
isResizable: true,
onColumnClick: this._onColumnClick,
data: 'number',
data: 'date',
onRender: (item: IFile) => {
//const dateModified = moment(item.modified).format(strings.DateFormat);
return <span>{item.modified}</span>;
Expand All @@ -108,7 +108,7 @@ export class FileBrowser extends React.Component<IFileBrowserProps, IFileBrowser
{
key: 'column5',
name: strings.FileSizeField,
fieldName: 'fileSizeRaw',
fieldName: 'fileSize',
minWidth: 70,
maxWidth: 90,
isResizable: true,
Expand Down Expand Up @@ -169,9 +169,9 @@ export class FileBrowser extends React.Component<IFileBrowserProps, IFileBrowser
<div className={styles.scrollablePaneWrapper}>
<ScrollablePane>

{
this.state.selectedView !== 'tiles' ?
(
{
this.state.selectedView !== 'tiles' ?
(
<DetailsList
items={this.state.items}
compact={this.state.selectedView === 'compact'}
Expand All @@ -187,17 +187,17 @@ export class FileBrowser extends React.Component<IFileBrowserProps, IFileBrowser
onRenderRow={this._onRenderRow}
onRenderMissingItem={() => { this._loadNextDataRequest(); return null; }}
/>) :
(<TilesList
fileBrowserService={this.props.fileBrowserService}
filePickerResult={this.state.filePickerResult}
selection={this._selection}
items={this.state.items}

onFolderOpen={this._handleOpenFolder}
onFileSelected={this._itemSelectionChanged}
onNextPageDataRequest={this._loadNextDataRequest}
/>)
}
(<TilesList
fileBrowserService={this.props.fileBrowserService}
filePickerResult={this.state.filePickerResult}
selection={this._selection}
items={this.state.items}

onFolderOpen={this._handleOpenFolder}
onFileSelected={this._itemSelectionChanged}
onNextPageDataRequest={this._loadNextDataRequest}
/>)
}
</ScrollablePane>
</div>
</div>
Expand Down Expand Up @@ -378,31 +378,56 @@ export class FileBrowser extends React.Component<IFileBrowserProps, IFileBrowser
isSortedDescending = !isSortedDescending;
}

// Sort the items.
items = items!.concat([]).sort((a, b) => {
const firstValue = a[column.fieldName || ''];
const secondValue = b[column.fieldName || ''];
const updatedColumns: IColumn[] = columns!.map(col => {
col.isSorted = col.key === column.key;

if (isSortedDescending) {
return firstValue > secondValue ? -1 : 1;
} else {
return firstValue > secondValue ? 1 : -1;
if (col.isSorted) {
col.isSortedDescending = isSortedDescending;
}

return col;
});

// Reset the items and columns to match the state.
this.setState({
items: items,
columns: columns!.map(col => {
col.isSorted = col.key === column.key;
if (!this.state.nextPageQueryString) { // all items have been loaded to the client
// Sort the items.
items = items!.concat([]).sort((a, b) => {
if (a.isFolder && !b.isFolder) {
return 1;
}
else if (!a.isFolder && b.isFolder) {
return -1;
}
let firstValue = a[column.fieldName] || '';
let secondValue = b[column.fieldName] || '';

if (col.isSorted) {
col.isSortedDescending = isSortedDescending;
if (column.data === 'string') {
return sortString(firstValue, secondValue, isSortedDescending);
}
else if (column.data === 'date') {
return sortDate(firstValue, secondValue, isSortedDescending);
}
else if (column.data === 'number') {
firstValue = parseFloat(firstValue);
secondValue = parseFloat(secondValue);
}

return col;
})
});
return isSortedDescending ? secondValue - firstValue : firstValue - secondValue;
});

// Reset the items and columns to match the state.
this.setState({
items: items,
columns: updatedColumns
});
}
else {
this.setState({
items: [],
columns: updatedColumns
}, () => {
this._getListItems(false);
});
}
}

/**
Expand Down Expand Up @@ -454,20 +479,20 @@ export class FileBrowser extends React.Component<IFileBrowserProps, IFileBrowser
* Handles item click.
*/
private _handleItemInvoked = (item: IFile) => {
// If a file is selected, open the library
if (item.isFolder) {
this._handleOpenFolder(item);
} else {
// Otherwise, remember it was selected
this._itemSelectionChanged(item);
}
}
// If a file is selected, open the library
if (item.isFolder) {
this._handleOpenFolder(item);
} else {
// Otherwise, remember it was selected
this._itemSelectionChanged(item);
}
}

/**
* Gets all files in a library with a matchihg path
*/
private async _getListItems(concatenateResults: boolean = false) {
const { libraryUrl, folderPath, accepts } = this.props;
const { libraryUrl, folderPath, accepts, fileBrowserService } = this.props;
let { items, nextPageQueryString } = this.state;

let filesQueryResult: FilesQueryResult = { items: [], nextHref: null };
Expand All @@ -480,8 +505,18 @@ export class FileBrowser extends React.Component<IFileBrowserProps, IFileBrowser
loadingState,
nextPageQueryString
});

let sortField: string | undefined = undefined;
let isDesc: boolean | undefined = undefined;

const sortByCol = this.state.columns!.filter(c => c.isSorted)[0];
if (sortByCol) {
sortField = fileBrowserService.getSPFieldNameForFileProperty(sortByCol.fieldName);
isDesc = !!sortByCol.isSortedDescending;
}

// Load files in the folder
filesQueryResult = await this.props.fileBrowserService.getListItems(libraryUrl, folderPath, accepts, nextPageQueryString);
filesQueryResult = await this.props.fileBrowserService.getListItems(libraryUrl, folderPath, accepts, nextPageQueryString, sortField, isDesc);
} catch (error) {
filesQueryResult.items = null;
console.error(error.message);
Expand Down Expand Up @@ -515,4 +550,8 @@ export class FileBrowser extends React.Component<IFileBrowserProps, IFileBrowser
});
}
}

private _onClientSort(column: IColumn): void {

}
}
47 changes: 40 additions & 7 deletions src/services/FileBrowserService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ export class FileBrowserService {
* @param folderPath
* @param acceptedFilesExtensions
*/
public getListItems = async (listUrl: string, folderPath: string, acceptedFilesExtensions?: string[], nextPageQueryStringParams?: string): Promise<FilesQueryResult> => {
public getListItems = async (listUrl: string, folderPath: string, acceptedFilesExtensions?: string[], nextPageQueryStringParams?: string, sortBy?: string, isDesc?: boolean): Promise<FilesQueryResult> => {
let filesQueryResult: FilesQueryResult = { items: [], nextHref: null };
try {
let restApi = `${this.context.pageContext.web.absoluteUrl}/_api/web/GetList('${listUrl}')/RenderListDataAsStream`;
Expand All @@ -36,7 +36,7 @@ export class FileBrowserService {
folderPath = null;
}

filesQueryResult = await this._getListDataAsStream(restApi, folderPath, acceptedFilesExtensions);
filesQueryResult = await this._getListDataAsStream(restApi, folderPath, acceptedFilesExtensions, sortBy, isDesc);
} catch (error) {
filesQueryResult.items = null;
console.error(error.message);
Expand Down Expand Up @@ -123,21 +123,53 @@ export class FileBrowserService {
}
}

/**
* Maps IFile property name to SharePoint item field name
* @param filePropertyName File Property
* @returns SharePoint Field Name
*/
public getSPFieldNameForFileProperty(filePropertyName: string): string {
let fieldName = '';
switch (filePropertyName) {
case 'fileIcon':
fieldName = 'DocIcon';
break;
case 'serverRelativeUrl':
fieldName = 'FileRef';
break;
case 'modified':
case 'modifiedDate':
fieldName = 'Modified';
break;
case 'fileSize':
fieldName = 'File_x0020_Size';
break;
case 'fileType':
fieldName = 'File_x0020_Type';
break;
case 'modifiedBy':
fieldName = 'Editor';
break;
}

return fieldName;
}

/**
* Executes query to load files with possible extension filtering
* @param restApi
* @param folderPath
* @param acceptedFilesExtensions
*/
protected _getListDataAsStream = async (restApi: string, folderPath: string, acceptedFilesExtensions?: string[]): Promise<FilesQueryResult> => {
protected _getListDataAsStream = async (restApi: string, folderPath: string, acceptedFilesExtensions?: string[], sortBy?: string, isDesc?: boolean): Promise<FilesQueryResult> => {
let filesQueryResult: FilesQueryResult = { items: [], nextHref: null };
try {
const body = {
parameters: {
AllowMultipleValueFilterForTaxonomyFields: true,
// ContextInfo (1), ListData (2), ListSchema (4), ViewMetadata (1024), EnableMediaTAUrls (4096), ParentInfo (8192)
RenderOptions: 1 | 2 | 4 | 1024 | 4096 | 8192,
ViewXml: this.getFilesCamlQueryViewXml(acceptedFilesExtensions)
ViewXml: this.getFilesCamlQueryViewXml(acceptedFilesExtensions, sortBy || 'FileLeafRef', !!isDesc)
}
};
if (folderPath) {
Expand Down Expand Up @@ -195,7 +227,7 @@ export class FileBrowserService {
/**
* Generates Files CamlQuery ViewXml
*/
protected getFilesCamlQueryViewXml = (accepts: string[]) => {
protected getFilesCamlQueryViewXml = (accepts: string[], sortBy: string, isDesc: boolean) => {
const fileFilter: string = this.getFileTypeFilter(accepts);
let queryCondition = fileFilter && fileFilter != "" ?
`<Query>
Expand All @@ -217,8 +249,8 @@ export class FileBrowserService {
</In>
</Or>
</Where>
<OrderBy><FieldRef Name="FileLeafRef" /></OrderBy>
</Query>` : `<Query><OrderBy><FieldRef Name="FileLeafRef" /></OrderBy></Query>`;
<OrderBy><FieldRef Name="${sortBy}" Ascending="${isDesc ? 'False' : 'True'}" /></OrderBy>
</Query>` : `<Query><OrderBy><FieldRef Name="${sortBy}" Ascending="${isDesc ? 'False' : 'True'}" /></OrderBy></Query>`;

// Add files types condiiton
const viewXml = `<View>
Expand Down Expand Up @@ -264,6 +296,7 @@ export class FileBrowserService {
fileIcon: fileItem.DocIcon,
serverRelativeUrl: fileItem.FileRef,
modified: modified,
modifiedDate: new Date(fileItem.Modified),
fileSize: fileItem.File_x0020_Size,
fileType: fileItem.File_x0020_Type,
modifiedBy: fileItem.Editor![0]!.title,
Expand Down
1 change: 1 addition & 0 deletions src/services/FileBrowserService.types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ export interface IFile {
serverRelativeUrl: string;
isFolder: boolean;
modified: string;
modifiedDate: Date;
modifiedBy?: string;


Expand Down

0 comments on commit 70fb2ab

Please sign in to comment.