Skip to content
Open
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
79 changes: 76 additions & 3 deletions graphql/resolvers.js
Original file line number Diff line number Diff line change
Expand Up @@ -325,6 +325,19 @@ const resolvers = {
groupLeader: group.leader,
});

// Publish beacon update for real-time loading
pubsub.publish("BEACON_UPDATE", {
beaconUpdate: {
beacon: newBeacon,
groupId: groupID,
type: "CREATED",
},
groupID: groupID,
groupMembers: group.members,
groupLeader: group.leader,
creatorID: user.id,
});

return newBeacon;
},

Expand Down Expand Up @@ -408,6 +421,19 @@ const resolvers = {
groupLeader: beacon.group.leader.toString(),
});

// Publish beacon update for real-time loading
pubsub.publish("BEACON_UPDATE", {
beaconUpdate: {
beacon: beacon,
groupId: beacon.group.id,
type: "UPDATED",
},
groupID: beacon.group.id,
groupMembers: beacon.group.members,
groupLeader: beacon.group.leader.toString(),
creatorID: user.id,
});

return beacon;
},

Expand Down Expand Up @@ -462,14 +488,17 @@ const resolvers = {
},

deleteBeacon: async (_parent, { id }, { user, pubsub }) => {
const beacon = await Beacon.findById(id);
const beacon = await Beacon.findById(id).populate("leader followers");
if (!beacon) {
return new UserInputError("No beacon exists with this id!");
}

if (beacon.leader.toString() !== user.id)
if (beacon.leader._id.toString() !== user.id)
return new Error("Beacon leader is allowed to delete the beacon!");

// Store beacon data before deletion for subscription payload
const beaconData = beacon.toObject();

await User.updateOne({ _id: user.id }, { $pull: { beacons: id } });

const group = await Group.findById(beacon.group);
Expand All @@ -485,7 +514,7 @@ const resolvers = {
groupUpdate: {
newUser: null,
newBeacon: null,
deletedBeacon: deletedBeacon,
deletedBeacon: beaconData,
updatedBeacon: null,
groupId: group.id,
},
Expand All @@ -494,6 +523,19 @@ const resolvers = {
groupLeader: group.leader.toString(),
});

// Publish beacon update for real-time loading
pubsub.publish("BEACON_UPDATE", {
beaconUpdate: {
beacon: beaconData,
groupId: group.id,
type: "DELETED",
},
groupID: group.id,
groupMembers: group.members,
groupLeader: group.leader.toString(),
creatorID: user.id,
});

return deletedBeacon !== null;
},

Expand Down Expand Up @@ -795,6 +837,37 @@ const resolvers = {
}
),
},
// Subscription for real-time beacon loading
beaconUpdate: {
subscribe: withFilter(
(_, __, { pubsub }) => pubsub.asyncIterator(["BEACON_UPDATE"]),
(payload, variables, { user }) => {
const { groupID, groupMembers, groupLeader, creatorID, beaconUpdate } = payload;
const { beacon, groupId, type } = beaconUpdate;

// Don't notify the user who created/updated/deleted the beacon
if (creatorID === user.id) {
return false;
}

// Check if the beacon's group is in the subscribed groupIds
if (!variables.groupIds.includes(groupID)) {
return false;
}

// Check if user is part of the group
const isGroupLeader = groupLeader === user.id.toString();
const isGroupMember = groupMembers.some(memberId => memberId.toString() === user.id.toString());

// Parse beacon object for proper serialization
if (beacon != null) {
payload.beaconUpdate.beacon = parseBeaconObject(beacon);
}

return (isGroupLeader || isGroupMember) && variables.groupIds.includes(groupId);
}
),
},
},
}),
};
Expand Down
32 changes: 32 additions & 0 deletions graphql/schema.js
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,33 @@ const typeDefs = gql`
updatedBeacon: Beacon
}

"""
Enum representing the type of beacon update event
"""
enum BeaconUpdateType {
CREATED
UPDATED
DELETED
}

"""
Payload for real-time beacon updates subscription
"""
type BeaconPayload {
"""
The beacon that was created, updated, or deleted
"""
beacon: Beacon!
"""
The ID of the group this beacon belongs to
"""
groupId: ID!
"""
The type of update: CREATED, UPDATED, or DELETED
"""
type: BeaconUpdateType!
}

type BeaconLocationsPayload {
userSOS: User
route: [Location]
Expand Down Expand Up @@ -165,6 +192,11 @@ const typeDefs = gql`
beaconLocations(id: ID!): BeaconLocationsPayload!
JoinLeaveBeacon(id: ID!): JoinLeaveBeaconPayload!
groupUpdate(groupIds: [ID!]): UpdatedGroupPayload!
"""
Subscribe to real-time beacon updates (create, update, delete) for specified groups.
This enables instantaneous loading of beacons for a smoother user experience.
"""
beaconUpdate(groupIds: [ID!]!): BeaconPayload!
}

schema {
Expand Down