Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Module/map/backend v2 #550

Merged
merged 2 commits into from
Aug 28, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 7 additions & 6 deletions src/mocks/maps.mock.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,18 @@ import {
IMapPin,
IMapPinDetail,
IPinType,
IDatabaseMapPin,
EntityType,
} from 'src/models/maps.models'
import { MOCK_DB_META } from './db.mock'

export const generatePins = (count: number): Array<IDatabaseMapPin> => {
export const generatePins = (count: number): Array<IMapPin> => {
const filters = generatePinFilters()
const newPins = [] as Array<IDatabaseMapPin>
const newPins = [] as Array<IMapPin>
for (let i = 0; i < count; i++) {
const pinType = filters[Math.floor(Math.random() * filters.length)]

newPins.push({
id: '' + Math.random(),
...MOCK_DB_META(),
location: {
address: 'testing',
lat: 51 + (Math.random() * 1000 - 500) / 500,
Expand All @@ -27,8 +27,9 @@ export const generatePins = (count: number): Array<IDatabaseMapPin> => {
}

export const generatePinDetails = (pin: IMapPin): IMapPinDetail => {
const lastActive = new Date()
lastActive.setSeconds(lastActive.getSeconds() - Math.random() * 10000)
const randomDate = new Date()
randomDate.setSeconds(randomDate.getSeconds() - Math.random() * 10000)
const lastActive = randomDate.toISOString()
return {
...pin,
name: loremIpsum({ count: 2, units: 'words' })
Expand Down
16 changes: 8 additions & 8 deletions src/models/maps.models.tsx
Original file line number Diff line number Diff line change
@@ -1,23 +1,23 @@
export interface IDatabaseMapPin {
id: string
import { IDbDoc, ISODateString } from './common.models'

interface IMapPinBase {
_id: string
location: ILatLng & {
address: string
}
}
export interface IMapPin extends IMapPinBase {
pinType: string
}

export interface IMapPin {
id: string
location: ILatLng & {
address: string
}
export interface IMapPinWithType extends IMapPinBase {
pinType: IPinType
}

export interface IMapPinDetail extends IMapPin {
name: string
shortDescription: string
lastActive: Date
lastActive: ISODateString
profilePicUrl: string
profileUrl: string
heroImageUrl: string
Expand Down
1 change: 1 addition & 0 deletions src/models/user.models.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ export interface ILink {
export interface IUser extends IDbDoc {
// authID is additional id populated by firebase auth, required for some auth operations
_authID: string
_lastActive?: ISODateString
// userName is same as legacy 'mention_name', e.g. @my-name. It will also be the doc _id and
// firebase auth displayName property
userName: string
Expand Down
2 changes: 1 addition & 1 deletion src/pages/Maps/Content/Controls/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ class Controls extends React.Component<IProps> {
position: 'absolute',
left: '10%',
borderRadius: '5px',
zIndex: 99999,
zIndex: 2,
marginTop: '30px',
}}
>
Expand Down
8 changes: 4 additions & 4 deletions src/pages/Maps/Content/View/Cluster.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,10 @@ import 'react-leaflet-markercluster/dist/styles.min.css'

import { createClusterIcon, createMarkerIcon } from './Sprites'

import { IMapPin, IPinType, EntityType } from 'src/models/maps.models'
import { IPinType, EntityType, IMapPinWithType } from 'src/models/maps.models'

interface IProps {
pins: Array<IMapPin>
pins: Array<IMapPinWithType>
onPinClick: (pin: IPinType) => void
}

Expand All @@ -23,7 +23,7 @@ export const Clusters: React.SFC<IProps> = ({ pins, onPinClick }) => {
accumulator[grouping].push(pin)
return accumulator
},
{} as Record<EntityType, Array<IMapPin>>,
{} as Record<EntityType, Array<IMapPinWithType>>,
)

return (
Expand All @@ -37,7 +37,7 @@ export const Clusters: React.SFC<IProps> = ({ pins, onPinClick }) => {
>
{entities[key].map(pin => (
<Marker
key={pin.id}
key={pin._id}
position={[pin.location.lat, pin.location.lng]}
icon={createMarkerIcon(pin)}
onClick={() => {
Expand Down
2 changes: 1 addition & 1 deletion src/pages/Maps/Content/View/Popup.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ export class Popup extends React.Component<IProps> {

if (
prevProps.pinDetail === undefined ||
prevProps.pinDetail.id !== this.props.pinDetail!.id
prevProps.pinDetail._id !== this.props.pinDetail!._id
) {
this.setPinLocation(this.props.pinDetail)
}
Expand Down
4 changes: 2 additions & 2 deletions src/pages/Maps/Content/View/Sprites.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import L from 'leaflet'
import './sprites.css'
import { IMapPin } from 'src/models/maps.models'
import { IMapPinWithType } from 'src/models/maps.models'

// mmm curry
export const createClusterIcon = clusterKey => {
Expand All @@ -13,7 +13,7 @@ export const createClusterIcon = clusterKey => {
}
}

export const createMarkerIcon = (pin: IMapPin) => {
export const createMarkerIcon = (pin: IMapPinWithType) => {
const { grouping, icon } = pin.pinType
return icon === ''
? L.divIcon({
Expand Down
13 changes: 11 additions & 2 deletions src/pages/Maps/Content/View/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,11 @@ import {
ILatLng,
IBoundingBox,
IPinType,
IMapPinWithType,
} from 'src/models/maps.models'

interface IProps {
pins: Array<IMapPin>
pins: Array<IMapPinWithType>
filters: Array<IPinType>
onBoundingBoxChange: (boundingBox: IBoundingBox) => void
onPinClicked: (pin: IMapPin) => void
Expand Down Expand Up @@ -67,7 +68,7 @@ class MapView extends React.Component<IProps, IState> {
center={[center.lat, center.lng]}
zoom={zoom}
maxZoom={18}
style={{ height: '100%' }}
style={{ height: '100%', zIndex: 1 }}
onMove={this.updateBoundingBox}
>
<TileLayer
Expand All @@ -79,6 +80,14 @@ class MapView extends React.Component<IProps, IState> {
</Map>
)
}
static defaultProps: Partial<IProps> = {
onBoundingBoxChange: () => null,
onPinClicked: () => null,
pins: [],
filters: [],
center: { lat: 51.0, lng: 19.0 },
zoom: 3,
}
}

export { MapView }
5 changes: 5 additions & 0 deletions src/pages/Maps/Maps.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,11 @@ class MapsPageClass extends React.Component<IProps, IState> {
this.props.mapsStore.retrievePinFilters()
}

public async componentWillUnmount() {
console.log('map pins unmount')
this.props.mapsStore.removeSubscriptions()
}

private setCenter(location) {
this.setState({
center: location.latlng as ILatLng,
Expand Down
2 changes: 2 additions & 0 deletions src/pages/Settings/SettingsPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import { TextNotification } from 'src/components/Notification/TextNotification'
import { Flex } from 'rebass'
import { Avatar } from 'src/components/Avatar'
import Text from 'src/components/Text'
import { UserMapPinEdit } from './content/UserMapPinEdit'

interface IProps {
user: IUser
Expand Down Expand Up @@ -59,6 +60,7 @@ export class UserSettings extends React.Component<IProps, IState> {
</BoxContainer>

<SettingsEditForm onProfileSave={() => this.showSaveNotification()} />
<UserMapPinEdit />
</BoxContainer>
{/* post guidelines container */}
<BoxContainer
Expand Down
123 changes: 20 additions & 103 deletions src/pages/Settings/content/SettingsEdit.form.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,16 +21,12 @@ import { getCountryCode } from 'src/utils/helpers'
import 'react-flags-select/scss/react-flags-select.scss'
import styled from 'styled-components'
import theme from 'src/themes/styled.theme'

import { Map, TileLayer, Marker, Popup, ZoomControl } from 'react-leaflet'
import L from 'leaflet'
import 'leaflet/dist/leaflet.css'
import { LocationSearchField } from 'src/components/Form/LocationSearch.field'
import { FieldArray } from 'react-final-form-arrays'
import { Link } from './Link.field'
import { timestampToYear } from 'src/utils/helpers'
import { Icon } from 'src/components/Icons'
import { toJS } from 'mobx'
import { ISODateString } from 'src/models/common.models'
import { ILocation } from 'src/components/LocationSearch/LocationSearch'

interface IFormValues extends Partial<IUser> {
// form values are simply subset of user profile fields
Expand All @@ -48,10 +44,6 @@ interface IState {
showYearSelector?: boolean
showNotification?: boolean
showComLinks?: boolean
showMap?: boolean
lat: number
lng: number
zoom: number
}

// validation - return undefined if no error (i.e. valid)
Expand All @@ -63,12 +55,6 @@ const FlagSelectContainer = styled(Flex)`
height: 40px;
`

const customMarker = L.icon({
iconUrl: require('src/assets/icons/map-marker.png'),
iconSize: [20, 28],
iconAnchor: [20, 56],
})

const YearBox = styled(Box)`
${inputStyles}
cursor: pointer;
Expand All @@ -92,32 +78,15 @@ export class SettingsEditForm extends React.Component<IProps, IState> {
formValues: user ? user : {},
readOnly: true,
showYearSelector: false,
showComLinks: true,
showMap: true,
lat: 51.4416,
lng: 5.4697,
zoom: 8,
}
if (user) {
if (user.links) {
this.setState({ showComLinks: false })
}
if (user.location) {
this.setState({ showMap: false })
}
showComLinks: user && user.links ? true : false,
}
this.changeComLinkSwitch = this.changeComLinkSwitch.bind(this)
this.changeMapSwitch = this.changeMapSwitch.bind(this)
}

public changeComLinkSwitch() {
this.setState({ showComLinks: !this.state.showComLinks })
}

public changeMapSwitch() {
this.setState({ showMap: !this.state.showMap })
}

get injected() {
return this.props as IInjectedProps
}
Expand All @@ -130,20 +99,21 @@ export class SettingsEditForm extends React.Component<IProps, IState> {
this.setState({ readOnly: true, showNotification: true })
}

public displayYear(date: ISODateString) {
return new Date(date).getFullYear()
}

public onLocationChange(v) {
this.setState({ lat: v.latlng.lat, lng: v.latlng.lng, zoom: 15 })
public displayYear(dateOrTmstp) {
// if date comes from db, it will be formated in firebase.Timestamp whereas if it comes from calendar (user modifications) it's a Date object
// this fn check the type of the date and return a year in format YYYY
if (dateOrTmstp instanceof Date && !isNaN(dateOrTmstp.valueOf())) {
return dateOrTmstp.getFullYear()
} else {
return timestampToYear(dateOrTmstp.seconds)
}
}

render() {
const user = this.injected.userStore.user
// Need to convert mobx observable user object into a Javasrcipt structure using toJS fn
// to allow final-form-array to display the initial values
const initialFormValues = toJS(user)
const { lat, lng, zoom } = this.state

return user ? (
<Form
Expand Down Expand Up @@ -247,70 +217,17 @@ export class SettingsEditForm extends React.Component<IProps, IState> {
)}
</FieldArray>
</HideShowBox>
</BoxContainer>
<BoxContainer id="your-map-pin" mt={4}>
<Heading small bold>
Your map pin
</Heading>
<Flex wrap={'nowrap'} alignItems={'center'}>
<Text inline>Add me to the map</Text>
<Switch
checked={this.state.showMap}
onChange={this.changeMapSwitch}
/>
</Flex>
<HideShowBox disabled={this.state.showMap}>
<Field
name="about"
component={TextAreaField}
placeholder="About"
/>
<Field
name={
user && user.location
? `${user.location.value}`
: 'location'
}
customChange={v => this.onLocationChange(v)}
component={LocationSearchField}
/>
<Map
center={
user.location
? [user.location.latlng.lat, user.location.latlng.lng]
: [lat, lng]
}
zoom={zoom}
zoomControl={false}
style={{
height: '300px',
zIndex: 1,
}}
>
<ZoomControl position="topright" />
<TileLayer
attribution='&amp;copy <a href="http://osm.org/copyright">OpenStreetMap</a> contributors'
url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
/>
<Marker
position={
user.location && user.location.latlng
? [
user.location.latlng.lat,
user.location.latlng.lng,
]
: [lat, lng]
}
icon={customMarker}
>
<Popup maxWidth={225} minWidth={225}>
Add more content here later
</Popup>
</Marker>
</Map>
</HideShowBox>
<Text width={1} mt={2} medium>
About Me
</Text>
<Field
name="about"
component={TextAreaField}
placeholder="About"
/>
</BoxContainer>
</form>
{/* Map update separate to rest of form */}
</>
)
}}
Expand Down
Loading