diff --git a/functions/index.js b/functions/index.js
index fee14f5..d60d7fc 100644
--- a/functions/index.js
+++ b/functions/index.js
@@ -8,6 +8,70 @@ admin.initializeApp();
const axios = require('axios');
const parseString = require('xml2js').parseString;
+// function to fetch station data from the Firestore database
+exports.getStationData = functions.https.onRequest((request, response) => {
+ response.set('Access-Control-Allow-Origin', '*');
+ response.set('Access-Control-Allow-Credentials', 'true');
+ let jsonData = [];
+
+ cors(request, response, () => {
+ // fetch the "stations" collection
+ admin.firestore().collection('stations').get().then((snapshot) => {
+ if (snapshot.empty) {
+ response.send({data: "Error fetching station data from the database"})
+ return;
+ }
+ // iterate through each of the collection's documents
+ snapshot.forEach(doc => {
+ jsonData.push(doc.data());
+ });
+ response.json({data: jsonData});
+ })
+ });
+})
+
+// function to populate the Firestore database with station data from Irish Rail
+exports.postStationData = functions.https.onRequest((request, response) => {
+ response.set('Access-Control-Allow-Origin', '*');
+ response.set('Access-Control-Allow-Credentials', 'true');
+
+ cors(request, response, () => {
+ axios.get('http://api.irishrail.ie/realtime/realtime.asmx/getAllStationsXML')
+ .then((res) => {
+ // XML to JSON
+ parseString(res.data, function(err, result) {
+ let jsonStr = JSON.stringify(result);
+ let jsonObj = JSON.parse(jsonStr);
+ let jsonData = jsonObj.ArrayOfObjStation.objStation;
+
+ // batch delete all of the "stations" collection's documents
+ var db = admin.firestore();
+ admin.firestore().collection('stations').get().then((snapshot) => {
+ var batchDelete = db.batch();
+ snapshot.forEach(doc => {
+ batchDelete.delete(doc.ref);
+ });
+
+ batchDelete.commit().then(function() {
+ // batch write all station JSON objects to the "stations" collection
+ var batchWrite = db.batch();
+
+ jsonData.forEach((doc) => {
+ // set the station's ID as the document ID
+ var docID = db.collection('stations').doc(doc["StationCode"][0]);
+ batchWrite.set(docID, doc);
+ });
+
+ batchWrite.commit().then(function () {
+ response.send({data: "Successfully fetched and uploaded station data from Irish Rail"});
+ });
+ })
+ })
+ })
+ })
+ })
+})
+
// function to fetch live train data from the Firestore database
exports.getLiveTrainData = functions.https.onRequest((request, response) => {
response.set('Access-Control-Allow-Origin', '*');
@@ -30,85 +94,74 @@ exports.getLiveTrainData = functions.https.onRequest((request, response) => {
});
})
-// function to fetch station data from the Firestore database
-exports.getStationData = functions.https.onRequest((request, response) => {
- response.set('Access-Control-Allow-Origin', '*');
- response.set('Access-Control-Allow-Credentials', 'true');
- let jsonData = [];
-
- cors(request, response, () => {
- // fetch the "stations" collection
- admin.firestore().collection('stations').get().then((snapshot) => {
- if (snapshot.empty) {
- response.status(404).send({data: "Error fetching station data from the database"})
- return;
- }
- // iterate through each of the collection's documents
- snapshot.forEach(doc => {
- jsonData.push(doc.data());
- });
- response.json({data: jsonData});
- })
- });
-})
-
-// helper function to fetch data from Irish Rail given a train type (mainland, suburban, dart)
-function callIrishRail(request, response, db, trainTypeCode) {
- cors(request, response, () => {
- let url = 'https://api.irishrail.ie/realtime/realtime.asmx/getCurrentTrainsXML_WithTrainType?TrainType=' + trainTypeCode
- axios.get(url)
- .then((res) => {
- var batchWrite = db.batch();
- // XML to JSON
- parseString(res.data, function(err, result) {
- let jsonStr = JSON.stringify(result);
- let jsonObj = JSON.parse(jsonStr);
- let jsonData = jsonObj.ArrayOfObjTrainPositions.objTrainPositions;
-
- jsonData.forEach((doc) => {
- // ignore trains with longitudes or latitudes equal zero
- if (!(doc["TrainLongitude"] == 0 || doc["TrainLatitude"] == 0)) {
- doc["TrainType"] = [trainTypeCode]
- // set the train's code as the document ID
- var docID = db.collection('liveTrainData').doc(doc["TrainCode"][0]);
- batchWrite.set(docID, doc);
- }
- });
-
- batchWrite.commit()
- .catch((error) => {
- return false;
- })
- })
- })
- .catch((error) => {
- return false;
- })
- })
-}
-
// function to populate the Firestore database with live train data from Irish Rail
exports.postLiveTrainData = functions.https.onRequest((request, response) => {
+ // helper function to parse train objects
+ function parseJSON(result) {
+ let jsonStr = JSON.stringify(result);
+ let jsonObj = JSON.parse(jsonStr);
+ let jsonData = jsonObj.ArrayOfObjTrainPositions.objTrainPositions;
+ return jsonData;
+ }
+
+ // helper function to write to the database
+ function batchWriteDB(request, response, db, jsonData, trainTypeCode) {
+ response.set('Access-Control-Allow-Origin', '*');
+ response.set('Access-Control-Allow-Credentials', 'true');
+
+ cors(request, response, () => {
+ var batchWrite = db.batch();
+ jsonData.forEach((doc) => {
+ // ignore trains with longitudes or latitudes equal zero
+ if (!(doc["TrainLongitude"] == 0 || doc["TrainLatitude"] == 0)) {
+ doc["TrainType"] = [trainTypeCode]
+ var docID = db.collection('liveTrainData').doc(doc["TrainCode"][0]);
+ batchWrite.set(docID, doc);
+ }
+ });
+ batchWrite.commit()
+ })
+ }
+
response.set('Access-Control-Allow-Origin', '*');
response.set('Access-Control-Allow-Credentials', 'true');
-
cors(request, response, () => {
- // batch delete all of the "liveTrainData" collections's documents
- var db = admin.firestore();
- admin.firestore().collection('liveTrainData').get().then((snapshot) => {
- var batchDelete = db.batch();
- snapshot.forEach(doc => {
- batchDelete.delete(doc.ref);
- });
+ // fetch mainland trains
+ axios.get('https://api.irishrail.ie/realtime/realtime.asmx/getCurrentTrainsXML_WithTrainType?TrainType=M').then(res => {
+ // XML to JSON
+ parseString(res.data, function(err, result) {
+ let jsonData = parseJSON(result)
- // fetch data using codes M (mainland), S (suburban), D (dart)
- batchDelete.commit().then(function() {
- if (callIrishRail(request, response, db, "M") == false ||
- callIrishRail(request, response, db, "S") == false ||
- callIrishRail(request, response, db, "D") == false) {
- response.send({data: "Error fetching data from the IrishRail API"});
- }
- response.send({data: "Successfully fetched and uploaded live train data from Irish Rail"});
+ // batch delete all of the liveTrainData collections's documents
+ var db = admin.firestore();
+ admin.firestore().collection('liveTrainData').get().then((snapshot) => {
+ var batchDelete = db.batch();
+ snapshot.forEach(doc => {
+ batchDelete.delete(doc.ref);
+ });
+
+ batchDelete.commit().then(function() {
+ // batch write all station JSON objects to the liveTrainData collection
+ batchWriteDB(request, response, db, jsonData, "M");
+
+ // fetch suburban trains
+ axios.get('https://api.irishrail.ie/realtime/realtime.asmx/getCurrentTrainsXML_WithTrainType?TrainType=S').then(res => {
+ parseString(res.data, function(err, result) {
+ let jsonData = parseJSON(result)
+ batchWriteDB(request, response, db, jsonData, "S");
+
+ // fetch dart trains
+ axios.get('https://api.irishrail.ie/realtime/realtime.asmx/getCurrentTrainsXML_WithTrainType?TrainType=D').then(res => {
+ parseString(res.data, function(err, result) {
+ let jsonData = parseJSON(result)
+ batchWriteDB(request, response, db, jsonData, "D");
+ response.send({data: "Successfully fetched and uploaded live train data from Irish Rail"});
+ })
+ })
+ })
+ })
+ })
+ })
})
})
})
diff --git a/functions/package-lock.json b/functions/package-lock.json
index 634926f..7a3c1ba 100644
--- a/functions/package-lock.json
+++ b/functions/package-lock.json
@@ -9,6 +9,7 @@
"axios": "^1.3.3",
"chai": "^4.3.7",
"chai-http": "^4.3.0",
+ "cors": "^2.8.5",
"firebase": "^9.17.1",
"firebase-admin": "^11.5.0",
"firebase-functions": "^4.2.0",
diff --git a/functions/package.json b/functions/package.json
index c7c283b..3192bf0 100644
--- a/functions/package.json
+++ b/functions/package.json
@@ -17,6 +17,7 @@
"axios": "^1.3.3",
"chai": "^4.3.7",
"chai-http": "^4.3.0",
+ "cors": "^2.8.5",
"firebase": "^9.17.1",
"firebase-admin": "^11.5.0",
"firebase-functions": "^4.2.0",
diff --git a/functions/test/index.test.js b/functions/test/index.test.js
index d8e5961..ce172dc 100644
--- a/functions/test/index.test.js
+++ b/functions/test/index.test.js
@@ -6,7 +6,7 @@ const expect = chai.expect;
describe('Firebase cloud function tests', function() {
this.timeout(100000);
- it('Test getting live train data', async() => {
+ it('Test getting live train data from the database', async() => {
const result = await chai.request('https://us-central1-irishrailtracker.cloudfunctions.net')
.get('/getLiveTrainData')
expect(result.statusCode).to.equal(200);
@@ -18,6 +18,20 @@ describe('Firebase cloud function tests', function() {
expect(result.body.data[0]).haveOwnProperty('TrainLongitude');
expect(result.body.data[0]).haveOwnProperty('TrainCode');
expect(result.body.data[0]).haveOwnProperty('TrainDate');
+ expect(result.body.data[0]).haveOwnProperty('TrainType');
+ }),
+
+ this.timeout(100000);
+ it('Test getting station data from the database', async() => {
+ const result = await chai.request('https://us-central1-irishrailtracker.cloudfunctions.net')
+ .get('/getStationData')
+ expect(result.statusCode).to.equal(200);
+ expect(result.body.data).to.be.an('Array');
+ expect(result.body.data[0]).haveOwnProperty('StationDesc');
+ expect(result.body.data[0]).haveOwnProperty('StationLatitude');
+ expect(result.body.data[0]).haveOwnProperty('StationLongitude');
+ expect(result.body.data[0]).haveOwnProperty('StationCode');
+ expect(result.body.data[0]).haveOwnProperty('StationId');
}),
this.timeout(100000);
@@ -27,19 +41,6 @@ describe('Firebase cloud function tests', function() {
expect(result.statusCode).to.equal(200);
}),
- this.timeout(100000);
- it('test getting station data', async() => {
- const result = await chai.request('https://us-central1-irishrailtracker.cloudfunctions.net')
- .get('/getStationData')
- expect(result.statusCode).to.equal(200);
- expect(result.body.data).to.be.an('Array');
- expect(result.body.data[0]).haveOwnProperty('StationDesc');
- expect(result.body.data[0]).haveOwnProperty('StationLatitude');
- expect(result.body.data[0]).haveOwnProperty('StationLongitude');
- expect(result.body.data[0]).haveOwnProperty('StationCode');
- expect(result.body.data[0]).haveOwnProperty('StationId');
- })
-
this.timeout(100000);
it('Test updating the database with live station data', async() => {
const result = await chai.request('https://us-central1-irishrailtracker.cloudfunctions.net')
diff --git a/package-lock.json b/package-lock.json
index a52ed87..35360be 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -13,6 +13,7 @@
"ol": "^7.2.2",
"vue": "^3.2.45",
"vue-loading-overlay": "^6.0.3",
+ "vue-router": "^4.1.6",
"vue3-openlayers": "^0.1.71"
},
"devDependencies": {
@@ -1121,6 +1122,11 @@
"@vue/shared": "3.2.45"
}
},
+ "node_modules/@vue/devtools-api": {
+ "version": "6.5.0",
+ "resolved": "https://registry.npmjs.org/@vue/devtools-api/-/devtools-api-6.5.0.tgz",
+ "integrity": "sha512-o9KfBeaBmCKl10usN4crU53fYtC1r7jJwdGKjPT24t348rHxgfpZ0xL3Xm/gLUYnc0oTp8LAmrxOeLyu6tbk2Q=="
+ },
"node_modules/@vue/reactivity": {
"version": "3.2.45",
"resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.2.45.tgz",
@@ -2201,6 +2207,20 @@
"vue": "^3.2.0"
}
},
+ "node_modules/vue-router": {
+ "version": "4.1.6",
+ "resolved": "https://registry.npmjs.org/vue-router/-/vue-router-4.1.6.tgz",
+ "integrity": "sha512-DYWYwsG6xNPmLq/FmZn8Ip+qrhFEzA14EI12MsMgVxvHFDYvlr4NXpVF5hrRH1wVcDP8fGi5F4rxuJSl8/r+EQ==",
+ "dependencies": {
+ "@vue/devtools-api": "^6.4.5"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/posva"
+ },
+ "peerDependencies": {
+ "vue": "^3.2.0"
+ }
+ },
"node_modules/vue3-openlayers": {
"version": "0.1.71",
"resolved": "https://registry.npmjs.org/vue3-openlayers/-/vue3-openlayers-0.1.71.tgz",
diff --git a/package.json b/package.json
index fef980b..0974d79 100644
--- a/package.json
+++ b/package.json
@@ -13,6 +13,7 @@
"ol": "^7.2.2",
"vue": "^3.2.45",
"vue-loading-overlay": "^6.0.3",
+ "vue-router": "^4.1.6",
"vue3-openlayers": "^0.1.71"
},
"devDependencies": {
diff --git a/src/App.vue b/src/App.vue
index 166abed..ccbcd97 100644
--- a/src/App.vue
+++ b/src/App.vue
@@ -1,9 +1,8 @@
-
+
\ No newline at end of file
diff --git a/src/pages/MapPage.vue b/src/pages/MapPage.vue
new file mode 100644
index 0000000..cdef6c2
--- /dev/null
+++ b/src/pages/MapPage.vue
@@ -0,0 +1,364 @@
+
+Home
+Insights
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

+

+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/router/routes.js b/src/router/routes.js
new file mode 100644
index 0000000..0716a20
--- /dev/null
+++ b/src/router/routes.js
@@ -0,0 +1,7 @@
+function loadPage(component) {
+ return () => import(`@/pages/${component}.vue`)
+}
+export default [
+ {path: "/", component:loadPage("MapPage")},
+ {path: "/insights", component:loadPage("InsightsPage")}
+]
\ No newline at end of file
diff --git a/src/store/store.js b/src/store/store.js
new file mode 100644
index 0000000..627fa79
--- /dev/null
+++ b/src/store/store.js
@@ -0,0 +1,17 @@
+import { reactive } from 'vue'
+
+export const store = reactive({
+ insights: {},
+ latestTrain: {},
+ earliestTrain: {},
+
+ setInsights(insights) {
+ this.insights = insights
+ },
+ setLatestTrain(latestTrain) {
+ this.latestTrain = latestTrain
+ },
+ setEarliestTrain(earliestTrain) {
+ this.earliestTrain = earliestTrain
+ }
+})
\ No newline at end of file