Skip to content

Commit

Permalink
Merge branch 'joeljeffery-master' into dev
Browse files Browse the repository at this point in the history
  • Loading branch information
AJIXuMuK committed Jul 7, 2020
2 parents c8634be + 39cceca commit 97a9359
Show file tree
Hide file tree
Showing 12 changed files with 83 additions and 38 deletions.
1 change: 1 addition & 0 deletions docs/documentation/docs/controls/ListItemAttachments.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,5 +41,6 @@ The `ListItemAttachments` control can be configured with the following propertie
| listId | string | yes | Guid of the list. |
| webUrl | string | no | URL of the site. By default it uses the current site URL. |
| disabled | boolean | no | Specifies if the control is disabled or not. |
| openAttachmentsInNewWindow | boolean | no | Specifies if the attachment should be openend in a separate browser tab. Use this property set to `true` if you plan to use the component in Microsoft Teams. |

![](https://telemetry.sharepointpnp.com/sp-dev-fx-controls-react/wiki/controls/ListItemAttachments)
1 change: 1 addition & 0 deletions docs/documentation/docs/controls/ListItemPicker.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,5 +61,6 @@ The `ListItemPicker` control can be configured with the following properties:
| disabled | boolean | no | Specifies if the control is disabled or not. |
| filter | string | no | condition to filter list Item, same as $filter ODATA parameter|
| placeholder | string | no | Short text hint to display in empty picker |
| substringSearch | boolean | no | Specifies if substring search should be used |

![](https://telemetry.sharepointpnp.com/sp-dev-fx-controls-react/wiki/controls/ListItemPicker)
2 changes: 2 additions & 0 deletions docs/documentation/docs/controls/Map.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,8 @@ The `Map` control can be configured with the following properties:
| ---- | ---- | ---- | ---- | ---- |
| latitude | number | yes | Latitude of the map to display. | |
| longitude | number | yes | Longitude of the map to display. | |
| displayName | string | no | Display Name of the location. | |
| address | any | no | Address of the location. | |

`MapType` enum:

Expand Down
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,8 @@
"@pnp/telemetry-js": "2.0.0",
"@types/chart.js": "2.7.40",
"chart.js": "2.7.3",
"color": "3.1.2",
"lodash": "4.17.3",
"color": "^3.1.2",
"lodash": "4.17.13",
"office-ui-fabric-react": "5.131.0",
"react-quill": "1.3.3"
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,5 @@ export interface IListItemAttachmentsProps {
webUrl?:string;
disabled?: boolean;
context: WebPartContext | ExtensionContext;
openAttachmentsInNewWindow?: boolean; // JJ - 20200613 - needed to support Microsoft Teams
}
4 changes: 3 additions & 1 deletion src/controls/listItemAttachments/ListItemAttachments.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,7 @@ export class ListItemAttachments extends React.Component<IListItemAttachmentsPro
* Default React render method
*/
public render() {
const { openAttachmentsInNewWindow } = this.props;
return (
<div className={styles.ListItemAttachments}>
<UploadAttachment
Expand Down Expand Up @@ -208,7 +209,8 @@ export class ListItemAttachments extends React.Component<IListItemAttachmentsPro
directionalHint={DirectionalHint.rightCenter}>

<DocumentCard
onClickHref={`${file.ServerRelativeUrl}?web=1`}
onClickHref={!openAttachmentsInNewWindow && `${file.ServerRelativeUrl}?web=1`}
onClick={openAttachmentsInNewWindow && (() => window.open(`${file.ServerRelativeUrl}?web=1`, "_blank"))} // JJ - 20200613 - needed to support Microsoft Teams
className={styles.documentCard}>
<DocumentCardPreview previewImages={[previewImage]} />
<Label className={styles.fileLabel}>{fileName}</Label>
Expand Down
1 change: 1 addition & 0 deletions src/controls/listItemPicker/IListItemPickerProps.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ export interface IListItemPickerProps {
disabled?: boolean;
suggestionsHeaderText?:string;
noResultsFoundText?:string;
substringSearch?: boolean; // JJ - 20200613 - find by substring as an option
/**
* Placeholder to be displayed in an empty term picker
*/
Expand Down
4 changes: 2 additions & 2 deletions src/controls/listItemPicker/ListItemPicker.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -115,12 +115,12 @@ export class ListItemPicker extends React.Component<IListItemPickerProps, IListI
* Function to load List Items
*/
private loadListItems = async (filterText: string): Promise<{ key: string; name: string }[]> => {
let { listId, columnInternalName, keyColumnInternalName, webUrl, filter } = this.props;
let { listId, columnInternalName, keyColumnInternalName, webUrl, filter, substringSearch } = this.props;
let arrayItems: { key: string; name: string }[] = [];
let keyColumn: string = keyColumnInternalName || 'Id';

try {
let listItems = await this._spservice.getListItems(filterText, listId, columnInternalName, keyColumn, webUrl, filter);
let listItems = await this._spservice.getListItems(filterText, listId, columnInternalName, keyColumn, webUrl, filter, substringSearch); // JJ - 20200613 - find by substring as an option
// Check if the list had items
if (listItems.length > 0) {
for (const item of listItems) {
Expand Down
9 changes: 9 additions & 0 deletions src/controls/map/IMap.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,14 @@ export interface ICoordinates {
* Longitude of the map to display
*/
longitude: number;
/**
* Display Name of the location
*/
displayName?: string; // 20200614 - JJ - displayname
/**
* Address of the location
*/
address?: any; // 20200614 - JJ - address
}

export enum MapType {
Expand All @@ -30,4 +38,5 @@ export interface LocationInfo {
type: string;
importance: number;
icon: string;
address?: any; // 20200614 - JJ - the address data from nominatim
}
1 change: 1 addition & 0 deletions src/controls/map/IMapProps.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { ICoordinates, MapType } from ".";

export interface IMapProps {
mapSource?: "OpenStreetMap" | "BingStatic" | "BingDraggable";
/**
* Text of the Control
*/
Expand Down
87 changes: 56 additions & 31 deletions src/controls/map/Map.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,12 @@ export class Map extends React.Component<IMapProps, IMapState> {

constructor(props: IMapProps) {
super(props);
const { coordinates } = this.props;

telemetry.track('ReactMap', {});

this.state = {
coordinates: {
coordinates: coordinates || {
latitude: null,
longitude: null
},
Expand All @@ -35,11 +36,11 @@ export class Map extends React.Component<IMapProps, IMapState> {
/**
* componentWillMount lifecycle hook
*/
public componentWillMount(): void {
this.setState({
coordinates: this.props.coordinates
});
}
// public componentWillMount(): void {
// this.setState({
// coordinates: this.props.coordinates
// });
// }

/**
* componentWillUpdate lifecycle hook
Expand All @@ -56,8 +57,11 @@ export class Map extends React.Component<IMapProps, IMapState> {
* Get the dif value based on zoom supplied (dif is for calculating the 4 corners of the map)
*/
private _getDif(): number {
let zoom: number = this.props.zoom >= 0 ? this.props.zoom : 10;
return 0.0025 + (0.005 * (15 - zoom));
const { zoom } = this.props;
// 20200614 - JJ - support zoom levels beyond 15
const newZoom: number = zoom >= 0 ? zoom % 16 : 10;
const multiplier = Math.floor(newZoom / 16) + 1;
return (0.0025 + (0.005 * (15 - (newZoom))))/multiplier;
}

/**
Expand Down Expand Up @@ -115,20 +119,39 @@ export class Map extends React.Component<IMapProps, IMapState> {
}

/**
* Get coordinates using the Bing API
* Gets map url for a static Bing map
*
* @private
* @param {(string | number)} width
* @param {(string | number)} height
* @returns {string}
* @memberof Map
*/
private _getBingMapUrl(width: string | number, height: string | number): string {
const { mapSource, zoom } = this.props;
const { coordinates: {latitude, longitude}} = this.state;
const mapType = mapSource === "BingStatic" ? "s" : "d";// s for static or d for draggable
return `https://www.bing.com/maps/embed?h=${height}&w=${width}&cp=${latitude}~${longitude}&lvl=${zoom}&typ=${mapType}&sty=r`;
}

/**
* Get coordinates using the OpenStreetMap nominatim API
*/
//20200614 - updated comment to reflect API used
private _getCoordinates = async (): Promise<void> => {
this._startLoading();

try {
const response = await fetch(`https://nominatim.openstreetmap.org/search?format=json&limit=1&q=${this.state.address}`);
const response = await fetch(`https://nominatim.openstreetmap.org/search?format=json&limit=1&addressdetails=1&q=${this.state.address}`); // 20200614 - JJ - added addressdetails parameter
const mapData: LocationInfo[] = await response.json();
if (mapData && mapData.length > 0) {
const location = mapData[0];

const coordinates = {
const coordinates: ICoordinates = { // 20200614 - JJ - added typing
latitude: parseFloat(location.lat),
longitude: parseFloat(location.lon)
longitude: parseFloat(location.lon),
displayName: location.display_name, // 20200614 - JJ - let's keep the display name
address: location.address, // 20200614 - JJ - and the address
};

this.setState({
Expand Down Expand Up @@ -183,9 +206,10 @@ export class Map extends React.Component<IMapProps, IMapState> {
* Default React render method
*/
public render(): React.ReactElement<IMapProps> {
const { mapSource } = this.props;
let width: string = this._getWidth();
let height: number = this._getHeight();
let mapUrl: string = this._getMapUrl();
let mapUrl: string = ["BingDraggable", "BingStatic"].indexOf(mapSource) !== -1 ? this._getBingMapUrl(width, height) : this._getMapUrl(); //20200614 - JJ - rudimentary bing map support (draggable/static) with pushpin (static only)

return (
<div id="mapsContainer" className={`${styles.mapContainer} ${this.props.mapsClassName ? this.props.mapsClassName : ''}`}>
Expand All @@ -199,16 +223,16 @@ export class Map extends React.Component<IMapProps, IMapState> {
(this.props.enableSearch) && (
<div id="mapsSearch" className={styles.searchContainer}>
<TextField value={this.state.address}
onChanged={this._onChangedAddress}
onKeyPress={(event) => event.key === "Enter" ? this._getCoordinates() : null}
iconProps={{ iconName: 'World' }}
className={styles.searchTextBox} />
onChanged={this._onChangedAddress}
onKeyPress={(event) => event.key === "Enter" ? this._getCoordinates() : null}
iconProps={{ iconName: 'World' }}
className={styles.searchTextBox} />

<PrimaryButton text={strings.mapsSearchButtonText}
title={strings.mapsSearchButtonText}
className={styles.submitButton}
iconProps={{ iconName: 'Search' }}
onClick={this._getCoordinates} />
title={strings.mapsSearchButtonText}
className={styles.submitButton}
iconProps={{ iconName: 'Search' }}
onClick={this._getCoordinates} />
</div>
)
}
Expand All @@ -217,17 +241,18 @@ export class Map extends React.Component<IMapProps, IMapState> {
this.state.loading ? (
<Spinner size={SpinnerSize.large} label={this.props.loadingMessage ? this.props.loadingMessage : strings.mapsLoadingText} />
) : (
(mapUrl.length > 0 && !this.state.showmessageerror) ? (
<div id="mapsIframe">
<iframe width={width} height={height} scrolling="no" src={mapUrl}></iframe>
</div>
) : (
<p className={`ms-TextField-errorMessage ${styles.errorMessage} ${this.props.errorMessageClassName ? this.props.errorMessageClassName : ''}`}>
<Icon iconName='Error' className={styles.errorIcon} />
<span data-automation-id="error-message">{this.props.errorMessage ? this.props.errorMessage : strings.mapsErrorMessage}</span>
</p>
(mapUrl.length > 0 && !this.state.showmessageerror) ? (
<div id="mapsIframe">
<iframe width={width} height={height} scrolling="no" src={mapUrl}></iframe>
{mapSource === "BingStatic" && <Icon iconName="Location" style={{fontSize: "26px", position:"relative", top: (Math.floor(-height/2)), left: "50%", marginTop: "-14px"}} ></Icon>}{/* 20200614 - JJ - rudimentary bing map support (draggable/static) with pushpin (static only)*/}
</div>
) : (
<p className={`ms-TextField-errorMessage ${styles.errorMessage} ${this.props.errorMessageClassName ? this.props.errorMessageClassName : ''}`}>
<Icon iconName='Error' className={styles.errorIcon} />
<span data-automation-id="error-message">{this.props.errorMessage ? this.props.errorMessage : strings.mapsErrorMessage}</span>
</p>
)
)
)
}
</div>
);
Expand Down
6 changes: 4 additions & 2 deletions src/services/SPService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,9 +47,11 @@ export default class SPService implements ISPService {
/**
* Get List Items
*/
public async getListItems(filterText: string, listId: string, internalColumnName: string, keyInternalColumnName?: string, webUrl?: string, filter?: string ): Promise<any[]> {
public async getListItems(filterText: string, listId: string, internalColumnName: string, keyInternalColumnName?: string, webUrl?: string, filter?: string, substringSearch: boolean = false ): Promise<any[]> {
let returnItems: any[];
const filterStr = `startswith(${internalColumnName},'${encodeURIComponent(filterText.replace("'","''"))}')${filter ? ' and ' + filter : ''}`; //string = filterList ? `and ${filterList}` : '';
const filterStr = substringSearch ? // JJ - 20200613 - find by substring as an option
`substringof('${encodeURIComponent(filterText.replace("'","''"))}',${internalColumnName})${filter ? ' and ' + filter : ''}`
: `startswith(${internalColumnName},'${encodeURIComponent(filterText.replace("'","''"))}')${filter ? ' and ' + filter : ''}`; //string = filterList ? `and ${filterList}` : '';
try {
const webAbsoluteUrl = !webUrl ? this._context.pageContext.web.absoluteUrl : webUrl;
const apiUrl = `${webAbsoluteUrl}/_api/web/lists('${listId}')/items?$select=${keyInternalColumnName || 'Id'},${internalColumnName}&$filter=${filterStr}`;
Expand Down

0 comments on commit 97a9359

Please sign in to comment.