Compare commits
4 Commits
master
...
page-struc
| Author | SHA1 | Date | |
|---|---|---|---|
| 6101a2f218 | |||
| a7cd381e96 | |||
| 57cbb68a6d | |||
| d19137a6f6 |
27
README.md
27
README.md
@@ -1,5 +1,30 @@
|
||||
# subtaskio
|
||||
Subtask Io
|
||||
|
||||
frontend - React JS frontend
|
||||
#Frontend
|
||||
## How to use - React JS frontend
|
||||
|
||||
- Clone git
|
||||
|
||||
- Switch to frontend directory
|
||||
`$ cd frontend`
|
||||
|
||||
- Install dependencies:
|
||||
`$ npm install`
|
||||
|
||||
- Host dev environment and start
|
||||
`$ npm start`
|
||||
|
||||
## Stack:
|
||||
- React 16.3.1
|
||||
- React-Router-dom 4.2.2
|
||||
- babel-core 6.26.0
|
||||
- Webpack 3.8.1
|
||||
|
||||
- Unit Testing :
|
||||
- Jest 22.4.3.8
|
||||
- Enzyme 3.3.0
|
||||
|
||||
|
||||
#Backend
|
||||
backend - Aws Lambda backend
|
||||
|
||||
@@ -1,6 +0,0 @@
|
||||
build:
|
||||
go get github.com/aws/aws-lambda-go/lambda
|
||||
go get github.com/aws/aws-lambda-go/events
|
||||
set GOOS=linux
|
||||
go build -o bin/Task_API Tasks.go
|
||||
C:\Users\Emir\go\bin\build-lambda-zip.exe -o bin/Task_API.zip bin/Task_API
|
||||
@@ -1,149 +0,0 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"encoding/json"
|
||||
|
||||
"github.com/aws/aws-lambda-go/events"
|
||||
"github.com/aws/aws-lambda-go/lambda"
|
||||
)
|
||||
|
||||
type User struct {
|
||||
Username string
|
||||
FirstName string
|
||||
LastName string
|
||||
ListOfTasks []Task
|
||||
}
|
||||
|
||||
type Project struct {
|
||||
Name string
|
||||
Description string
|
||||
Leader User
|
||||
ListOfTasks []Task
|
||||
}
|
||||
|
||||
type Task struct {
|
||||
Title string
|
||||
Description string
|
||||
UsersOnTask []User
|
||||
Date string
|
||||
TaskProject Project
|
||||
}
|
||||
|
||||
|
||||
func main() {
|
||||
lambda.Start(Handler)
|
||||
}
|
||||
|
||||
func Handler() (events.APIGatewayProxyResponse, error) {
|
||||
// Getting JSON as []byte
|
||||
b, err := convertTasksToJSON()
|
||||
status := 200
|
||||
if err != nil {
|
||||
status = 500
|
||||
}
|
||||
|
||||
return events.APIGatewayProxyResponse {
|
||||
Body: string(b[:]),
|
||||
StatusCode: status,
|
||||
}, err
|
||||
}
|
||||
|
||||
func convertTasksToJSON() ([]byte, error) {
|
||||
user1 := User {
|
||||
Username: "emirbarucija",
|
||||
FirstName: "Emir",
|
||||
LastName: "Baručija",
|
||||
}
|
||||
|
||||
user2 := User {
|
||||
Username: "noviUser",
|
||||
FirstName: "Novi",
|
||||
LastName: "User",
|
||||
}
|
||||
|
||||
|
||||
project1 := Project {
|
||||
Name: "GO language project",
|
||||
Description: "Making Web API in GO language",
|
||||
Leader: user1,
|
||||
}
|
||||
|
||||
project2 := Project {
|
||||
Name: "Movie collection",
|
||||
Description: "Collection of movies, listed by categories. Make Web API in Java, and connect it with frontend application",
|
||||
Leader: user2,
|
||||
}
|
||||
|
||||
|
||||
task1 := Task {
|
||||
Title: "First task",
|
||||
Description: "This is my first task in GO language",
|
||||
UsersOnTask: []User{user1},
|
||||
Date: "10.04.2018.",
|
||||
TaskProject: project1,
|
||||
}
|
||||
|
||||
task2 := Task {
|
||||
Title: "Second task",
|
||||
Description: "This is my second task in GO language",
|
||||
UsersOnTask: []User{user1},
|
||||
Date: "14.04.2018.",
|
||||
TaskProject: project1,
|
||||
}
|
||||
|
||||
task3 := Task {
|
||||
Title: "Models in Java",
|
||||
Description: "The goal of task is to make some models for Java application",
|
||||
UsersOnTask: []User{user2},
|
||||
Date: "05.02.2018.",
|
||||
TaskProject: project2,
|
||||
}
|
||||
|
||||
task4 := Task {
|
||||
Title: "Controllers in Java",
|
||||
Description: "The goal is to make controllers for CRUD operations on models",
|
||||
UsersOnTask: []User{user1, user2},
|
||||
Date: "15.02.2018.",
|
||||
TaskProject: project2,
|
||||
}
|
||||
|
||||
task5 := Task {
|
||||
Title: "Correct menu items positions",
|
||||
Description: "Items in menu need to be corrected via CSS, all items should be of the same size and aligned in the same way",
|
||||
UsersOnTask: []User{user1},
|
||||
Date: "12.03.2018.",
|
||||
TaskProject: project2,
|
||||
}
|
||||
|
||||
task6 := Task {
|
||||
Title: "Diplay entries from database in list",
|
||||
Description: "Categories from the database need to be displayed in the list of the Categories menu",
|
||||
UsersOnTask: []User{user1, user2},
|
||||
Date: "24.03.2018.",
|
||||
TaskProject: project2,
|
||||
}
|
||||
|
||||
project1.ListOfTasks = []Task{task1, task2}
|
||||
project2.ListOfTasks = []Task{task3, task4, task5, task6}
|
||||
|
||||
user1.ListOfTasks = []Task{task1, task2, task4, task5, task6}
|
||||
user2.ListOfTasks = []Task{task3, task4, task6}
|
||||
|
||||
|
||||
tasks := []Task{task1, task2, task3, task4, task5, task6}
|
||||
b, err := json.Marshal(tasks)
|
||||
return b, err
|
||||
}
|
||||
|
||||
func (u User) String() string {
|
||||
return fmt.Sprintf("Username: %v\nFirst name: %v\nLast name: %v\nTAsks: %v", u.Username, u.FirstName, u.LastName, u.ListOfTasks)
|
||||
}
|
||||
|
||||
func (t Task) String() string {
|
||||
return fmt.Sprintf("Title: %v\nDescription: %v\nUsers: %v\nDate: %v\nProject: %v", t.Title, t.Description, t.UsersOnTask, t.Date, t.TaskProject)
|
||||
}
|
||||
|
||||
func (p Project) String() string {
|
||||
return fmt.Sprintf("Name: %v\nDescription: %v\nLeader: %v", p.Name, p.Description, p.Leader)
|
||||
}
|
||||
Binary file not shown.
Binary file not shown.
@@ -1,2 +0,0 @@
|
||||
# Serverless directories
|
||||
.serverless
|
||||
@@ -1,6 +0,0 @@
|
||||
build:
|
||||
go get github.com/aws/aws-lambda-go/lambda
|
||||
go get github.com/aws/aws-lambda-go/events
|
||||
set GOOS=linux
|
||||
go build -o bin/Task_API Tasks.go
|
||||
C:\Users\Emir\go\bin\build-lambda-zip.exe -o bin/Task_API.zip bin/Task_API
|
||||
@@ -1,149 +0,0 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"encoding/json"
|
||||
|
||||
"github.com/aws/aws-lambda-go/events"
|
||||
"github.com/aws/aws-lambda-go/lambda"
|
||||
)
|
||||
|
||||
type User struct {
|
||||
Username string
|
||||
FirstName string
|
||||
LastName string
|
||||
ListOfTasks []Task
|
||||
}
|
||||
|
||||
type Project struct {
|
||||
Name string
|
||||
Description string
|
||||
Leader User
|
||||
ListOfTasks []Task
|
||||
}
|
||||
|
||||
type Task struct {
|
||||
Title string
|
||||
Description string
|
||||
UsersOnTask []User
|
||||
Date string
|
||||
TaskProject Project
|
||||
}
|
||||
|
||||
|
||||
func main() {
|
||||
lambda.Start(Handler)
|
||||
}
|
||||
|
||||
func Handler() (events.APIGatewayProxyResponse, error) {
|
||||
// Getting JSON as []byte
|
||||
b, err := convertTasksToJSON()
|
||||
status := 200
|
||||
if err != nil {
|
||||
status = 500
|
||||
}
|
||||
|
||||
return events.APIGatewayProxyResponse {
|
||||
Body: string(b[:]),
|
||||
StatusCode: status,
|
||||
}, err
|
||||
}
|
||||
|
||||
func convertTasksToJSON() ([]byte, error) {
|
||||
user1 := User {
|
||||
Username: "emirbarucija",
|
||||
FirstName: "Emir",
|
||||
LastName: "Baručija",
|
||||
}
|
||||
|
||||
user2 := User {
|
||||
Username: "noviUser",
|
||||
FirstName: "Novi",
|
||||
LastName: "User",
|
||||
}
|
||||
|
||||
|
||||
project1 := Project {
|
||||
Name: "GO language project",
|
||||
Description: "Making Web API in GO language",
|
||||
Leader: user1,
|
||||
}
|
||||
|
||||
project2 := Project {
|
||||
Name: "Movie collection",
|
||||
Description: "Collection of movies, listed by categories. Make Web API in Java, and connect it with frontend application",
|
||||
Leader: user2,
|
||||
}
|
||||
|
||||
|
||||
task1 := Task {
|
||||
Title: "First task",
|
||||
Description: "This is my first task in GO language",
|
||||
UsersOnTask: []User{user1},
|
||||
Date: "10.04.2018.",
|
||||
TaskProject: project1,
|
||||
}
|
||||
|
||||
task2 := Task {
|
||||
Title: "Second task",
|
||||
Description: "This is my second task in GO language",
|
||||
UsersOnTask: []User{user1},
|
||||
Date: "14.04.2018.",
|
||||
TaskProject: project1,
|
||||
}
|
||||
|
||||
task3 := Task {
|
||||
Title: "Models in Java",
|
||||
Description: "The goal of task is to make some models for Java application",
|
||||
UsersOnTask: []User{user2},
|
||||
Date: "05.02.2018.",
|
||||
TaskProject: project2,
|
||||
}
|
||||
|
||||
task4 := Task {
|
||||
Title: "Controllers in Java",
|
||||
Description: "The goal is to make controllers for CRUD operations on models",
|
||||
UsersOnTask: []User{user1, user2},
|
||||
Date: "15.02.2018.",
|
||||
TaskProject: project2,
|
||||
}
|
||||
|
||||
task5 := Task {
|
||||
Title: "Correct menu items positions",
|
||||
Description: "Items in menu need to be corrected via CSS, all items should be of the same size and aligned in the same way",
|
||||
UsersOnTask: []User{user1},
|
||||
Date: "12.03.2018.",
|
||||
TaskProject: project2,
|
||||
}
|
||||
|
||||
task6 := Task {
|
||||
Title: "Diplay entries from database in list",
|
||||
Description: "Categories from the database need to be displayed in the list of the Categories menu",
|
||||
UsersOnTask: []User{user1, user2},
|
||||
Date: "24.03.2018.",
|
||||
TaskProject: project2,
|
||||
}
|
||||
|
||||
project1.ListOfTasks = []Task{task1, task2}
|
||||
project2.ListOfTasks = []Task{task3, task4, task5, task6}
|
||||
|
||||
user1.ListOfTasks = []Task{task1, task2, task4, task5, task6}
|
||||
user2.ListOfTasks = []Task{task3, task4, task6}
|
||||
|
||||
|
||||
tasks := []Task{task1, task2, task3, task4, task5, task6}
|
||||
b, err := json.Marshal(tasks)
|
||||
return b, err
|
||||
}
|
||||
|
||||
func (u User) String() string {
|
||||
return fmt.Sprintf("Username: %v\nFirst name: %v\nLast name: %v\nTAsks: %v", u.Username, u.FirstName, u.LastName, u.ListOfTasks)
|
||||
}
|
||||
|
||||
func (t Task) String() string {
|
||||
return fmt.Sprintf("Title: %v\nDescription: %v\nUsers: %v\nDate: %v\nProject: %v", t.Title, t.Description, t.UsersOnTask, t.Date, t.TaskProject)
|
||||
}
|
||||
|
||||
func (p Project) String() string {
|
||||
return fmt.Sprintf("Name: %v\nDescription: %v\nLeader: %v", p.Name, p.Description, p.Leader)
|
||||
}
|
||||
Binary file not shown.
Binary file not shown.
@@ -1,19 +0,0 @@
|
||||
service: Task_API_service
|
||||
|
||||
provider:
|
||||
name: aws
|
||||
runtime: go1.x
|
||||
|
||||
package:
|
||||
exclude:
|
||||
- ./**
|
||||
include:
|
||||
- ./bin/**
|
||||
|
||||
functions:
|
||||
Task_API:
|
||||
handler: bin/Task_API
|
||||
events:
|
||||
- http:
|
||||
path: tasks
|
||||
method: GET
|
||||
@@ -79,6 +79,7 @@ module.exports = function(proxy, allowedHost) {
|
||||
// See https://github.com/facebookincubator/create-react-app/issues/387.
|
||||
disableDotRule: true,
|
||||
},
|
||||
historyApiFallback: true,
|
||||
public: allowedHost,
|
||||
proxy,
|
||||
before(app) {
|
||||
|
||||
12963
frontend/package-lock.json
generated
Normal file
12963
frontend/package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
@@ -40,7 +40,10 @@
|
||||
"react": "^16.3.1",
|
||||
"react-dev-utils": "^5.0.1",
|
||||
"react-dom": "^16.3.1",
|
||||
"react-redux": "^5.0.7",
|
||||
"react-router-dom": "^4.2.2",
|
||||
"react-test-renderer": "^16.3.1",
|
||||
"redux": "^3.7.2",
|
||||
"resolve": "1.6.0",
|
||||
"sass-loader": "^6.0.7",
|
||||
"style-loader": "0.19.0",
|
||||
@@ -59,6 +62,7 @@
|
||||
"watch-css": "npm run build-css && node-sass-chokidar src/ -o src/ --watch --recursive"
|
||||
},
|
||||
"jest": {
|
||||
"setupTestFrameworkScriptFile": "<rootDir>/src/setupTests.js",
|
||||
"collectCoverageFrom": [
|
||||
"src/**/*.{js,jsx,mjs}"
|
||||
],
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
work correctly both with client-side routing and a non-root public URL.
|
||||
Learn how to configure a non-root public URL by running `npm run build`.
|
||||
-->
|
||||
<title>React App</title>
|
||||
<title>Sutask io</title>
|
||||
</head>
|
||||
<body>
|
||||
<noscript>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"short_name": "React App",
|
||||
"name": "Create React App Sample",
|
||||
"short_name": "Subtask IO",
|
||||
"name": "Subtask",
|
||||
"icons": [
|
||||
{
|
||||
"src": "favicon.ico",
|
||||
|
||||
6
frontend/src/actions/index.js
Normal file
6
frontend/src/actions/index.js
Normal file
@@ -0,0 +1,6 @@
|
||||
export const INIT_PAGE = 'INIT_PAGE'
|
||||
|
||||
export const initPage = titles => ({
|
||||
type: INIT_PAGE,
|
||||
titles
|
||||
})
|
||||
@@ -1,9 +1,10 @@
|
||||
import React from 'react';
|
||||
import ReactDOM from 'react-dom';
|
||||
import {MemoryRouter as Router} from 'react-router-dom'
|
||||
import App from './index';
|
||||
|
||||
it('renders without crashing', () => {
|
||||
const div = document.createElement('div');
|
||||
ReactDOM.render(<App />, div);
|
||||
ReactDOM.render(<Router><App/></Router>, div);
|
||||
ReactDOM.unmountComponentAtNode(div);
|
||||
});
|
||||
|
||||
@@ -0,0 +1,111 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`Daoardshb renders correctly 1`] = `
|
||||
ShallowWrapper {
|
||||
"length": 1,
|
||||
Symbol(enzyme.__root__): [Circular],
|
||||
Symbol(enzyme.__unrendered__): <HashRouter>
|
||||
<Unknown
|
||||
title="Dashboard"
|
||||
/>
|
||||
</HashRouter>,
|
||||
Symbol(enzyme.__renderer__): Object {
|
||||
"batchedUpdates": [Function],
|
||||
"getNode": [Function],
|
||||
"render": [Function],
|
||||
"simulateEvent": [Function],
|
||||
"unmount": [Function],
|
||||
},
|
||||
Symbol(enzyme.__node__): Object {
|
||||
"instance": null,
|
||||
"key": undefined,
|
||||
"nodeType": "class",
|
||||
"props": Object {
|
||||
"children": <Unknown
|
||||
title="Dashboard"
|
||||
/>,
|
||||
"history": Object {
|
||||
"action": "POP",
|
||||
"block": [Function],
|
||||
"createHref": [Function],
|
||||
"go": [Function],
|
||||
"goBack": [Function],
|
||||
"goForward": [Function],
|
||||
"length": 1,
|
||||
"listen": [Function],
|
||||
"location": Object {
|
||||
"hash": "",
|
||||
"pathname": "/",
|
||||
"search": "",
|
||||
"state": undefined,
|
||||
},
|
||||
"push": [Function],
|
||||
"replace": [Function],
|
||||
},
|
||||
},
|
||||
"ref": null,
|
||||
"rendered": Object {
|
||||
"instance": null,
|
||||
"key": undefined,
|
||||
"nodeType": "function",
|
||||
"props": Object {
|
||||
"title": "Dashboard",
|
||||
},
|
||||
"ref": null,
|
||||
"rendered": null,
|
||||
"type": [Function],
|
||||
},
|
||||
"type": [Function],
|
||||
},
|
||||
Symbol(enzyme.__nodes__): Array [
|
||||
Object {
|
||||
"instance": null,
|
||||
"key": undefined,
|
||||
"nodeType": "class",
|
||||
"props": Object {
|
||||
"children": <Unknown
|
||||
title="Dashboard"
|
||||
/>,
|
||||
"history": Object {
|
||||
"action": "POP",
|
||||
"block": [Function],
|
||||
"createHref": [Function],
|
||||
"go": [Function],
|
||||
"goBack": [Function],
|
||||
"goForward": [Function],
|
||||
"length": 1,
|
||||
"listen": [Function],
|
||||
"location": Object {
|
||||
"hash": "",
|
||||
"pathname": "/",
|
||||
"search": "",
|
||||
"state": undefined,
|
||||
},
|
||||
"push": [Function],
|
||||
"replace": [Function],
|
||||
},
|
||||
},
|
||||
"ref": null,
|
||||
"rendered": Object {
|
||||
"instance": null,
|
||||
"key": undefined,
|
||||
"nodeType": "function",
|
||||
"props": Object {
|
||||
"title": "Dashboard",
|
||||
},
|
||||
"ref": null,
|
||||
"rendered": null,
|
||||
"type": [Function],
|
||||
},
|
||||
"type": [Function],
|
||||
},
|
||||
],
|
||||
Symbol(enzyme.__options__): Object {
|
||||
"adapter": ReactSixteenAdapter {
|
||||
"options": Object {
|
||||
"enableComponentDidUpdateOnSetState": true,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
`;
|
||||
13
frontend/src/components/App/Dashboard/dashboard.test.js
Normal file
13
frontend/src/components/App/Dashboard/dashboard.test.js
Normal file
@@ -0,0 +1,13 @@
|
||||
import React from 'react';
|
||||
import {HashRouter as Router} from 'react-router-dom'
|
||||
import {Dashboard} from './index';
|
||||
import {shallow} from 'enzyme'
|
||||
import renderer from 'react-test-renderer';
|
||||
|
||||
test('Daoardshb renders correctly', () => {
|
||||
const props = {
|
||||
title: 'Dashboard'
|
||||
}
|
||||
const component = shallow((<Router><Dashboard {...props} /></Router>))
|
||||
expect(component).toMatchSnapshot();
|
||||
});
|
||||
16
frontend/src/components/App/Dashboard/index.js
Normal file
16
frontend/src/components/App/Dashboard/index.js
Normal file
@@ -0,0 +1,16 @@
|
||||
import React from 'react';
|
||||
import { connect } from 'react-redux'
|
||||
import styles from './styles.scss';
|
||||
import Header from '../Header/index'
|
||||
|
||||
export const Dashboard = (props) => {
|
||||
return <div className={styles.colored}><Header />Title {props.title}</div>;
|
||||
};
|
||||
|
||||
const mapStateToProps = (state) => {
|
||||
return {
|
||||
title: state.pageInitialised.titles.title,
|
||||
}
|
||||
}
|
||||
|
||||
export default connect(mapStateToProps)(Dashboard);
|
||||
@@ -1,10 +0,0 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`Dummy renders correctly 1`] = `
|
||||
<div
|
||||
className={undefined}
|
||||
>
|
||||
Hello,
|
||||
Hamo
|
||||
</div>
|
||||
`;
|
||||
@@ -1,8 +0,0 @@
|
||||
import React from 'react';
|
||||
import styles from './styles.scss';
|
||||
|
||||
const Dummy = (props) => {
|
||||
return <div className={styles.colored}>Hello, {props.name}</div>;
|
||||
};
|
||||
|
||||
export default Dummy;
|
||||
@@ -1,3 +0,0 @@
|
||||
.colored {
|
||||
color: blueviolet;
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`Header renders correctly 1`] = `
|
||||
<div
|
||||
className={undefined}
|
||||
>
|
||||
<h1>
|
||||
SUBTASK
|
||||
</h1>
|
||||
<div
|
||||
className={undefined}
|
||||
>
|
||||
<a
|
||||
className={undefined}
|
||||
href="#/mytask"
|
||||
onClick={[Function]}
|
||||
>
|
||||
My Task
|
||||
</a>
|
||||
<a
|
||||
className={undefined}
|
||||
href="#/inbox"
|
||||
onClick={[Function]}
|
||||
>
|
||||
Inbox
|
||||
</a>
|
||||
<a
|
||||
className={undefined}
|
||||
href="#/dashboard"
|
||||
onClick={[Function]}
|
||||
>
|
||||
Dashboard
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
@@ -1,12 +1,12 @@
|
||||
import React from 'react';
|
||||
import Dummy from './index';
|
||||
import {HashRouter as Router} from 'react-router-dom'
|
||||
import Header from './index';
|
||||
import renderer from 'react-test-renderer';
|
||||
|
||||
test('Dummy renders correctly', () => {
|
||||
test('Header renders correctly', () => {
|
||||
const component = renderer.create(
|
||||
<Dummy name="Hamo"/>,
|
||||
<Router><Header/></Router>,
|
||||
);
|
||||
let tree = component.toJSON();
|
||||
expect(tree).toMatchSnapshot();
|
||||
});
|
||||
|
||||
});
|
||||
16
frontend/src/components/App/Header/index.js
Normal file
16
frontend/src/components/App/Header/index.js
Normal file
@@ -0,0 +1,16 @@
|
||||
import React from 'react';
|
||||
import { Link } from 'react-router-dom'
|
||||
import styles from './styles.scss';
|
||||
|
||||
export const Header = () => {
|
||||
return <div className={styles.Header}>
|
||||
<h1>SUBTASK</h1>
|
||||
<div className={styles.HeaderContainer}>
|
||||
<Link className={styles.HeaderContainer} to="/mytask">My Task</Link>
|
||||
<Link className={styles.HeaderContainer} to="/inbox">Inbox</Link>
|
||||
<Link className={styles.HeaderContainer} to="/dashboard">Dashboard</Link>
|
||||
</div>
|
||||
</div>;
|
||||
};
|
||||
|
||||
export default Header;
|
||||
14
frontend/src/components/App/Header/styles.scss
Normal file
14
frontend/src/components/App/Header/styles.scss
Normal file
@@ -0,0 +1,14 @@
|
||||
.Header {
|
||||
padding-top : 6px;
|
||||
padding-bottom : 6px;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items:center;
|
||||
display: flex;
|
||||
margin-left: 8px;
|
||||
margin-right: 8px;
|
||||
}
|
||||
|
||||
.HeaderContainer {
|
||||
padding: 10px;
|
||||
}
|
||||
@@ -0,0 +1,111 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`Inbox renders correctly 1`] = `
|
||||
ShallowWrapper {
|
||||
"length": 1,
|
||||
Symbol(enzyme.__root__): [Circular],
|
||||
Symbol(enzyme.__unrendered__): <HashRouter>
|
||||
<Unknown
|
||||
title="Inbox"
|
||||
/>
|
||||
</HashRouter>,
|
||||
Symbol(enzyme.__renderer__): Object {
|
||||
"batchedUpdates": [Function],
|
||||
"getNode": [Function],
|
||||
"render": [Function],
|
||||
"simulateEvent": [Function],
|
||||
"unmount": [Function],
|
||||
},
|
||||
Symbol(enzyme.__node__): Object {
|
||||
"instance": null,
|
||||
"key": undefined,
|
||||
"nodeType": "class",
|
||||
"props": Object {
|
||||
"children": <Unknown
|
||||
title="Inbox"
|
||||
/>,
|
||||
"history": Object {
|
||||
"action": "POP",
|
||||
"block": [Function],
|
||||
"createHref": [Function],
|
||||
"go": [Function],
|
||||
"goBack": [Function],
|
||||
"goForward": [Function],
|
||||
"length": 1,
|
||||
"listen": [Function],
|
||||
"location": Object {
|
||||
"hash": "",
|
||||
"pathname": "/",
|
||||
"search": "",
|
||||
"state": undefined,
|
||||
},
|
||||
"push": [Function],
|
||||
"replace": [Function],
|
||||
},
|
||||
},
|
||||
"ref": null,
|
||||
"rendered": Object {
|
||||
"instance": null,
|
||||
"key": undefined,
|
||||
"nodeType": "function",
|
||||
"props": Object {
|
||||
"title": "Inbox",
|
||||
},
|
||||
"ref": null,
|
||||
"rendered": null,
|
||||
"type": [Function],
|
||||
},
|
||||
"type": [Function],
|
||||
},
|
||||
Symbol(enzyme.__nodes__): Array [
|
||||
Object {
|
||||
"instance": null,
|
||||
"key": undefined,
|
||||
"nodeType": "class",
|
||||
"props": Object {
|
||||
"children": <Unknown
|
||||
title="Inbox"
|
||||
/>,
|
||||
"history": Object {
|
||||
"action": "POP",
|
||||
"block": [Function],
|
||||
"createHref": [Function],
|
||||
"go": [Function],
|
||||
"goBack": [Function],
|
||||
"goForward": [Function],
|
||||
"length": 1,
|
||||
"listen": [Function],
|
||||
"location": Object {
|
||||
"hash": "",
|
||||
"pathname": "/",
|
||||
"search": "",
|
||||
"state": undefined,
|
||||
},
|
||||
"push": [Function],
|
||||
"replace": [Function],
|
||||
},
|
||||
},
|
||||
"ref": null,
|
||||
"rendered": Object {
|
||||
"instance": null,
|
||||
"key": undefined,
|
||||
"nodeType": "function",
|
||||
"props": Object {
|
||||
"title": "Inbox",
|
||||
},
|
||||
"ref": null,
|
||||
"rendered": null,
|
||||
"type": [Function],
|
||||
},
|
||||
"type": [Function],
|
||||
},
|
||||
],
|
||||
Symbol(enzyme.__options__): Object {
|
||||
"adapter": ReactSixteenAdapter {
|
||||
"options": Object {
|
||||
"enableComponentDidUpdateOnSetState": true,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
`;
|
||||
13
frontend/src/components/App/Inbox/inbox.test.js
Normal file
13
frontend/src/components/App/Inbox/inbox.test.js
Normal file
@@ -0,0 +1,13 @@
|
||||
import React from 'react';
|
||||
import {HashRouter as Router} from 'react-router-dom'
|
||||
import {shallow} from 'enzyme'
|
||||
import {Inbox} from './index';
|
||||
import renderer from 'react-test-renderer';
|
||||
|
||||
test('Inbox renders correctly', () => {
|
||||
const props = {
|
||||
title: 'Inbox'
|
||||
}
|
||||
const component = shallow((<Router><Inbox {...props} /></Router>))
|
||||
expect(component).toMatchSnapshot();
|
||||
});
|
||||
16
frontend/src/components/App/Inbox/index.js
Normal file
16
frontend/src/components/App/Inbox/index.js
Normal file
@@ -0,0 +1,16 @@
|
||||
import React from 'react';
|
||||
import { connect } from 'react-redux'
|
||||
import styles from './styles.scss';
|
||||
import Header from '../Header/index'
|
||||
|
||||
export const Inbox = (props) => {
|
||||
return <div className={styles.colored}><Header />Title {props.title}</div>;
|
||||
};
|
||||
|
||||
const mapStateToProps = (state) => {
|
||||
return {
|
||||
title: state.pageInitialised.titles.title,
|
||||
}
|
||||
}
|
||||
|
||||
export default connect(mapStateToProps)(Inbox);
|
||||
0
frontend/src/components/App/Inbox/styles.scss
Normal file
0
frontend/src/components/App/Inbox/styles.scss
Normal file
@@ -0,0 +1,111 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`MyTask renders correctly 1`] = `
|
||||
ShallowWrapper {
|
||||
"length": 1,
|
||||
Symbol(enzyme.__root__): [Circular],
|
||||
Symbol(enzyme.__unrendered__): <HashRouter>
|
||||
<Unknown
|
||||
title="MyTask"
|
||||
/>
|
||||
</HashRouter>,
|
||||
Symbol(enzyme.__renderer__): Object {
|
||||
"batchedUpdates": [Function],
|
||||
"getNode": [Function],
|
||||
"render": [Function],
|
||||
"simulateEvent": [Function],
|
||||
"unmount": [Function],
|
||||
},
|
||||
Symbol(enzyme.__node__): Object {
|
||||
"instance": null,
|
||||
"key": undefined,
|
||||
"nodeType": "class",
|
||||
"props": Object {
|
||||
"children": <Unknown
|
||||
title="MyTask"
|
||||
/>,
|
||||
"history": Object {
|
||||
"action": "POP",
|
||||
"block": [Function],
|
||||
"createHref": [Function],
|
||||
"go": [Function],
|
||||
"goBack": [Function],
|
||||
"goForward": [Function],
|
||||
"length": 1,
|
||||
"listen": [Function],
|
||||
"location": Object {
|
||||
"hash": "",
|
||||
"pathname": "/",
|
||||
"search": "",
|
||||
"state": undefined,
|
||||
},
|
||||
"push": [Function],
|
||||
"replace": [Function],
|
||||
},
|
||||
},
|
||||
"ref": null,
|
||||
"rendered": Object {
|
||||
"instance": null,
|
||||
"key": undefined,
|
||||
"nodeType": "function",
|
||||
"props": Object {
|
||||
"title": "MyTask",
|
||||
},
|
||||
"ref": null,
|
||||
"rendered": null,
|
||||
"type": [Function],
|
||||
},
|
||||
"type": [Function],
|
||||
},
|
||||
Symbol(enzyme.__nodes__): Array [
|
||||
Object {
|
||||
"instance": null,
|
||||
"key": undefined,
|
||||
"nodeType": "class",
|
||||
"props": Object {
|
||||
"children": <Unknown
|
||||
title="MyTask"
|
||||
/>,
|
||||
"history": Object {
|
||||
"action": "POP",
|
||||
"block": [Function],
|
||||
"createHref": [Function],
|
||||
"go": [Function],
|
||||
"goBack": [Function],
|
||||
"goForward": [Function],
|
||||
"length": 1,
|
||||
"listen": [Function],
|
||||
"location": Object {
|
||||
"hash": "",
|
||||
"pathname": "/",
|
||||
"search": "",
|
||||
"state": undefined,
|
||||
},
|
||||
"push": [Function],
|
||||
"replace": [Function],
|
||||
},
|
||||
},
|
||||
"ref": null,
|
||||
"rendered": Object {
|
||||
"instance": null,
|
||||
"key": undefined,
|
||||
"nodeType": "function",
|
||||
"props": Object {
|
||||
"title": "MyTask",
|
||||
},
|
||||
"ref": null,
|
||||
"rendered": null,
|
||||
"type": [Function],
|
||||
},
|
||||
"type": [Function],
|
||||
},
|
||||
],
|
||||
Symbol(enzyme.__options__): Object {
|
||||
"adapter": ReactSixteenAdapter {
|
||||
"options": Object {
|
||||
"enableComponentDidUpdateOnSetState": true,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
`;
|
||||
16
frontend/src/components/App/Mytask/index.js
Normal file
16
frontend/src/components/App/Mytask/index.js
Normal file
@@ -0,0 +1,16 @@
|
||||
import React from 'react';
|
||||
import { connect } from 'react-redux'
|
||||
import styles from './styles.scss';
|
||||
import Header from '../Header/index'
|
||||
|
||||
export const MyTask = (props) => {
|
||||
return <div className={styles.colored}><Header />Title {props.title}</div>;
|
||||
};
|
||||
|
||||
const mapStateToProps = (state) => {
|
||||
return {
|
||||
title: state.pageInitialised.titles.title,
|
||||
}
|
||||
}
|
||||
|
||||
export default connect(mapStateToProps)(MyTask);
|
||||
14
frontend/src/components/App/Mytask/mytask.test.js
Normal file
14
frontend/src/components/App/Mytask/mytask.test.js
Normal file
@@ -0,0 +1,14 @@
|
||||
import React from 'react';
|
||||
import {HashRouter as Router} from 'react-router-dom'
|
||||
import {shallow} from 'enzyme'
|
||||
import {MyTask} from './index';
|
||||
import renderer from 'react-test-renderer';
|
||||
|
||||
test('MyTask renders correctly', () => {
|
||||
|
||||
const props = {
|
||||
title: 'MyTask'
|
||||
}
|
||||
const component = shallow((<Router><MyTask {...props} /></Router>))
|
||||
expect(component).toMatchSnapshot();
|
||||
});
|
||||
0
frontend/src/components/App/Mytask/styles.scss
Normal file
0
frontend/src/components/App/Mytask/styles.scss
Normal file
53
frontend/src/components/App/Root/index.js
Normal file
53
frontend/src/components/App/Root/index.js
Normal file
@@ -0,0 +1,53 @@
|
||||
import React, { Component } from 'react'
|
||||
import { Provider } from 'react-redux'
|
||||
import { BrowserRouter as Router, Route } from 'react-router-dom'
|
||||
|
||||
import App from '../index'
|
||||
import Inbox from '../Inbox/index';
|
||||
import MyTask from '../Mytask/index';
|
||||
import Dashboard from '../Dashboard/index';
|
||||
import { initPage } from '../../../actions/index'
|
||||
|
||||
class Root extends Component {
|
||||
|
||||
|
||||
render() {
|
||||
return (
|
||||
<Provider store={this.props.store}>
|
||||
<Router>
|
||||
<div>
|
||||
<Route path='/' exact component={App} />
|
||||
<Route path="/mytask" exact component={mountComponentWithPathAction(MyTask, this.props)} />
|
||||
<Route path="/inbox" exact component={mountComponentWithPathAction(Inbox, this.props)} />
|
||||
<Route path="/dashboard" exact component={mountComponentWithPathAction(Dashboard, this.props)} />
|
||||
</div>
|
||||
</Router>
|
||||
</Provider>
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Pass this function to `react-router-dom` Route component property
|
||||
* In orderd to triger redux action that is related to te Route path
|
||||
* If such action exists
|
||||
*
|
||||
* @param {} WrappedComponent a React component to render
|
||||
* @param {*} props a an object containing redux `store` to dispach initPage action with route path name
|
||||
* @returns A new HIGHT ORDER React component from WrappedComponent after redux action is dispatched
|
||||
*/
|
||||
let mountComponentWithPathAction = function (WrappedComponent, props) {
|
||||
return class extends Component {
|
||||
|
||||
componentWillMount() {
|
||||
props.store.dispatch(initPage({ pathName: this.props.location.pathname }))
|
||||
}
|
||||
|
||||
render() {
|
||||
return <WrappedComponent {...this.props} />
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default Root
|
||||
@@ -1,20 +1,10 @@
|
||||
import React, { Component } from 'react';
|
||||
import logo from '../../logo.svg';
|
||||
import styles from './styles.scss';
|
||||
import Dummy from './Dummy';
|
||||
import Header from './Header';
|
||||
|
||||
class App extends Component {
|
||||
render() {
|
||||
return (
|
||||
<div className={styles.App}>
|
||||
<header className={styles["App-header"]}>
|
||||
<img src={logo} className={styles["App-logo"]} alt="logo" />
|
||||
<h1 className={styles["App-title"]}><Dummy name="Hamo"/> </h1>
|
||||
</header>
|
||||
<p className={styles["App-intro"]}>
|
||||
To get started ba, edit <code>src/App.js</code> and save to reload.
|
||||
</p>
|
||||
</div>
|
||||
<Header />
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +1,15 @@
|
||||
import React from 'react';
|
||||
import ReactDOM from 'react-dom';
|
||||
import { createStore } from 'redux'
|
||||
import './index.css';
|
||||
import App from './components/App';
|
||||
import registerServiceWorker from './registerServiceWorker';
|
||||
|
||||
ReactDOM.render(<App />, document.getElementById('root'));
|
||||
import subtaskIo from './reducers/index'
|
||||
import Root from './components/App/Root/index';
|
||||
|
||||
const store = createStore(subtaskIo)
|
||||
|
||||
ReactDOM.render(
|
||||
<Root store={store} />,
|
||||
document.getElementById('root'));
|
||||
registerServiceWorker();
|
||||
|
||||
7
frontend/src/reducers/index.js
Normal file
7
frontend/src/reducers/index.js
Normal file
@@ -0,0 +1,7 @@
|
||||
import { combineReducers } from 'redux'
|
||||
import pageInitialised from './router'
|
||||
|
||||
const subtaskIo = combineReducers({
|
||||
pageInitialised,
|
||||
})
|
||||
export default subtaskIo
|
||||
14
frontend/src/reducers/router.js
Normal file
14
frontend/src/reducers/router.js
Normal file
@@ -0,0 +1,14 @@
|
||||
const pageInitialised = (state = {
|
||||
titles: { title: 'Default title' },
|
||||
}, action) => {
|
||||
switch (action.type) {
|
||||
case 'INIT_PAGE':
|
||||
return {
|
||||
...state,
|
||||
titles: { title: action.titles.pathName }
|
||||
}
|
||||
default:
|
||||
return state
|
||||
}
|
||||
}
|
||||
export default pageInitialised
|
||||
4
frontend/src/setupTests.js
Normal file
4
frontend/src/setupTests.js
Normal file
@@ -0,0 +1,4 @@
|
||||
import { configure } from 'enzyme';
|
||||
import Adapter from 'enzyme-adapter-react-16';
|
||||
|
||||
configure({ adapter: new Adapter() });
|
||||
Reference in New Issue
Block a user