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

admin create notification page and route #160

Merged
merged 5 commits into from
Apr 10, 2020
Merged
Show file tree
Hide file tree
Changes from 4 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
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import ca.mcgill.cooperator.service.AdminService;
import ca.mcgill.cooperator.service.NotificationService;
import ca.mcgill.cooperator.service.StudentService;
import java.util.ArrayList;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.CrossOrigin;
Expand All @@ -19,6 +20,7 @@
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

@CrossOrigin(origins = "*")
Expand Down Expand Up @@ -65,6 +67,40 @@ public NotificationDto createNotification(@RequestBody NotificationDto n) {
return ControllerUtils.convertToDto(notification);
}

/**
* Creates a new Notification for all the students in the list
*
*
* @param title
* @param body
* @param list of student Ids
* @param sender Id
* @return list of the created Notifications
*/
@PostMapping("/many")
public List<NotificationDto> createManyNotifications(
@RequestParam("studentIds") List<Integer> stuIds,
@RequestParam("admin") Integer adminId,
@RequestParam("title") String title,
@RequestParam("body") String body) {

Admin sender = null;
if (adminId != null) {
sender = adminService.getAdmin(adminId);
}

Student student = null;
List<Notification> notifs = new ArrayList<>();
for (Integer id : stuIds) {
student = studentService.getStudentById(id);
Notification notification =
notificationService.createNotification(title, body, student, sender);
notifs.add(notification);
}

return ControllerUtils.convertNotifListToDto(notifs);
}

/**
* Gets a Notification by ID
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,29 @@ public StudentDto createTestStudent() throws Exception {
return studentDto;
}

public StudentDto createTestStudent(String email, String stuId) throws Exception {
StudentDto studentDto = new StudentDto();
studentDto.setEmail(email);
studentDto.setFirstName("Emma");
studentDto.setLastName("Eagles");
studentDto.setStudentId(stuId);
MvcResult mvcResult =
mvc.perform(
post("/students")
.contentType(MediaType.APPLICATION_JSON)
.content(objectMapper.writeValueAsString(studentDto))
.characterEncoding("utf-8"))
.andExpect(status().isOk())
.andReturn();

// get object from response
studentDto =
objectMapper.readValue(
mvcResult.getResponse().getContentAsString(), StudentDto.class);

return studentDto;
}

public CoopDto createTestCoop(
CourseOfferingDto courseOfferingDto, StudentDto studentDto, CoopStatus coopStatus)
throws Exception {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -212,4 +212,42 @@ public void testNotificationFlow() throws Exception {

assertEquals(0, notifDtos.size());
}

@Test
public void testManyNotificationsFlow() throws Exception {
StudentDto studentDto1 = createTestStudent("[email protected]", "123123123");
StudentDto studentDto2 = createTestStudent("[email protected]", "321321321");
AdminDto adminDto = createTestAdmin();

String title = "Hello";
String body = "Please attend meeting.";

// 1. create notification

MvcResult mvcResult =
mvc.perform(
post("/notifications/many?admin="
+ adminDto.getId()
+ "&title="
+ title
+ "&body="
+ body
+ "&studentIds="
+ studentDto1.getId()
+ ","
+ studentDto2.getId())
.contentType(MediaType.APPLICATION_JSON)
.characterEncoding("utf-8"))
.andExpect(status().isOk())
.andReturn();

// get object from response
List<NotificationDto> notifDtos =
Arrays.asList(
objectMapper.readValue(
mvcResult.getResponse().getContentAsString(),
NotificationDto[].class));

assertEquals(2, notifDtos.size());
}
}
6 changes: 0 additions & 6 deletions Frontend/src/layouts/AdminLoggedInLayout.vue
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,6 @@
<span class="text-caption q-ml-sm">ADMIN</span>
</q-toolbar-title>

<q-btn dense round flat class="q-mr-sm" icon="notifications">
<q-badge color="white" text-color="red" floating transparent>
4
</q-badge>
</q-btn>

<q-btn flat dense round icon="settings" aria-label="Settings">
<q-menu>
<q-list style="min-width: 200px">
Expand Down
174 changes: 174 additions & 0 deletions Frontend/src/pages/admin/AdminCreateNotificationPage.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,174 @@
<template>
<BasePage title="Send Notification">
<q-card>
<div class="q-pa-md">
<q-table
title="Select Students"
:data="tableStudents"
:columns="columns"
row-key="email"
selection="multiple"
:selected.sync="toSendTo"
/>
<q-input
outlined
v-model="title"
label="Title"
class="notifPageComponents"
/>
<q-input
v-model="body"
label="Body"
outlined
type="textarea"
class="notifPageComponents"
/>
<q-btn
color="primary"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add :disabled="sending" here to disable the button while it's sending

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it doesnt show up when its sending tho

@click="sendNotification()"
label="Send Notification"
class="notifPageComponents"
/>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add a q-spinner here that should show while the notifications are being created (just better for UX, it's been done in a bunch of other pages/components already)

</div>
</q-card>
</BasePage>
</template>

<script>
import BasePage from "../BasePage.vue";

export default {
components: {
BasePage
},
props: {
selected: {
type: Array,
required: false
}
},
name: "HomeMainInfo",

data: () => ({
tableStudents: [],
toSendTo: [],
body: "",
title: "",
selectedString: "Please select a student",
columns: [
{
name: "studentLastName",
required: true,
label: "Student Last Name",
align: "left",
field: "lastName",
sortable: true,
classes: "my-class",
style: "width: 500px"
},
{
name: "studentFirstName",
required: true,
label: "Student First Name",
align: "left",
field: "firstName",
sortable: true,
classes: "my-class",
style: "width: 500px"
},
{
name: "studentID",
required: true,
label: "Student ID",
align: "left",
field: "id",
sortable: true,
classes: "my-class",
style: "width: 500px"
},
{
name: "email",
required: true,
label: "Email",
align: "left",
field: "email",
sortable: true,
classes: "my-class",
style: "width: 500px"
}
]
}),
created: function() {
this.$axios
.get("/students", {
headers: {
Authorization: this.$store.state.token
}
})
.then(resp => {
this.tableStudents = resp.data;
});
this.toSendTo = this.selected;
},
methods: {
goToStudentCoop() {
this.$router.push("/admin/studentcoops");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: change this route to /admin/student-coops

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this isnt even a real page but ok lol

},
sendNotification() {
var adminId = this.$store.state.currentUser.id;
var stuIds = [];
for (var i = 0; i < this.toSendTo.length; i++) {
stuIds.push(this.toSendTo[i].id);
}

// create the notification
this.$axios
.post(
"/notifications/many?admin=" +
adminId +
"&title=" +
this.title +
"&body=" +
this.body +
"&studentIds=" +
stuIds
)
.then(_resp => {
this.body = "";
this.title = "";
this.toSendTo = [];
this.$q.notify({
color: "green-4",
position: "top",
textColor: "white",
icon: "cloud_done",
message: "Notification(s) sent successfully!"
});
})
.catch(_err => {
this.$q.notify({
color: "red-4",
position: "top",
textColor: "white",
icon: "error",
message: "Something went wrong, please try again"
});
});
}
}
};
</script>

<style scoped lang="scss">
h6 {
margin: 10px;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can use the q-ma-md class instead of defining the styles yourself (ma = margin-all, md= medium). https://quasar.dev/style/spacing#Examples

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this literally never ends up working the way i want it to so i really dont want to waste more time trying to get this shit to align properly so i dont rlly want to go down this road again

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok no worries it's not a big deal

}
#card {
width: 100%;
margin-top: 25px;
margin-right: 10px;
}
.notifPageComponents {
margin-top: 3%;
}
</style>
35 changes: 31 additions & 4 deletions Frontend/src/pages/admin/AdminStudentsPage.vue
Original file line number Diff line number Diff line change
Expand Up @@ -29,16 +29,24 @@
/>
</div>
<div class="q-pa-md">
<q-btn @click="applyFilter" class="q-mr-sm">Apply Filter</q-btn>
<q-btn @click="clearFilter" class="q-mr-sm">Clear Filter</q-btn>
<q-btn @click="applyFilter" class="filterBtn">Apply Filter</q-btn>
<q-btn @click="clearFilter" class="filterBtn">Clear Filter</q-btn>
</div>

<div class="q-pa-md">
<q-table
:data="students"
:columns="columns"
row-key="studentName"
row-key="email"
@row-click="goToStudentCoop"
selection="multiple"
:selected.sync="selected"
/>
<q-btn
class="dashBtn"
label="Send Notification to Selected Students"
color="primary"
@click="sendNotif"
/>
</div>
</q-card-section>
Expand Down Expand Up @@ -73,6 +81,7 @@ export default {
}
},
data: () => ({
selected: [],
students: [],
courseNames: [],
courseNameData: "",
Expand Down Expand Up @@ -177,6 +186,15 @@ export default {
goToStudentCoop() {
this.$router.push("/admin/student-coops");
},
sendNotif() {
this.$router.push({
path: "/admin/notification",
name: "CreateNotif",
params: {
selected: this.selected
}
});
},
clearFilter() {
this.courseNameData = "";
this.termData = "";
Expand Down Expand Up @@ -217,4 +235,13 @@ export default {
};
</script>

<style lang="scss" scoped></style>
<style lang="scss">
.dashBtn {
width: 40%;
margin-top: 4%;
}
.filterBtn {
width: 19%;
margin-right: 2%;
}
</style>
6 changes: 6 additions & 0 deletions Frontend/src/router/routes.js
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,12 @@ const routes = [
{
path: "csv-parse",
component: () => import("pages/admin/CsvParse.vue")
},
{
path: "create-notification",
component: () => import("pages/admin/AdminCreateNotificationPage.vue"),
props: true,
name: "CreateNotif"
}
]
}
Expand Down