Merge pull request #29 from Tiqa/feat/api/add_statement
Feat/api/add statement
This commit is contained in:
commit
73599eb131
16 changed files with 61 additions and 107 deletions
2
.babelrc
2
.babelrc
|
|
@ -1,4 +1,4 @@
|
||||||
{
|
{
|
||||||
"presets": ["es2015", "react", "stage-0"],
|
"presets": ["es2015", "react", "stage-0"],
|
||||||
"plugins": ["transform-decorators-legacy", "react-hot-loader/babel"]
|
"plugins": ["transform-decorators-legacy", "react-hot-loader/babel", "ramda"]
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -79,6 +79,7 @@
|
||||||
"babel-core": "<6.3.0",
|
"babel-core": "<6.3.0",
|
||||||
"babel-eslint": "^7.1.0",
|
"babel-eslint": "^7.1.0",
|
||||||
"babel-loader": "~6.2.1",
|
"babel-loader": "~6.2.1",
|
||||||
|
"babel-plugin-ramda": "^1.1.6",
|
||||||
"babel-plugin-transform-decorators-legacy": "^1.3.4",
|
"babel-plugin-transform-decorators-legacy": "^1.3.4",
|
||||||
"babel-plugin-transform-es2015-modules-umd": "^6.8.0",
|
"babel-plugin-transform-es2015-modules-umd": "^6.8.0",
|
||||||
"babel-preset-es2015": "<6.3.0",
|
"babel-preset-es2015": "<6.3.0",
|
||||||
|
|
|
||||||
|
|
@ -15,3 +15,4 @@ export const getStatements = () => get('statements');
|
||||||
export const getPublicFiguresAutocomplete = typed => get(`autocomplete/public_figure/${typed}`);
|
export const getPublicFiguresAutocomplete = typed => get(`autocomplete/public_figure/${typed}`);
|
||||||
export const getSubjectsAutocomplete = typed => get(`autocomplete/subject/${typed}`);
|
export const getSubjectsAutocomplete = typed => get(`autocomplete/subject/${typed}`);
|
||||||
export const getPositions = subjectId => get(`subjects/${subjectId}/positions`);
|
export const getPositions = subjectId => get(`subjects/${subjectId}/positions`);
|
||||||
|
export const postStatement = statement => post('statements', statement);
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ import moment from 'moment';
|
||||||
import 'bootstrap-loader';
|
import 'bootstrap-loader';
|
||||||
|
|
||||||
const locale = 'fr';
|
const locale = 'fr';
|
||||||
|
moment.locale(locale);
|
||||||
moment.locale(locale, {
|
moment.locale(locale, {
|
||||||
calendar : {
|
calendar : {
|
||||||
lastDay : '[Hier]',
|
lastDay : '[Hier]',
|
||||||
|
|
|
||||||
10
src/components/AddStatementButton/connector.js
Normal file
10
src/components/AddStatementButton/connector.js
Normal file
|
|
@ -0,0 +1,10 @@
|
||||||
|
import { connect } from 'react-redux';
|
||||||
|
import { onAddStatementValidate } from 'store/actions';
|
||||||
|
|
||||||
|
const mapStateToProps = () => ({});
|
||||||
|
|
||||||
|
const mapDispatchToProps = dispatch => ({
|
||||||
|
onValidate: statement => dispatch(onAddStatementValidate(statement)),
|
||||||
|
});
|
||||||
|
|
||||||
|
export default connect(mapStateToProps, mapDispatchToProps);
|
||||||
|
|
@ -1,11 +1,16 @@
|
||||||
import React, { Component } from 'react';
|
import React, { Component, PropTypes } from 'react';
|
||||||
import { Button } from 'react-bootstrap';
|
import { Button } from 'react-bootstrap';
|
||||||
import AddStatementModal from 'components/AddStatementModal';
|
import AddStatementModal from 'components/AddStatementModal';
|
||||||
|
import connect from './connector';
|
||||||
|
|
||||||
class AddStatementButton extends Component {
|
class AddStatementButton extends Component {
|
||||||
|
static propTypes = {
|
||||||
|
onValidate: PropTypes.func.isRequired,
|
||||||
|
};
|
||||||
|
|
||||||
state = {
|
state = {
|
||||||
showModal: false,
|
showModal: false,
|
||||||
}
|
};
|
||||||
|
|
||||||
close = () => this.setState({ showModal: false });
|
close = () => this.setState({ showModal: false });
|
||||||
open = () => this.setState({ showModal: true });
|
open = () => this.setState({ showModal: true });
|
||||||
|
|
@ -20,10 +25,10 @@ class AddStatementButton extends Component {
|
||||||
>
|
>
|
||||||
Nouvelle prise de position
|
Nouvelle prise de position
|
||||||
</Button>
|
</Button>
|
||||||
<AddStatementModal show={this.state.showModal} onHide={this.close} />
|
<AddStatementModal show={this.state.showModal} onHide={this.close} onValidate={this.props.onValidate} />
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default AddStatementButton;
|
export default connect(AddStatementButton);
|
||||||
|
|
|
||||||
|
|
@ -285,7 +285,7 @@ class AddStatementModal extends Component {
|
||||||
}
|
}
|
||||||
{step === steps.SUMMARY &&
|
{step === steps.SUMMARY &&
|
||||||
<Button
|
<Button
|
||||||
onClick={onValidate}
|
onClick={() => onValidate(this.state)}
|
||||||
disabled={!this.isComplete()}
|
disabled={!this.isComplete()}
|
||||||
bsStyle="success"
|
bsStyle="success"
|
||||||
>
|
>
|
||||||
|
|
|
||||||
|
|
@ -4,9 +4,11 @@ import LastStatements from 'components/LastStatements';
|
||||||
import HomeSubjects from './HomeSubjects';
|
import HomeSubjects from './HomeSubjects';
|
||||||
import bgSrc from './images/intro-bg.jpg';
|
import bgSrc from './images/intro-bg.jpg';
|
||||||
import styles from './Home.css';
|
import styles from './Home.css';
|
||||||
|
import AddStatementButton from 'components/AddStatementButton';
|
||||||
|
|
||||||
const Home = () => (
|
const Home = () => (
|
||||||
<div className="container-fluid" styleName="container">
|
<div className="container-fluid" styleName="container">
|
||||||
|
<AddStatementButton />
|
||||||
<div className="row" styleName="background-title" style={{ backgroundImage: `url(${bgSrc})` }}>
|
<div className="row" styleName="background-title" style={{ backgroundImage: `url(${bgSrc})` }}>
|
||||||
<div styleName="title-mask">
|
<div styleName="title-mask">
|
||||||
<h5 >Bienvenue sur Débats.co</h5>
|
<h5 >Bienvenue sur Débats.co</h5>
|
||||||
|
|
@ -16,7 +18,7 @@ const Home = () => (
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="col-md-1" />
|
<div className="col-md-1"></div>
|
||||||
<div className="subjects-index col-md-7 subjects-home">
|
<div className="subjects-index col-md-7 subjects-home">
|
||||||
<h1>Sujets d'actualité</h1>
|
<h1>Sujets d'actualité</h1>
|
||||||
<table className="table">
|
<table className="table">
|
||||||
|
|
@ -27,7 +29,8 @@ const Home = () => (
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
<div className="col-md-3 col-centered" style={{ textAlign: 'right' }} >
|
<div className="col-md-1" />
|
||||||
|
<div className="col-md-3 col-centered" style={{ textAlign: 'right' }}>
|
||||||
<LastStatements />
|
<LastStatements />
|
||||||
</div>
|
</div>
|
||||||
<div className="col-md-1" />
|
<div className="col-md-1" />
|
||||||
|
|
|
||||||
|
|
@ -1,27 +1,6 @@
|
||||||
import types from '../actions_types';
|
import types from '../actions_types';
|
||||||
|
|
||||||
export const onAddStatementPublicFigureSelection = id => ({
|
export const onAddStatementValidate = newStatement => ({
|
||||||
type: types.ADD_STATEMENT_PUBLIC_FIGURE_SELECTION,
|
|
||||||
id,
|
|
||||||
});
|
|
||||||
export const onAddStatementSubjectSelection = id => ({
|
|
||||||
type: types.ADD_STATEMENT_SUBJECT_SELECTION,
|
|
||||||
id,
|
|
||||||
});
|
|
||||||
export const onAddStatementPositionSelection = id => ({
|
|
||||||
type: types.ADD_STATEMENT_POSITION_SELECTION,
|
|
||||||
id,
|
|
||||||
});
|
|
||||||
|
|
||||||
export const onAddStatementUpdateEvidenceUrl = url => ({
|
|
||||||
type: types.ADD_STATEMENT_UPDATE_EVIDENCE_URL,
|
|
||||||
url,
|
|
||||||
});
|
|
||||||
export const onAddStatementUpdateEvidenceFile = file => ({
|
|
||||||
type: types.ADD_STATEMENT_UPDATE_EVIDENCE_FILE,
|
|
||||||
file,
|
|
||||||
});
|
|
||||||
|
|
||||||
export const onAddStatementValidate = () => ({
|
|
||||||
type: types.ADD_STATEMENT_VALIDATE,
|
type: types.ADD_STATEMENT_VALIDATE,
|
||||||
|
payload: { ...newStatement },
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,6 @@
|
||||||
export default {
|
export default {
|
||||||
ENTITY_ACCESS: 'ENTITY_ACCESS',
|
ENTITY_ACCESS: 'ENTITY_ACCESS',
|
||||||
ENTITY_READ: 'ENTITY_READ',
|
ENTITY_READ: 'ENTITY_READ',
|
||||||
ADD_STATEMENT_NEXT_STEP: 'ADD_STATEMENT_NEXT_STEP',
|
|
||||||
ADD_STATEMENT_PUBLIC_FIGURE_SELECTION: 'ADD_STATEMENT_PUBLIC_FIGURE_SELECTION',
|
|
||||||
ADD_STATEMENT_SUBJECT_SELECTION: 'ADD_STATEMENT_SUBJECT_SELECTION',
|
|
||||||
ADD_STATEMENT_POSITION_SELECTION: 'ADD_STATEMENT_POSITION_SELECTION',
|
|
||||||
ADD_STATEMENT_UPDATE_EVIDENCE_URL: 'ADD_STATEMENT_UPDATE_EVIDENCE_URL',
|
|
||||||
ADD_STATEMENT_UPDATE_EVIDENCE_FILE: 'ADD_STATEMENT_UPDATE_EVIDENCE_FILE',
|
|
||||||
ADD_STATEMENT_VALIDATE: 'ADD_STATEMENT_VALIDATE',
|
ADD_STATEMENT_VALIDATE: 'ADD_STATEMENT_VALIDATE',
|
||||||
|
STATEMENT_POST_BEGIN: 'STATEMENT_POST_BEGIN',
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@ import createHashHistory from 'history/lib/createHashHistory';
|
||||||
import createMemoryHistory from 'history/lib/createMemoryHistory';
|
import createMemoryHistory from 'history/lib/createMemoryHistory';
|
||||||
|
|
||||||
import rootSaga from './sagas';
|
import rootSaga from './sagas';
|
||||||
import { entitiesReducer, addStatementReducer } from './reducers';
|
import { entitiesReducer } from './reducers';
|
||||||
|
|
||||||
// Build history
|
// Build history
|
||||||
const createHistory = isClientSide() ? createHashHistory : createMemoryHistory;
|
const createHistory = isClientSide() ? createHashHistory : createMemoryHistory;
|
||||||
|
|
@ -22,7 +22,6 @@ const initialState = isClientSide() ? window.__INITIAL_STATE__ : {};
|
||||||
const reducer = combineReducers({
|
const reducer = combineReducers({
|
||||||
routing: routerReducer,
|
routing: routerReducer,
|
||||||
entities: entitiesReducer,
|
entities: entitiesReducer,
|
||||||
addStatement: addStatementReducer,
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// MIDDLEWARE
|
// MIDDLEWARE
|
||||||
|
|
|
||||||
|
|
@ -1,46 +0,0 @@
|
||||||
import {
|
|
||||||
assoc, compose, not, allPass, prop, isNil, either, complement,
|
|
||||||
} from 'ramda';
|
|
||||||
import actionsTypes from '../actions_types';
|
|
||||||
|
|
||||||
const initialState = {
|
|
||||||
publicFigureId: null,
|
|
||||||
subjectId: null,
|
|
||||||
positionId: null,
|
|
||||||
statementDate: null,
|
|
||||||
evidenceUrl: null,
|
|
||||||
evidenceFile: null,
|
|
||||||
quote: null,
|
|
||||||
note: null,
|
|
||||||
tags: [],
|
|
||||||
};
|
|
||||||
|
|
||||||
const isPublicFigureChosen = compose(not, isNil, prop('publicFigureId'));
|
|
||||||
const isSubjectChosen = compose(not, isNil, prop('publicFigureId'));
|
|
||||||
const isPositionChosen = compose(not, isNil, prop('publicFigureId'));
|
|
||||||
const isStatementComplete = allPass([
|
|
||||||
compose(not, isNil, prop('statementDate')),
|
|
||||||
compose(not, isNil, prop('quote')),
|
|
||||||
compose(not, isNil, prop('statementDate')),
|
|
||||||
either(
|
|
||||||
compose(not, isNil, prop('evidenceUrl')),
|
|
||||||
compose(not, isNil, prop('evidenceFile')),
|
|
||||||
),
|
|
||||||
]);
|
|
||||||
|
|
||||||
/* eslint-disable no-unused-vars */
|
|
||||||
const isPublicFigureMissing = complement(isPublicFigureChosen);
|
|
||||||
const isSubjectMissing = complement(isSubjectChosen);
|
|
||||||
const isPositionMissing = complement(isPositionChosen);
|
|
||||||
const isStatementIncomplete = complement(isStatementComplete);
|
|
||||||
|
|
||||||
export const addStatementReducer = (state = initialState, action) => {
|
|
||||||
switch (action.type) {
|
|
||||||
case actionsTypes.ADD_STATEMENT_PUBLIC_FIGURE_SELECTION: return assoc('publicFigureId', action.id, state);
|
|
||||||
case actionsTypes.ADD_STATEMENT_SUBJECT_SELECTION: return assoc('subjectId', action.id, state);
|
|
||||||
case actionsTypes.ADD_STATEMENT_POSITION_SELECTION: return assoc('positionId', action.id, state);
|
|
||||||
case actionsTypes.ADD_STATEMENT_UPDATE_EVIDENCE_URL: return assoc('evidenceUrl', action.url, state);
|
|
||||||
case actionsTypes.ADD_STATEMENT_UPDATE_EVIDENCE_FILE: return assoc('evidenceFile', action.file, state);
|
|
||||||
default: return state;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
@ -1,2 +1,2 @@
|
||||||
export * from './entities';
|
export * from './entities';
|
||||||
export * from './addStatement';
|
|
||||||
|
|
|
||||||
|
|
@ -42,18 +42,4 @@ function* fetchEntityIfNeeded(action) {
|
||||||
export function* watchEntityAccess() {
|
export function* watchEntityAccess() {
|
||||||
yield* takeEvery(actionsTypes.ENTITY_ACCESS, fetchEntityIfNeeded);
|
yield* takeEvery(actionsTypes.ENTITY_ACCESS, fetchEntityIfNeeded);
|
||||||
}
|
}
|
||||||
function* fetchPositionsOfSubject(action) {
|
|
||||||
if (action.id) {
|
|
||||||
// Call API
|
|
||||||
const response = yield call(getPositions, action.id);
|
|
||||||
|
|
||||||
// Error actions
|
|
||||||
|
|
||||||
// Success actions
|
|
||||||
yield put({ type: actionsTypes.ENTITY_READ, data: response.data });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export function* watchSubjectSelection() {
|
|
||||||
yield* takeEvery(actionsTypes.ADD_STATEMENT_SUBJECT_SELECTION, fetchPositionsOfSubject);
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,9 @@
|
||||||
import { watchEntityAccess, watchSubjectSelection } from './apiSaga';
|
import { watchEntityAccess } from './apiSaga';
|
||||||
|
import { watchStatementValidation } from './postStatement';
|
||||||
|
|
||||||
export default function* rootSaga() {
|
export default function* rootSaga() {
|
||||||
yield [
|
yield [
|
||||||
watchEntityAccess(),
|
watchEntityAccess(),
|
||||||
watchSubjectSelection(),
|
watchStatementValidation(),
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
|
||||||
21
src/store/sagas/postStatement.js
Normal file
21
src/store/sagas/postStatement.js
Normal file
|
|
@ -0,0 +1,21 @@
|
||||||
|
import { takeEvery } from 'redux-saga';
|
||||||
|
import { call, put } from 'redux-saga/effects';
|
||||||
|
import actionsTypes from '../actions_types';
|
||||||
|
import { postStatement } from 'api/debats';
|
||||||
|
|
||||||
|
function* postNewStatement(action) {
|
||||||
|
yield put({ type: actionsTypes.STATEMENT_POST_BEGIN, payload: action.payload });
|
||||||
|
|
||||||
|
// Gérer d'abord les transferts de fichier sur un ID de transation
|
||||||
|
|
||||||
|
const response = yield call(postStatement);
|
||||||
|
|
||||||
|
// Error actions
|
||||||
|
|
||||||
|
// Success actions
|
||||||
|
yield put({ type: actionsTypes.STATEMENT_POST_SUCCESS, payload: action.payload });
|
||||||
|
}
|
||||||
|
|
||||||
|
export function* watchStatementValidation() {
|
||||||
|
yield* takeEvery(actionsTypes.ADD_STATEMENT_VALIDATE, postNewStatement);
|
||||||
|
}
|
||||||
Loading…
Add table
Reference in a new issue