Skip to content
This repository was archived by the owner on Aug 7, 2024. It is now read-only.

Commit 646eb38

Browse files
committed
resolved conflicts
1 parent 47cd7bb commit 646eb38

9 files changed

Lines changed: 194 additions & 37 deletions

File tree

components/map/Clusters.js

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,9 @@ import { Marker, useMap } from "react-leaflet";
44
import useSupercluster from "use-supercluster";
55
import UserMarker from "./UserMarker";
66
import styles from "./Clusters.module.css";
7+
import EventMarker from "./EventMarker";
78

8-
export default function Clusters({users}) {
9+
export default function Clusters({points}) {
910
const map = useMap();
1011
const mapB = map.getBounds();
1112
const [bounds, setBounds] = useState([
@@ -32,15 +33,15 @@ export default function Clusters({users}) {
3233
})
3334

3435
const { clusters, supercluster } = useSupercluster({
35-
points: users,
36+
points: points,
3637
bounds,
3738
zoom,
3839
options: {
3940
radius: zoom < 17 ? 75 : 50,
4041
maxZoom: 18
4142
}
4243
});
43-
44+
4445
const icons = {};
4546
const fetchIcon = (count) => {
4647
const size =
@@ -65,7 +66,8 @@ export default function Clusters({users}) {
6566
const {
6667
cluster: isCluster,
6768
point_count: pointCount,
68-
username
69+
username,
70+
name
6971
} = cluster.properties;
7072

7173
// we have a cluster to render
@@ -91,7 +93,9 @@ export default function Clusters({users}) {
9193
}
9294

9395
// we have a single point to render
94-
return (
96+
return cluster.properties.isEvent ? (
97+
<EventMarker event={cluster} key={name} />
98+
) : (
9599
<UserMarker user={cluster} key={username} />
96100
);
97101
})}

components/map/EventMarker.js

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
import L from "leaflet";
2+
import { Marker, Popup } from "react-leaflet";
3+
import { ReactMarkdown } from "react-markdown/lib/react-markdown";
4+
import Link from "@components/Link";
5+
6+
export default function EventMarker({event}) {
7+
// Custom component for rendering links within ReactMarkdown
8+
const LinkRenderer = ({ href, children }) => (
9+
<Link href={href}>
10+
{children}
11+
</Link>
12+
);
13+
14+
return (
15+
<Marker
16+
icon={L.icon({
17+
className: "rounded-full",
18+
iconUrl: `/placard.png`,
19+
popupAnchor: [0, -10],
20+
iconSize: [40, 40],
21+
iconAnchor: [20, 20],
22+
})}
23+
position={[event.geometry.coordinates[1], event.geometry.coordinates[0]]}
24+
>
25+
<Popup>
26+
<div className="flex flex-col gap-[5px]">
27+
<h1 className="font-[600]">
28+
<Link href={`${event.properties.url}`}>
29+
{event.properties.name}
30+
</Link>
31+
</h1>
32+
<span>
33+
{[
34+
event.properties.location.city,
35+
event.properties.location.state,
36+
event.properties.location.country,
37+
]
38+
.filter((x) => x)
39+
.join(", ")}
40+
</span>
41+
<span>
42+
<ReactMarkdown components={{ a: LinkRenderer }}>
43+
{event.properties.description}
44+
</ReactMarkdown>
45+
</span>
46+
<span>
47+
{`${new Date(event.properties.date.start).toLocaleDateString()} -
48+
${new Date(event.properties.date.end).toLocaleDateString()}`}
49+
</span>
50+
</div>
51+
</Popup>
52+
</Marker>
53+
)
54+
}

components/map/Map.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { MapContainer, TileLayer } from "react-leaflet";
22
import Clusters from "./Clusters";
33
import "leaflet/dist/leaflet.css";
44

5-
export default function Map({ users }) {
5+
export default function Map({ points }) {
66
const boundsMap = [
77
[-90, -180], // Southwest coordinates
88
[90, 180], // Northeast coordinates
@@ -23,7 +23,7 @@ export default function Map({ users }) {
2323
attribution='&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
2424
url="https://b.tile.openstreetmap.org/{z}/{x}/{y}.png"
2525
/>
26-
<Clusters users={users} />
26+
<Clusters points={points} />
2727
</MapContainer>
2828
);
2929
}

models/Profile.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,5 +100,6 @@ const ProfileSchema = new Schema(
100100
{ timestamps: true }
101101
);
102102

103+
103104
module.exports =
104105
mongoose.models.Profile || mongoose.model("Profile", ProfileSchema);

models/Profile/Event.js

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,14 @@ const EventSchema = new Schema({
3535
price: {
3636
startingFrom: Number,
3737
},
38+
location:{
39+
road:String,
40+
city:String,
41+
state:String,
42+
country:String,
43+
lat:Number,
44+
lon:Number
45+
}
3846
});
3947

4048
EventSchema.pre("save", () => {

pages/api/events.js

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,14 +12,29 @@ export default async function handler(req, res) {
1212
return res.status(200).json(events);
1313
}
1414

15-
export async function getEvents() {
15+
export async function getEvents(inMap = false) {
1616
let events = [];
1717
try {
1818
events = await Profile.aggregate([
1919
{ $project: { username: 1, events: 1, isEnabled: 1 } },
2020
{ $match: { "events.date.start": { $gt: new Date() }, isEnabled: true } },
2121
{ $unwind: "$events" },
2222
{ $match: { "events.date.end": { $gt: new Date() } } },
23+
...(inMap
24+
? [
25+
{
26+
$match: {
27+
$and: [
28+
{ "events.location": { $exists: true } },
29+
{ "events.location.lat": { $exists: true } },
30+
{ "events.location.lon": { $exists: true } },
31+
{ "events.location.lat": { $ne: null } },
32+
{ "events.location.lon": { $ne: null } },
33+
],
34+
},
35+
},
36+
]
37+
: []),
2338
{ $sort: { "events.date.start": 1 } },
2439
{
2540
$group: {
@@ -31,6 +46,7 @@ export async function getEvents() {
3146
url: { $first: "$events.url" },
3247
name: { $first: "$events.name" },
3348
description: { $first: "$events.description" },
49+
location: { $first: "$events.location" },
3450
isEnabled: { $first: "$isEnabled" },
3551
},
3652
},

pages/api/system/reload.js

Lines changed: 58 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -239,29 +239,68 @@ export default async function handler(req, res) {
239239
}
240240

241241
// - events
242-
try {
243-
if (profile.events) {
242+
async function getCoordinates(city, state, country) {
243+
let locationDb = {};
244+
const provided = [city, state, country].filter((x) => x).join(",");
245+
if (locationDb[provided]) {
246+
return locationDb[provided];
247+
}
248+
try {
249+
const location = await fetch(
250+
`https://nominatim.openstreetmap.org/?addressdetails=1&q=
251+
${encodeURIComponent(provided)}&format=json&limit=1`
252+
);
253+
const coordinates = await location.json();
254+
if (coordinates) {
255+
const point = {
256+
lat: coordinates[0].lat,
257+
lon: coordinates[0].lon,
258+
};
259+
locationDb[provided] = point;
260+
return point;
261+
}
262+
} catch (e) {
263+
return null;
264+
}
265+
return null;
266+
}
267+
268+
if (profile.events) {
269+
try {
270+
const events = await Promise.all(
271+
profile.events.map(async (event, position) => {
272+
let location = {};
273+
if (event.location) {
274+
location = {
275+
location: { ...event.location },
276+
};
277+
if (new Date(event.date.start) > Date.now() || new Date(event.date.end) > Date.now()) {
278+
const coordinates = await getCoordinates(
279+
event.location.city,
280+
event.location.state,
281+
event.location.country
282+
);
283+
if (coordinates) {
284+
location.location.lat = coordinates.lat;
285+
location.location.lon = coordinates.lon;
286+
}
287+
}
288+
}
289+
return {
290+
order: position,
291+
...event,
292+
...location,
293+
};
294+
})
295+
);
296+
244297
await Profile.findOneAndUpdate(
245298
{ username: profile.username },
246-
{
247-
events: profile.events.map((event, position) => ({
248-
isVirtual: event.isVirtual,
249-
color: event.color,
250-
name: event.name,
251-
description: event.description,
252-
date: {
253-
start: event.date.start,
254-
end: event.date.end,
255-
},
256-
url: event.url,
257-
order: position,
258-
price: event.price,
259-
})),
260-
}
299+
{ events }
261300
);
301+
} catch (e) {
302+
logger.error(e,`failed to update events for ${profile.username}`);
262303
}
263-
} catch (e) {
264-
logger.error(e, `failed to update events for ${profile.username}`);
265304
}
266305
})
267306
);

pages/map.js

Lines changed: 45 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import Page from "@components/Page";
99
import Badge from "@components/Badge";
1010
import { getTags } from "./api/discover/tags";
1111
import { getUsers } from "./api/profiles";
12+
import { getEvents } from "./api/events";
1213
import config from "@config/app.json";
1314

1415
//this is required as leaflet is not compatible with SSR
@@ -21,6 +22,8 @@ export async function getStaticProps() {
2122
let data = {
2223
users: [],
2324
tags: [],
25+
events:[],
26+
points: []
2427
};
2528
try {
2629
data.users = await getUsers();
@@ -85,15 +88,47 @@ export async function getStaticProps() {
8588
logger.error(e, "ERROR loading tags");
8689
}
8790

91+
try {
92+
data.events = await getEvents(true);
93+
} catch (e) {
94+
logger.error(e, "ERROR loading Events");
95+
}
96+
97+
data.events = data.events.map((event, index) => {
98+
const offset = Math.random() * 0.02; // ~2.2km
99+
const offset2 = Math.random() * 0.02; // ~2.2km
100+
return {
101+
type: "Feature",
102+
properties: {
103+
cluster: false,
104+
isEvent: true,
105+
description: event.description,
106+
name: event.name,
107+
location: event.location,
108+
date: event.date,
109+
url: event.url || ''
110+
},
111+
geometry: {
112+
type: "Point",
113+
coordinates: adjustCoords(
114+
[parseFloat(event.location.lon), parseFloat(event.location.lat)],
115+
offset,
116+
offset2,
117+
index
118+
),
119+
},
120+
};
121+
});
122+
data.points=[...data.users,...data.events]
88123
return {
89124
props: { data },
90125
revalidate: pageConfig.revalidateSeconds,
91126
};
92127
}
93128

94129
export default function Map({ data }) {
95-
let { users, tags } = data;
96-
const [filteredUsers, setFilteredUsers] = useState([]);
130+
let { tags, points } = data;
131+
const [filteredPoints, setFilteredPoints] = useState([]);
97132
const [selectedTags, setSelectedTags] = useState(new Set());
98133

99134
let results = [];
@@ -115,12 +150,12 @@ export default function Map({ data }) {
115150
const valueLower = value.toLowerCase();
116151
const terms = [...updateSelectedTagsFilter(value)];
117152

118-
results = users.filter((user) => {
119-
if (user.properties.name.toLowerCase().includes(valueLower)) {
153+
results = points.filter((point) => {
154+
if (point.properties.name.toLowerCase().includes(valueLower)) {
120155
return true;
121156
}
122157

123-
let userTags = user.properties.tags?.map((tag) => tag.toLowerCase());
158+
let userTags = point.properties.tags?.map((tag) => tag.toLowerCase());
124159

125160
if (terms.every((keyword) => userTags?.includes(keyword.toLowerCase()))) {
126161
return true;
@@ -129,11 +164,11 @@ export default function Map({ data }) {
129164
return false;
130165
});
131166

132-
setFilteredUsers(results);
167+
setFilteredPoints(results);
133168
};
134169

135170
const resetFilter = () => {
136-
setFilteredUsers([]);
171+
setFilteredPoints([]);
137172
setSelectedTags(new Set());
138173
};
139174

@@ -172,9 +207,9 @@ export default function Map({ data }) {
172207
<Badge
173208
disable={selectedTags.size == 0 ? true : false}
174209
content={
175-
filteredUsers.length > 0 ? filteredUsers.length : users.length
210+
filteredPoints.length > 0 ? filteredPoints.length : points.length
176211
}
177-
>
212+
>
178213
<Button
179214
onClick={resetFilter}
180215
primary={true}
@@ -196,7 +231,7 @@ export default function Map({ data }) {
196231
</div>
197232
<div className="h-screen">
198233
<DynamicMap
199-
users={filteredUsers.length > 0 ? filteredUsers : users}
234+
points={filteredPoints.length > 0 ? filteredPoints : points}
200235
/>
201236
</div>
202237
</Page>

public/placard.png

23.2 KB
Loading

0 commit comments

Comments
 (0)