From ada58864e0079ba0491571278c790aa45c47d42e Mon Sep 17 00:00:00 2001 From: Jeroen Vijgen Date: Sat, 22 Feb 2020 22:38:28 +0100 Subject: [PATCH] Bind dashboard front-end to component --- README.md | 9 ++-- package.json | 3 +- .../DashboardComponent/Dashboard.tsx | 45 ++++++++++++------- src/Components/LoginComponent/Login.tsx | 2 - src/DTOs/IDTO.ts | 1 + src/DTOs/api.dto.ts | 38 ++++++++++++++-- src/Repositories/IRepository.ts | 6 +++ src/Repositories/ReportingRepository.ts | 16 +++++++ src/Views/DashboardView.tsx | 26 ++++++----- src/Views/LoginView.tsx | 2 +- src/Views/TableView.tsx | 14 +++++- src/index.css | 5 +++ src/react-app-env.d.ts | 2 + yarn.lock | 5 +++ 14 files changed, 136 insertions(+), 38 deletions(-) create mode 100644 src/DTOs/IDTO.ts create mode 100644 src/Repositories/IRepository.ts create mode 100644 src/Repositories/ReportingRepository.ts diff --git a/README.md b/README.md index e2defce..76b1fd5 100644 --- a/README.md +++ b/README.md @@ -18,14 +18,16 @@ It correctly bundles React in production mode and optimizes the build for the be The build is minified and the filenames include the hashes. Your app is ready to be deployed! -### Requirement list +## Requirement list + - [X] Create React web app - [X] It should have fields for giving start date, end date and access token as arguments to the app. - [ ] App should make HTTP GET request to the API to fetch chat counts between those two given dates. - [ ] The dashboard should render three values from the API. -- [ ] The dashboard should render a Paginated List. +- [X] The dashboard should render a Paginated List. + +## Software used -### Software used \# | Software | Reason | --- | --- | --- | 1 | React | Requirement. | @@ -34,3 +36,4 @@ The build is minified and the filenames include the hashes. Your app is ready to 4 | Bootstrap | To structure the front-end, bootstrap is used. | 5 | Axios | To communicate with external API's, I added Axios. | 6 | FontAwesome | To communicate actions to the user, I have added some relatable icons for actions. | +7 | react-bootstrap-table2-* | To get a paginated table, React Bootstrap Table is used. | diff --git a/package.json b/package.json index 31c5511..f362835 100644 --- a/package.json +++ b/package.json @@ -28,6 +28,7 @@ "react": "^16.12.0", "react-bootstrap": "^1.0.0-beta.16", "react-bootstrap-table-next": "^3.3.5", + "react-bootstrap-table2-paginator": "^2.1.0", "react-dom": "^16.12.0", "react-router-dom": "^5.1.2", "react-scripts": "^3.4.0", @@ -63,4 +64,4 @@ "eslint-plugin-react": "^7.18.3", "prettier": "^1.19.1" } -} \ No newline at end of file +} diff --git a/src/Components/DashboardComponent/Dashboard.tsx b/src/Components/DashboardComponent/Dashboard.tsx index 5333dcc..7732009 100644 --- a/src/Components/DashboardComponent/Dashboard.tsx +++ b/src/Components/DashboardComponent/Dashboard.tsx @@ -1,40 +1,53 @@ import React from 'react'; import DashboardView from '../../Views/DashboardView' +import API_DTO from '../../DTOs/api.dto'; +import ReportingRepository from '../../Repositories/ReportingRepository'; export default class Dashboard extends React.Component<{ history: any }, { - dto: any + dto: API_DTO, + ReportingRepository: ReportingRepository }> { - state!: { - dto: { - API_Link: string | null; - API_Token: string | null; - }; - }; - props: any; constructor(props: any) { super(props); if (props.location.state.dto !== undefined) { // If the state exists being routed from /, fill in Dashboard State. - this.state = { dto: props.location.state.dto }; + this.setState({ dto: props.location.state.dto }); } else if (localStorage.getItem("APILink") !== null && localStorage.getItem("AccessToken") !== null) { // Check if localStorage has valid items, if this is the case, we can use those. // Resolve issue with cold navigation to /dashboard. - this.state = { - dto: { - API_Link: localStorage.getItem("APILink"), - API_Token: localStorage.getItem("AccessToken") - } - } + const DTO = new API_DTO(); + DTO.setApiLink(localStorage.getItem("APILink")); + DTO.setApiToken(localStorage.getItem("AccessToken")); + this.setState({ dto: DTO }); } else { // Route back to / if neither is the case. this.props.history.push('/'); } + this.checkFirstDate = this.checkFirstDate.bind(this); + this.checkSecondDate = this.checkSecondDate.bind(this); + this.getItemsFromApi = this.getItemsFromApi.bind(this); + } + + checkFirstDate(_e: any) { + this.state.dto.setFirstDate(_e.target.value); + } + + checkSecondDate(_e: any) { + this.state.dto.setSecondDate(_e.target.value); + } + + getItemsFromApi() { + // TODO: Connect to ReportingRepository. } render () { - return () + return () } } diff --git a/src/Components/LoginComponent/Login.tsx b/src/Components/LoginComponent/Login.tsx index 59a85c2..9f0a690 100644 --- a/src/Components/LoginComponent/Login.tsx +++ b/src/Components/LoginComponent/Login.tsx @@ -25,8 +25,6 @@ export default class Login extends React.Component<{ } verifyLogin() { - console.log("API Link: " + this.state.dto.getApiLink()); - console.log("API Token: " + this.state.dto.getApiToken()); localStorage.setItem("lastLoggedIn", new Date().toUTCString()); // eslint-disable-next-line this.props.history.push({ diff --git a/src/DTOs/IDTO.ts b/src/DTOs/IDTO.ts new file mode 100644 index 0000000..d5c1913 --- /dev/null +++ b/src/DTOs/IDTO.ts @@ -0,0 +1 @@ +export default interface IDTO { }; diff --git a/src/DTOs/api.dto.ts b/src/DTOs/api.dto.ts index df15a8e..df5a370 100644 --- a/src/DTOs/api.dto.ts +++ b/src/DTOs/api.dto.ts @@ -1,10 +1,17 @@ -export default class API_DTO { +import IDTO from './IDTO'; + +export default class API_DTO implements IDTO { API_Link: string; API_Token: string; + First_Date: string; + Second_Date: string; + checkDate = /((\d{4})-(\d{2})-(\d{2}))/g constructor() { this.API_Link = ""; this.API_Token = ""; + this.First_Date = ""; + this.Second_Date = ""; } setApiLink(_api_link: string | null): void { @@ -19,11 +26,36 @@ export default class API_DTO { localStorage.setItem("AccessToken", this.API_Token); } - getApiLink() { + setFirstDate(_first_date: string | null): void { + if (!this.checkDate.test(_first_date || "") + || _first_date === null) _first_date = "2017-05-01"; + // TODO: Check validity of range of first date. + this.First_Date = _first_date; + localStorage.setItem("FirstDate", this.First_Date); + + } + + setSecondDate(_second_date: string | null): void { + if (!this.checkDate.test(_second_date || "") + || _second_date === null) _second_date = "2017-06-15"; + // TODO: Check validity of range of second date. + this.Second_Date = _second_date; + localStorage.setItem("SecondDate", this.Second_Date); + } + + getApiLink(): string { return this.API_Link; } - getApiToken() { + getApiToken(): string { return this.API_Token; } + + getFirstDate(): string { + return this.First_Date; + } + + getSecondDate(): string { + return this.Second_Date; + } } diff --git a/src/Repositories/IRepository.ts b/src/Repositories/IRepository.ts new file mode 100644 index 0000000..b6046b3 --- /dev/null +++ b/src/Repositories/IRepository.ts @@ -0,0 +1,6 @@ +export default interface IRepository { + Create(t: any): any; + Read(t: any): any; + Update(t: any): any; + Delete(t: any): any; +} diff --git a/src/Repositories/ReportingRepository.ts b/src/Repositories/ReportingRepository.ts new file mode 100644 index 0000000..588c24a --- /dev/null +++ b/src/Repositories/ReportingRepository.ts @@ -0,0 +1,16 @@ +import IRepository from './IRepository'; + +export default class ReportingRepository implements IRepository { + Create(_t: any) { + throw new Error("Method not implemented."); + } + Read(_t: any) { + throw new Error("Method not implemented."); + } + Update(_t: any) { + throw new Error("Method not implemented."); + } + Delete(_t: any) { + throw new Error("Method not implemented."); + } +} diff --git a/src/Views/DashboardView.tsx b/src/Views/DashboardView.tsx index f6e3b79..c5d7eec 100644 --- a/src/Views/DashboardView.tsx +++ b/src/Views/DashboardView.tsx @@ -4,7 +4,11 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { faSync } from '@fortawesome/free-solid-svg-icons'; import Table from "./TableView"; -export default class DashboardView extends React.Component { +export default class DashboardView extends React.Component<{ + checkFirstDate: any, + checkSecondDate: any, + getItemsFromApi: any +}> { render () { return (
@@ -26,7 +30,8 @@ export default class DashboardView extends React.Component { placeholder="2017-05-01" aria-label="2017-05-01" aria-describedby="basic-addon1" - defaultValue={localStorage.getItem("FirstDate") || ""} + defaultValue={localStorage.getItem("FirstDate") || "2017-05-01"} + onChange={(e: any) => this.props.checkFirstDate(e)} /> @@ -40,13 +45,14 @@ export default class DashboardView extends React.Component { placeholder="2017-06-15" aria-label="2017-06-15" aria-describedby="basic-addon1" - defaultValue={localStorage.getItem("SecondDate") || ""} + defaultValue={localStorage.getItem("SecondDate") || "2017-06-15"} + onChange={(e: any) => this.props.checkSecondDate(e)} /> - @@ -80,14 +86,14 @@ export default class DashboardView extends React.Component { diff --git a/src/Views/LoginView.tsx b/src/Views/LoginView.tsx index 956f597..f70e715 100644 --- a/src/Views/LoginView.tsx +++ b/src/Views/LoginView.tsx @@ -18,7 +18,7 @@ export default class LoginView extends React.Component<{ this.props.persistApiLink(e)} /> diff --git a/src/Views/TableView.tsx b/src/Views/TableView.tsx index ee071fc..991f0a4 100644 --- a/src/Views/TableView.tsx +++ b/src/Views/TableView.tsx @@ -1,17 +1,27 @@ import React from 'react'; import BootstrapTable from 'react-bootstrap-table-next'; +import paginationFactory from 'react-bootstrap-table2-paginator'; +import 'react-bootstrap-table2-paginator/dist/react-bootstrap-table2-paginator.min.css'; export default class Table extends React.Component<{ columns: any, data: any }> { render () { - return (
+ return (
+
+ data={ this.props.data } + pagination={ paginationFactory({ + paginationSize: 4, + pageStartIndex: 0, + showTotal: true, + sizePerPageList: [5] + }) } + />
) } } diff --git a/src/index.css b/src/index.css index d5f7bf9..5717f9b 100644 --- a/src/index.css +++ b/src/index.css @@ -22,3 +22,8 @@ body { background-color: white; border-radius: 7px; } + +.fullSize { + width: 96%; + margin: 0 auto; +} diff --git a/src/react-app-env.d.ts b/src/react-app-env.d.ts index f75a832..e714db7 100644 --- a/src/react-app-env.d.ts +++ b/src/react-app-env.d.ts @@ -1,2 +1,4 @@ // / +// Set module declaration for modules that do not have @types/* available on NPM repository declare module 'react-bootstrap-table-next'; +declare module 'react-bootstrap-table2-paginator'; diff --git a/yarn.lock b/yarn.lock index ed67060..790a25d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -8505,6 +8505,11 @@ react-bootstrap-table-next@^3.3.5: react-transition-group "2.5.3" underscore "1.9.1" +react-bootstrap-table2-paginator@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/react-bootstrap-table2-paginator/-/react-bootstrap-table2-paginator-2.1.0.tgz#fa3b8de029fe27d511b493685a0f0c4376f9b753" + integrity sha512-VtXIu8ogLZnQfvlSDTCVctr1oTuW2I7/Y7p0ikMuQXDlXwo8wP2MQ6ThQp2s7AvK7uZHsCkEgRPdjXGCe+veMg== + react-bootstrap@^1.0.0-beta.16: version "1.0.0-beta.16" resolved "https://registry.yarnpkg.com/react-bootstrap/-/react-bootstrap-1.0.0-beta.16.tgz#42da0314aee6754494e478687b8e6953de1aaf62"