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
26 changes: 26 additions & 0 deletions api/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.

# dependencies
/node_modules
/.pnp
.pnp.js
.vscode/

# testing
/coverage

# production
/build

# misc
.DS_Store
.env.local
.env.development.local
.env.test.local
.env.production.local

npm-debug.log*
yarn-debug.log*
yarn-error.log*

package-lock.json
4 changes: 2 additions & 2 deletions api/absences.spec.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import assert from 'assert';
import assert from "assert";

it('your tests here', () => {
it("your tests here", () => {
assert(false);
});
16 changes: 16 additions & 0 deletions api/downloads/event.ics
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
BEGIN:VCALENDAR
VERSION:2.0
CALSCALE:GREGORIAN
PRODID:adamgibbons/ics
METHOD:PUBLISH
X-PUBLISHED-TTL:PT1H
BEGIN:VEVENT
UID:a4476cdc-3689-4bc9-bd59-a6e8e64a00c9
SUMMARY:Daniel wants leave
DTSTAMP:20210503T210800Z
DTSTART:20210629T000000Z
DESCRIPTION:Daniel wants leave due to vacation
X-MICROSOFT-CDO-BUSYSTATUS:BUSY
DURATION:P1DT
END:VEVENT
END:VCALENDAR
158 changes: 158 additions & 0 deletions api/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,158 @@
import express from "express";
import cors from "cors";
import mongoose from "mongoose";
import ics from "ics";
import { writeFileSync } from "fs";
import moment from "moment";

//Importing models
import User from "./models/User.js";
import Absence from "./models/Absence.js";

//Ical file folder
const __dirname = "./downloads";

//Initialiing app
const app = express();

//Allowing cors
app.use(cors());

//Database connection
mongoose.connect(
"mongodb+srv://ram_kumar89:ramkumar12345_@cluster0.fdhoh.mongodb.net/test",
{ useNewUrlParser: true, useUnifiedTopology: true },
() => {
console.log("Connected to database");
}
);

//Routes for the app
app.get("/api/absences", async (req, res) => {
try {
const {
limit = 10,
page = 1,
status = "",
startDate = null,
endDate = null,
} = req.query;
const skip = (parseInt(page) - 1) * parseInt(limit);

//Status related filters
let match = getStatusForTotal(status);

//Start date filter
if (startDate) {
match = {
...match,
startDate: { $gte: new Date(parseInt(startDate)) },
};
}

//End date filter
if (endDate) {
match = {
...match,
endDate: { $lte: new Date(parseInt(endDate)) },
};
}

//Querying in absences table
const absences = await Absence.find(match)
.populate("user")
.limit(parseInt(limit))
.skip(skip);

//Returning payload
res.json({
message: "Success",
payload: absences,
total: await getTotalAbsences(match),
});
} catch (e) {
res.json(e);
}
});

app.get("/api/ical/:id", async (req, res) => {
try {
const { id } = req.params;

//Find absence by id
const absence = await Absence.findOne({ _id: id }).populate("user");

const startDate = moment(new Date(absence.startDate));
const endDate = moment(new Date(absence.endDate));
const days = endDate.diff(startDate, "days");
const strDate = new Date(absence.startDate);

//Creating Calendar event
ics.createEvent(
{
title: `${absence.user.name} wants leave`,
description: `${absence.user.name} wants leave due to ${absence.type}`,
busyStatus: "BUSY",
start: [
strDate.getFullYear(),
strDate.getMonth() + 1,
strDate.getDate(),
strDate.getHours(),
strDate.getMinutes(),
],
duration: { days: days ? days : 1 },
},
(error, value) => {
if (error) {
return res.status(404).json({ error });
}

writeFileSync(`${__dirname}/event.ics`, value);

var file = __dirname + "/event.ics";
res.download(file, "event.ics");
}
);
} catch (error) {
return res.status(404).json({ error });
}
});

//This function is responsible to get the total absences in the table
export async function getTotalAbsences(match) {
try {
const absences = await Absence.find(match);
return absences.length;
} catch (err) {
return 0;
}
}

//This function is responsible to return the filters for particular status type
export function getStatusForTotal(status) {
switch (status) {
case "requested":
return {
confirmedAt: null,
rejectedAt: null,
};

case "confirmed":
return {
confirmedAt: { $ne: null },
};

case "rejected":
return {
rejectedAt: { $ne: null },
};
default:
return {};
}
}

app.listen(3001, () => {
console.log("Listening on 3001");
});

export default app;
50 changes: 50 additions & 0 deletions api/models/Absence.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import mongoose from "mongoose";

const AbsenceSchema = mongoose.Schema({
admitterId: {
type: Number,
},
admitterNote: {
type: String,
},
confirmedAt: {
type: Date,
},
createdAt: {
type: Date,
},
crewId: {
required: true,
type: Number,
},
endDate: {
type: Date,
},
id: {
required: true,
type: Number,
},
memberNote: {
type: String,
},
rejectedAt: {
type: Date,
},
startDate: {
type: Date,
},
type: {
type: String,
},
userId: {
required: true,
type: Number,
},
user: {
type: mongoose.Schema.Types.ObjectId,
ref: "User",
},
});

export default mongoose.models.Absence ||
mongoose.model("Absence", AbsenceSchema);
24 changes: 24 additions & 0 deletions api/models/User.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import mongoose from "mongoose";

const UserSchema = mongoose.Schema({
crewId: {
type: Number,
required: true,
},
id: {
type: Number,
required: true,
},
image: {
type: String,
},
name: {
type: String,
},
userId: {
required: true,
type: Number,
},
});

export default mongoose.models.User || mongoose.model("User", UserSchema);
Loading