diff --git a/README.md b/README.md index b8ace67..4401a72 100644 --- a/README.md +++ b/README.md @@ -17,18 +17,6 @@ 1. [Unit tests](#unit-tests) 2. [Cucumber tests](#cucumber-tests) - -2. [Introduction](#introduction) - -3. [To Start](#to-start) - - 1. [Create a POD](#create-a-pod) - - 2. [Login](#login) - - 3. [Create a route](#create-a-route) - - 4. [View a route](#view-a-route) 4. [Miscellaneous information](#miscellaneous-information) @@ -57,59 +45,9 @@ npm test #### Cucumber tests For executing the [Cucumber](https://cucumber.io/) tests run: ```shell -npm run-script test:e2e +npm run test:e2e ``` -## Introduction -Viade is an Application whose task is to manage routes. -

- -

- -It allows you to store your favourite scenic routes on your [Solid Pod](https://solid.inrupt.com/how-it-works) and to share it with your friends and family as well as comment on those of your friends'. - -

- -

- -## To Start -### Create a POD - -If you are not an owner of a POD you can create one by pressing the register button. -This will redirect you to a provider, where you can create your POD. - -### Login - -Once the POD is created, press the login button and a popup will ask you for credentials. -Once logged in you will have access to new options. - -### Create a route - -From "Route Management > Create a new Route" you can create a new route. -Just set a title, description, select the waypoints of the route and press "Save route in POD". -

- - -

- -### View a route - -We can now navigate to "Route Management > My Routes", where the routes you have created are listed. -When clicking on "Info" of the new route a new window will display all the information recorded, as well as comments posted and a elevation chart of the waypoints. - -

- -

- -### Share with friends - -When displaying all routes "Route Management > My Routes", you can click on the share option. -This will list all friends and when clicking share, a message with the route will be sent to the inbox of your friend. - -

- -

- ## Miscellaneous information This project is an assignment for the [Software Architecture course](https://arquisoft.github.io/) following [these requirements](https://labra.solid.community/public/SoftwareArchitecture/AssignmentDescription/). diff --git a/docker-compose.yml b/docker-compose.yml index 5a71d22..4d1bc93 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -5,7 +5,7 @@ services: container_name: solidserver ports: - "8443:8443" - sampleweb: + viadeen3a: build: . ports: - "3000:3000" diff --git a/loadTests/results/simulation1-100users.zip b/loadTests/results/simulation1-100users.zip new file mode 100644 index 0000000..0d7db42 Binary files /dev/null and b/loadTests/results/simulation1-100users.zip differ diff --git a/loadTests/results/simulation1-10users.zip b/loadTests/results/simulation1-10users.zip new file mode 100644 index 0000000..75ed7a9 Binary files /dev/null and b/loadTests/results/simulation1-10users.zip differ diff --git a/loadTests/results/simulation1-50users.zip b/loadTests/results/simulation1-50users.zip new file mode 100644 index 0000000..2080d65 Binary files /dev/null and b/loadTests/results/simulation1-50users.zip differ diff --git a/loadTests/results/simulation1-rampUp.zip b/loadTests/results/simulation1-rampUp.zip new file mode 100644 index 0000000..6450ebe Binary files /dev/null and b/loadTests/results/simulation1-rampUp.zip differ diff --git a/loadTests/results/simulation2-100users.zip b/loadTests/results/simulation2-100users.zip new file mode 100644 index 0000000..da1182b Binary files /dev/null and b/loadTests/results/simulation2-100users.zip differ diff --git a/loadTests/results/simulation2-10users.zip b/loadTests/results/simulation2-10users.zip new file mode 100644 index 0000000..723ff3e Binary files /dev/null and b/loadTests/results/simulation2-10users.zip differ diff --git a/loadTests/results/simulation2-50users.zip b/loadTests/results/simulation2-50users.zip new file mode 100644 index 0000000..a9a586f Binary files /dev/null and b/loadTests/results/simulation2-50users.zip differ diff --git a/loadTests/results/simulation2-rampUp.zip b/loadTests/results/simulation2-rampUp.zip new file mode 100644 index 0000000..c176a39 Binary files /dev/null and b/loadTests/results/simulation2-rampUp.zip differ diff --git a/loadTests/simulations/Simulations.zip b/loadTests/simulations/Simulations.zip new file mode 100644 index 0000000..5b49c4f Binary files /dev/null and b/loadTests/simulations/Simulations.zip differ diff --git a/public/favicon.ico b/public/favicon.ico index a11777c..24bf74a 100644 Binary files a/public/favicon.ico and b/public/favicon.ico differ diff --git a/public/index.html b/public/index.html index 63ef8dd..306ecef 100644 --- a/public/index.html +++ b/public/index.html @@ -1,5 +1,5 @@ - + diff --git a/src/App.js b/src/App.js index 28170c1..d26e428 100644 --- a/src/App.js +++ b/src/App.js @@ -7,16 +7,20 @@ import { HashRouter } from "react-router-dom"; function App() { return ( -
- - - - - - - - -
+
{ + if (el) { + el.style.setProperty('background-color', 'white', 'important'); + } + }}> + + < LoggedOut > + + + + + + +
); } diff --git a/src/assets/howRoutesWork/Screenshot_1.png b/src/assets/howRoutesWork/Screenshot_1.png new file mode 100644 index 0000000..5443f30 Binary files /dev/null and b/src/assets/howRoutesWork/Screenshot_1.png differ diff --git a/src/assets/howRoutesWork/Screenshot_4.png b/src/assets/howRoutesWork/Screenshot_4.png new file mode 100644 index 0000000..3aea706 Binary files /dev/null and b/src/assets/howRoutesWork/Screenshot_4.png differ diff --git a/src/assets/howRoutesWork/newRouteList.png b/src/assets/howRoutesWork/newRouteList.png new file mode 100644 index 0000000..2f22ab9 Binary files /dev/null and b/src/assets/howRoutesWork/newRouteList.png differ diff --git a/src/components/podService/podPermissionHandler.js b/src/components/podService/podPermissionHandler.js index 5e1750b..bdf3eff 100644 --- a/src/components/podService/podPermissionHandler.js +++ b/src/components/podService/podPermissionHandler.js @@ -9,7 +9,7 @@ const { AclApi } = SolidAclUtils; // const { AclApi, AclDoc, AclParser, AclRule, Permissions, Agents } = SolidAclUtils; // const { READ, WRITE, APPEND, CONTROL } = Permissions; -export default class PodPermissionHandler extends PodHandler{ +export default class PodPermissionHandler extends PodHandler { /** * @param {Session} currentSession - auth.currentSession() @@ -31,7 +31,7 @@ export default class PodPermissionHandler extends PodHandler{ // Share resources this.podStoreHandler.getFile(url).then( (file) => { this._processRouteFileForUnshare(file, permissions, webIds); }, - (error) => { } + (error) => { } ); // Share route @@ -50,7 +50,7 @@ export default class PodPermissionHandler extends PodHandler{ // Share resources this.podStoreHandler.getFile(url).then( (file) => { this._processRouteFileForShare(file, permissions, webIds); }, - (error) => { } + (error) => { } ); // Share route @@ -62,7 +62,7 @@ export default class PodPermissionHandler extends PodHandler{ * @param {SolidAclUtils.Permissions} permissions - Permission to give to the file * @param {String|Array|SolidAclUtils.Agents} agents - People to share with */ - async shareFile(url, permissions, agents){ + async shareFile(url, permissions, agents) { const fetch = auth.fetch.bind(auth); const utils = new AclApi(fetch, { autoSave: true }); const acl = await utils.loadFromFileUrl(url); @@ -79,7 +79,7 @@ export default class PodPermissionHandler extends PodHandler{ * @param {SolidAclUtils.Permissions} permissions - Permission to remove of the file * @param {String|Array|SolidAclUtils.Agents} agents - People to unshare with */ - async unshareFile(url, permissions, agents){ + async unshareFile(url, permissions, agents) { const fetch = auth.fetch.bind(auth); const utils = new AclApi(fetch, { autoSave: true }); const acl = await utils.loadFromFileUrl(url); @@ -92,20 +92,26 @@ export default class PodPermissionHandler extends PodHandler{ } _processRouteFileForShare(routeJson, permissions, agents) { - let parsedRoute = JSON.parse(routeJson); - let mediaURIs = parsedRoute["media"].map( (j) => {return j["@id"];}); - - for(let i = 0; i < mediaURIs.length; i++) { - this.shareFile(mediaURIs[i], permissions, agents); + try { + let parsedRoute = JSON.parse(routeJson); + let mediaURIs = parsedRoute["media"].map((j) => { return j["@id"]; }); + for (let i = 0; i < mediaURIs.length; i++) { + this.shareFile(mediaURIs[i], permissions, agents); + } + } catch (error) { + // Continue with the execution and ignore the error } } _processRouteFileForUnshare(routeJson, permissions, agents) { - let parsedRoute = JSON.parse(routeJson); - let mediaURIs = parsedRoute["media"].map( (j) => {return j["@id"];}); - - for(let i = 0; i < mediaURIs.length; i++) { - this.unshareFile(mediaURIs[i], permissions, agents); + try { + let parsedRoute = JSON.parse(routeJson); + let mediaURIs = parsedRoute["media"].map((j) => { return j["@id"]; }); + for (let i = 0; i < mediaURIs.length; i++) { + this.unshareFile(mediaURIs[i], permissions, agents); + } + } catch (error) { + // Continue with the execution and ignore the error } } } \ No newline at end of file diff --git a/src/components/podService/podStoreHandler.js b/src/components/podService/podStoreHandler.js index e85560c..41d4dd5 100644 --- a/src/components/podService/podStoreHandler.js +++ b/src/components/podService/podStoreHandler.js @@ -139,17 +139,21 @@ export default class PodStorageHandler extends PodHandler { for (let i = 0; i < directory.files.length; i++) { await this.getFile(directory.files[i].url).then( async (sharedRoutesfile) => { - let parsedFileRoutes = JSON.parse(sharedRoutesfile).routes; - for (let j = 0; j < parsedFileRoutes.length; j++) { - await this.getFile(parsedFileRoutes[j]["@id"]).then( - (fileContents) => { - let lastFile = - (i === directory.files.length - 1) && - (j === parsedFileRoutes.length - 1); - forEachFile(fileContents, null, lastFile); - }, - (error) => { forEachFile(); } - ); + try { + let parsedFileRoutes = JSON.parse(sharedRoutesfile).routes; + for (let j = 0; j < parsedFileRoutes.length; j++) { + await this.getFile(parsedFileRoutes[j]["@id"]).then( + (fileContents) => { + let lastFile = + (i === directory.files.length - 1) && + (j === parsedFileRoutes.length - 1); + forEachFile(fileContents, null, lastFile); + }, + (error) => { forEachFile(); } + ); + } + } catch (error) { + // Continue with execution and ignore the route } }, (error) => { forEachFile(null, error); } diff --git a/src/i18n.js b/src/i18n.js index c9cf188..f540298 100644 --- a/src/i18n.js +++ b/src/i18n.js @@ -131,6 +131,7 @@ const resources = { "actions":"Actions", "editMessage": "Click over a point to edit it", "grupos": "Groups", + "invalidRoute": "Route with invalid format ignored", } }, es: { @@ -169,7 +170,7 @@ const resources = { "editProfileChangePass": "Cambiar contraseña", "editProfileNewPass": "Nueva contraseña", "editProfileSave": "Guardar", - "homeWelcome": "Hola", + "homeWelcome": "Hola ", "homeWelcome2": "bienvenido a", "profileTitle": "Tu Perfil", "profileUsername": "Usuario:", @@ -261,6 +262,7 @@ const resources = { "actions":"Acciones", "editMessage": "Pincha sobre un punto para editarlo", "grupos": "Grupos", + "invalidRoute": "Ruta con formato inválido ignorada", } } }; diff --git a/src/model/MyRoute.js b/src/model/MyRoute.js index 6b5d295..9378057 100644 --- a/src/model/MyRoute.js +++ b/src/model/MyRoute.js @@ -152,59 +152,75 @@ class MyRoute { } getComparableString() { - let parsedRoute = JSON.parse(this.toJsonLd()); - parsedRoute["@context"] = ""; - parsedRoute["id"] = ""; - return JSON.stringify(parsedRoute); + try { + let parsedRoute = JSON.parse(this.toJsonLd()); + parsedRoute["@context"] = ""; + parsedRoute["id"] = ""; + return JSON.stringify(parsedRoute); + } catch (error) { + return JSON.stringify({}); + } } modifyFromJsonLd(parsedRoute) { - if (parsedRoute["id"] === undefined) { - this.id = uuid().toString(); - } else { - this.id = parsedRoute["id"]; - } - - this.name = parsedRoute["name"]; - this.author = parsedRoute["author"]; - this.description = parsedRoute["description"]; + try { + parsedRoute = JSON.parse(parsedRoute); + if (parsedRoute["id"] === undefined) { + this.id = uuid().toString(); + } else { + this.id = parsedRoute["id"]; + } - let rawWaypoints = parsedRoute["waypoints"]; - rawWaypoints = rawWaypoints.map((jsonPoint) => { - return { - lat: jsonPoint["latitude"], - lng: jsonPoint["longitude"], - elv: jsonPoint["elevation"], - name: jsonPoint["name"], - description: jsonPoint["description"] - }; - }); + this.name = parsedRoute["name"]; + this.author = parsedRoute["author"]; + this.description = parsedRoute["description"]; - this.points = processPoints(rawWaypoints); + let rawWaypoints = parsedRoute["waypoints"]; + if (rawWaypoints !== undefined) { + rawWaypoints = rawWaypoints.map((jsonPoint) => { + return { + lat: jsonPoint["latitude"], + lng: jsonPoint["longitude"], + elv: jsonPoint["elevation"], + name: jsonPoint["name"], + description: jsonPoint["description"] + }; + }); - let rawPoints = parsedRoute["points"]; - rawPoints = rawPoints.map((jsonPoint) => { - return { - lat: jsonPoint["latitude"], - lng: jsonPoint["longitude"], - elv: jsonPoint["elevation"] - }; - }); - this.addSimplePoints(rawPoints); - + this.points = processPoints(rawWaypoints); + } - this.media = []; - let mediaURIs = parsedRoute["media"]; - mediaURIs.map((j) => { return j["@id"]; }).forEach(function (url) { - let newMedia = new RouteMedia(this); - newMedia.isInPod = true; - newMedia.podURL = url; - this.media.push(newMedia); - }.bind(this)); - - this.routeLength = calculateRouteLength(rawPoints); + let rawPoints = parsedRoute["points"]; + if (rawPoints !== undefined) { + rawPoints = rawPoints.map((jsonPoint) => { + return { + lat: jsonPoint["latitude"], + lng: jsonPoint["longitude"], + elv: jsonPoint["elevation"] + }; + }); + this.addSimplePoints(rawPoints); + } + if (this.points.length === 0) { + return false; + } + this.media = []; + let mediaURIs = parsedRoute["media"]; + mediaURIs.map((j) => { return j["@id"]; }).forEach(function (url) { + let newMedia = new RouteMedia(this); + newMedia.isInPod = true; + newMedia.podURL = url; + this.media.push(newMedia); + }.bind(this)); + + this.routeLength = calculateRouteLength(rawPoints); + + return true; + } catch (error) { + return false; + } } toJsonLd() { diff --git a/src/pages/Groups.js b/src/pages/Groups.js index 4fb41a1..b0fa9e6 100644 --- a/src/pages/Groups.js +++ b/src/pages/Groups.js @@ -46,15 +46,19 @@ class Groups extends React.Component { toast.error(i18n.t('alertAccessPOD')); } else { if (groupJson.length !== 0) { - let tempGroup = new MyGroup("", []); - tempGroup.modifyFromJsonLd(JSON.parse(groupJson)); - this.groupManager.addGroup(tempGroup); - let tempList = this.state.groups; - tempList.push(tempGroup); - this.processedGroups += 1; - if (this.processedGroups === this.retrievedGroups) { - this.setState({ groups: tempList }); - $("#messageArea").empty(); + try { + let tempGroup = new MyGroup("", []); + tempGroup.modifyFromJsonLd(JSON.parse(groupJson)); + this.groupManager.addGroup(tempGroup); + let tempList = this.state.groups; + tempList.push(tempGroup); + this.processedGroups += 1; + if (this.processedGroups === this.retrievedGroups) { + this.setState({ groups: tempList }); + $("#messageArea").empty(); + } + } catch (error) { + // Ignored } } } diff --git a/src/pages/InfoView.js b/src/pages/InfoView.js index dc6140a..9da7129 100644 --- a/src/pages/InfoView.js +++ b/src/pages/InfoView.js @@ -182,7 +182,7 @@ class InfoView extends React.Component { } else { if (jsonRoute.includes(this.id)) { let tempRoute = new MyRoute("", "", "", []); - tempRoute.modifyFromJsonLd(JSON.parse(jsonRoute)); + tempRoute.modifyFromJsonLd(jsonRoute); this.setState({ route: tempRoute }); } } diff --git a/src/pages/RouteCreation.js b/src/pages/RouteCreation.js index 7c94da2..159e716 100644 --- a/src/pages/RouteCreation.js +++ b/src/pages/RouteCreation.js @@ -93,7 +93,7 @@ class RouteCreation extends Component { render() { return ( -
+

{i18n.t('mapCreationTitle')}

- + { if (routeJson === null) { toast.error(i18n.t('alertAccessPOD')); + return 0; } else { if (routeJson.length !== 0) { let tempRoute = new MyRoute("", "", "", []); - tempRoute.modifyFromJsonLd(JSON.parse(routeJson)); - this.routeManager.addRoute(tempRoute); - let tempList = this.state.routes; - tempList.push(tempRoute); - this.processedRoutes += 1; - if (this.processedRoutes === this.retrievedRoutes) { - this.setState({ routes: tempList }); - $("#messageArea").empty(); + if (tempRoute.modifyFromJsonLd(routeJson)) { //isValid + this.routeManager.addRoute(tempRoute); + let tempList = this.state.routes; + tempList.push(tempRoute); + this.processedRoutes += 1; + if (this.processedRoutes === this.retrievedRoutes) { + this.setState({ routes: tempList }); + $("#messageArea").empty(); + } + } else { //isinvalid + toast.error(i18n.t('invalidRoute')); + this.retrievedRoutes--; + if (this.processedRoutes === this.retrievedRoutes) { + this.setState({ routes: this.state.routes }); + $("#messageArea").empty(); + } } } + return this.processedRoutes; } }).then( (result) => { @@ -111,11 +121,14 @@ class RouteList extends React.Component { } else { this.retrievedRoutes = result; } + } ); } } + + } export default RouteList; \ No newline at end of file diff --git a/src/pages/RouteSharedList.js b/src/pages/RouteSharedList.js index 30ba61c..ae42a97 100644 --- a/src/pages/RouteSharedList.js +++ b/src/pages/RouteSharedList.js @@ -94,7 +94,7 @@ export default class RouteSharedList extends React.Component { } else { if (routeJson.length !== 0) { let tempRoute = new MyRoute("", "", "", []); - tempRoute.modifyFromJsonLd(JSON.parse(routeJson)); + tempRoute.modifyFromJsonLd(routeJson); this.routeManager.addSharedRoute(tempRoute); let tempList = this.state.sharedRoutes; tempList.push(tempRoute); diff --git a/src/pages/ShareView.js b/src/pages/ShareView.js index 8ae276c..8ad4e20 100644 --- a/src/pages/ShareView.js +++ b/src/pages/ShareView.js @@ -185,15 +185,19 @@ class ShareView extends React.Component { toast.error(i18n.t('alertAccessPOD')); } else { if (groupJson.length !== 0) { - let tempGroup = new MyGroup("", []); - tempGroup.modifyFromJsonLd(JSON.parse(groupJson)); - this.groupManager.addGroup(tempGroup); - let tempList = this.state.groups; - tempList.push(tempGroup); - this.processedGroups += 1; - if (this.processedGroups === this.retrievedGroups) { - this.setState({ groups: tempList }); - $("#messageArea").empty(); + try { + let tempGroup = new MyGroup("", []); + tempGroup.modifyFromJsonLd(JSON.parse(groupJson)); + this.groupManager.addGroup(tempGroup); + let tempList = this.state.groups; + tempList.push(tempGroup); + this.processedGroups += 1; + if (this.processedGroups === this.retrievedGroups) { + this.setState({ groups: tempList }); + $("#messageArea").empty(); + } + } catch (error) { + // Ignored } } } diff --git a/src/tests/InfoView.test.js b/src/tests/InfoView.test.js index 9f0286a..0238e19 100644 --- a/src/tests/InfoView.test.js +++ b/src/tests/InfoView.test.js @@ -23,7 +23,7 @@ test('Test create route', async () => { assert.equal(author, "María santísima"); const jsonLd = myRoute.toJsonLd(); const temproute = new MyRoute("", "", "", []); - temproute.modifyFromJsonLd(JSON.parse(jsonLd)); + temproute.modifyFromJsonLd(jsonLd); myRoute.getId(); const match = { params: { id: myRoute.getId() } }; await sleep(2000); diff --git a/src/tests/RouteManager.test.js b/src/tests/RouteManager.test.js index 4cc67ba..849badf 100644 --- a/src/tests/RouteManager.test.js +++ b/src/tests/RouteManager.test.js @@ -16,12 +16,12 @@ test('Test add route to manager', () => { let jsonLd = myRoute.toJsonLd(); - const route = new MyRoute("","","",[]); - route.modifyFromJsonLd(JSON.parse(jsonLd)); + const route = new MyRoute("", "", "", []); + route.modifyFromJsonLd(jsonLd); const string1 = myRoute.getComparableString(); const string2 = route.getComparableString(); - assert.equal(string1,string2,"Route comparable string equal"); + assert.equal(string1, string2, "Route comparable string equal"); routeManager.addRoute(myRoute); routeManager.addRoute(myRoute);