Add connected but unstyled workload list
This commit is contained in:
@@ -8,6 +8,8 @@
|
|||||||
"react-dom": "^16.7.0",
|
"react-dom": "^16.7.0",
|
||||||
"react-redux": "^6.0.0",
|
"react-redux": "^6.0.0",
|
||||||
"react-scripts": "2.1.3",
|
"react-scripts": "2.1.3",
|
||||||
|
"react-timeago": "^4.3.0",
|
||||||
|
"redux": "^4.0.1",
|
||||||
"redux-observable": "^1.0.0",
|
"redux-observable": "^1.0.0",
|
||||||
"rxjs": "^6.4.0",
|
"rxjs": "^6.4.0",
|
||||||
"typescript": "3.2.4"
|
"typescript": "3.2.4"
|
||||||
@@ -32,6 +34,7 @@
|
|||||||
"@types/node": "10.12.18",
|
"@types/node": "10.12.18",
|
||||||
"@types/react": "16.7.22",
|
"@types/react": "16.7.22",
|
||||||
"@types/react-dom": "16.0.11",
|
"@types/react-dom": "16.0.11",
|
||||||
"@types/react-redux": "^7.0.1"
|
"@types/react-redux": "^7.0.1",
|
||||||
|
"@types/react-timeago": "^4.1.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
14
src/App.tsx
14
src/App.tsx
@@ -1,14 +0,0 @@
|
|||||||
import React, { PureComponent } from 'react';
|
|
||||||
import './App.css';
|
|
||||||
|
|
||||||
class App extends PureComponent {
|
|
||||||
render() {
|
|
||||||
return (
|
|
||||||
<div className="App">
|
|
||||||
App goes here…
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export default App;
|
|
||||||
22
src/components/App/App.tsx
Executable file
22
src/components/App/App.tsx
Executable file
@@ -0,0 +1,22 @@
|
|||||||
|
import React, { PureComponent } from 'react';
|
||||||
|
|
||||||
|
import { WorkloadListContainer } from '../WorkloadList';
|
||||||
|
import './App.css';
|
||||||
|
|
||||||
|
|
||||||
|
class App extends PureComponent {
|
||||||
|
render() {
|
||||||
|
return (
|
||||||
|
<div className="App">
|
||||||
|
<div className="App-mainColumn">
|
||||||
|
<WorkloadListContainer />
|
||||||
|
</div>
|
||||||
|
<div className="App-asideColumn">
|
||||||
|
{/* <WorkloadFormContainer /> */}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default App;
|
||||||
2
src/components/App/index.ts
Normal file
2
src/components/App/index.ts
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
export { default } from './App';
|
||||||
|
export * from './App';
|
||||||
3
src/components/WorkloadItem/WorkloadItem.css
Normal file
3
src/components/WorkloadItem/WorkloadItem.css
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
.WorkloadItem {
|
||||||
|
border: 2px solid var(--wf-blue);
|
||||||
|
}
|
||||||
54
src/components/WorkloadItem/WorkloadItem.tsx
Normal file
54
src/components/WorkloadItem/WorkloadItem.tsx
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import TimeAgo from 'react-timeago';
|
||||||
|
import { Status } from '../../state/workloads'
|
||||||
|
|
||||||
|
|
||||||
|
export interface WorkloadItemStateProps {
|
||||||
|
id: number;
|
||||||
|
complexity: number;
|
||||||
|
status: Status;
|
||||||
|
completeDate: Date;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface WorkloadItemMethodProps {
|
||||||
|
onCancel: () => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface WorkloadItemProps extends
|
||||||
|
WorkloadItemStateProps,
|
||||||
|
WorkloadItemMethodProps {}
|
||||||
|
|
||||||
|
|
||||||
|
const WorkloadItem: React.SFC<WorkloadItemProps> = (props) => (
|
||||||
|
<div className="WorkloadItem">
|
||||||
|
<div>
|
||||||
|
<h3 className="WorkloadItem-heading">Workload #{props.id}</h3>
|
||||||
|
<span className="WorkloadItem-subHeading">Complexity: {props.complexity}</span>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
{props.status === 'WORKING'
|
||||||
|
? (
|
||||||
|
<>
|
||||||
|
<span><TimeAgo date={props.completeDate} /></span>
|
||||||
|
<button
|
||||||
|
className="WorkloadItem-secondaryButton"
|
||||||
|
onClick={props.onCancel}
|
||||||
|
>
|
||||||
|
Cancel
|
||||||
|
</button>
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
: (
|
||||||
|
<span className="WorkloadItem-statusText">{props.status.toLowerCase()}</span>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
export {
|
||||||
|
WorkloadItem,
|
||||||
|
};
|
||||||
|
|
||||||
|
export default WorkloadItem;
|
||||||
2
src/components/WorkloadItem/index.ts
Normal file
2
src/components/WorkloadItem/index.ts
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
export { default } from './WorkloadItem';
|
||||||
|
export * from './WorkloadItem';
|
||||||
55
src/components/WorkloadList/WorkloadList.tsx
Normal file
55
src/components/WorkloadList/WorkloadList.tsx
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import { Dispatch } from 'redux';
|
||||||
|
import { connect } from 'react-redux';
|
||||||
|
import { Action, State } from '../../state';
|
||||||
|
import { cancel } from '../../state/workloads/actions';
|
||||||
|
import { WorkloadItem, WorkloadItemStateProps } from '../WorkloadItem';
|
||||||
|
|
||||||
|
|
||||||
|
export interface WorkloadListStateProps {
|
||||||
|
workloads: WorkloadItemStateProps[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface WorkloadListDispatchProps {
|
||||||
|
cancelWorkload: (id: number) => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface WorkloadListProps extends
|
||||||
|
WorkloadListStateProps,
|
||||||
|
WorkloadListDispatchProps {}
|
||||||
|
|
||||||
|
|
||||||
|
const WorkloadList: React.SFC<WorkloadListProps> = ({ workloads, cancelWorkload }) => (
|
||||||
|
!workloads.length
|
||||||
|
? (
|
||||||
|
<span>No workloads to display</span>
|
||||||
|
)
|
||||||
|
: (
|
||||||
|
<ol>
|
||||||
|
{workloads.map((workload) => (
|
||||||
|
<li key={workload.id}>
|
||||||
|
<WorkloadItem {...workload} onCancel={() => cancelWorkload(workload.id)} />
|
||||||
|
</li>
|
||||||
|
))}
|
||||||
|
</ol>
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
const mapStateToProps = (state: State): WorkloadListStateProps => ({
|
||||||
|
workloads: Object.values(state.workloads),
|
||||||
|
});
|
||||||
|
|
||||||
|
const mapDispatchToProps = (dispatch: Dispatch<Action>): WorkloadListDispatchProps => ({
|
||||||
|
cancelWorkload: (id: number) => dispatch(cancel({ id })),
|
||||||
|
})
|
||||||
|
|
||||||
|
const WorkloadListContainer = connect(mapStateToProps, mapDispatchToProps)(WorkloadList);
|
||||||
|
|
||||||
|
|
||||||
|
export {
|
||||||
|
WorkloadList,
|
||||||
|
WorkloadListContainer,
|
||||||
|
};
|
||||||
|
|
||||||
|
export default WorkloadList;
|
||||||
1
src/components/WorkloadList/index.ts
Normal file
1
src/components/WorkloadList/index.ts
Normal file
@@ -0,0 +1 @@
|
|||||||
|
export * from './WorkloadList';
|
||||||
@@ -7,7 +7,7 @@ import { createEpicMiddleware } from 'redux-observable';
|
|||||||
import { reducers, epics, Action, State } from './state';
|
import { reducers, epics, Action, State } from './state';
|
||||||
import * as WorkloadActions from './state/workloads/actions';
|
import * as WorkloadActions from './state/workloads/actions';
|
||||||
import './index.css';
|
import './index.css';
|
||||||
import App from './App';
|
import App from './components/App';
|
||||||
|
|
||||||
|
|
||||||
const epicMiddleware = createEpicMiddleware<Action, Action, State>();
|
const epicMiddleware = createEpicMiddleware<Action, Action, State>();
|
||||||
@@ -15,6 +15,7 @@ const store = createStore(reducers, applyMiddleware(epicMiddleware));
|
|||||||
|
|
||||||
epicMiddleware.run(epics);
|
epicMiddleware.run(epics);
|
||||||
store.dispatch(WorkloadActions.submit({ complexity: 100 }));
|
store.dispatch(WorkloadActions.submit({ complexity: 100 }));
|
||||||
|
store.dispatch(WorkloadActions.created({ id: 0, complexity: 100, completeDate: new Date() }));
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
export * from './types';
|
||||||
export * from './actions';
|
export * from './actions';
|
||||||
export * from './reducers';
|
export * from './reducers';
|
||||||
export * from './epics';
|
export * from './epics';
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import { Status } from './types';
|
|||||||
|
|
||||||
interface Entry<Id extends number> {
|
interface Entry<Id extends number> {
|
||||||
id: Id;
|
id: Id;
|
||||||
|
complexity: number;
|
||||||
completeDate: Date;
|
completeDate: Date;
|
||||||
status: Status;
|
status: Status;
|
||||||
}
|
}
|
||||||
@@ -20,6 +21,7 @@ export const reducer = (state: State = initialState, action: Action): State => {
|
|||||||
return {
|
return {
|
||||||
[action.payload.id]: {
|
[action.payload.id]: {
|
||||||
id: action.payload.id,
|
id: action.payload.id,
|
||||||
|
complexity: action.payload.complexity,
|
||||||
completeDate: action.payload.completeDate,
|
completeDate: action.payload.completeDate,
|
||||||
status: 'WORKING',
|
status: 'WORKING',
|
||||||
},
|
},
|
||||||
|
|||||||
14
yarn.lock
14
yarn.lock
@@ -943,6 +943,13 @@
|
|||||||
"@types/react" "*"
|
"@types/react" "*"
|
||||||
redux "^4.0.0"
|
redux "^4.0.0"
|
||||||
|
|
||||||
|
"@types/react-timeago@^4.1.0":
|
||||||
|
version "4.1.0"
|
||||||
|
resolved "https://npm.nutterlogic.com/@types%2freact-timeago/-/react-timeago-4.1.0.tgz#e8ebc0add9de6d768fda610922879382bdc2f327"
|
||||||
|
integrity sha512-rQihM3unIJ2i3gxJhoM9hktqrMsrqv2OVyz4zWG7T6hUdmt4V5IGs6B65EJgo+4Rt9Z5pscc0H9YcZX4hPuLkA==
|
||||||
|
dependencies:
|
||||||
|
"@types/react" "*"
|
||||||
|
|
||||||
"@types/react@*", "@types/react@16.7.22":
|
"@types/react@*", "@types/react@16.7.22":
|
||||||
version "16.7.22"
|
version "16.7.22"
|
||||||
resolved "https://npm.nutterlogic.com/@types%2freact/-/react-16.7.22.tgz#5bc6d166d5ac34b835756f0b736c7b1af0043e81"
|
resolved "https://npm.nutterlogic.com/@types%2freact/-/react-16.7.22.tgz#5bc6d166d5ac34b835756f0b736c7b1af0043e81"
|
||||||
@@ -8050,6 +8057,11 @@ react-scripts@2.1.3:
|
|||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
fsevents "1.2.4"
|
fsevents "1.2.4"
|
||||||
|
|
||||||
|
react-timeago@^4.3.0:
|
||||||
|
version "4.3.0"
|
||||||
|
resolved "https://npm.nutterlogic.com/react-timeago/-/react-timeago-4.3.0.tgz#ff47bb12c3c2a40bc31e6b3e457f5ac4a690a3ec"
|
||||||
|
integrity sha512-q89RXb4K16xyDdy2GR/mIRYrDw8ll/RlohSIgjCr1J85eHKeL/XEl4XPKICMdJnJpaXwRzOjlsdnEuxWsi61RQ==
|
||||||
|
|
||||||
react@^16.7.0:
|
react@^16.7.0:
|
||||||
version "16.7.0"
|
version "16.7.0"
|
||||||
resolved "https://npm.nutterlogic.com/react/-/react-16.7.0.tgz#b674ec396b0a5715873b350446f7ea0802ab6381"
|
resolved "https://npm.nutterlogic.com/react/-/react-16.7.0.tgz#b674ec396b0a5715873b350446f7ea0802ab6381"
|
||||||
@@ -8154,7 +8166,7 @@ redux-observable@^1.0.0:
|
|||||||
resolved "https://npm.nutterlogic.com/redux-observable/-/redux-observable-1.0.0.tgz#780ff2455493eedcef806616fe286b454fd15d91"
|
resolved "https://npm.nutterlogic.com/redux-observable/-/redux-observable-1.0.0.tgz#780ff2455493eedcef806616fe286b454fd15d91"
|
||||||
integrity sha512-6bXnpqWTBeLaLQjXHyN1giXq4nLxCmv+SUkdmiwBgvmVxvDbdmydvL1Z7DGo0WItyzI/kqXQKiucUuTxnrPRkA==
|
integrity sha512-6bXnpqWTBeLaLQjXHyN1giXq4nLxCmv+SUkdmiwBgvmVxvDbdmydvL1Z7DGo0WItyzI/kqXQKiucUuTxnrPRkA==
|
||||||
|
|
||||||
redux@^4.0.0:
|
redux@^4.0.0, redux@^4.0.1:
|
||||||
version "4.0.1"
|
version "4.0.1"
|
||||||
resolved "https://npm.nutterlogic.com/redux/-/redux-4.0.1.tgz#436cae6cc40fbe4727689d7c8fae44808f1bfef5"
|
resolved "https://npm.nutterlogic.com/redux/-/redux-4.0.1.tgz#436cae6cc40fbe4727689d7c8fae44808f1bfef5"
|
||||||
integrity sha512-R7bAtSkk7nY6O/OYMVR9RiBI+XghjF9rlbl5806HJbQph0LJVHZrU5oaO4q70eUKiqMRqm4y07KLTlMZ2BlVmg==
|
integrity sha512-R7bAtSkk7nY6O/OYMVR9RiBI+XghjF9rlbl5806HJbQph0LJVHZrU5oaO4q70eUKiqMRqm4y07KLTlMZ2BlVmg==
|
||||||
|
|||||||
Reference in New Issue
Block a user