Skip to content

Commit 85c24e3

Browse files
N-Beacons-1-Grp-PR1 (#167)
* PR1-Changes * fix: unique shortcode in groups. * Error handling for duplicate shortcode! * Update .gitignore Co-authored-by: Aadi Bajpai <[email protected]> * Delete .DS_Store Co-authored-by: Aadi Bajpai <[email protected]>
1 parent d46ff79 commit 85c24e3

File tree

6 files changed

+98
-1
lines changed

6 files changed

+98
-1
lines changed

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,3 +102,6 @@ dist
102102

103103
# TernJS port file
104104
.tern-port
105+
106+
# .DS_Store files
107+
.DS_Store

graphql/resolvers.js

Lines changed: 58 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,10 @@ const { customAlphabet } = require("nanoid");
55
const geolib = require("geolib");
66
const { isPointWithinRadius } = geolib;
77
const Beacon = require("../models/beacon.js");
8+
const Group = require("../models/group.js");
89
const Landmark = require("../models/landmark.js");
910
const { User } = require("../models/user.js");
11+
const { MongoServerError } = require("mongodb");
1012

1113
const alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
1214
// even if we generate 10 IDs per hour,
@@ -17,7 +19,7 @@ const resolvers = {
1719
Query: {
1820
hello: () => "Hello world!",
1921
me: async (_parent, _args, { user }) => {
20-
await user.populate("beacons.leader beacons.landmarks");
22+
await user.populate("groups beacons.leader beacons.landmarks");
2123
return user;
2224
},
2325
beacon: async (_parent, { id }, { user }) => {
@@ -115,6 +117,35 @@ const resolvers = {
115117
return newBeacon;
116118
},
117119

120+
createGroup: async (_, { group }, { user }) => {
121+
console.log(group);
122+
//since there is a very minute chance of shortcode colliding, we try to make the group 2 times if 1st one results in a collision.
123+
for (let i = 0; i < 2; i++) {
124+
try {
125+
const groupDoc = new Group({
126+
leader: user.id,
127+
shortcode: nanoid(),
128+
...group,
129+
});
130+
const newGroup = await groupDoc.save().then(g => g.populate("leader"));
131+
user.groups.push(newGroup.id);
132+
await user.save();
133+
console.log(newGroup);
134+
return newGroup;
135+
} catch (e) {
136+
//try again only if shortcode collides.
137+
if (e instanceof MongoServerError && e.keyValue["shortcode"]) {
138+
console.error(e);
139+
} else {
140+
//else return the error;
141+
return new Error(e);
142+
}
143+
}
144+
}
145+
//if shortcode collides two times then return an error saying please try again.
146+
return new Error("Please try again!");
147+
},
148+
118149
changeBeaconDuration: async (_, { newExpiresAt, beaconID }, { user }) => {
119150
const beacon = await Beacon.findById(beaconID);
120151

@@ -147,6 +178,26 @@ const resolvers = {
147178
return beacon;
148179
},
149180

181+
joinGroup: async (_, { shortcode }, { user, pubsub }) => {
182+
const group = await Group.findOne({ shortcode });
183+
184+
if (!group) return new UserInputError("No group exists with that shortcode!");
185+
if (group.members.includes(user.id)) return new Error("Already a member of the group!");
186+
if (group.leader == user.id) return new Error("You are the leader of the group!");
187+
188+
group.members.push(user.id);
189+
console.log("user joined group: ", user);
190+
await group.save();
191+
await group.populate("leader");
192+
193+
//publish this change over GROUP_JOINED subscription.
194+
pubsub.publish("GROUP_JOINED", { groupJoined: user, groupID: group.id });
195+
196+
user.groups.push(group.id);
197+
await user.save();
198+
return group;
199+
},
200+
150201
createLandmark: async (_, { landmark, beaconID }, { user }) => {
151202
const beacon = await Beacon.findById(beaconID);
152203
// to save on a db call to populate leader, we just use the stored id to compare
@@ -223,6 +274,12 @@ const resolvers = {
223274
(payload, variables) => payload.beaconID === variables.id
224275
),
225276
},
277+
groupJoined: {
278+
subscribe: withFilter(
279+
(_, __, { pubsub }) => pubsub.asyncIterator(["GROUP_JOINED"]),
280+
(payload, variables) => payload.groupID === variables.groupID
281+
),
282+
},
226283
},
227284
}),
228285
};

graphql/schema.js

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ const typeDefs = gql`
6969
email: String
7070
location: Location
7171
beacons: [Beacon!]!
72+
groups: [Group!]!
7273
}
7374
7475
input AuthPayload {
@@ -81,6 +82,19 @@ const typeDefs = gql`
8182
credentials: AuthPayload
8283
}
8384
85+
type Group {
86+
_id: ID!
87+
title: String
88+
shortcode: String!
89+
leader: User!
90+
members: [User!]!
91+
beacons: [Beacon!]!
92+
}
93+
94+
input GroupInput {
95+
title: String!
96+
}
97+
8498
type Query {
8599
beacon(id: ID!): Beacon!
86100
nearbyBeacons(location: LocationInput!): [Beacon!]!
@@ -104,12 +118,15 @@ const typeDefs = gql`
104118
updateUserLocation(id: ID!, location: LocationInput!): User!
105119
changeLeader(beaconID: ID!, newLeaderID: ID!): Beacon!
106120
changeBeaconDuration(newExpiresAt: Float!, beaconID: ID!): Beacon!
121+
createGroup(group: GroupInput): Group!
122+
joinGroup(shortcode: String!): Group!
107123
}
108124
109125
type Subscription {
110126
beaconLocation(id: ID!): Location
111127
userLocation(id: ID!): User
112128
beaconJoined(id: ID!): User
129+
groupJoined(groupID: ID!): User
113130
}
114131
115132
schema {

models/beacon.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ const beaconSchema = new Schema(
1616
followers: [UserSchema],
1717
route: [LocationSchema],
1818
landmarks: { type: [Schema.Types.ObjectId], ref: "Landmark" },
19+
group: { type: Schema.Types.ObjectId, ref: "Group" },
1920
},
2021
{
2122
timestamps: true,

models/group.js

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
const mongoose = require("mongoose");
2+
3+
const { Schema, model } = mongoose;
4+
5+
const groupSchema = new Schema(
6+
{
7+
title: String,
8+
shortcode: { type: String, required: true, unique: true },
9+
leader: { type: Schema.Types.ObjectId, required: true, ref: "User" },
10+
members: { type: [Schema.Types.ObjectId], ref: "User" },
11+
beacons: { type: [Schema.Types.ObjectId], ref: "Beacon" },
12+
},
13+
{
14+
timestamps: true,
15+
}
16+
);
17+
18+
module.exports = model("Group", groupSchema, "Groups");

models/user.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ const UserSchema = new Schema(
1212
// store most recent location
1313
location: LocationSchema,
1414
beacons: { type: [Schema.Types.ObjectId], ref: "Beacon" },
15+
groups: { type: [Schema.Types.ObjectId], ref: "Group" },
1516
},
1617
{
1718
timestamps: true,

0 commit comments

Comments
 (0)