diff --git a/README.md b/README.md index 8e0e19db..6270cf92 100644 --- a/README.md +++ b/README.md @@ -1,96 +1,90 @@ -# Onboarding project for JavaScript +# Onboarding project for JavaScript -This is a JavaScript project for all new developers to complete before venturing into our web frontend codebase. +This is a JavaScript project for all new developers to complete before venturing into our web frontend codebase. Once you complete this project, and have been through code review, you will have a much better understanding of JavaScript -and it's superset, TypeScript, that we use for development. +and it's superset, TypeScript, that we use for development. -## Technologies you will encounter +## Technologies you will encounter -1. HTML -1. CSS -1. JavaScript -1. TypeScript +1. HTML +1. CSS +1. JavaScript +1. TypeScript 1. Node Package Manager (npm) -1. JQuery +1. JQuery -## Brief +## Brief -You task is to build a grid/table in TypeScript that fetches data from a server and displays it. Here are the requirements: +You task is to build a grid/table in TypeScript that fetches data from a server and displays it. Here are the requirements: -1. The grid should cover the entire screen. The browser scrollbar should not appear. -1. The columns widths should be distributed evenly. -1. Display column headings based on the data you get back from the web service. -1. The grid should have controls to navigate through data. You can choose a suitable way of doing this. -1. Display the first page of data when you open up page for first time. -1. Don't use any third-party libraries other than JQuery (already included in `third_party` directory). +1. The grid should cover the entire screen. The browser scrollbar should not appear. +1. The columns widths should be distributed evenly. +1. Display column headings based on the data you get back from the web service. +1. The grid should have controls to navigate through data. You can choose a suitable way of doing this. +1. Display the first page of data when you open up page for first time. +1. Don't use any third-party libraries other than JQuery (already included in `third_party` directory). -## Web Service API +## Web Service API -The web service you will retrieve data from is a little Golang REST service that is packaged with this repository. It runs on port 2050. +The web service you will retrieve data from is a little Golang REST service that is packaged with this repository. It runs on port 2050. Here are the relevant API calls: 1. Get total number of records - Path: `HTTP GET /recordCount` - Response: Integer number in body of response - Example response: - `350` + Path: `HTTP GET /recordCount` + Response: Integer number in body of response + Example response: + `350` 1. Get column names - Path: `HTTP GET /columns` - Response: JSON in body of response - Example response: - `[ - "ID", - "City", - "Population" - ]` + Path: `HTTP GET /columns` + Response: JSON in body of response + Example response: + `[ "ID", "City", "Population" ]` 1. Get records - Path: `HTTP GET /records?from={fromID}&to={toID}` - Response: JSON in body of response - The order of entries in a record corresponds to the order of the columns returned by the `/columns` API - The `from` and `to` parameters correspond to the record index which run from `0` to `record count - 1` - Example response: - `[ - [0, "Cape Town", 3500000], - [1, "New York", 8500000], - [2, "Johannesburg", 4500000] - ]` - -## Code Review - -Once you are done and happy with your solution, submit your code for code review by creating a pull request in GITHUB. The code review will take the following into account: - -1. Was the brief correctly followed, does the grid work as expected -1. Is the code style according to our [JavaScript Style Guide](https://imqssoftware.atlassian.net/wiki/display/AR/Javascript+Style+Guide) -1. User-centric thinking - is the grid easy to use -1. Suitable comments -1. Performance considerations -1. Aesthetics - -## Pre-requisites - -1. You need to have set up your development environment [as described here](https://imqssoftware.atlassian.net/wiki/display/AR/Dev+Environment). -1. We suggest using VSCode, but you can use your IDE of choice. - -## Getting Started + Path: `HTTP GET /records?from={fromID}&to={toID}` + Response: JSON in body of response + The order of entries in a record corresponds to the order of the columns returned by the `/columns` API + The `from` and `to` parameters correspond to the record index which run from `0` to `record count - 1` + Example response: + `[ [0, "Cape Town", 3500000], [1, "New York", 8500000], [2, "Johannesburg", 4500000] ]` + +## Code Review + +Once you are done and happy with your solution, submit your code for code review by creating a pull request in GITHUB. The code review will take the following into account: + +1. Was the brief correctly followed, does the grid work as expected +1. Is the code style according to our [JavaScript Style Guide](https://imqssoftware.atlassian.net/wiki/display/AR/Javascript+Style+Guide) +1. User-centric thinking - is the grid easy to use +1. Suitable comments +1. Performance considerations +1. Aesthetics + +## Pre-requisites + +1. You need to have set up your development environment [as described here](https://imqssoftware.atlassian.net/wiki/display/AR/Dev+Environment). +1. We suggest using VSCode, but you can use your IDE of choice. + +## Getting Started + These steps include just enough detail to guide you. Each step will require some additional research on your part: -1. Fork this GIT repository under your own GIT account + +1. Fork this GIT repository under your own GIT account 1. Start up the backend server: - - Open console and change directory to `server` directory - - Run `env.bat` - - Run `go run main.go` - - Open up your browser and point it to [http://localhost:2050](http://localhost:2050). You should see "Hello" -1. Create the frontend project: - - Open another console in the project root directory - - Run `npm init` to initialise the JavaScript project. You can just use the default options. - - Install the TypeScript npm package. - - Install TypeScript type definitions for JQuery. - - Create an `app.ts` file in the root directory and add the following code to it: - `window.onload = () => { $("body").text("Hello world"); }` - - Add a npm script called "build" to `package.json` that does the TypeScript build (using the `tsconfig.json` included in the project). - - Run `npm run build` - - You will see a new file `app.js` in the project root. Add an entry for this script in `index.html`. - - Refresh [http://localhost:2050](http://localhost:2050). You should see "Hello world" -1. Get coding! + - Open console and change directory to `server` directory + - Run `env.bat` + - Run `go run main.go` + - Open up your browser and point it to [http://localhost:2050](http://localhost:2050). You should see "Hello" +1. Create the frontend project: + - Open another console in the project root directory + - Run `npm init` to initialise the JavaScript project. You can just use the default options. + - Install the TypeScript npm package. + - Install TypeScript type definitions for JQuery. + - Create an `app.ts` file in the root directory and add the following code to it: + `window.onload = () => { $("body").text("Hello world"); }` + - Add a npm script called "build" to `package.json` that does the TypeScript build (using the `tsconfig.json` included in the project). + - Run `npm run build` + - You will see a new file `app.js` in the project root. Add an entry for this script in `index.html`. + - Refresh [http://localhost:2050](http://localhost:2050). You should see "Hello world" +1. Get coding! diff --git a/app.css b/app.css new file mode 100644 index 00000000..9ad51aa7 --- /dev/null +++ b/app.css @@ -0,0 +1,104 @@ + + + +body{ + background-image: url("https://previews.123rf.com/images/provector/provector1303/provector130300080/18783350-abstract-technology-database-background.jpg"); +} + + +table { + + top: 6%; + bottom: 20; + left: 0; + right: 0; + width: 100%; + height: 100%; + table-layout: fixed; + position: relative; + text-align: left; +} + +body{ + + overflow: hidden; +} + +th { + width: 100/11%; + border: 2px solid red; + background-color: red; +} + +tr:hover td{ + background-color: blueviolet; +} + +td { + width: 100/11%; + border: 2px solid blue; + background:black; + color: yellow; +} + + + + + +.searchButtons{ + top:1%; + left: 50%; + border-radius: 20px; + background-color: blueviolet; + border: none; + color: white; + padding: 8px 16px; + text-align: center; + display: inline-flex; + font-size: 16px; + margin: 0%; + -webkit-transition-duration: 0.4s; /* Safari */ + transition-duration: 0.4s; + cursor: pointer; + height: 20px; + +} + +#previousPage{ + + top:1%; + float: left; + border-radius: 20px; + border: none; + background-color:blueviolet; + color: white; + padding: 8px 16px; + text-align: center; + /* display: inline-flex; */ + font-size: 16px; + -webkit-transition-duration: 0.4s; /* Safari */ + transition-duration: 0.4s; + cursor: pointer; + + + +} + +#nextPage { + + + top:1%; + float: right; + transition: 0.5s; + border-radius: 20px; + border: none; + background-color: blueviolet; + color: white; + padding: 8px 16px; + text-align: center; + /* display: inline-flex; */ + font-size: 16px; + -webkit-transition-duration: 0.4s; /* Safari */ + transition-duration: 0.4s; + cursor: pointer; + } diff --git a/app.ts b/app.ts new file mode 100644 index 00000000..279620f6 --- /dev/null +++ b/app.ts @@ -0,0 +1,193 @@ +//Loads the table to the screen +window.onload = () => GetTotalNumberOfRecords(); +//Resizes page during window resizing +window.onresize = () => Resize(); + +//Variable declarations +let totalRecordCount: number; +let columnNames: any[]; +let records: any[]; +let from: number = 0; +let to: number = 0; +let NumberOfRows = Math.floor((window.innerHeight - 50) / 24) - 1; +let timeout: any; + +//Function to retrieve total amount of records +function GetTotalNumberOfRecords() { + $.ajax({ + url: "/recordCount", + type: "GET", + timeout: 12000, + dataType: "text" + }) + .done(function(responseText: any) { + totalRecordCount = responseText; + console.log(totalRecordCount); + Resize(); + }) + + .fail(function() { + alert("Could not retrieve total record number"); + }); +} + +//function to retrieve column names +function GetColumnNames() { + $.ajax({ + url: "/columns", + type: "GET", + timeout: 12000, + dataType: "json" + }) + .done((responsejson: any) => { + columnNames = responsejson; + GetActualRecordsAmount(); + }) + .fail(() => { + alert("Could not display column names"); + }); +} + +//Function to retrieve the record data +function GetActualRecordsAmount() { + $.ajax({ + url: "/records?from=" + from + "&to=" + to, + timeout: 12000, + dataType: "JSON" + }) + .done((responseRecords: any) => { + records = responseRecords; + BuildTable(); + }) + .fail(() => { + alert("No available records for your selection"); + }); +} + +//Function builds the table and populates with data from the API calls +function BuildTable() { + if (document.getElementById("Table") != null) { + $("Table").remove(); + } + + const body = document.getElementsByTagName("body")[0]; + + const ourTable = document.createElement("table"); + ourTable.setAttribute("id", "Table"); + //ourTable.style.borderCollapse = "collapse"; + ourTable.style.borderSpacing = "0"; + + const thead = document.createElement("thead"); + ourTable.appendChild(thead); + + //Column names are created for the table + for (let c = 0; c < columnNames.length; c++) { + thead + .appendChild(document.createElement("th")) + .appendChild(document.createTextNode(columnNames[c])); + } + + //Cells are created and populated with data + for (let i = 0; i < records.length; i++) { + const tableRow = document.createElement("tr"); + tableRow.setAttribute("id", "rows"); + ourTable.appendChild(tableRow); + + const innerArrayLength = records[i].length; + + for (let j = 0; j < innerArrayLength; j++) { + tableRow + .appendChild(document.createElement("td")) + .appendChild(document.createTextNode(records[i][j])); + } + } + body.appendChild(ourTable); +} + +//Pages to the next set of data +function NextPage() { + let NumberOfRows = Math.floor((window.innerHeight - 50) / 24) - 1; + if (from < from - NumberOfRows) { + from = totalRecordCount - NumberOfRows; + to = Math.min(from + (NumberOfRows - 1), totalRecordCount); + console.log(from + " " + to); + //Resize(); + GetActualRecordsAmount(); + } else { + from = from + NumberOfRows; + to = to + NumberOfRows; + //Resize(); + GetActualRecordsAmount(); + } +} + +//Pages backwards through data +function PreviousPage() { + let NumberOfRows = Math.floor((window.innerHeight - 50) / 24) - 1; + if (NumberOfRows > from) { + from = Math.max(0, from - NumberOfRows); + to = NumberOfRows - from; + console.log(from); + Resize(); + GetActualRecordsAmount(); + } else { + from = from - NumberOfRows; + to = from + NumberOfRows; + Resize(); + GetActualRecordsAmount(); + } +} + +//Activates the submit button to produce users search results +function SearchBar() { + let userInput = document.getElementById("userInput"); + let NumberOfRows = Math.floor((window.innerHeight - 50) / 24) - 1; + + from = Math.min(parseInt(userInput.value), totalRecordCount - NumberOfRows); + + console.log("userInput: " + from); + + to = Math.min(from + NumberOfRows, totalRecordCount - 1); + + console.log("NumberOfRows:" + NumberOfRows); + + Resize(); + GetActualRecordsAmount(); +} + +function Resize() { + if (timeout) clearTimeout(timeout); + timeout = setTimeout(() => { + let NumberOfRows = Math.floor((window.innerHeight - 50 - 24) / 24) - 1; + if (!from) { + from = 0; + } else { + from = from; + } + console.log(from); + + if (NumberOfRows * (totalRecordCount - 1) > to) { + to = Math.min(from + NumberOfRows, totalRecordCount - 1); + from = to - NumberOfRows; + } + console.log(from + " " + to); + GetColumnNames(); + + if (to > from + NumberOfRows) { + to = Math.min(from + NumberOfRows, totalRecordCount - 1); + from = to - NumberOfRows; + } else if (to <= from + NumberOfRows) { + to = from + NumberOfRows; + } + + console.log("userInput: " + from); + GetColumnNames(); + }, 500); +} + +function restrictAlphabets(e: any) { + var x = e.which || e.keycode; + if ((x >= 48 && x <= 57) || x == 8 || (x >= 35 && x <= 40) || x == 46) + return true; + else return false; +} diff --git a/index.html b/index.html index add5e736..8dd60719 100644 --- a/index.html +++ b/index.html @@ -1,13 +1,33 @@ - - JS Onboard Project - - + ONBoardingProject - -

Hello

- + + + + + + +
+ + +
+ + + +
+
+ - diff --git a/package.json b/package.json new file mode 100644 index 00000000..6841655b --- /dev/null +++ b/package.json @@ -0,0 +1,22 @@ +{ + "name": "onboard-javascript", + "version": "1.0.0", + "description": "This is a JavaScript project for all new developers to complete before venturing into our web frontend codebase.", + "main": "app.js", + "dependencies": {}, + "devDependencies": {}, + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1", + "build": "tsc" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/YuveerMaharaj/onboard-javascript.git" + }, + "author": "", + "license": "ISC", + "bugs": { + "url": "https://github.com/YuveerMaharaj/onboard-javascript/issues" + }, + "homepage": "https://github.com/YuveerMaharaj/onboard-javascript#readme" +} diff --git a/tsconfig.json b/tsconfig.json index dbf43618..64380699 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,22 +1,15 @@ { - "compilerOptions": { - "sourceMap": true, - "strict": true, - "noImplicitThis": true, - "noImplicitAny": true, - "noImplicitReturns": true, - "module": "es2015", - "moduleResolution": "node", - "target": "es5", - "typeRoots": [ - "./node_modules/@types" - ], - "lib": [ - "dom", - "es2016" - ], - }, - "include": [ - "./**/*.ts" - ] + "compilerOptions": { + "sourceMap": true, + "strict": true, + "noImplicitThis": true, + "noImplicitAny": true, + "noImplicitReturns": true, + "module": "es2015", + "moduleResolution": "node", + "target": "es5", + "typeRoots": ["./node_modules/@types"], + "lib": ["dom", "es2016"] + }, + "include": ["./**/*.ts", "test.js"] }