# iSumo Documentation Max node version: v10.19.0 # General install instructions. This application is Nodejs and javascript based. You will need two things installed. NPM and Node The installation instructions can be found online. https://nodejs.org/en/download/ Once you have downloaded the application the first thing you must do is navigate to the project directory and make sure you have node and npm installed. You can run the following commands to test this. ```shell= $ node -v ``` Return a number similar to this: v10.15.3 ```shell= $ npm -v ``` Return a number similar to this: 6.4.1 Secondly make sure you are in the right directory. Then run ```shell= npm install ``` This will take a little bit, it is downloading all the dependencies we need to make the application work. **AFTER THIS FOLLOW THE SPECIFIC SECTIONS ON COMMANDS AND WHAT THEY DO** # Frontend **This area of the documentation will cover the frontend application.** ## The server global **THIS IS VERY IMPORTANT** If you want to run the frontend and backend clients locally for development and modification. You must swap these two lines. ```javascript= window.remote_url = 'https://lit-thicket-30449.herokuapp.com/'; // window.remote_url = 'https://localhost:4000/'; ``` Line 1 is the default. This will make it run the backend requests against the remote host. Line 2 is commented out by default, this will make you used the local enviroment if you want to edit endpoints and work on it yourself. **You must switch these round if you want to work locally on the code.** ## Frontend commands and what they do. ```shell= npm start ``` This starts a live webserver that you can find on port 9000 + /filename.html * This will monitor for changes automatically compile them. All you need to do is then refresh the page. * If you want it to automatically refresh the page for you too. That can be found in the settings file webpack.config.js * As you can imagine, while doing styling and coding the frontend this command is going to be your best friend. ```shell= npm build ``` This compiles all the files in the project and dumps them in /dist/ ready for you to place on your static site host. ```shell= npm deploy ``` This is currently not going to be used. But if you ever want to deploy to free hosting on git hub pages. I added this little script so you can automatically take the contents of /dist/ and post it there free of charge. ## File structure (frontend) ### /src This is the route of the application frontend code. Here all the things you want to change you can change. This is where you place your css inside the /styles folder and javascript inside the /scripts folder. **Just dont forget to import them from inside the index.js** You can see two examples of that below: ```javascript= // Styles import './styles/search.scss'; // Page Js import './scripts/public_profile'; ``` ### /certs These are the self signed certificates for hosting on https locally. You don't used them when running the application on the web. But they are needed for CORS when developing locally. CORS is a complex topic, too much for docs if you want to read more check out this below: https://www.codecademy.com/articles/what-is-cors ### /dist This is where the compiled files from the build command go. You should copy this file to host it on your static host of choice. ### webpack.config.js This hosts the config settings for webpack. It is not recommended that beginners go around changing this file. For docs on this file please go to: https://webpack.js.org/ ### package.json * This handles your dependencies. * If you are interested in what packages we are using to run the frontend here is the place you can find the names and versions for research. * This is also the place that if you install new packages this is where they will go. # Backend **This area of the documentation will cover the backend application.** ## Backend commands and what they do. ```shell= npm start ``` This starts the web server for the backend on port 4000, before doing this please make sure you have copied the contents of the .env.example to a new file called .env * For more information on this please see the subtitle Backend .env variables what they mean and do. ```shell= npm test ``` This runs all the test files. Its super important to check that they all pass when making code changes. Of course when you add new code you should also add a test that covers it. * Feel free to dig around in any of the .test files and you should be able to get a feel for how it works. ```shell= npm run cluster ``` This is currently depeciated and **should not be used** but will run a multi thread worker file. Designed for used if we ever want to multi core the application. ## How to deploy the backend to heroku. ```shell= git push heroku master ``` This will trigger the deployment. You need to have the heroku cli installed for this to function. ## File structure (backend) ### /certs This is the same for frontend. For a more detailed explanation please see above. https://www.codecademy.com/articles/what-is-cors ### /cluster This hosts the draft code for clustering if we need to do that in the future. For now its depreciated and should be ignored. ### /data This hosts the files that are served to people and are edited to represent the iSumo search and company criteria. For more information check out the Solid specification. ### /database This hosts the database connection code. Its the javascript that runs storing and retrieving the webid's. For a complete breakdown of functions check out the ./databaseConnection.mjs file. ### /user This handles the bulk of the application functionality. Each file here is titled after what they functionaly handle. For example: * The public_profile.mjs holds the functions for handing fetching the public profile, * Wheras the search.mjs handles the functions for searching. ### .env You must create this file yourself, the reason is that this will change depending on what machine you are running. For example if you are running it on a server it will change, for a more detailed explination see below. ## Backend .env variables what they mean and do. ```= local_dev=true db=test ``` These are currently the own two variables for the backend that you need. * local_dev: checks if its a local development environment. If you are running a local server pods must be accessed over https:// so enabling this will allow correct server function. * db: sets what database the application will point to when you run queries and hit endpoints. It is recommended that during development you point it to test. ## Backend routes and descriptions. file route: **\iSumoBackend\app.mjs** ### get / * This will display the turtle vocabulary on get. * This is useful for building out your own isumo company from the definitions. ```javascript= app.get('/', function(req, res, next) { let options = { root: "./data", dotfiles: 'deny', headers: { 'content-type': "text/turtle; charset=utf-8" } }; res.sendFile('vocabulary.ttl', options, function (err) { if (err) { next(err); } else { console.log('Sent:', 'vocabulary.ttl'); } }); } ); ``` Here we can see that it grabs the vocabulary file from the data folder renders it and places it here accordingly. ### get /examplecsv * This will offer a download for the company_template csv from the data folder. * This is used as a example file for the bulk csv uploader on the private user repository. ``` javascript app.get('/examplecsv', function(req, res, next) { res.download('./data/company_template.csv', 'company_template.csv') } ); ``` ### post /webid * This method adds the webid to the database collection based on .env setting for database. ```javascript= app.post('/webid', async function (req, res) { try { if (!req.body.webid) { throw new Error('No web id') } await database.databaseConnection.connectToDatabase(); await database.databaseConnection.insertWebIDToCollection(req.body.webid); res.sendStatus(200); } catch (e) { console.log(e); res.sendStatus(400); } }); ``` ### post /findCatagory * This will search the store of webid's stored by post /webid and find them by a given category. * You may find this method useful in templating. ```javascript= app.post('/findCatagory', async function (req, res) { if (req.body.search_term) { let ArrayOfWebIDs = await database.databaseConnection.fetchAllWebIDs(); let search_term = req.body.search_term; let result = await user.search.getCategoryByName(ArrayOfWebIDs, search_term); res.json(JSON.stringify(result)); } else { res.sendStatus(400); } }); ``` ### post /findSearchTerm * This is the method used when looking for a search term. * The only required fields to post to this endpoint are search_term_doc. ```javascript= app.post('/findSearchTerm', async function (req, res) { if (req.body.search_term_doc) { await database.databaseConnection.connectToDatabase(); let ArrayOfWebIDs = await database.databaseConnection.fetchAllWebIDs(); let search_term = req.body.search_term_doc; console.log(ArrayOfWebIDs, search_term); let result = await user.search.getBySearch(ArrayOfWebIDs, search_term); res.json(JSON.stringify(result)); } else { res.sendStatus(400); } }); ``` ### post /login * This logs in the user ```javascript= app.post('/login', async function (req, res) { let result = null; result = await user.privateProfile.login(JSON.parse(req.body.data)); if (result instanceof Error) { res.sendStatus(401); } else { res.sendStatus(200); } }) ``` ### post /getProfile * this is used for getting the PRIVATE profile of a user. This requires them to already have there login details in session ```javascript= app.post('/getProfile', async function(req, res) { try { await user.helpers.clearStore(); let session = await user.privateProfile.login(req.body); let result = await user.privateProfile.fetchUserProfile(session.webId); res.json(result); } catch (e) { console.log(e); res.sendStatus(500); } }); ``` ### post /getPublicProfile ```javascript= app.post('/getPublicProfile', async function(req, res) { try { await user.helpers.clearStore(); let result = await user.publicProfile.fetchPublicProfile(req.body.webid); res.json(result); } catch (e) { console.log(e); res.sendStatus(500); } }); ``` ### post /updateProfile * This is used to update the users profile with multi level fields. * What this means is that they are fields that are not meant to be duplicated. Such as company name etc. * If you want duplicated fields please see the method below this one. ```javascript= app.post('/updateProfile', async function (req, res) { let data = JSON.parse(req.body.data); let session = await user.privateProfile.login(data.login_details) console.log(`logged in as <${session.webId}>`); let result = await user.privateProfile.UpdateFieldsMutli(data.webid , data.fields_object); if (result) { res.json(result); } else { res.sendStatus(500) } }) ``` ### post /updateProfileInsert * This is used to update a profile with a insertion method. * What this means is it will add to a profile rather then trying to find and update a parameter. * It is good for adding lists, like exclusions certs etc. ```javascript= app.post('/updateProfileInsert', async function (req, res) { let data = JSON.parse(req.body.data); let session = await user.privateProfile.login(data.login_details) console.log(`logged in as <${session.webId}>`); let result = await user.privateProfile.UpdateFieldsMutli(data.webid , data.fields_object, true); if (result) { res.json(result); } else { res.sendStatus(500) } }) ``` ### post /file * This route may be renamed * This is for uploading files to be parsed and uploaded to a iSumo authenticated pod. * Currently it only supports cvs's. * It is useful for first time bulk uploading of a user profile. As well as live updates to the profile. Providing you have the login details for your pod. ```javascript= app.post('/file', async function (req, res) { let csvData = req.files.csvfile.data.toString('utf8'); let csvRow = await csvtojson({ noheader:false, output: "csv" }) .fromString(csvData); if (req.body.login_details) { let session = await user.privateProfile.login(JSON.parse(req.body.login_details)); console.log(`logged in as <${session.webId}>`); let updated_results = []; for (var i = 0; i < csvRow.length; i++) { let result = await user.privateProfile.UpdateFieldsCSV(session.webId , csvRow[i][0], csvRow[i][1], csvRow[i][2],csvRow[i][3]); updated_results.push(result); } if (updated_results) { res.json(updated_results); } else { res.sendStatus(500) } } }); ```