Skip to content

Commit

Permalink
changed folder get controller to include chip code, added chip table …
Browse files Browse the repository at this point in the history
…for single folder page
  • Loading branch information
BlueAccords committed Jun 4, 2018
1 parent bba7ce8 commit 7b7d612
Show file tree
Hide file tree
Showing 12 changed files with 220 additions and 9 deletions.
35 changes: 34 additions & 1 deletion client/DESIGN.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,38 @@ This file contains the rough design documentation for the front end of this site
- We can store JWT on the client side in either localStorage or cookies. localStorage is vulnerable to XSS(Cross-Site Scripting) attacks, while cookies are vulnerable to CSRF(Cross Site Request Forgery) attacks. After doing some research on this it seems like storing the JWT in cookies is the better option as CSRF is easier to mitigate than XSS.

## Flows
### Get single folder
#### Router
- User should be able to navigate to single folder page
- react router should support this under `/folders/:id` route

#### Page component
- `componentDidMount()` should fetch individual folder information.
- storage should be done in REDUX store
- This is so when the user wants to edit the page(if they have permission) the information will already be fetched.
- `fetchSingleFolder(folderId)` action, should get `folderId` from react-router `:id` parameter.
- dispatch fetch `action`
- `saga` should perform api call, and dispatch `folderGetSuccess` or `folderGetFailure`
- `reducer` should handle following entities:
- `folder` data
- `chip_copies` data
- `author` data(may not be necessary, only 1 author)
- `reducer` state should be normalized

#### Chip Order
- For chip order, there will be an `index` column for each chip copy
- the SERVER will be returning the order of the chip copies, by their id
- the client will store the order as an array of ids
- the client will IGNORE the `index` column for each chip_copy, and instead will order by the returned array of ids.
- on EDIT SUCCESS
- update item in byId list
- update order property: array of ids
- on DELETE SUCCESS
- remote item from byId list
- update order property: array of ids



### Register Account Flow
- User Opens Register modal
- User enters information
Expand All @@ -50,4 +82,5 @@ This file contains the rough design documentation for the front end of this site
## Redux, Components, Design Patterns
- Problem: child components are nested inside of a container and need actions/state from redux store
- This means we would have to pass state/actions through multiple child components who don't use the action/state we're passing through until it reaches the nested child that actually uses it.
- Solution: Organize by feature, if passing child props through too many components then consider adding the props directly to the needed container
- Solution: Organize by feature, if passing child props through too many components then consider adding the props directly to the needed container

2 changes: 1 addition & 1 deletion client/package.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"name": "webpack-demo",
"name": "xtra-redux client",
"version": "1.0.0",
"description": "",
"private": true,
Expand Down
4 changes: 3 additions & 1 deletion client/src/App.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import Login from './views/pages/Login.jsx';
import Forbidden from './views/pages/Forbidden.jsx';
import NotFound from './views/pages/NotFound.jsx';
import SearchFolders from './views/pages/SearchFolders.jsx';
import Folder from './views/pages/Folder.jsx';
import RequireRole from './views/components/RequireRole/index.jsx';

const App = () => {
Expand All @@ -31,7 +32,8 @@ const App = () => {
<Route path="/dashboard" component={RequireRole(Dashboard)}/>
<Route path="/profile" component={Profile}/>
<Route path="/settings" component={RequireRole(Settings)}/>
<Route path="/folders" component={SearchFolders}/>
<Route exact path="/folders/:id" component={Folder}/>
<Route exact path="/folders" component={SearchFolders}/>
<Route path="/login" component={Login}/>
<Route path="/forbidden" component={Forbidden}/>
<Route exact path="/404" component={NotFound}/>
Expand Down
37 changes: 37 additions & 0 deletions client/src/theme.scss
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,43 @@

// override bulma + add custom scss here

// single folder
.single-folder-container {
@include until($desktop) {
padding: 1rem;
}

@include from($desktop) {
padding: 1.5rem 0;
}
}

.chip-body-info {
display: flex;
justify-content: space-between;
flex-wrap: wrap;

p:not(:last-child){
padding-right: 1rem;
}
}

.card-content {
@include until($tablet) {
padding: 1rem;
}
}

.card:not(:last-child) {
@include until($desktop) {
margin-bottom: 1rem;
}

@include from($desktop) {
margin-bottom: 1.5rem;
}
}

// sticky footer
// TODO: re examine to ensure maximum browser compatibility
#app {
Expand Down
7 changes: 6 additions & 1 deletion client/src/views/containers/FoldersList/Folder.jsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,16 @@
import React from 'react';
import { Link } from 'react-router-dom';
import PT from 'prop-types';

const Folder = ({ id, title, description, author }) => {
return (
<tr>
<td>{id}</td>
<td>{title}</td>
<td>
<Link to={`/folders/${id}`}>
{title}
</Link>
</td>
<td>{description}</td>
<td>{author.username}</td>
</tr>
Expand Down
37 changes: 37 additions & 0 deletions client/src/views/containers/SingleFolder/ChipList.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import React, { Fragment } from 'react';


const ChipList = ({chips = null}) => {
return(
<Fragment>
{
chips.map((chip) => {
return (
<div key={chip.id} className="card">
<header className="card-header">
<div className="card-header-title">
<p className="">No. {chip.chip_number} - {chip.original_name}</p>
</div>
</header>
<div className="card-content">
<div className="content chip-body-info">
<p>Element: {chip.element}</p>
<p>Memory: {chip.memory}</p>
<p>Rarity: {chip.rarity}</p>
<p>Type: {chip.type}</p>
</div>
</div>
<footer className="card-footer">
<div href="#" className="card-footer-item">{chip.damage}</div>
<a href="#" className="card-footer-item">Edit</a>
<a href="#" className="card-footer-item">Delete</a>
</footer>
</div>
);
})
}
</Fragment>
)
}

export default ChipList;
39 changes: 39 additions & 0 deletions client/src/views/containers/SingleFolder/ChipTable.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import React, { Fragment } from 'react';
import PT from 'prop-types';

const ChipTable = ({chips}) => {
return(
<div className="table-container">
<table className='table is-fullwidth is-striped'>
<thead>
<tr>
<th>No.</th>
<th>Name</th>
<th>Element</th>
<th>Damage</th>
<th>Code</th>
<th>Memory</th>
<th>Rarity</th>
</tr>
</thead>
<tbody>
{
chips.map((chip) => {
return (<tr>
<td>{chip.chip_number}</td>
<td>{chip.original_name}</td>
<td>{chip.element}</td>
<td>{chip.damage}</td>
<td>{chip.code}</td>
<td>{chip.memory}</td>
<td>{chip.rarity}</td>
</tr>)
})
}
</tbody>
</table>
</div>
)
}

export default ChipTable;
34 changes: 34 additions & 0 deletions client/src/views/containers/SingleFolder/index.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import React, { Fragment } from 'react';
import ChipList from './ChipList.jsx';
import ChipTable from './ChipTable.jsx'

class SingleFolder extends React.Component {
constructor(props) {
super(props);
}

render() {
const { title, author, created_at, child_chips = [] } = this.props;
return (
<Fragment>
<section className="hero is-primary">
<div className="hero-body">
<div className="container">
<h1 className="title">
{title}
</h1>
<h2 className="subtitle">
By - {author && author.username}
</h2>
</div>
</div>
</section>
<div className="container single-folder-container">
<ChipTable chips = {child_chips}/>
</div>
</Fragment>
);
}
}

export default SingleFolder;
27 changes: 27 additions & 0 deletions client/src/views/pages/Folder.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import React from 'react';
import axios from 'axios';
import SingleFolder from './../containers/SingleFolder/index.jsx';

class Folder extends React.Component {
constructor(props) {
super(props);
}

componentDidMount() {
const BASE_URL = 'http://localhost:3000/api/'
const { match: { params } } = this.props;
axios.get(BASE_URL.concat('folder/', params.id))
.then((response) => {
this.setState(response.data.data);
console.log(response.data)
})
}

render() {
return (
<SingleFolder {...this.state} />
)
}
}

export default Folder;
1 change: 1 addition & 0 deletions server/models/folder.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ class Folder extends DbErrors(Sch.Model) {
child_chips: {
relation: Model.ManyToManyRelation,
modelClass: __dirname + '/chip',
filter: query => query.select('chip_copy.code'),
join: {
from: 'folder.id',
// ManyToMany relation needs the `through` object
Expand Down
4 changes: 0 additions & 4 deletions server/routes/v1.js
Original file line number Diff line number Diff line change
Expand Up @@ -77,10 +77,6 @@ router.post(`${folderBaseUrl}`,

// GET#get single folder by id
router.get(`${folderBaseUrl}/:id`,
isAllowed.check({
resource : folderResource,
action: 'read',
}),
folderController.get);

// PUT#update single folder by id
Expand Down
2 changes: 1 addition & 1 deletion server/test/routes.folder.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ describe('# routes : folder', () => {
it('should return all folders', (done) => {
testHelper.login(agent, chai).then(() => {
agent
.get('/api/folder?sortKey=id&sortDirection=ASC')
.get('/api/folder?sortBy=id&order=ASC')
.end((err, res) => {
should.not.exist(err);
res.status.should.equal(200);
Expand Down

0 comments on commit 7b7d612

Please sign in to comment.