Merge pull request #3 from SPFxAppDev/feature/legend

Updated Legend control (UI)
This commit is contained in:
SPFxAppDev 2022-03-04 15:48:54 +01:00 committed by GitHub
commit 6644f13f32
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 151 additions and 59 deletions

View File

@ -172,47 +172,6 @@
border: solid 1px $ms-color-themeDarker !important;
}
.map-legend {
display: flex;
margin-top: 5px;
&-title {
font-weight: 700;
padding-right: 4px;
font-size: 12px;
}
&-marker-wrapper {
position: relative;
height: 36px;
float: left;
& > div {
position: absolute;
}
svg {
height: 18px !important;
}
.map-icon,
.map-icon i {
font-size: 6px;
}
.map-icon {
left: 3px;
top: 4px;
}
}
label {
margin: 0 10px 0 16px;
padding: 1px 0;
font-size: 12px;
}
}
.panel-footer {
button {
margin: 0 5px;

View File

@ -19,7 +19,8 @@ import { isFunction } from 'lodash';
import { MarkerIcon } from './MarkerIcon';
import MarkerClusterGroup from 'react-leaflet-markercluster';
import * as strings from 'MapWebPartStrings';
import SearchPlugin from './plugin/SearchPlugin';
import SearchPlugin from './plugins/search/SearchPlugin';
import LegendPlugin from './plugins/legend/LegendPlugin';
interface IMapState {
markerItems: IMarker[];
@ -151,9 +152,10 @@ export default class Map extends React.Component<IMapProps, IMapState> {
}
{this.renderSearchBox()}
{this.renderLegend(isZoomControlEnabled)}
</MapContainer>
{this.renderLegend()}
{this.props.isEditMode &&
<ContextualMenu
@ -319,26 +321,14 @@ export default class Map extends React.Component<IMapProps, IMapState> {
);
}
private renderLegend(): JSX.Element {
private renderLegend(isZoomControlEnabled: boolean): JSX.Element {
if(!getDeepOrDefault<boolean>(this.props, "plugins.legend", false) || isNullOrEmpty(this.state.markerCategories)) {
return (<></>);
}
return (
<div className='map-legend'>
<span className="map-legend-title">{strings.LegendLabel}:</span>
{this.state.markerCategories.map((cat: IMarkerCategory): JSX.Element => {
return (
<div key={`legend_${cat.id}`}>
<div className='map-legend-marker-wrapper'>
<div style={{}}>
<MarkerIcon {...cat.iconProperties} />
</div>
</div>
<Label style={{}}>{cat.name}</Label>
</div>);
})}
</div>);
<LegendPlugin isZoomControlVisible={isZoomControlEnabled} markerCategories={this.state.markerCategories} />
);
}
private renderSearchBox(): JSX.Element {

View File

@ -0,0 +1,62 @@
@import '~@microsoft/sp-office-ui-fabric-core/dist/sass/SPFabricCore.scss';
.map-plugin-legend {
display: block;
&-bottom {
top: 80px;
}
button {
outline: none;
border-radius: 2px;
height: 32px;
border: 2px solid rgba(0,0,0,0.2);
background-clip: padding-box;
font-size: 1.4em;
background: #fff;
cursor: pointer;
}
}
:global {
.map-legend {
margin: 10px;
&-title {
font-weight: 700;
// padding-right: 4px;
// font-size: 12px;
text-align: center;
font-size: 1.5em;
}
&-marker-item {
display: flex;
padding: 5px 10px;
align-items: center;
&-icon {
width: 35px;
}
}
&-marker-wrapper {
position: relative;
height: 36px;
// float: left;
& > div {
position: absolute;
}
}
label {
margin: 0 10px 0 16px;
padding: 1px 0;
font-size: 12px;
}
}
}

View File

@ -0,0 +1,82 @@
import { Callout } from '@microsoft/office-ui-fabric-react-bundle';
import { randomString } from '@spfxappdev/utility';
import * as strings from 'MapWebPartStrings';
import { Icon, Label, Separator } from 'office-ui-fabric-react';
import * as React from 'react';
import { IMarkerCategory } from '../../IMapProps';
import { MarkerIcon } from '../../MarkerIcon';
import styles from './LegendPlugin.module.scss';
export interface ILegendPluginProps {
markerCategories: IMarkerCategory[];
isZoomControlVisible: boolean;
}
interface ILegendPluginState {
isCalloutVisible: boolean;
}
export default class LegendPlugin extends React.Component<ILegendPluginProps, ILegendPluginState> {
public state: ILegendPluginState = {
isCalloutVisible: false
};
private randomId: string;
constructor(props: ILegendPluginProps) {
super(props);
this.randomId = `map_legend_${randomString(6)}`;
}
public render(): React.ReactElement<ILegendPluginProps> {
let cssClass = styles['map-plugin-legend'];
if(this.props.isZoomControlVisible) {
cssClass += ' ' + styles['map-plugin-legend-bottom'];
}
return (
<div className={`leaflet-top leaflet-left ${cssClass}`}>
<div className="leaflet-control leaflet-bar">
<button
type="button"
id={this.randomId}
onClick={() => {
const isVisible: boolean = this.state.isCalloutVisible ? false : true;
this.setState({
isCalloutVisible: isVisible
});
}}
>
<Icon iconName="Info" />
</button>
<Callout
target={`#${this.randomId}`}
onDismiss={() => { this.setState({ isCalloutVisible: false }); }}
hidden={!this.state.isCalloutVisible}>
<div className='map-legend'>
<Label className="map-legend-title">{strings.LegendLabel}</Label>
<Separator />
{this.props.markerCategories.map((cat: IMarkerCategory): JSX.Element => {
return (
<div key={`legend_${cat.id}`} className="map-legend-marker-item">
<div className='map-legend-marker-item-icon'>
<div className='map-legend-marker-wrapper'>
<div style={{}}>
<MarkerIcon {...cat.iconProperties} />
</div>
</div>
</div>
<Label>{cat.name}</Label>
</div>);
})}
</div>
</Callout>
</div>
</div>);
}
}

View File

@ -100,7 +100,6 @@ export default class SearchPlugin extends React.Component<ISearchPluginProps, IS
const response = await fetch(`${this.props.nominatimUrl}?format=json&limit=${this.props.resultLimit}&q=${searchTerm}`);
const responseJson = await response.json();
console.log("SSC", responseJson);
return responseJson;
}
}