First Release

This commit is contained in:
Sergej Schwabauer 2022-03-03 16:59:12 +01:00
parent ace849b28e
commit 4c9a148dbf
13 changed files with 60 additions and 36 deletions

View File

@ -19,3 +19,4 @@ npm i react-leaflet-markercluster
npm run serve
npm install @pnp/spfx-property-controls --save --save-exact
npm run serve
gulp clean; gulp build; gulp bundle --ship; gulp package-solution --ship;

View File

@ -1,25 +1,25 @@
{
"$schema": "https://developer.microsoft.com/json-schemas/spfx-build/package-solution.schema.json",
"solution": {
"name": "SPFx app dev Map Webpart",
"name": "SPFx app dev - interactive map webpart",
"id": "cc048abe-6531-4295-ab7a-12a1c95de606",
"version": "1.0.0.0",
"includeClientSideAssets": true,
"skipFeatureDeployment": true,
"isDomainIsolated": false,
"developer": {
"name": "",
"websiteUrl": "",
"name": "Sergej Schwabauer",
"websiteUrl": "https://spfx-app.dev/",
"privacyUrl": "",
"termsOfUseUrl": "",
"mpnId": "Undefined-1.14.0"
},
"metadata": {
"shortDescription": {
"default": "spfxappdev.webparts.map description"
"default": "Includes an interactive map module with which you can create markers"
},
"longDescription": {
"default": "spfxappdev.webparts.map description"
"default": "Includes an interactive map module with which you can create markers"
},
"screenshotPaths": [],
"videoUrl": "",

View File

@ -3,6 +3,7 @@
const build = require('@microsoft/sp-build-web');
build.addSuppression(`Warning - [sass] The local CSS class 'ms-Grid' is not camelCase and will not be type-safe.`);
build.addSuppression(/Warning - \[sass\] The local CSS class/gi);
var getTasks = build.rig.getTasks;
build.rig.getTasks = function () {

View File

@ -1,6 +1,6 @@
{
"name": "spfxappdev-webparts-map",
"version": "0.0.1",
"version": "1.0.0",
"private": true,
"main": "lib/index.js",
"scripts": {

View File

@ -21,7 +21,7 @@ export class InlineColorPicker extends React.Component<IInlineColorPickerProps,
public static defaultProps: IInlineColorPickerProps = {
color: '#000000',
isDisbaled: false
}
};
private targetElement: HTMLDivElement = null;

View File

@ -24,11 +24,12 @@
"de-de": "Interaktive Karte"
},
"description": {
"default": "Map description"
"default": "An interactive map with which you can create markers",
"de-de": "Eine interactive Karte mit der man Markierungen erstellen kann"
},
"officeFabricIconFontName": "MapPin",
"properties": {
"title": "Map",
"title": "",
"markerItems": [],
"markerCategories": [],
"center": [51.505, -0.09],

View File

@ -215,8 +215,13 @@ export default class MapWebPart extends BaseClientSideWebPart<IMapWebPartProps>
groupName: strings.WebPartPropertyGroupAbout,
groupFields: [
PropertyPaneWebPartInformation({
description: `This is a <strong>demo webpart</strong>, used to demonstrate all the <a href="https://aka.ms/sppnp">PnP</a> property controls`,
moreInfoLink: `https://pnp.github.io/sp-dev-fx-property-controls/`,
description: `<h3>Author</h3>
<a href='https://spfx-app.dev/'>SPFx-App.dev</a>
<h3>Version</h3>
${this.context.manifest.version}
<h3>Web Part Instance id</h3>
${this.context.instanceId}`,
moreInfoLink: `https://spfx-app.dev/`,
key: '3f860b48-1dc3-496d-bd28-b145672289cc'
})
]

View File

@ -2,7 +2,7 @@
import * as React from 'react';
import { IMarker, IMarkerCategory, MarkerType } from './IMapProps';
import './Map.module.scss';
import { clone } from '@microsoft/sp-lodash-subset';
import { cloneDeep } from '@microsoft/sp-lodash-subset';
import { Icon, Panel, TextField, IPanelProps, PrimaryButton, DefaultButton, IChoiceGroupOption, ChoiceGroup, IDropdownOption, Dropdown, getColorFromString, IColor, PanelType, Label, TooltipHost } from 'office-ui-fabric-react';
import { Guid } from '@microsoft/sp-core-library';
import { isNullOrEmpty, isFunction } from '@spfxappdev/utility';
@ -35,9 +35,9 @@ interface IAddOrEditPanelState {
export default class AddOrEditPanel extends React.Component<IAddOrEditPanelProps, IAddOrEditPanelState> {
public state: IAddOrEditPanelState = {
markerItem: clone(this.props.markerItem),
markerCategories: clone(this.props.markerCategories),
isSaveButtonDisabled: true,
markerItem: cloneDeep(this.props.markerItem),
markerCategories: cloneDeep(this.props.markerCategories),
isSaveButtonDisabled: false,
isManageCategoriesDialogVisible: false
};
@ -63,7 +63,18 @@ export default class AddOrEditPanel extends React.Component<IAddOrEditPanelProps
this.isNewMarker = this.props.markerItem.id.Equals(Guid.empty.toString());
this.headerText = this.isNewMarker ? strings.PanelHeaderNewLabel : strings.PanelHeaderEditLabel;
}
public componentDidUpdate(prevProps: Readonly<IAddOrEditPanelProps>, prevState: Readonly<IAddOrEditPanelState>, snapshot?: any): void {
if(!JSON.stringify(prevProps.markerCategories).Equals(JSON.stringify(this.props.markerCategories)) ||
!JSON.stringify(prevProps.markerItem).Equals(JSON.stringify(this.props.markerItem))) {
this.setState({
markerCategories: cloneDeep(this.props.markerCategories),
markerItem: cloneDeep(this.props.markerItem),
isSaveButtonDisabled: false
});
}
}
public render(): React.ReactElement<IAddOrEditPanelProps> {
@ -74,7 +85,7 @@ export default class AddOrEditPanel extends React.Component<IAddOrEditPanelProps
<Panel
type={PanelType.medium}
isOpen={true}
onDismiss={() => { this.onConfigPanelDismiss() }}
onDismiss={() => { this.onConfigPanelDismiss(); }}
headerText={this.headerText}
closeButtonAriaLabel={strings.CloseLabel}
onRenderFooterContent={(props: IPanelProps) => {
@ -233,7 +244,7 @@ export default class AddOrEditPanel extends React.Component<IAddOrEditPanelProps
return (<></>);
}
const headerLabel: string = this.state.markerItem.type == "Dialog" ? strings.LabelDialogHeader : strings.LabelPanelHeader
const headerLabel: string = this.state.markerItem.type == "Dialog" ? strings.LabelDialogHeader : strings.LabelPanelHeader;
return (<>
<TextField label={headerLabel} defaultValue={this.state.markerItem.markerClickProps.content.headerText} onChange={(ev: any, headerText: string) => {
@ -255,7 +266,7 @@ export default class AddOrEditPanel extends React.Component<IAddOrEditPanelProps
return content;
}} />
</>)
</>);
}
private renderUrlSettings(): JSX.Element {

View File

@ -6,18 +6,18 @@ export type MarkerType = "Panel"|"Dialog"|"Url"|"None";
export interface IMarkerClickProps {
url: IMarkerUrlProperties;
content: IMarkerContentProperties
content: IMarkerContentProperties;
}
export interface IMarkerUrlProperties {
href: string;
target: '_self'|'_blank'|'embedded';
};
}
export interface IMarkerContentProperties {
headerText: string;
html: string;
};
}
export interface IMarkerIcon {
markerColor: string;

View File

@ -1,7 +1,7 @@
import * as React from 'react';
import { IMarkerCategory } from './IMapProps';
import './Map.module.scss';
import { clone } from '@microsoft/sp-lodash-subset';
import { cloneDeep } from '@microsoft/sp-lodash-subset';
import { Icon, Dialog, TextField, PrimaryButton, DefaultButton, getColorFromString, IColor, DialogFooter, DialogContent, DialogType, MessageBar, TooltipHost } from 'office-ui-fabric-react';
import { Guid } from '@microsoft/sp-core-library';
import { isNullOrEmpty, isFunction } from '@spfxappdev/utility';
@ -28,7 +28,7 @@ interface IManageMarkerCategoriesDialogState {
export default class ManageMarkerCategoriesDialog extends React.Component<IManageMarkerCategoriesDialogProps, IManageMarkerCategoriesDialogState> {
public state: IManageMarkerCategoriesDialogState = {
markerCategories: clone(this.props.markerCategories),
markerCategories: cloneDeep(this.props.markerCategories),
isSaveButtonDisabled: false,
isNewFormVisible: false,
isDialogVisible: true
@ -39,7 +39,7 @@ export default class ManageMarkerCategoriesDialog extends React.Component<IManag
}
componentDidMount(): void {
public componentDidMount(): void {
this.validateForm();
}
@ -89,7 +89,7 @@ export default class ManageMarkerCategoriesDialog extends React.Component<IManag
{this.state.markerCategories.map((cat: IMarkerCategory, index: number): JSX.Element => {
return (<div key={cat.id} className='spfxappdev-grid-row categories-grid' data-catid={cat.id}>
{this.renderForm(cat, index)}
</div>)
</div>);
})}
</>
}

View File

@ -252,4 +252,8 @@
.category-messagebar {
margin-bottom: 10px;
}
.CanvasControlToolbar {
z-index: 2000 !important;
}
}

View File

@ -2,7 +2,7 @@ import * as React from 'react';
import * as ReactDom from 'react-dom';
import styles from './Map.module.scss';
import { IMapProps, IMarker, IMarkerCategory, IMarkerIcon, emptyMarkerItem } from './IMapProps';
import { clone } from '@microsoft/sp-lodash-subset';
import { cloneDeep } from '@microsoft/sp-lodash-subset';
import { MapContainer, TileLayer, Marker, Popup } from 'react-leaflet';
import "leaflet/dist/leaflet.css";
import "react-leaflet-markercluster/dist/styles.min.css";
@ -33,8 +33,8 @@ interface IMapState {
export default class Map extends React.Component<IMapProps, IMapState> {
public state: IMapState = {
markerItems: clone(this.props.markerItems),
markerCategories: clone(this.props.markerCategories),
markerItems: cloneDeep(this.props.markerItems),
markerCategories: cloneDeep(this.props.markerCategories),
showAddOrEditMarkerPanel: false,
showClickContent: false,
changePositionMarkerId: '-1'
@ -71,14 +71,14 @@ export default class Map extends React.Component<IMapProps, IMapState> {
this.setAllCatagoriesDictionary();
}
componentDidUpdate(prevProps: Readonly<IMapProps>, prevState: Readonly<IMapState>, snapshot?: any): void {
public componentDidUpdate(prevProps: Readonly<IMapProps>, prevState: Readonly<IMapState>, snapshot?: any): void {
if(!JSON.stringify(prevProps.markerCategories).Equals(JSON.stringify(this.props.markerCategories))) {
this.setState({
markerCategories: this.props.markerCategories
markerCategories: cloneDeep(this.props.markerCategories)
}, () => {
this.setAllCatagoriesDictionary();
})
});
}
}
@ -105,6 +105,7 @@ export default class Map extends React.Component<IMapProps, IMapState> {
maxZoom={this.props.maxZoom}
scrollWheelZoom={isScrollWheelZoomEnabled}
touchZoom={isScrollWheelZoomEnabled}
doubleClickZoom={isScrollWheelZoomEnabled}
dragging={isDraggingEnabled}
whenCreated={(map: L.Map) => {
@ -329,7 +330,7 @@ export default class Map extends React.Component<IMapProps, IMapState> {
</div>
</div>
<Label style={{}}>{cat.name}</Label>
</div>)
</div>);
})}
</div>);
}
@ -352,7 +353,7 @@ export default class Map extends React.Component<IMapProps, IMapState> {
return (<Panel
type={PanelType.medium}
isOpen={true}
onDismiss={() => { this.onContentPanelOrDialogDismiss() }}
onDismiss={() => { this.onContentPanelOrDialogDismiss(); }}
headerText={this.state.currentMarker.markerClickProps.content.headerText}
closeButtonAriaLabel="Close"
onRenderFooterContent={(props: IPanelProps) => {
@ -521,12 +522,12 @@ export default class Map extends React.Component<IMapProps, IMapState> {
}
private onCreateNewMarkerContextMenuItemClick(): void {
this.state.currentMarker = clone(emptyMarkerItem);
this.state.currentMarker = cloneDeep(emptyMarkerItem);
this.state.currentMarker.latitude = this.lastLatLngRightClickPosition.lat;
this.state.currentMarker.longitude = this.lastLatLngRightClickPosition.lng;
this.state.showAddOrEditMarkerPanel = true;
this.setState({...this.state})
this.setState({...this.state});
}
private onSetStartView(): void {

View File

@ -18,4 +18,4 @@ export const MarkerIcon: React.FunctionComponent<IMarkerIcon> = (iconProperties)
<span className="map-icon" style={iconColor}><Icon iconName={iconProperties.iconName} /></span>
</span>
);
}
};