From cd4bd6b3a55edaaeb98a4a44a562a059b8026588 Mon Sep 17 00:00:00 2001 From: MOAL Fleurian Date: Mon, 6 Jan 2020 21:17:20 +0100 Subject: [PATCH 1/7] quelques modifs locales colorimetrique --- client/src/components/BarChart.js | 7 ++++--- client/src/components/Donut.js | 19 ++++++++++++------- client/src/components/LineChart.js | 5 ++--- client/src/index.js | 1 - 4 files changed, 18 insertions(+), 14 deletions(-) diff --git a/client/src/components/BarChart.js b/client/src/components/BarChart.js index 9d35d63..a6bf422 100644 --- a/client/src/components/BarChart.js +++ b/client/src/components/BarChart.js @@ -13,7 +13,8 @@ class BarChart extends Component { drawChart() { - const data = [12, 5, 6, 6, 9, 10, 20, 10,20,34,11,21]; + const data = [12, 5, 6, 6, 9, 10, 20, 10,20,34,11,21,51]; + const Tick = [12, 5, 6, 6, 9, 10, 20, 10,20,34,11,21,51]; // const data = this.props.data; const margin = {top:100, right: 40, bottom: 100, left: 100}; const x = 400; @@ -37,6 +38,7 @@ class BarChart extends Component { .tickSizeInner(5) .tickSizeOuter(5) .tickPadding(10) + var y_axis = d3.axisLeft() .scale(yScale) @@ -49,7 +51,6 @@ class BarChart extends Component { .attr("height", height) .style("margin-top", margin.top) .style("margin-left", margin.left) - .style("border", "1px solid black"); // - - - - - - - - - - - // Draw header @@ -122,7 +123,7 @@ class BarChart extends Component { .attr("y", (d, i) => height - 10 * d) .attr("width", 27) .attr("height", (d, i) => d * 10) - .attr("fill", '#b5a') + .attr("fill", "rgb(8, 48, 107)") .attr("transform", `translate(${margin.left}, ${-margin.top})`) svg.selectAll("text") diff --git a/client/src/components/Donut.js b/client/src/components/Donut.js index 5c195d5..7eea461 100644 --- a/client/src/components/Donut.js +++ b/client/src/components/Donut.js @@ -14,9 +14,9 @@ class Donut extends Component { drawChart() { - var regions = ["Normandie", "Normandie-2", "Region centre loire", "Bretage", "PACA", "elit", "sed", "do", "eiusmod", "tempor", "incididunt"]; - var percentage = [0,1,2,3,4,5,6,8,8,9,10]; - var datas = [51,12,32,48,51,63,48,39,60,48,10]; + var regions = ["Normandie", "Normandie-2", "Region centre loire", "Bretage", "PACA", "elit", "sed", "do", "eiusmod", "tempor", "incididunt","Normandie-2", "Normandie-2-2", "Region centre loire-2", "Bretage-2", "PACA-2", "elit-2", "sed-2", "do-2", "eiusmod-2", "tempor-2", "incididunt-2"]; + var percentage = [0,1,2,3,4,5,6,8,8,9,10,0,1,2,3,4,5,6,8,8,9,10]; + var datas = [51,12,32,48,51,63,48,39,60,48,100,51,12,32,48,51,63,48,39,60,48,100]; var data2 = [10,84,28,12,1,58,64,1,30,10,80]; var regionsjson = [ @@ -64,13 +64,17 @@ class Donut extends Component { var key = function(d){ return d.data.label; }; var percentkey = function(d,i){ return {idx: i, data: d.data.percent}; }; - var colorRange = d3.schemePastel1; - colorRange.push(...d3.schemePaired); + var colorRange = []; + for (let index = 0; index < regions.length; index++) { + colorRange[index] = d3.interpolateBlues((index*1.0)/regions.length); + } + var color = d3.scaleOrdinal().range(colorRange).domain(regions); function randomData (){ var labels = color.domain(); - console.log(labels); + console.log(regions); + console.log(labels); return labels.map(function(label,i){ return { label: label, value: datas[i],percent:percentage[i] } }); @@ -326,7 +330,8 @@ class Donut extends Component { render() { - return
+ return
+
} } diff --git a/client/src/components/LineChart.js b/client/src/components/LineChart.js index 0b5c7a5..4375de4 100644 --- a/client/src/components/LineChart.js +++ b/client/src/components/LineChart.js @@ -78,7 +78,6 @@ class LineChart extends Component { .attr("height", height + 100) .style("margin-top", margin.top) .style("margin-left", margin.left) - .style("border", "1px solid black") .append('g') .attr('transform', `translate(${margin.left}, ${margin.top})`); @@ -90,7 +89,7 @@ class LineChart extends Component { .append('g') .attr('transform', `translate(0, ${height})`) .attr('class', 'x axis') - .call(xAxis); + .call(xAxis);`` // Draw y axis. const yAxis = d3 @@ -112,7 +111,7 @@ class LineChart extends Component { .data([data]) .attr("class", "line") .attr("fill", "none") - .attr("stroke", "red") + .attr("stroke", "blue") .attr("d", line) diff --git a/client/src/index.js b/client/src/index.js index 5a507bb..30ebefe 100644 --- a/client/src/index.js +++ b/client/src/index.js @@ -38,7 +38,6 @@ const store = createStore( }), applyMiddleware(routerMiddleware(history), thunk) ); - ReactDOM.render( -- GitLab From 25580b7c6a8035d5f5201449ad899a9c53754d36 Mon Sep 17 00:00:00 2001 From: MOAL Fleurian Date: Mon, 6 Jan 2020 23:45:12 +0100 Subject: [PATCH 2/7] =?UTF-8?q?d=C3=A9but=20de=20la=20conversion=20react?= =?UTF-8?q?=20redux=20donut?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- client/src/actions/book/create.js | 45 --- client/src/actions/book/delete.js | 29 -- client/src/actions/book/list.js | 85 ----- client/src/actions/book/show.js | 78 ---- client/src/actions/book/update.js | 131 ------- .../propertysale/average_surface_price.js | 32 ++ client/src/actions/propertysale/create.js | 45 --- client/src/actions/propertysale/delete.js | 29 -- client/src/actions/propertysale/list.js | 85 ----- .../actions/propertysale/sales_by_regions.js | 32 ++ client/src/actions/propertysale/show.js | 78 ---- client/src/actions/propertysale/update.js | 131 ------- client/src/actions/review/create.js | 45 --- client/src/actions/review/delete.js | 29 -- client/src/actions/review/list.js | 85 ----- client/src/actions/review/show.js | 78 ---- client/src/actions/review/update.js | 131 ------- client/src/components/Donut.js | 338 ------------------ client/src/components/LineChart.js | 147 -------- client/src/components/book/Create.js | 64 ---- client/src/components/book/Form.js | 102 ------ client/src/components/book/List.js | 182 ---------- client/src/components/book/Show.js | 144 -------- client/src/components/book/Update.js | 123 ------- client/src/components/book/index.js | 6 - .../src/components/{ => charts}/BarChart.js | 0 client/src/components/charts/Donut.js | 321 +++++++++++++++++ client/src/components/charts/LineChart.js | 113 ++++++ .../src/components/{ => charts/css}/Donut.css | 0 client/src/components/charts/index.js | 9 + .../propertysale/AverageSurfacePrice.js | 61 ++++ client/src/components/propertysale/Create.js | 64 ---- client/src/components/propertysale/Form.js | 98 ----- client/src/components/propertysale/List.js | 180 ---------- .../components/propertysale/SalesByRegions.js | 69 ++++ client/src/components/propertysale/Show.js | 140 -------- client/src/components/propertysale/Update.js | 123 ------- client/src/components/propertysale/index.js | 8 +- client/src/components/review/Create.js | 64 ---- client/src/components/review/Form.js | 96 ----- client/src/components/review/List.js | 180 ---------- client/src/components/review/Show.js | 140 -------- client/src/components/review/Update.js | 123 ------- client/src/components/review/index.js | 6 - client/src/homepage.js | 10 + client/src/index.js | 10 +- client/src/reducers/book/create.js | 33 -- client/src/reducers/book/delete.js | 33 -- client/src/reducers/book/index.js | 8 - client/src/reducers/book/list.js | 74 ---- client/src/reducers/book/show.js | 59 --- client/src/reducers/book/update.js | 106 ------ .../propertysale/averageSurfacePrice.js | 34 ++ client/src/reducers/propertysale/create.js | 33 -- client/src/reducers/propertysale/delete.js | 33 -- client/src/reducers/propertysale/index.js | 13 +- client/src/reducers/propertysale/list.js | 74 ---- .../reducers/propertysale/salesByRegions.js | 34 ++ client/src/reducers/propertysale/show.js | 59 --- client/src/reducers/propertysale/update.js | 106 ------ client/src/reducers/review/create.js | 33 -- client/src/reducers/review/delete.js | 33 -- client/src/reducers/review/index.js | 8 - client/src/reducers/review/list.js | 74 ---- client/src/reducers/review/show.js | 59 --- client/src/reducers/review/update.js | 106 ------ client/src/routes/book.js | 11 - client/src/routes/propertysale.js | 9 +- client/src/routes/review.js | 11 - 69 files changed, 729 insertions(+), 4403 deletions(-) delete mode 100644 client/src/actions/book/create.js delete mode 100644 client/src/actions/book/delete.js delete mode 100644 client/src/actions/book/list.js delete mode 100644 client/src/actions/book/show.js delete mode 100644 client/src/actions/book/update.js create mode 100644 client/src/actions/propertysale/average_surface_price.js delete mode 100644 client/src/actions/propertysale/create.js delete mode 100644 client/src/actions/propertysale/delete.js delete mode 100644 client/src/actions/propertysale/list.js create mode 100644 client/src/actions/propertysale/sales_by_regions.js delete mode 100644 client/src/actions/propertysale/show.js delete mode 100644 client/src/actions/propertysale/update.js delete mode 100644 client/src/actions/review/create.js delete mode 100644 client/src/actions/review/delete.js delete mode 100644 client/src/actions/review/list.js delete mode 100644 client/src/actions/review/show.js delete mode 100644 client/src/actions/review/update.js delete mode 100644 client/src/components/Donut.js delete mode 100644 client/src/components/LineChart.js delete mode 100644 client/src/components/book/Create.js delete mode 100644 client/src/components/book/Form.js delete mode 100644 client/src/components/book/List.js delete mode 100644 client/src/components/book/Show.js delete mode 100644 client/src/components/book/Update.js delete mode 100644 client/src/components/book/index.js rename client/src/components/{ => charts}/BarChart.js (100%) create mode 100644 client/src/components/charts/Donut.js create mode 100644 client/src/components/charts/LineChart.js rename client/src/components/{ => charts/css}/Donut.css (100%) create mode 100644 client/src/components/charts/index.js create mode 100644 client/src/components/propertysale/AverageSurfacePrice.js delete mode 100644 client/src/components/propertysale/Create.js delete mode 100644 client/src/components/propertysale/Form.js delete mode 100644 client/src/components/propertysale/List.js create mode 100644 client/src/components/propertysale/SalesByRegions.js delete mode 100644 client/src/components/propertysale/Show.js delete mode 100644 client/src/components/propertysale/Update.js delete mode 100644 client/src/components/review/Create.js delete mode 100644 client/src/components/review/Form.js delete mode 100644 client/src/components/review/List.js delete mode 100644 client/src/components/review/Show.js delete mode 100644 client/src/components/review/Update.js delete mode 100644 client/src/components/review/index.js delete mode 100644 client/src/reducers/book/create.js delete mode 100644 client/src/reducers/book/delete.js delete mode 100644 client/src/reducers/book/index.js delete mode 100644 client/src/reducers/book/list.js delete mode 100644 client/src/reducers/book/show.js delete mode 100644 client/src/reducers/book/update.js create mode 100644 client/src/reducers/propertysale/averageSurfacePrice.js delete mode 100644 client/src/reducers/propertysale/create.js delete mode 100644 client/src/reducers/propertysale/delete.js delete mode 100644 client/src/reducers/propertysale/list.js create mode 100644 client/src/reducers/propertysale/salesByRegions.js delete mode 100644 client/src/reducers/propertysale/show.js delete mode 100644 client/src/reducers/propertysale/update.js delete mode 100644 client/src/reducers/review/create.js delete mode 100644 client/src/reducers/review/delete.js delete mode 100644 client/src/reducers/review/index.js delete mode 100644 client/src/reducers/review/list.js delete mode 100644 client/src/reducers/review/show.js delete mode 100644 client/src/reducers/review/update.js delete mode 100644 client/src/routes/book.js delete mode 100644 client/src/routes/review.js diff --git a/client/src/actions/book/create.js b/client/src/actions/book/create.js deleted file mode 100644 index 376ca52..0000000 --- a/client/src/actions/book/create.js +++ /dev/null @@ -1,45 +0,0 @@ -import { SubmissionError } from 'redux-form'; -import { fetch } from '../../utils/dataAccess'; - -export function error(error) { - return { type: 'BOOK_CREATE_ERROR', error }; -} - -export function loading(loading) { - return { type: 'BOOK_CREATE_LOADING', loading }; -} - -export function success(created) { - return { type: 'BOOK_CREATE_SUCCESS', created }; -} - -export function create(values) { - return dispatch => { - dispatch(loading(true)); - - return fetch('books', { method: 'POST', body: JSON.stringify(values) }) - .then(response => { - dispatch(loading(false)); - - return response.json(); - }) - .then(retrieved => dispatch(success(retrieved))) - .catch(e => { - dispatch(loading(false)); - - if (e instanceof SubmissionError) { - dispatch(error(e.errors._error)); - throw e; - } - - dispatch(error(e.message)); - }); - }; -} - -export function reset() { - return dispatch => { - dispatch(loading(false)); - dispatch(error(null)); - }; -} diff --git a/client/src/actions/book/delete.js b/client/src/actions/book/delete.js deleted file mode 100644 index dd164b0..0000000 --- a/client/src/actions/book/delete.js +++ /dev/null @@ -1,29 +0,0 @@ -import { fetch } from '../../utils/dataAccess'; - -export function error(error) { - return { type: 'BOOK_DELETE_ERROR', error }; -} - -export function loading(loading) { - return { type: 'BOOK_DELETE_LOADING', loading }; -} - -export function success(deleted) { - return { type: 'BOOK_DELETE_SUCCESS', deleted }; -} - -export function del(item) { - return dispatch => { - dispatch(loading(true)); - - return fetch(item['@id'], { method: 'DELETE' }) - .then(() => { - dispatch(loading(false)); - dispatch(success(item)); - }) - .catch(e => { - dispatch(loading(false)); - dispatch(error(e.message)); - }); - }; -} diff --git a/client/src/actions/book/list.js b/client/src/actions/book/list.js deleted file mode 100644 index 6133330..0000000 --- a/client/src/actions/book/list.js +++ /dev/null @@ -1,85 +0,0 @@ -import { - fetch, - normalize, - extractHubURL, - mercureSubscribe as subscribe -} from '../../utils/dataAccess'; -import { success as deleteSuccess } from './delete'; - -export function error(error) { - return { type: 'BOOK_LIST_ERROR', error }; -} - -export function loading(loading) { - return { type: 'BOOK_LIST_LOADING', loading }; -} - -export function success(retrieved) { - return { type: 'BOOK_LIST_SUCCESS', retrieved }; -} - -export function list(page = 'books') { - return dispatch => { - dispatch(loading(true)); - dispatch(error('')); - - fetch(page) - .then(response => - response - .json() - .then(retrieved => ({ retrieved, hubURL: extractHubURL(response) })) - ) - .then(({ retrieved, hubURL }) => { - retrieved = normalize(retrieved); - - dispatch(loading(false)); - dispatch(success(retrieved)); - - if (hubURL && retrieved['hydra:member'].length) - dispatch( - mercureSubscribe( - hubURL, - retrieved['hydra:member'].map(i => i['@id']) - ) - ); - }) - .catch(e => { - dispatch(loading(false)); - dispatch(error(e.message)); - }); - }; -} - -export function reset(eventSource) { - return dispatch => { - if (eventSource) eventSource.close(); - - dispatch({ type: 'BOOK_LIST_RESET' }); - dispatch(deleteSuccess(null)); - }; -} - -export function mercureSubscribe(hubURL, topics) { - return dispatch => { - const eventSource = subscribe(hubURL, topics); - dispatch(mercureOpen(eventSource)); - eventSource.addEventListener('message', event => - dispatch(mercureMessage(normalize(JSON.parse(event.data)))) - ); - }; -} - -export function mercureOpen(eventSource) { - return { type: 'BOOK_LIST_MERCURE_OPEN', eventSource }; -} - -export function mercureMessage(retrieved) { - return dispatch => { - if (1 === Object.keys(retrieved).length) { - dispatch({ type: 'BOOK_LIST_MERCURE_DELETED', retrieved }); - return; - } - - dispatch({ type: 'BOOK_LIST_MERCURE_MESSAGE', retrieved }); - }; -} diff --git a/client/src/actions/book/show.js b/client/src/actions/book/show.js deleted file mode 100644 index f9c5ff7..0000000 --- a/client/src/actions/book/show.js +++ /dev/null @@ -1,78 +0,0 @@ -import { - fetch, - extractHubURL, - normalize, - mercureSubscribe as subscribe -} from '../../utils/dataAccess'; - -export function error(error) { - return { type: 'BOOK_SHOW_ERROR', error }; -} - -export function loading(loading) { - return { type: 'BOOK_SHOW_LOADING', loading }; -} - -export function success(retrieved) { - return { type: 'BOOK_SHOW_SUCCESS', retrieved }; -} - -export function retrieve(id) { - return dispatch => { - dispatch(loading(true)); - - return fetch(id) - .then(response => - response - .json() - .then(retrieved => ({ retrieved, hubURL: extractHubURL(response) })) - ) - .then(({ retrieved, hubURL }) => { - retrieved = normalize(retrieved); - - dispatch(loading(false)); - dispatch(success(retrieved)); - - if (hubURL) dispatch(mercureSubscribe(hubURL, retrieved['@id'])); - }) - .catch(e => { - dispatch(loading(false)); - dispatch(error(e.message)); - }); - }; -} - -export function reset(eventSource) { - return dispatch => { - if (eventSource) eventSource.close(); - - dispatch({ type: 'BOOK_SHOW_RESET' }); - dispatch(error(null)); - dispatch(loading(false)); - }; -} - -export function mercureSubscribe(hubURL, topic) { - return dispatch => { - const eventSource = subscribe(hubURL, [topic]); - dispatch(mercureOpen(eventSource)); - eventSource.addEventListener('message', event => - dispatch(mercureMessage(normalize(JSON.parse(event.data)))) - ); - }; -} - -export function mercureOpen(eventSource) { - return { type: 'BOOK_SHOW_MERCURE_OPEN', eventSource }; -} - -export function mercureMessage(retrieved) { - return dispatch => { - if (1 === Object.keys(retrieved).length) { - dispatch({ type: 'BOOK_SHOW_MERCURE_DELETED', retrieved }); - return; - } - - dispatch({ type: 'BOOK_SHOW_MERCURE_MESSAGE', retrieved }); - }; -} diff --git a/client/src/actions/book/update.js b/client/src/actions/book/update.js deleted file mode 100644 index d109c3b..0000000 --- a/client/src/actions/book/update.js +++ /dev/null @@ -1,131 +0,0 @@ -import { SubmissionError } from 'redux-form'; -import { - fetch, - extractHubURL, - normalize, - mercureSubscribe as subscribe -} from '../../utils/dataAccess'; -import { success as createSuccess } from './create'; -import { loading, error } from './delete'; - -export function retrieveError(retrieveError) { - return { type: 'BOOK_UPDATE_RETRIEVE_ERROR', retrieveError }; -} - -export function retrieveLoading(retrieveLoading) { - return { type: 'BOOK_UPDATE_RETRIEVE_LOADING', retrieveLoading }; -} - -export function retrieveSuccess(retrieved) { - return { type: 'BOOK_UPDATE_RETRIEVE_SUCCESS', retrieved }; -} - -export function retrieve(id) { - return dispatch => { - dispatch(retrieveLoading(true)); - - return fetch(id) - .then(response => - response - .json() - .then(retrieved => ({ retrieved, hubURL: extractHubURL(response) })) - ) - .then(({ retrieved, hubURL }) => { - retrieved = normalize(retrieved); - - dispatch(retrieveLoading(false)); - dispatch(retrieveSuccess(retrieved)); - - if (hubURL) dispatch(mercureSubscribe(hubURL, retrieved['@id'])); - }) - .catch(e => { - dispatch(retrieveLoading(false)); - dispatch(retrieveError(e.message)); - }); - }; -} - -export function updateError(updateError) { - return { type: 'BOOK_UPDATE_UPDATE_ERROR', updateError }; -} - -export function updateLoading(updateLoading) { - return { type: 'BOOK_UPDATE_UPDATE_LOADING', updateLoading }; -} - -export function updateSuccess(updated) { - return { type: 'BOOK_UPDATE_UPDATE_SUCCESS', updated }; -} - -export function update(item, values) { - return dispatch => { - dispatch(updateError(null)); - dispatch(createSuccess(null)); - dispatch(updateLoading(true)); - - return fetch(item['@id'], { - method: 'PUT', - headers: new Headers({ 'Content-Type': 'application/ld+json' }), - body: JSON.stringify(values) - }) - .then(response => - response - .json() - .then(retrieved => ({ retrieved, hubURL: extractHubURL(response) })) - ) - .then(({ retrieved, hubURL }) => { - retrieved = normalize(retrieved); - - dispatch(updateLoading(false)); - dispatch(updateSuccess(retrieved)); - - if (hubURL) dispatch(mercureSubscribe(hubURL, retrieved['@id'])); - }) - .catch(e => { - dispatch(updateLoading(false)); - - if (e instanceof SubmissionError) { - dispatch(updateError(e.errors._error)); - throw e; - } - - dispatch(updateError(e.message)); - }); - }; -} - -export function reset(eventSource) { - return dispatch => { - if (eventSource) eventSource.close(); - - dispatch({ type: 'BOOK_UPDATE_RESET' }); - dispatch(error(null)); - dispatch(loading(false)); - dispatch(createSuccess(null)); - }; -} - -export function mercureSubscribe(hubURL, topic) { - return dispatch => { - const eventSource = subscribe(hubURL, [topic]); - dispatch(mercureOpen(eventSource)); - eventSource.addEventListener('message', event => - dispatch(mercureMessage(normalize(JSON.parse(event.data)))) - ); - }; -} - -export function mercureOpen(eventSource) { - return { type: 'BOOK_UPDATE_MERCURE_OPEN', eventSource }; -} - -export function mercureMessage(retrieved) { - return dispatch => { - if (1 === Object.keys(retrieved).length) { - dispatch({ type: 'BOOK_UPDATE_MERCURE_DELETED', retrieved }); - return; - } - - dispatch({ type: 'BOOK_UPDATE_MERCURE_MESSAGE', retrieved }); - }; -} diff --git a/client/src/actions/propertysale/average_surface_price.js b/client/src/actions/propertysale/average_surface_price.js new file mode 100644 index 0000000..4431c5e --- /dev/null +++ b/client/src/actions/propertysale/average_surface_price.js @@ -0,0 +1,32 @@ +import { fetch } from '../../utils/dataAccess'; + +export function loading(loading) { + return { type: 'PROPERTY_SALE_AVERAGE_SURFACE_PRICE_LOADING', loading }; +} + +export function success(retrieved) { + return { type: 'PROPERTY_SALE_AVERAGE_SURFACE_PRICE_SUCCESS', retrieved }; +} + +export function error(error) { + return { type: 'PROPERTY_SALE_AVERAGE_SURFACE_PRICE_ERROR', error }; +} + +export function fetch_data() { + return dispatch => { + dispatch(loading(true)); + + return fetch("property_sales/average_surface_price", { method: "GET" }) + .then(res => { + dispatch(loading(false)); + + return res.json(); + }) + .then(retrieved => dispatch(success(retrieved))) + .catch(e => { + dispatch(loading(false)); + + dispatch(error(e.message)); + }); + }; +} diff --git a/client/src/actions/propertysale/create.js b/client/src/actions/propertysale/create.js deleted file mode 100644 index 3552a91..0000000 --- a/client/src/actions/propertysale/create.js +++ /dev/null @@ -1,45 +0,0 @@ -import { SubmissionError } from 'redux-form'; -import { fetch } from '../../utils/dataAccess'; - -export function error(error) { - return { type: 'PROPERTYSALE_CREATE_ERROR', error }; -} - -export function loading(loading) { - return { type: 'PROPERTYSALE_CREATE_LOADING', loading }; -} - -export function success(created) { - return { type: 'PROPERTYSALE_CREATE_SUCCESS', created }; -} - -export function create(values) { - return dispatch => { - dispatch(loading(true)); - - return fetch('property_sales', { method: 'POST', body: JSON.stringify(values) }) - .then(response => { - dispatch(loading(false)); - - return response.json(); - }) - .then(retrieved => dispatch(success(retrieved))) - .catch(e => { - dispatch(loading(false)); - - if (e instanceof SubmissionError) { - dispatch(error(e.errors._error)); - throw e; - } - - dispatch(error(e.message)); - }); - }; -} - -export function reset() { - return dispatch => { - dispatch(loading(false)); - dispatch(error(null)); - }; -} diff --git a/client/src/actions/propertysale/delete.js b/client/src/actions/propertysale/delete.js deleted file mode 100644 index 635b194..0000000 --- a/client/src/actions/propertysale/delete.js +++ /dev/null @@ -1,29 +0,0 @@ -import { fetch } from '../../utils/dataAccess'; - -export function error(error) { - return { type: 'PROPERTYSALE_DELETE_ERROR', error }; -} - -export function loading(loading) { - return { type: 'PROPERTYSALE_DELETE_LOADING', loading }; -} - -export function success(deleted) { - return { type: 'PROPERTYSALE_DELETE_SUCCESS', deleted }; -} - -export function del(item) { - return dispatch => { - dispatch(loading(true)); - - return fetch(item['@id'], { method: 'DELETE' }) - .then(() => { - dispatch(loading(false)); - dispatch(success(item)); - }) - .catch(e => { - dispatch(loading(false)); - dispatch(error(e.message)); - }); - }; -} diff --git a/client/src/actions/propertysale/list.js b/client/src/actions/propertysale/list.js deleted file mode 100644 index 9297b42..0000000 --- a/client/src/actions/propertysale/list.js +++ /dev/null @@ -1,85 +0,0 @@ -import { - fetch, - normalize, - extractHubURL, - mercureSubscribe as subscribe -} from '../../utils/dataAccess'; -import { success as deleteSuccess } from './delete'; - -export function error(error) { - return { type: 'PROPERTYSALE_LIST_ERROR', error }; -} - -export function loading(loading) { - return { type: 'PROPERTYSALE_LIST_LOADING', loading }; -} - -export function success(retrieved) { - return { type: 'PROPERTYSALE_LIST_SUCCESS', retrieved }; -} - -export function list(page = 'property_sales') { - return dispatch => { - dispatch(loading(true)); - dispatch(error('')); - - fetch(page) - .then(response => - response - .json() - .then(retrieved => ({ retrieved, hubURL: extractHubURL(response) })) - ) - .then(({ retrieved, hubURL }) => { - retrieved = normalize(retrieved); - - dispatch(loading(false)); - dispatch(success(retrieved)); - - if (hubURL && retrieved['hydra:member'].length) - dispatch( - mercureSubscribe( - hubURL, - retrieved['hydra:member'].map(i => i['@id']) - ) - ); - }) - .catch(e => { - dispatch(loading(false)); - dispatch(error(e.message)); - }); - }; -} - -export function reset(eventSource) { - return dispatch => { - if (eventSource) eventSource.close(); - - dispatch({ type: 'PROPERTYSALE_LIST_RESET' }); - dispatch(deleteSuccess(null)); - }; -} - -export function mercureSubscribe(hubURL, topics) { - return dispatch => { - const eventSource = subscribe(hubURL, topics); - dispatch(mercureOpen(eventSource)); - eventSource.addEventListener('message', event => - dispatch(mercureMessage(normalize(JSON.parse(event.data)))) - ); - }; -} - -export function mercureOpen(eventSource) { - return { type: 'PROPERTYSALE_LIST_MERCURE_OPEN', eventSource }; -} - -export function mercureMessage(retrieved) { - return dispatch => { - if (1 === Object.keys(retrieved).length) { - dispatch({ type: 'PROPERTYSALE_LIST_MERCURE_DELETED', retrieved }); - return; - } - - dispatch({ type: 'PROPERTYSALE_LIST_MERCURE_MESSAGE', retrieved }); - }; -} diff --git a/client/src/actions/propertysale/sales_by_regions.js b/client/src/actions/propertysale/sales_by_regions.js new file mode 100644 index 0000000..e22d94a --- /dev/null +++ b/client/src/actions/propertysale/sales_by_regions.js @@ -0,0 +1,32 @@ +import { fetch } from '../../utils/dataAccess'; + +export function loading(loading) { + return { type: 'PROPERTY_SALE_SALES_BY_REGION_LOADING', loading }; +} + +export function success(retrieved) { + return { type: 'PROPERTY_SALE_SALES_BY_REGION_SUCCESS', retrieved }; +} + +export function error(error) { + return { type: 'PROPERTY_SALE_SALES_BY_REGION_ERROR', error }; +} + +export function fetch_data(year) { + console.log("year"); + console.log(year); + return dispatch => { + dispatch(loading(true)); + + return fetch("property_sales/sales_by_region/?year="+encodeURIComponent(year), { method: "GET" }) + .then(res => { + dispatch(loading(false)); + return res.json(); + }) + .then(retrieved => dispatch(success(retrieved))) + .catch(e => { + dispatch(loading(false)); + dispatch(error(e.message)); + }); + }; +} diff --git a/client/src/actions/propertysale/show.js b/client/src/actions/propertysale/show.js deleted file mode 100644 index b0a84a6..0000000 --- a/client/src/actions/propertysale/show.js +++ /dev/null @@ -1,78 +0,0 @@ -import { - fetch, - extractHubURL, - normalize, - mercureSubscribe as subscribe -} from '../../utils/dataAccess'; - -export function error(error) { - return { type: 'PROPERTYSALE_SHOW_ERROR', error }; -} - -export function loading(loading) { - return { type: 'PROPERTYSALE_SHOW_LOADING', loading }; -} - -export function success(retrieved) { - return { type: 'PROPERTYSALE_SHOW_SUCCESS', retrieved }; -} - -export function retrieve(id) { - return dispatch => { - dispatch(loading(true)); - - return fetch(id) - .then(response => - response - .json() - .then(retrieved => ({ retrieved, hubURL: extractHubURL(response) })) - ) - .then(({ retrieved, hubURL }) => { - retrieved = normalize(retrieved); - - dispatch(loading(false)); - dispatch(success(retrieved)); - - if (hubURL) dispatch(mercureSubscribe(hubURL, retrieved['@id'])); - }) - .catch(e => { - dispatch(loading(false)); - dispatch(error(e.message)); - }); - }; -} - -export function reset(eventSource) { - return dispatch => { - if (eventSource) eventSource.close(); - - dispatch({ type: 'PROPERTYSALE_SHOW_RESET' }); - dispatch(error(null)); - dispatch(loading(false)); - }; -} - -export function mercureSubscribe(hubURL, topic) { - return dispatch => { - const eventSource = subscribe(hubURL, [topic]); - dispatch(mercureOpen(eventSource)); - eventSource.addEventListener('message', event => - dispatch(mercureMessage(normalize(JSON.parse(event.data)))) - ); - }; -} - -export function mercureOpen(eventSource) { - return { type: 'PROPERTYSALE_SHOW_MERCURE_OPEN', eventSource }; -} - -export function mercureMessage(retrieved) { - return dispatch => { - if (1 === Object.keys(retrieved).length) { - dispatch({ type: 'PROPERTYSALE_SHOW_MERCURE_DELETED', retrieved }); - return; - } - - dispatch({ type: 'PROPERTYSALE_SHOW_MERCURE_MESSAGE', retrieved }); - }; -} diff --git a/client/src/actions/propertysale/update.js b/client/src/actions/propertysale/update.js deleted file mode 100644 index c9caa10..0000000 --- a/client/src/actions/propertysale/update.js +++ /dev/null @@ -1,131 +0,0 @@ -import { SubmissionError } from 'redux-form'; -import { - fetch, - extractHubURL, - normalize, - mercureSubscribe as subscribe -} from '../../utils/dataAccess'; -import { success as createSuccess } from './create'; -import { loading, error } from './delete'; - -export function retrieveError(retrieveError) { - return { type: 'PROPERTYSALE_UPDATE_RETRIEVE_ERROR', retrieveError }; -} - -export function retrieveLoading(retrieveLoading) { - return { type: 'PROPERTYSALE_UPDATE_RETRIEVE_LOADING', retrieveLoading }; -} - -export function retrieveSuccess(retrieved) { - return { type: 'PROPERTYSALE_UPDATE_RETRIEVE_SUCCESS', retrieved }; -} - -export function retrieve(id) { - return dispatch => { - dispatch(retrieveLoading(true)); - - return fetch(id) - .then(response => - response - .json() - .then(retrieved => ({ retrieved, hubURL: extractHubURL(response) })) - ) - .then(({ retrieved, hubURL }) => { - retrieved = normalize(retrieved); - - dispatch(retrieveLoading(false)); - dispatch(retrieveSuccess(retrieved)); - - if (hubURL) dispatch(mercureSubscribe(hubURL, retrieved['@id'])); - }) - .catch(e => { - dispatch(retrieveLoading(false)); - dispatch(retrieveError(e.message)); - }); - }; -} - -export function updateError(updateError) { - return { type: 'PROPERTYSALE_UPDATE_UPDATE_ERROR', updateError }; -} - -export function updateLoading(updateLoading) { - return { type: 'PROPERTYSALE_UPDATE_UPDATE_LOADING', updateLoading }; -} - -export function updateSuccess(updated) { - return { type: 'PROPERTYSALE_UPDATE_UPDATE_SUCCESS', updated }; -} - -export function update(item, values) { - return dispatch => { - dispatch(updateError(null)); - dispatch(createSuccess(null)); - dispatch(updateLoading(true)); - - return fetch(item['@id'], { - method: 'PUT', - headers: new Headers({ 'Content-Type': 'application/ld+json' }), - body: JSON.stringify(values) - }) - .then(response => - response - .json() - .then(retrieved => ({ retrieved, hubURL: extractHubURL(response) })) - ) - .then(({ retrieved, hubURL }) => { - retrieved = normalize(retrieved); - - dispatch(updateLoading(false)); - dispatch(updateSuccess(retrieved)); - - if (hubURL) dispatch(mercureSubscribe(hubURL, retrieved['@id'])); - }) - .catch(e => { - dispatch(updateLoading(false)); - - if (e instanceof SubmissionError) { - dispatch(updateError(e.errors._error)); - throw e; - } - - dispatch(updateError(e.message)); - }); - }; -} - -export function reset(eventSource) { - return dispatch => { - if (eventSource) eventSource.close(); - - dispatch({ type: 'PROPERTYSALE_UPDATE_RESET' }); - dispatch(error(null)); - dispatch(loading(false)); - dispatch(createSuccess(null)); - }; -} - -export function mercureSubscribe(hubURL, topic) { - return dispatch => { - const eventSource = subscribe(hubURL, [topic]); - dispatch(mercureOpen(eventSource)); - eventSource.addEventListener('message', event => - dispatch(mercureMessage(normalize(JSON.parse(event.data)))) - ); - }; -} - -export function mercureOpen(eventSource) { - return { type: 'PROPERTYSALE_UPDATE_MERCURE_OPEN', eventSource }; -} - -export function mercureMessage(retrieved) { - return dispatch => { - if (1 === Object.keys(retrieved).length) { - dispatch({ type: 'PROPERTYSALE_UPDATE_MERCURE_DELETED', retrieved }); - return; - } - - dispatch({ type: 'PROPERTYSALE_UPDATE_MERCURE_MESSAGE', retrieved }); - }; -} diff --git a/client/src/actions/review/create.js b/client/src/actions/review/create.js deleted file mode 100644 index f51ddb2..0000000 --- a/client/src/actions/review/create.js +++ /dev/null @@ -1,45 +0,0 @@ -import { SubmissionError } from 'redux-form'; -import { fetch } from '../../utils/dataAccess'; - -export function error(error) { - return { type: 'REVIEW_CREATE_ERROR', error }; -} - -export function loading(loading) { - return { type: 'REVIEW_CREATE_LOADING', loading }; -} - -export function success(created) { - return { type: 'REVIEW_CREATE_SUCCESS', created }; -} - -export function create(values) { - return dispatch => { - dispatch(loading(true)); - - return fetch('reviews', { method: 'POST', body: JSON.stringify(values) }) - .then(response => { - dispatch(loading(false)); - - return response.json(); - }) - .then(retrieved => dispatch(success(retrieved))) - .catch(e => { - dispatch(loading(false)); - - if (e instanceof SubmissionError) { - dispatch(error(e.errors._error)); - throw e; - } - - dispatch(error(e.message)); - }); - }; -} - -export function reset() { - return dispatch => { - dispatch(loading(false)); - dispatch(error(null)); - }; -} diff --git a/client/src/actions/review/delete.js b/client/src/actions/review/delete.js deleted file mode 100644 index e464f97..0000000 --- a/client/src/actions/review/delete.js +++ /dev/null @@ -1,29 +0,0 @@ -import { fetch } from '../../utils/dataAccess'; - -export function error(error) { - return { type: 'REVIEW_DELETE_ERROR', error }; -} - -export function loading(loading) { - return { type: 'REVIEW_DELETE_LOADING', loading }; -} - -export function success(deleted) { - return { type: 'REVIEW_DELETE_SUCCESS', deleted }; -} - -export function del(item) { - return dispatch => { - dispatch(loading(true)); - - return fetch(item['@id'], { method: 'DELETE' }) - .then(() => { - dispatch(loading(false)); - dispatch(success(item)); - }) - .catch(e => { - dispatch(loading(false)); - dispatch(error(e.message)); - }); - }; -} diff --git a/client/src/actions/review/list.js b/client/src/actions/review/list.js deleted file mode 100644 index d909969..0000000 --- a/client/src/actions/review/list.js +++ /dev/null @@ -1,85 +0,0 @@ -import { - fetch, - normalize, - extractHubURL, - mercureSubscribe as subscribe -} from '../../utils/dataAccess'; -import { success as deleteSuccess } from './delete'; - -export function error(error) { - return { type: 'REVIEW_LIST_ERROR', error }; -} - -export function loading(loading) { - return { type: 'REVIEW_LIST_LOADING', loading }; -} - -export function success(retrieved) { - return { type: 'REVIEW_LIST_SUCCESS', retrieved }; -} - -export function list(page = 'reviews') { - return dispatch => { - dispatch(loading(true)); - dispatch(error('')); - - fetch(page) - .then(response => - response - .json() - .then(retrieved => ({ retrieved, hubURL: extractHubURL(response) })) - ) - .then(({ retrieved, hubURL }) => { - retrieved = normalize(retrieved); - - dispatch(loading(false)); - dispatch(success(retrieved)); - - if (hubURL && retrieved['hydra:member'].length) - dispatch( - mercureSubscribe( - hubURL, - retrieved['hydra:member'].map(i => i['@id']) - ) - ); - }) - .catch(e => { - dispatch(loading(false)); - dispatch(error(e.message)); - }); - }; -} - -export function reset(eventSource) { - return dispatch => { - if (eventSource) eventSource.close(); - - dispatch({ type: 'REVIEW_LIST_RESET' }); - dispatch(deleteSuccess(null)); - }; -} - -export function mercureSubscribe(hubURL, topics) { - return dispatch => { - const eventSource = subscribe(hubURL, topics); - dispatch(mercureOpen(eventSource)); - eventSource.addEventListener('message', event => - dispatch(mercureMessage(normalize(JSON.parse(event.data)))) - ); - }; -} - -export function mercureOpen(eventSource) { - return { type: 'REVIEW_LIST_MERCURE_OPEN', eventSource }; -} - -export function mercureMessage(retrieved) { - return dispatch => { - if (1 === Object.keys(retrieved).length) { - dispatch({ type: 'REVIEW_LIST_MERCURE_DELETED', retrieved }); - return; - } - - dispatch({ type: 'REVIEW_LIST_MERCURE_MESSAGE', retrieved }); - }; -} diff --git a/client/src/actions/review/show.js b/client/src/actions/review/show.js deleted file mode 100644 index 3276b60..0000000 --- a/client/src/actions/review/show.js +++ /dev/null @@ -1,78 +0,0 @@ -import { - fetch, - extractHubURL, - normalize, - mercureSubscribe as subscribe -} from '../../utils/dataAccess'; - -export function error(error) { - return { type: 'REVIEW_SHOW_ERROR', error }; -} - -export function loading(loading) { - return { type: 'REVIEW_SHOW_LOADING', loading }; -} - -export function success(retrieved) { - return { type: 'REVIEW_SHOW_SUCCESS', retrieved }; -} - -export function retrieve(id) { - return dispatch => { - dispatch(loading(true)); - - return fetch(id) - .then(response => - response - .json() - .then(retrieved => ({ retrieved, hubURL: extractHubURL(response) })) - ) - .then(({ retrieved, hubURL }) => { - retrieved = normalize(retrieved); - - dispatch(loading(false)); - dispatch(success(retrieved)); - - if (hubURL) dispatch(mercureSubscribe(hubURL, retrieved['@id'])); - }) - .catch(e => { - dispatch(loading(false)); - dispatch(error(e.message)); - }); - }; -} - -export function reset(eventSource) { - return dispatch => { - if (eventSource) eventSource.close(); - - dispatch({ type: 'REVIEW_SHOW_RESET' }); - dispatch(error(null)); - dispatch(loading(false)); - }; -} - -export function mercureSubscribe(hubURL, topic) { - return dispatch => { - const eventSource = subscribe(hubURL, [topic]); - dispatch(mercureOpen(eventSource)); - eventSource.addEventListener('message', event => - dispatch(mercureMessage(normalize(JSON.parse(event.data)))) - ); - }; -} - -export function mercureOpen(eventSource) { - return { type: 'REVIEW_SHOW_MERCURE_OPEN', eventSource }; -} - -export function mercureMessage(retrieved) { - return dispatch => { - if (1 === Object.keys(retrieved).length) { - dispatch({ type: 'REVIEW_SHOW_MERCURE_DELETED', retrieved }); - return; - } - - dispatch({ type: 'REVIEW_SHOW_MERCURE_MESSAGE', retrieved }); - }; -} diff --git a/client/src/actions/review/update.js b/client/src/actions/review/update.js deleted file mode 100644 index 6dd1581..0000000 --- a/client/src/actions/review/update.js +++ /dev/null @@ -1,131 +0,0 @@ -import { SubmissionError } from 'redux-form'; -import { - fetch, - extractHubURL, - normalize, - mercureSubscribe as subscribe -} from '../../utils/dataAccess'; -import { success as createSuccess } from './create'; -import { loading, error } from './delete'; - -export function retrieveError(retrieveError) { - return { type: 'REVIEW_UPDATE_RETRIEVE_ERROR', retrieveError }; -} - -export function retrieveLoading(retrieveLoading) { - return { type: 'REVIEW_UPDATE_RETRIEVE_LOADING', retrieveLoading }; -} - -export function retrieveSuccess(retrieved) { - return { type: 'REVIEW_UPDATE_RETRIEVE_SUCCESS', retrieved }; -} - -export function retrieve(id) { - return dispatch => { - dispatch(retrieveLoading(true)); - - return fetch(id) - .then(response => - response - .json() - .then(retrieved => ({ retrieved, hubURL: extractHubURL(response) })) - ) - .then(({ retrieved, hubURL }) => { - retrieved = normalize(retrieved); - - dispatch(retrieveLoading(false)); - dispatch(retrieveSuccess(retrieved)); - - if (hubURL) dispatch(mercureSubscribe(hubURL, retrieved['@id'])); - }) - .catch(e => { - dispatch(retrieveLoading(false)); - dispatch(retrieveError(e.message)); - }); - }; -} - -export function updateError(updateError) { - return { type: 'REVIEW_UPDATE_UPDATE_ERROR', updateError }; -} - -export function updateLoading(updateLoading) { - return { type: 'REVIEW_UPDATE_UPDATE_LOADING', updateLoading }; -} - -export function updateSuccess(updated) { - return { type: 'REVIEW_UPDATE_UPDATE_SUCCESS', updated }; -} - -export function update(item, values) { - return dispatch => { - dispatch(updateError(null)); - dispatch(createSuccess(null)); - dispatch(updateLoading(true)); - - return fetch(item['@id'], { - method: 'PUT', - headers: new Headers({ 'Content-Type': 'application/ld+json' }), - body: JSON.stringify(values) - }) - .then(response => - response - .json() - .then(retrieved => ({ retrieved, hubURL: extractHubURL(response) })) - ) - .then(({ retrieved, hubURL }) => { - retrieved = normalize(retrieved); - - dispatch(updateLoading(false)); - dispatch(updateSuccess(retrieved)); - - if (hubURL) dispatch(mercureSubscribe(hubURL, retrieved['@id'])); - }) - .catch(e => { - dispatch(updateLoading(false)); - - if (e instanceof SubmissionError) { - dispatch(updateError(e.errors._error)); - throw e; - } - - dispatch(updateError(e.message)); - }); - }; -} - -export function reset(eventSource) { - return dispatch => { - if (eventSource) eventSource.close(); - - dispatch({ type: 'REVIEW_UPDATE_RESET' }); - dispatch(error(null)); - dispatch(loading(false)); - dispatch(createSuccess(null)); - }; -} - -export function mercureSubscribe(hubURL, topic) { - return dispatch => { - const eventSource = subscribe(hubURL, [topic]); - dispatch(mercureOpen(eventSource)); - eventSource.addEventListener('message', event => - dispatch(mercureMessage(normalize(JSON.parse(event.data)))) - ); - }; -} - -export function mercureOpen(eventSource) { - return { type: 'REVIEW_UPDATE_MERCURE_OPEN', eventSource }; -} - -export function mercureMessage(retrieved) { - return dispatch => { - if (1 === Object.keys(retrieved).length) { - dispatch({ type: 'REVIEW_UPDATE_MERCURE_DELETED', retrieved }); - return; - } - - dispatch({ type: 'REVIEW_UPDATE_MERCURE_MESSAGE', retrieved }); - }; -} diff --git a/client/src/components/Donut.js b/client/src/components/Donut.js deleted file mode 100644 index 7eea461..0000000 --- a/client/src/components/Donut.js +++ /dev/null @@ -1,338 +0,0 @@ -import React, { Component } from 'react'; -import * as d3 from 'd3'; -import './Donut.css'; - -class Donut extends Component { - - componentDidMount() { - this.drawChart(); - } - - componentDidUpdate() { - this.drawChart(); - } - - - drawChart() { - var regions = ["Normandie", "Normandie-2", "Region centre loire", "Bretage", "PACA", "elit", "sed", "do", "eiusmod", "tempor", "incididunt","Normandie-2", "Normandie-2-2", "Region centre loire-2", "Bretage-2", "PACA-2", "elit-2", "sed-2", "do-2", "eiusmod-2", "tempor-2", "incididunt-2"]; - var percentage = [0,1,2,3,4,5,6,8,8,9,10,0,1,2,3,4,5,6,8,8,9,10]; - var datas = [51,12,32,48,51,63,48,39,60,48,100,51,12,32,48,51,63,48,39,60,48,100]; - var data2 = [10,84,28,12,1,58,64,1,30,10,80]; - - var regionsjson = [ - {nom: "reg1",percentage: "10" }, - {nom: "reg2",percentage: "20" }, - {nom: "reg3",percentage: "10" }, - {nom: "reg4",percentage: "20" }, - ] - - var width = 960, - height = 430; - - var svg = d3.select("div#app") - .append("svg") - .attr("width", width + 100) - .attr("height", height + 100) - .append("g") - - svg.append("g") - .attr("class", "slices"); - svg.append("g") - .attr("class", "percent"); - svg.append("g") - .attr("class", "labels"); - svg.append("g") - .attr("class", "lines"); - - var radius = Math.min(width, height) / 2; - - var pie = d3.pie() - .sort(null) - .value(function(d) { - return d.value; - }); - - var arc = d3.arc() - .outerRadius(radius * 0.8) - .innerRadius(radius * 0.4); - - var outerArc = d3.arc() - .innerRadius(radius * 0.9) - .outerRadius(radius * 0.9); - - svg.attr("transform", "translate(" + width / 2 + "," + height / 2 + ")"); - - var key = function(d){ return d.data.label; }; - var percentkey = function(d,i){ return {idx: i, data: d.data.percent}; }; - var colorRange = []; - for (let index = 0; index < regions.length; index++) { - colorRange[index] = d3.interpolateBlues((index*1.0)/regions.length); - } - - var color = d3.scaleOrdinal().range(colorRange).domain(regions); - - function randomData (){ - var labels = color.domain(); - console.log(regions); - console.log(labels); - return labels.map(function(label,i){ - return { label: label, value: datas[i],percent:percentage[i] } - }); - } - - - - - - function changeinit(data) { - - /* ------- PIE SLICES -------*/ - var slice = svg.select(".slices").selectAll("path.slice") - .data(pie(data), key); - - slice.enter() - .insert("path") - .style("fill", function(d,i) { return color(i); }) - .attr("class", "slice") - .transition().duration(1000) - .attrTween("d", function(d) { - this._current = this._current || d; - var interpolate = d3.interpolate(this._current, d); - this._current = interpolate(0); - return function(t) { - return arc(interpolate(t)); - }; - }) - - - - slice.exit() - .remove(); - - /* ------- TEXT LABELS -------*/ - var percent = svg.select(".percent").selectAll("text") - .data(pie(data), percentkey.data); - - percent.enter() - .append("text") - .attr("dy", ".35em") - .text(function(d) { - return d.data.percent+"%"; - }).transition().duration(1000) - .attrTween("transform", function(d) { - this._current = this._current || d; - var interpolate = d3.interpolate(this._current, d); - this._current = interpolate(0); - return function(t) { - var d2 = interpolate(t); - var pos = arc.centroid(d2); - //pos[0] = radius * (midAngle(d2) < Math.PI ? 1 : -1); - return "translate("+ pos +")"; - }; - }) - - percent.exit() - .remove(); - - var text = svg.select(".labels").selectAll("text") - .data(pie(data), key); - - - - - function midAngle(d){ - return d.startAngle + (d.endAngle - d.startAngle)/2; - } - text.enter() - .append("text") - .attr("dy", ".35em") - .text(function(d) { - return d.data.label; - }).transition().duration(1000) - .attrTween("transform", function(d) { - this._current = this._current || d; - var interpolate = d3.interpolate(this._current, d); - this._current = interpolate(0); - return function(t) { - var d2 = interpolate(t); - var pos = outerArc.centroid(d2); - pos[0] = radius * (midAngle(d2) < Math.PI ? 1 : -1); - return "translate("+ pos +")"; - }; - }) - - .styleTween("text-anchor", function(d){ - this._current = this._current || d; - var interpolate = d3.interpolate(this._current, d); - this._current = interpolate(0); - return function(t) { - var d2 = interpolate(t); - return midAngle(d2) < Math.PI ? "start":"end"; - }; - }); - - text.exit() - .remove(); - /* ------- SLICE TO TEXT POLYLINES -------*/ - - var polyline = svg.select(".lines").selectAll("polyline") - .data(pie(data), key); - - polyline.enter() - .append("polyline").transition().duration(1000) - .attrTween("points", function(d){ - this._current = this._current || d; - var interpolate = d3.interpolate(this._current, d); - this._current = interpolate(0); - return function(t) { - var d2 = interpolate(t); - var pos = outerArc.centroid(d2); - pos[0] = radius * 0.95 * (midAngle(d2) < Math.PI ? 1 : -1); - return [arc.centroid(d2), outerArc.centroid(d2), pos]; - }; - }); - - polyline.exit() - .remove(); - }; - - function changeupdate(data) { - - /* ------- PIE SLICES -------*/ - var slice = svg.select(".slices").selectAll("path.slice") - .data(pie(data), key); - - slice.enter() - .insert("path") - .style("fill", function(d,i) { return color(i); }) - .attr("class", "slice"); - - slice.transition().duration(1000) - .attrTween("d", function(d) { - this._current = this._current || d; - var interpolate = d3.interpolate(this._current, d); - this._current = interpolate(0); - return function(t) { - return arc(interpolate(t)); - }; - }) - - - - slice.exit() - .remove(); - - /* ------- TEXT LABELS -------*/ - var percent = svg.select(".percent").selectAll("text") - .data(pie(data), percentkey.data); - - percent.enter() - .append("text") - .attr("dy", ".35em") - .text(function(d) { - return d.data.percent+"%"; - }); - - percent.transition().duration(1000) - .attrTween("transform", function(d) { - this._current = this._current || d; - var interpolate = d3.interpolate(this._current, d); - this._current = interpolate(0); - return function(t) { - var d2 = interpolate(t); - var pos = arc.centroid(d2); - //pos[0] = radius * (midAngle(d2) < Math.PI ? 1 : -1); - return "translate("+ pos +")"; - }; - }) - - percent.exit() - .remove(); - - var text = svg.select(".labels").selectAll("text") - .data(pie(data), key); - - - - - function midAngle(d){ - return d.startAngle + (d.endAngle - d.startAngle)/2; - } - text.enter() - .append("text") - .attr("dy", ".35em") - .text(function(d) { - return d.data.label; - }); - - text.transition().duration(1000) - .attrTween("transform", function(d) { - this._current = this._current || d; - var interpolate = d3.interpolate(this._current, d); - this._current = interpolate(0); - return function(t) { - var d2 = interpolate(t); - var pos = outerArc.centroid(d2); - pos[0] = radius * (midAngle(d2) < Math.PI ? 1 : -1); - return "translate("+ pos +")"; - }; - }) - - .styleTween("text-anchor", function(d){ - this._current = this._current || d; - var interpolate = d3.interpolate(this._current, d); - this._current = interpolate(0); - return function(t) { - var d2 = interpolate(t); - return midAngle(d2) < Math.PI ? "start":"end"; - }; - }); - - text.exit() - .remove(); - /* ------- SLICE TO TEXT POLYLINES -------*/ - - var polyline = svg.select(".lines").selectAll("polyline") - .data(pie(data), key); - - polyline.enter() - .append("polyline"); - polyline.transition().duration(1000) - .attrTween("points", function(d){ - this._current = this._current || d; - var interpolate = d3.interpolate(this._current, d); - this._current = interpolate(0); - return function(t) { - var d2 = interpolate(t); - var pos = outerArc.centroid(d2); - pos[0] = radius * 0.95 * (midAngle(d2) < Math.PI ? 1 : -1); - return [arc.centroid(d2), outerArc.centroid(d2), pos]; - }; - }); - - polyline.exit() - .remove(); - }; - - - - - d3.select(".randomize") - .on("click", function(){ - color = d3.scaleOrdinal() - .range(colorRange) - .domain(regions); - changeupdate(randomData()); - }); - changeinit(randomData()); - } - - - - render() { - return
-
- } -} - -export default Donut; \ No newline at end of file diff --git a/client/src/components/LineChart.js b/client/src/components/LineChart.js deleted file mode 100644 index 4375de4..0000000 --- a/client/src/components/LineChart.js +++ /dev/null @@ -1,147 +0,0 @@ -import React, { Component } from 'react'; -import * as d3 from 'd3'; - -class LineChart extends Component { - - componentDidMount() { - this.drawChart(); - } - - componentDidUpdate() { - this.drawChart(); - } - - // - - - - - - - - - - - - drawChart() { - const data = [ - { date: "10/25/2018", value: 1 }, - { date: "10/26/2018", value: 3 }, - { date: "10/27/2018", value: 0 }, - { date: "10/28/2018", value: 0 }, - { date: "10/29/2018", value: 5 }, - { date: "10/30/2018", value: 8 }, - { date: "10/31/2018", value: 7 }, - { date: "11/01/2018", value: 11 }, - { date: "11/02/2018", value: 23 }, - { date: "11/03/2018", value: 13 }, - { date: "11/04/2018", value: 15 }, - { date: "11/05/2018", value: 37 }, - { date: "11/06/2018", value: 32 }, - { date: "11/07/2018", value: 38 }, - { date: "11/08/2018", value: 42 }, - { date: "11/09/2018", value: 43 }, - { date: "11/10/2018", value: 21 }, - { date: "11/11/2018", value: 24 }, - { date: "11/12/2018", value: 50 }, - { date: "11/13/2018", value: 53 }, - { date: "11/14/2018", value: 59 }, - { date: "11/15/2018", value: 61 }, - { date: "11/16/2018", value: 62 } - ]; - - - const margin = { top: 50, right: 40, bottom: 10, left: 100 }; - const padding = { top: 10, right: 10, bottom: 10, left: 10 }; - const x = 800; - const y = 600; - const width = 20 + x - margin.right - margin.left; - const height = padding.top + padding.right + padding.bottom + padding.left + y + margin.top + margin.bottom; - - // Line generator. - const line = d3 - .line() - .x((d) => xScale(d.date)) - .y((d) => yScale(d.value)) - .curve(d3.curveMonotoneX); - - var parseTime = d3.timeParse("%m/%d/%Y"); - - data.forEach(function(d) { - d.date = parseTime(d.date); - }); - - const xScale = d3 - .scaleTime() - .domain(d3.extent(data, function(d) { return d.date; })) - .range([0, width]); - - const yScale = d3 - .scaleLinear() - .domain(d3.extent(data, function(d) { return d.value })) - .range([height, 0]); - - // - - - - - - - - - - - - // Main SVG - const svg = d3.select("#app") - .append("svg") - .attr("width", width + 100) - .attr("height", height + 100) - .style("margin-top", margin.top) - .style("margin-left", margin.left) - .append('g') - .attr('transform', `translate(${margin.left}, ${margin.top})`); - - const xAxis = d3.axisBottom(xScale) - .tickSizeOuter(0) - .tickFormat(d3.timeFormat("%d %m %Y")); - - const xAxisDraw = svg - .append('g') - .attr('transform', `translate(0, ${height})`) - .attr('class', 'x axis') - .call(xAxis);`` - - // Draw y axis. - const yAxis = d3 - .axisLeft(yScale) - .ticks(3) - .tickSizeOuter(0) - .tickSizeInner(-width); - - const yAxisDraw = svg - .append('g') - .attr('class', 'y axis') - .style("color", "#999") - .call(yAxis); - - const chartGroup = svg.append('g').attr('class', 'line-chart'); - - // - - - - - - - - - - - - svg.append("path") - .data([data]) - .attr("class", "line") - .attr("fill", "none") - .attr("stroke", "blue") - .attr("d", line) - - - // - - - - - - - - - - - - // Draw header. - const header = svg - .append('g') - .attr('class', 'line-chart-header') - .attr('transform', `translate(${width / 2 }, ${0})`) - .append('text'); - - header.append('tspan').text('Prix Moyen du M²'); - - const yLabel = svg - .append('g') - .attr('class', 'yLabel') - .attr('transform', `translate(${ -80 },${height / 2})`) - .append('text') - .attr('dy', '1em') - .style('font-size', '2.0em') - .style('fill', '#555') - .text('K€'); - - - svg.exit().remove() - } - - render() { - return
- } -} - -export default LineChart; \ No newline at end of file diff --git a/client/src/components/book/Create.js b/client/src/components/book/Create.js deleted file mode 100644 index 87550ce..0000000 --- a/client/src/components/book/Create.js +++ /dev/null @@ -1,64 +0,0 @@ -import React, { Component } from 'react'; -import { connect } from 'react-redux'; -import { Link, Redirect } from 'react-router-dom'; -import PropTypes from 'prop-types'; -import Form from './Form'; -import { create, reset } from '../../actions/book/create'; - -class Create extends Component { - static propTypes = { - error: PropTypes.string, - loading: PropTypes.bool.isRequired, - created: PropTypes.object, - create: PropTypes.func.isRequired, - reset: PropTypes.func.isRequired - }; - - componentWillUnmount() { - this.props.reset(); - } - - render() { - if (this.props.created) - return ( - - ); - - return ( -
-

New Book

- - {this.props.loading && ( -
- Loading... -
- )} - {this.props.error && ( -
-
- )} - -
- - Back to list - -
- ); - } -} - -const mapStateToProps = state => { - const { created, error, loading } = state.book.create; - return { created, error, loading }; -}; - -const mapDispatchToProps = dispatch => ({ - create: values => dispatch(create(values)), - reset: () => dispatch(reset()) -}); - -export default connect(mapStateToProps, mapDispatchToProps)(Create); diff --git a/client/src/components/book/Form.js b/client/src/components/book/Form.js deleted file mode 100644 index 9cbb4e0..0000000 --- a/client/src/components/book/Form.js +++ /dev/null @@ -1,102 +0,0 @@ -import React, { Component } from 'react'; -import { Field, reduxForm } from 'redux-form'; -import PropTypes from 'prop-types'; - -class Form extends Component { - static propTypes = { - handleSubmit: PropTypes.func.isRequired, - error: PropTypes.string - }; - - renderField = data => { - data.input.className = 'form-control'; - - const isInvalid = data.meta.touched && !!data.meta.error; - if (isInvalid) { - data.input.className += ' is-invalid'; - data.input['aria-invalid'] = true; - } - - if (this.props.error && data.meta.touched && !data.meta.error) { - data.input.className += ' is-valid'; - } - - return ( -
- - - {isInvalid &&
{data.meta.error}
} -
- ); - }; - - render() { - return ( - - - - - - - (v === '' ? [] : v.split(','))} - /> - - - - ); - } -} - -export default reduxForm({ - form: 'book', - enableReinitialize: true, - keepDirtyOnReinitialize: true -})(Form); diff --git a/client/src/components/book/List.js b/client/src/components/book/List.js deleted file mode 100644 index 202a74b..0000000 --- a/client/src/components/book/List.js +++ /dev/null @@ -1,182 +0,0 @@ -import React, { Component } from 'react'; -import { connect } from 'react-redux'; -import { Link } from 'react-router-dom'; -import PropTypes from 'prop-types'; -import { list, reset } from '../../actions/book/list'; - -class List extends Component { - static propTypes = { - retrieved: PropTypes.object, - loading: PropTypes.bool.isRequired, - error: PropTypes.string, - eventSource: PropTypes.instanceOf(EventSource), - deletedItem: PropTypes.object, - list: PropTypes.func.isRequired, - reset: PropTypes.func.isRequired - }; - - componentDidMount() { - this.props.list( - this.props.match.params.page && - decodeURIComponent(this.props.match.params.page) - ); - } - - componentWillReceiveProps(nextProps) { - if (this.props.match.params.page !== nextProps.match.params.page) - nextProps.list( - nextProps.match.params.page && - decodeURIComponent(nextProps.match.params.page) - ); - } - - componentWillUnmount() { - this.props.reset(this.props.eventSource); - } - - render() { - return ( -
-

Book List

- - {this.props.loading && ( -
Loading...
- )} - {this.props.deletedItem && ( -
- {this.props.deletedItem['@id']} deleted. -
- )} - {this.props.error && ( -
{this.props.error}
- )} - -

- - Create - -

- - - - - - - - - - - - - - - {this.props.retrieved && - this.props.retrieved['hydra:member'].map(item => ( - - - - - - - - - - - - ))} - -
idisbntitledescriptionauthorpublicationDatereviews -
- - {item['@id']} - - {item['isbn']}{item['title']}{item['description']}{item['author']}{item['publicationDate']}{this.renderLinks('reviews', item['reviews'])} - - - -
- - {this.pagination()} -
- ); - } - - pagination() { - const view = this.props.retrieved && this.props.retrieved['hydra:view']; - if (!view) return; - - const { - 'hydra:first': first, - 'hydra:previous': previous, - 'hydra:next': next, - 'hydra:last': last - } = view; - - return ( - - ); - } - - renderLinks = (type, items) => { - if (Array.isArray(items)) { - return items.map((item, i) => ( -
{this.renderLinks(type, item)}
- )); - } - - return ( - {items} - ); - }; -} - -const mapStateToProps = state => { - const { - retrieved, - loading, - error, - eventSource, - deletedItem - } = state.book.list; - return { retrieved, loading, error, eventSource, deletedItem }; -}; - -const mapDispatchToProps = dispatch => ({ - list: page => dispatch(list(page)), - reset: eventSource => dispatch(reset(eventSource)) -}); - -export default connect(mapStateToProps, mapDispatchToProps)(List); diff --git a/client/src/components/book/Show.js b/client/src/components/book/Show.js deleted file mode 100644 index 42c3e70..0000000 --- a/client/src/components/book/Show.js +++ /dev/null @@ -1,144 +0,0 @@ -import React, { Component } from 'react'; -import { connect } from 'react-redux'; -import { Link, Redirect } from 'react-router-dom'; -import PropTypes from 'prop-types'; -import { retrieve, reset } from '../../actions/book/show'; -import { del } from '../../actions/book/delete'; - -class Show extends Component { - static propTypes = { - retrieved: PropTypes.object, - loading: PropTypes.bool.isRequired, - error: PropTypes.string, - eventSource: PropTypes.instanceOf(EventSource), - retrieve: PropTypes.func.isRequired, - reset: PropTypes.func.isRequired, - deleteError: PropTypes.string, - deleteLoading: PropTypes.bool.isRequired, - deleted: PropTypes.object, - del: PropTypes.func.isRequired - }; - - componentDidMount() { - this.props.retrieve(decodeURIComponent(this.props.match.params.id)); - } - - componentWillUnmount() { - this.props.reset(this.props.eventSource); - } - - del = () => { - if (window.confirm('Are you sure you want to delete this item?')) - this.props.del(this.props.retrieved); - }; - - render() { - if (this.props.deleted) return ; - - const item = this.props.retrieved; - - return ( -
-

Show {item && item['@id']}

- - {this.props.loading && ( -
- Loading... -
- )} - {this.props.error && ( -
-
- )} - {this.props.deleteError && ( -
-
- )} - - {item && ( - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
FieldValue
isbn{item['isbn']}
title{item['title']}
description{item['description']}
author{item['author']}
publicationDate{item['publicationDate']}
reviews{this.renderLinks('reviews', item['reviews'])}
- )} - - Back to list - - {item && ( - - - - )} - -
- ); - } - - renderLinks = (type, items) => { - if (Array.isArray(items)) { - return items.map((item, i) => ( -
{this.renderLinks(type, item)}
- )); - } - - return ( - - {items} - - ); - }; -} - -const mapStateToProps = state => ({ - retrieved: state.book.show.retrieved, - error: state.book.show.error, - loading: state.book.show.loading, - eventSource: state.book.show.eventSource, - deleteError: state.book.del.error, - deleteLoading: state.book.del.loading, - deleted: state.book.del.deleted -}); - -const mapDispatchToProps = dispatch => ({ - retrieve: id => dispatch(retrieve(id)), - del: item => dispatch(del(item)), - reset: eventSource => dispatch(reset(eventSource)) -}); - -export default connect(mapStateToProps, mapDispatchToProps)(Show); diff --git a/client/src/components/book/Update.js b/client/src/components/book/Update.js deleted file mode 100644 index ac13d32..0000000 --- a/client/src/components/book/Update.js +++ /dev/null @@ -1,123 +0,0 @@ -import React, { Component } from 'react'; -import { connect } from 'react-redux'; -import { Link, Redirect } from 'react-router-dom'; -import PropTypes from 'prop-types'; -import Form from './Form'; -import { retrieve, update, reset } from '../../actions/book/update'; -import { del } from '../../actions/book/delete'; - -class Update extends Component { - static propTypes = { - retrieved: PropTypes.object, - retrieveLoading: PropTypes.bool.isRequired, - retrieveError: PropTypes.string, - updateLoading: PropTypes.bool.isRequired, - updateError: PropTypes.string, - deleteLoading: PropTypes.bool.isRequired, - deleteError: PropTypes.string, - updated: PropTypes.object, - deleted: PropTypes.object, - eventSource: PropTypes.instanceOf(EventSource), - retrieve: PropTypes.func.isRequired, - update: PropTypes.func.isRequired, - del: PropTypes.func.isRequired, - reset: PropTypes.func.isRequired - }; - - componentDidMount() { - this.props.retrieve(decodeURIComponent(this.props.match.params.id)); - } - - componentWillUnmount() { - this.props.reset(this.props.eventSource); - } - - del = () => { - if (window.confirm('Are you sure you want to delete this item?')) - this.props.del(this.props.retrieved); - }; - - render() { - if (this.props.deleted) return ; - - const item = this.props.updated ? this.props.updated : this.props.retrieved; - - return ( -
-

Edit {item && item['@id']}

- - {this.props.created && ( -
- {this.props.created['@id']} created. -
- )} - {this.props.updated && ( -
- {this.props.updated['@id']} updated. -
- )} - {(this.props.retrieveLoading || - this.props.updateLoading || - this.props.deleteLoading) && ( -
- Loading... -
- )} - {this.props.retrieveError && ( -
-
- )} - {this.props.updateError && ( -
-
- )} - {this.props.deleteError && ( -
-
- )} - - {item && ( -
this.props.update(item, values)} - initialValues={item} - /> - )} - - Back to list - - -
- ); - } -} - -const mapStateToProps = state => ({ - retrieved: state.book.update.retrieved, - retrieveError: state.book.update.retrieveError, - retrieveLoading: state.book.update.retrieveLoading, - updateError: state.book.update.updateError, - updateLoading: state.book.update.updateLoading, - deleteError: state.book.del.error, - deleteLoading: state.book.del.loading, - eventSource: state.book.update.eventSource, - created: state.book.create.created, - deleted: state.book.del.deleted, - updated: state.book.update.updated -}); - -const mapDispatchToProps = dispatch => ({ - retrieve: id => dispatch(retrieve(id)), - update: (item, values) => dispatch(update(item, values)), - del: item => dispatch(del(item)), - reset: eventSource => dispatch(reset(eventSource)) -}); - -export default connect(mapStateToProps, mapDispatchToProps)(Update); diff --git a/client/src/components/book/index.js b/client/src/components/book/index.js deleted file mode 100644 index e936e55..0000000 --- a/client/src/components/book/index.js +++ /dev/null @@ -1,6 +0,0 @@ -import Create from './Create'; -import List from './List'; -import Update from './Update'; -import Show from './Show'; - -export { Create, List, Update, Show }; diff --git a/client/src/components/BarChart.js b/client/src/components/charts/BarChart.js similarity index 100% rename from client/src/components/BarChart.js rename to client/src/components/charts/BarChart.js diff --git a/client/src/components/charts/Donut.js b/client/src/components/charts/Donut.js new file mode 100644 index 0000000..b934afd --- /dev/null +++ b/client/src/components/charts/Donut.js @@ -0,0 +1,321 @@ +import React, { Component } from 'react'; +import PropTypes from "prop-types"; +import * as d3 from 'd3'; +import './css/Donut.css'; + +class Donut extends Component { + + static propTypes = { + data: PropTypes.array.isRequired + }; + + render() { + console.log("data"); + console.log(this.props.data); + var regions = ["Normandie", "Normandie-2", "Region centre loire", "Bretage", "PACA", "elit", "sed", "do", "eiusmod", "tempor", "incididunt"]; + var percentage = [0, 1, 2, 3, 4, 5, 6, 8, 8, 9, 10]; + var datas = [51, 12, 32, 48, 51, 63, 48, 39, 60, 48, 10]; + var data2 = [10, 84, 28, 12, 1, 58, 64, 1, 30, 10, 80]; + + var regionsjson = [ + { nom: "reg1", percentage: "10" }, + { nom: "reg2", percentage: "20" }, + { nom: "reg3", percentage: "10" }, + { nom: "reg4", percentage: "20" }, + ] + + var width = 960, + height = 430; + + var svg = d3.select("div#app") + .append("svg") + .attr("width", width + 100) + .attr("height", height + 100) + .append("g") + + svg.append("g") + .attr("class", "slices"); + svg.append("g") + .attr("class", "percent"); + svg.append("g") + .attr("class", "labels"); + svg.append("g") + .attr("class", "lines"); + + var radius = Math.min(width, height) / 2; + + var pie = d3.pie() + .sort(null) + .value(function (d) { + return d.value; + }); + + var arc = d3.arc() + .outerRadius(radius * 0.8) + .innerRadius(radius * 0.4); + + var outerArc = d3.arc() + .innerRadius(radius * 0.9) + .outerRadius(radius * 0.9); + + svg.attr("transform", "translate(" + width / 2 + "," + height / 2 + ")"); + + var key = function (d) { return d.data.label; }; + var percentkey = function (d, i) { return { idx: i, data: d.data.percent }; }; + var colorRange = d3.schemePastel1; + colorRange.push(...d3.schemePaired); + var color = d3.scaleOrdinal().range(colorRange).domain(regions); + + function randomData() { + var labels = color.domain(); + console.log(labels); + return labels.map(function (label, i) { + return { label: label, value: datas[i], percent: percentage[i] } + }); + } + + function changeinit(data) { + /* ------- PIE SLICES -------*/ + var slice = svg.select(".slices").selectAll("path.slice") + .data(pie(data), key); + + slice.enter() + .insert("path") + .style("fill", function (d, i) { return color(i); }) + .attr("class", "slice") + .transition().duration(1000) + .attrTween("d", function (d) { + this._current = this._current || d; + var interpolate = d3.interpolate(this._current, d); + this._current = interpolate(0); + return function (t) { + return arc(interpolate(t)); + }; + }) + + + + slice.exit() + .remove(); + + /* ------- TEXT LABELS -------*/ + var percent = svg.select(".percent").selectAll("text") + .data(pie(data), percentkey.data); + + percent.enter() + .append("text") + .attr("dy", ".35em") + .text(function (d) { + return d.data.percent + "%"; + }).transition().duration(1000) + .attrTween("transform", function (d) { + this._current = this._current || d; + var interpolate = d3.interpolate(this._current, d); + this._current = interpolate(0); + return function (t) { + var d2 = interpolate(t); + var pos = arc.centroid(d2); + //pos[0] = radius * (midAngle(d2) < Math.PI ? 1 : -1); + return "translate(" + pos + ")"; + }; + }) + + percent.exit() + .remove(); + + var text = svg.select(".labels").selectAll("text") + .data(pie(data), key); + + + + + function midAngle(d) { + return d.startAngle + (d.endAngle - d.startAngle) / 2; + } + text.enter() + .append("text") + .attr("dy", ".35em") + .text(function (d) { + return d.data.label; + }).transition().duration(1000) + .attrTween("transform", function (d) { + this._current = this._current || d; + var interpolate = d3.interpolate(this._current, d); + this._current = interpolate(0); + return function (t) { + var d2 = interpolate(t); + var pos = outerArc.centroid(d2); + pos[0] = radius * (midAngle(d2) < Math.PI ? 1 : -1); + return "translate(" + pos + ")"; + }; + }) + + .styleTween("text-anchor", function (d) { + this._current = this._current || d; + var interpolate = d3.interpolate(this._current, d); + this._current = interpolate(0); + return function (t) { + var d2 = interpolate(t); + return midAngle(d2) < Math.PI ? "start" : "end"; + }; + }); + + text.exit() + .remove(); + /* ------- SLICE TO TEXT POLYLINES -------*/ + + var polyline = svg.select(".lines").selectAll("polyline") + .data(pie(data), key); + + polyline.enter() + .append("polyline").transition().duration(1000) + .attrTween("points", function (d) { + this._current = this._current || d; + var interpolate = d3.interpolate(this._current, d); + this._current = interpolate(0); + return function (t) { + var d2 = interpolate(t); + var pos = outerArc.centroid(d2); + pos[0] = radius * 0.95 * (midAngle(d2) < Math.PI ? 1 : -1); + return [arc.centroid(d2), outerArc.centroid(d2), pos]; + }; + }); + + polyline.exit() + .remove(); + }; + + function changeupdate(data) { + + /* ------- PIE SLICES -------*/ + var slice = svg.select(".slices").selectAll("path.slice") + .data(pie(data), key); + + slice.enter() + .insert("path") + .style("fill", function (d, i) { return color(i); }) + .attr("class", "slice"); + + slice.transition().duration(1000) + .attrTween("d", function (d) { + this._current = this._current || d; + var interpolate = d3.interpolate(this._current, d); + this._current = interpolate(0); + return function (t) { + return arc(interpolate(t)); + }; + }) + + + + slice.exit() + .remove(); + + /* ------- TEXT LABELS -------*/ + var percent = svg.select(".percent").selectAll("text") + .data(pie(data), percentkey.data); + + percent.enter() + .append("text") + .attr("dy", ".35em") + .text(function (d) { + return d.data.percent + "%"; + }); + + percent.transition().duration(1000) + .attrTween("transform", function (d) { + this._current = this._current || d; + var interpolate = d3.interpolate(this._current, d); + this._current = interpolate(0); + return function (t) { + var d2 = interpolate(t); + var pos = arc.centroid(d2); + //pos[0] = radius * (midAngle(d2) < Math.PI ? 1 : -1); + return "translate(" + pos + ")"; + }; + }) + + percent.exit() + .remove(); + + var text = svg.select(".labels").selectAll("text") + .data(pie(data), key); + + + + + function midAngle(d) { + return d.startAngle + (d.endAngle - d.startAngle) / 2; + } + text.enter() + .append("text") + .attr("dy", ".35em") + .text(function (d) { + return d.data.label; + }); + + text.transition().duration(1000) + .attrTween("transform", function (d) { + this._current = this._current || d; + var interpolate = d3.interpolate(this._current, d); + this._current = interpolate(0); + return function (t) { + var d2 = interpolate(t); + var pos = outerArc.centroid(d2); + pos[0] = radius * (midAngle(d2) < Math.PI ? 1 : -1); + return "translate(" + pos + ")"; + }; + }) + + .styleTween("text-anchor", function (d) { + this._current = this._current || d; + var interpolate = d3.interpolate(this._current, d); + this._current = interpolate(0); + return function (t) { + var d2 = interpolate(t); + return midAngle(d2) < Math.PI ? "start" : "end"; + }; + }); + + text.exit() + .remove(); + /* ------- SLICE TO TEXT POLYLINES -------*/ + + var polyline = svg.select(".lines").selectAll("polyline") + .data(pie(data), key); + + polyline.enter() + .append("polyline"); + polyline.transition().duration(1000) + .attrTween("points", function (d) { + this._current = this._current || d; + var interpolate = d3.interpolate(this._current, d); + this._current = interpolate(0); + return function (t) { + var d2 = interpolate(t); + var pos = outerArc.centroid(d2); + pos[0] = radius * 0.95 * (midAngle(d2) < Math.PI ? 1 : -1); + return [arc.centroid(d2), outerArc.centroid(d2), pos]; + }; + }); + + polyline.exit() + .remove(); + }; + + d3.select(".randomize") + .on("click", function () { + color = d3.scaleOrdinal() + .range(colorRange) + .domain(regions); + changeupdate(randomData()); + }); + changeinit(randomData()); + return
+ +
; + } +} + + +export default Donut; \ No newline at end of file diff --git a/client/src/components/charts/LineChart.js b/client/src/components/charts/LineChart.js new file mode 100644 index 0000000..2ef409a --- /dev/null +++ b/client/src/components/charts/LineChart.js @@ -0,0 +1,113 @@ +import React, { Component } from 'react'; +import ReactDOM from "react-dom"; +import PropTypes from "prop-types"; +import * as d3 from 'd3'; + +class LineChart extends Component { + static propTypes = { + yLabel: PropTypes.string, + xLabel: PropTypes.string, + width: PropTypes.number.isRequired, + height: PropTypes.number.isRequired, + data: PropTypes.array.isRequired, + }; + + render() { + const margin = { top: 50, right: 40, bottom: 10, left: 50 }; + const padding = { top: 10, right: 10, bottom: 10, left: 10 }; + const x = this.props.width; + const y = this.props.height; + const width = x - margin.right - margin.left; + const height = padding.top + padding.right + padding.bottom + padding.left + y + margin.top + margin.bottom; + + const parseTime = d3.timeParse("%Y-%m-%d %H:%M:%S"); + + const plotData = this.props.data.map(({month, value}) => ({ + x: parseTime(month), + y: parseFloat(value) / 1000, + })); + + const xExtent = d3.extent(plotData, ({x}) => x); + const yExtent = d3.extent(plotData, ({y}) => y); + + yExtent[1] += 0.15 * (yExtent[1] - yExtent[0]); + + const xScale = d3 + .scaleTime() + .domain(xExtent) + .range([0, width]); + + const yScale = d3 + .scaleLinear() + .domain(yExtent) + .range([height, 0]); + + // Line generator. + const line = d3.line() + .x(({x}) => xScale(x)) + .y(({y}) => yScale(y)) + .curve(d3.curveMonotoneX); + + const yAxis = d3 + .axisLeft(yScale) + .tickSizeOuter(0) + .tickSizeInner(-width); + + const xAxis = d3.axisBottom(xScale) + .tickFormat(d3.timeFormat("%m/%Y")); + + return + {this.props.yLabel} + {this.props.xLabel} + + + + + + ; + } +} + +class Axis extends React.Component { + static propTypes = { + h: PropTypes.number, + axis: PropTypes.func, + axisType: PropTypes.oneOf(['x','y']) + }; + + componentDidUpdate() { + this.renderAxis(); + } + + componentDidMount() { + this.renderAxis(); + } + + renderAxis() { + const node = ReactDOM.findDOMNode(this); + d3.select(node).call(this.props.axis); + } + + render() { + const translate = "translate(0,"+(this.props.h)+")"; + + return ( + + ); + } +} + +export default LineChart; \ No newline at end of file diff --git a/client/src/components/Donut.css b/client/src/components/charts/css/Donut.css similarity index 100% rename from client/src/components/Donut.css rename to client/src/components/charts/css/Donut.css diff --git a/client/src/components/charts/index.js b/client/src/components/charts/index.js new file mode 100644 index 0000000..b7a1a21 --- /dev/null +++ b/client/src/components/charts/index.js @@ -0,0 +1,9 @@ +import LineChart from "./LineChart"; +import BarChart from "./BarChart"; +import Donut from "./Donut"; + +export default { + LineChart, + Donut, + BarChart, +}; \ No newline at end of file diff --git a/client/src/components/propertysale/AverageSurfacePrice.js b/client/src/components/propertysale/AverageSurfacePrice.js new file mode 100644 index 0000000..918ed8d --- /dev/null +++ b/client/src/components/propertysale/AverageSurfacePrice.js @@ -0,0 +1,61 @@ +import React from "react"; +import { connect } from "react-redux"; +import PropTypes from "prop-types"; + +import LineChart from "../charts/LineChart"; + +import * as actions from "../../actions/propertysale/average_surface_price"; + +class AverageSurfacePrice extends React.Component { + static propTypes = { + error: PropTypes.string, + loading: PropTypes.bool.isRequired, + data: PropTypes.array, + fetch_data: PropTypes.func.isRequired, + }; + + componentDidMount() { + this.props.fetch_data(); + } + + render() { + return
+

Evolution du prix du m² moyen

+ { + this.props.error && +

{this.props.error}

+ } + { + this.props.loading ? +

Chargement...

+ : + + } +
; + } +} + +const mapStateToProps = state => { + const { + propertysale: { + averageSurfacePrice: { + data, + loading, + error, + } = {}, + } = {}, + } = state; + + return { data, loading, error }; +} + +const mapDispatchToProps = dispatch => ({ + fetch_data: () => dispatch(actions.fetch_data()), +}); + +export default connect(mapStateToProps, mapDispatchToProps)(AverageSurfacePrice); \ No newline at end of file diff --git a/client/src/components/propertysale/Create.js b/client/src/components/propertysale/Create.js deleted file mode 100644 index 24a4e14..0000000 --- a/client/src/components/propertysale/Create.js +++ /dev/null @@ -1,64 +0,0 @@ -import React, { Component } from 'react'; -import { connect } from 'react-redux'; -import { Link, Redirect } from 'react-router-dom'; -import PropTypes from 'prop-types'; -import Form from './Form'; -import { create, reset } from '../../actions/propertysale/create'; - -class Create extends Component { - static propTypes = { - error: PropTypes.string, - loading: PropTypes.bool.isRequired, - created: PropTypes.object, - create: PropTypes.func.isRequired, - reset: PropTypes.func.isRequired - }; - - componentWillUnmount() { - this.props.reset(); - } - - render() { - if (this.props.created) - return ( - - ); - - return ( -
-

New PropertySale

- - {this.props.loading && ( -
- Loading... -
- )} - {this.props.error && ( -
-
- )} - - - - Back to list - -
- ); - } -} - -const mapStateToProps = state => { - const { created, error, loading } = state.propertysale.create; - return { created, error, loading }; -}; - -const mapDispatchToProps = dispatch => ({ - create: values => dispatch(create(values)), - reset: () => dispatch(reset()) -}); - -export default connect(mapStateToProps, mapDispatchToProps)(Create); diff --git a/client/src/components/propertysale/Form.js b/client/src/components/propertysale/Form.js deleted file mode 100644 index 2bf266c..0000000 --- a/client/src/components/propertysale/Form.js +++ /dev/null @@ -1,98 +0,0 @@ -import React, { Component } from 'react'; -import { Field, reduxForm } from 'redux-form'; -import PropTypes from 'prop-types'; - -class Form extends Component { - static propTypes = { - handleSubmit: PropTypes.func.isRequired, - error: PropTypes.string - }; - - renderField = data => { - data.input.className = 'form-control'; - - const isInvalid = data.meta.touched && !!data.meta.error; - if (isInvalid) { - data.input.className += ' is-invalid'; - data.input['aria-invalid'] = true; - } - - if (this.props.error && data.meta.touched && !data.meta.error) { - data.input.className += ' is-valid'; - } - - return ( -
- - - {isInvalid &&
{data.meta.error}
} -
- ); - }; - - render() { - return ( - - parseFloat(v)} - /> - parseFloat(v)} - /> - - - - - - - ); - } -} - -export default reduxForm({ - form: 'propertysale', - enableReinitialize: true, - keepDirtyOnReinitialize: true -})(Form); diff --git a/client/src/components/propertysale/List.js b/client/src/components/propertysale/List.js deleted file mode 100644 index 6d4ae87..0000000 --- a/client/src/components/propertysale/List.js +++ /dev/null @@ -1,180 +0,0 @@ -import React, { Component } from 'react'; -import { connect } from 'react-redux'; -import { Link } from 'react-router-dom'; -import PropTypes from 'prop-types'; -import { list, reset } from '../../actions/propertysale/list'; - -class List extends Component { - static propTypes = { - retrieved: PropTypes.object, - loading: PropTypes.bool.isRequired, - error: PropTypes.string, - eventSource: PropTypes.instanceOf(EventSource), - deletedItem: PropTypes.object, - list: PropTypes.func.isRequired, - reset: PropTypes.func.isRequired - }; - - componentDidMount() { - this.props.list( - this.props.match.params.page && - decodeURIComponent(this.props.match.params.page) - ); - } - - componentWillReceiveProps(nextProps) { - if (this.props.match.params.page !== nextProps.match.params.page) - nextProps.list( - nextProps.match.params.page && - decodeURIComponent(nextProps.match.params.page) - ); - } - - componentWillUnmount() { - this.props.reset(this.props.eventSource); - } - - render() { - return ( -
-

PropertySale List

- - {this.props.loading && ( -
Loading...
- )} - {this.props.deletedItem && ( -
- {this.props.deletedItem['@id']} deleted. -
- )} - {this.props.error && ( -
{this.props.error}
- )} - -

- - Create - -

- - - - - - - - - - - - - - {this.props.retrieved && - this.props.retrieved['hydra:member'].map(item => ( - - - - - - - - - - - ))} - -
idpricesurfacedatedepartmentregion -
- - {item['@id']} - - {item['price']}{item['surface']}{item['date']}{item['department']}{item['region']} - - - -
- - {this.pagination()} -
- ); - } - - pagination() { - const view = this.props.retrieved && this.props.retrieved['hydra:view']; - if (!view) return; - - const { - 'hydra:first': first, - 'hydra:previous': previous, - 'hydra:next': next, - 'hydra:last': last - } = view; - - return ( - - ); - } - - renderLinks = (type, items) => { - if (Array.isArray(items)) { - return items.map((item, i) => ( -
{this.renderLinks(type, item)}
- )); - } - - return ( - {items} - ); - }; -} - -const mapStateToProps = state => { - const { - retrieved, - loading, - error, - eventSource, - deletedItem - } = state.propertysale.list; - return { retrieved, loading, error, eventSource, deletedItem }; -}; - -const mapDispatchToProps = dispatch => ({ - list: page => dispatch(list(page)), - reset: eventSource => dispatch(reset(eventSource)) -}); - -export default connect(mapStateToProps, mapDispatchToProps)(List); diff --git a/client/src/components/propertysale/SalesByRegions.js b/client/src/components/propertysale/SalesByRegions.js new file mode 100644 index 0000000..c9004e6 --- /dev/null +++ b/client/src/components/propertysale/SalesByRegions.js @@ -0,0 +1,69 @@ +import React from "react"; +import { connect } from "react-redux"; +import PropTypes from "prop-types"; + +import Donut from "../charts/Donut"; + +import * as actions from "../../actions/propertysale/sales_by_regions"; + +class SalesByRegions extends React.Component { + static propTypes = { + error: PropTypes.string, + loading: PropTypes.bool.isRequired, + data: PropTypes.array, + fetch_data: PropTypes.func.isRequired, + }; + + componentDidMount() { + this.props.fetch_data(this.props.year); + } + + render() { + return
+

Evolution du prix du m² moyen

+ { + this.props.error && +

{this.props.error}

+ } + + { + this.props.loading ? +

Chargement...

+ : + + + } +
; + } +} + +const mapStateToProps = state => { + const { + propertysale: { + salesByRegions: { + year = 2015, + data = [], + loading = false, + error, + } = {}, + } = {}, + } = state; + + return { year, data, loading, error }; +} + +const mapDispatchToProps = dispatch => ({ + fetch_data: (year) => dispatch(actions.fetch_data(year)), +}); + +export default connect(mapStateToProps, mapDispatchToProps)(SalesByRegions); \ No newline at end of file diff --git a/client/src/components/propertysale/Show.js b/client/src/components/propertysale/Show.js deleted file mode 100644 index 10b3d74..0000000 --- a/client/src/components/propertysale/Show.js +++ /dev/null @@ -1,140 +0,0 @@ -import React, { Component } from 'react'; -import { connect } from 'react-redux'; -import { Link, Redirect } from 'react-router-dom'; -import PropTypes from 'prop-types'; -import { retrieve, reset } from '../../actions/propertysale/show'; -import { del } from '../../actions/propertysale/delete'; - -class Show extends Component { - static propTypes = { - retrieved: PropTypes.object, - loading: PropTypes.bool.isRequired, - error: PropTypes.string, - eventSource: PropTypes.instanceOf(EventSource), - retrieve: PropTypes.func.isRequired, - reset: PropTypes.func.isRequired, - deleteError: PropTypes.string, - deleteLoading: PropTypes.bool.isRequired, - deleted: PropTypes.object, - del: PropTypes.func.isRequired - }; - - componentDidMount() { - this.props.retrieve(decodeURIComponent(this.props.match.params.id)); - } - - componentWillUnmount() { - this.props.reset(this.props.eventSource); - } - - del = () => { - if (window.confirm('Are you sure you want to delete this item?')) - this.props.del(this.props.retrieved); - }; - - render() { - if (this.props.deleted) return ; - - const item = this.props.retrieved; - - return ( -
-

Show {item && item['@id']}

- - {this.props.loading && ( -
- Loading... -
- )} - {this.props.error && ( -
-
- )} - {this.props.deleteError && ( -
-
- )} - - {item && ( - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
FieldValue
price{item['price']}
surface{item['surface']}
date{item['date']}
department{item['department']}
region{item['region']}
- )} - - Back to list - - {item && ( - - - - )} - -
- ); - } - - renderLinks = (type, items) => { - if (Array.isArray(items)) { - return items.map((item, i) => ( -
{this.renderLinks(type, item)}
- )); - } - - return ( - - {items} - - ); - }; -} - -const mapStateToProps = state => ({ - retrieved: state.propertysale.show.retrieved, - error: state.propertysale.show.error, - loading: state.propertysale.show.loading, - eventSource: state.propertysale.show.eventSource, - deleteError: state.propertysale.del.error, - deleteLoading: state.propertysale.del.loading, - deleted: state.propertysale.del.deleted -}); - -const mapDispatchToProps = dispatch => ({ - retrieve: id => dispatch(retrieve(id)), - del: item => dispatch(del(item)), - reset: eventSource => dispatch(reset(eventSource)) -}); - -export default connect(mapStateToProps, mapDispatchToProps)(Show); diff --git a/client/src/components/propertysale/Update.js b/client/src/components/propertysale/Update.js deleted file mode 100644 index 9c04a2b..0000000 --- a/client/src/components/propertysale/Update.js +++ /dev/null @@ -1,123 +0,0 @@ -import React, { Component } from 'react'; -import { connect } from 'react-redux'; -import { Link, Redirect } from 'react-router-dom'; -import PropTypes from 'prop-types'; -import Form from './Form'; -import { retrieve, update, reset } from '../../actions/propertysale/update'; -import { del } from '../../actions/propertysale/delete'; - -class Update extends Component { - static propTypes = { - retrieved: PropTypes.object, - retrieveLoading: PropTypes.bool.isRequired, - retrieveError: PropTypes.string, - updateLoading: PropTypes.bool.isRequired, - updateError: PropTypes.string, - deleteLoading: PropTypes.bool.isRequired, - deleteError: PropTypes.string, - updated: PropTypes.object, - deleted: PropTypes.object, - eventSource: PropTypes.instanceOf(EventSource), - retrieve: PropTypes.func.isRequired, - update: PropTypes.func.isRequired, - del: PropTypes.func.isRequired, - reset: PropTypes.func.isRequired - }; - - componentDidMount() { - this.props.retrieve(decodeURIComponent(this.props.match.params.id)); - } - - componentWillUnmount() { - this.props.reset(this.props.eventSource); - } - - del = () => { - if (window.confirm('Are you sure you want to delete this item?')) - this.props.del(this.props.retrieved); - }; - - render() { - if (this.props.deleted) return ; - - const item = this.props.updated ? this.props.updated : this.props.retrieved; - - return ( -
-

Edit {item && item['@id']}

- - {this.props.created && ( -
- {this.props.created['@id']} created. -
- )} - {this.props.updated && ( -
- {this.props.updated['@id']} updated. -
- )} - {(this.props.retrieveLoading || - this.props.updateLoading || - this.props.deleteLoading) && ( -
- Loading... -
- )} - {this.props.retrieveError && ( -
-
- )} - {this.props.updateError && ( -
-
- )} - {this.props.deleteError && ( -
-
- )} - - {item && ( -
this.props.update(item, values)} - initialValues={item} - /> - )} - - Back to list - - -
- ); - } -} - -const mapStateToProps = state => ({ - retrieved: state.propertysale.update.retrieved, - retrieveError: state.propertysale.update.retrieveError, - retrieveLoading: state.propertysale.update.retrieveLoading, - updateError: state.propertysale.update.updateError, - updateLoading: state.propertysale.update.updateLoading, - deleteError: state.propertysale.del.error, - deleteLoading: state.propertysale.del.loading, - eventSource: state.propertysale.update.eventSource, - created: state.propertysale.create.created, - deleted: state.propertysale.del.deleted, - updated: state.propertysale.update.updated -}); - -const mapDispatchToProps = dispatch => ({ - retrieve: id => dispatch(retrieve(id)), - update: (item, values) => dispatch(update(item, values)), - del: item => dispatch(del(item)), - reset: eventSource => dispatch(reset(eventSource)) -}); - -export default connect(mapStateToProps, mapDispatchToProps)(Update); diff --git a/client/src/components/propertysale/index.js b/client/src/components/propertysale/index.js index e936e55..6b9d14b 100644 --- a/client/src/components/propertysale/index.js +++ b/client/src/components/propertysale/index.js @@ -1,6 +1,4 @@ -import Create from './Create'; -import List from './List'; -import Update from './Update'; -import Show from './Show'; +import AverageSurfacePrice from "./AverageSurfacePrice"; +import SalesByRegions from "./SalesByRegions"; -export { Create, List, Update, Show }; +export { AverageSurfacePrice, SalesByRegions }; diff --git a/client/src/components/review/Create.js b/client/src/components/review/Create.js deleted file mode 100644 index b5a7330..0000000 --- a/client/src/components/review/Create.js +++ /dev/null @@ -1,64 +0,0 @@ -import React, { Component } from 'react'; -import { connect } from 'react-redux'; -import { Link, Redirect } from 'react-router-dom'; -import PropTypes from 'prop-types'; -import Form from './Form'; -import { create, reset } from '../../actions/review/create'; - -class Create extends Component { - static propTypes = { - error: PropTypes.string, - loading: PropTypes.bool.isRequired, - created: PropTypes.object, - create: PropTypes.func.isRequired, - reset: PropTypes.func.isRequired - }; - - componentWillUnmount() { - this.props.reset(); - } - - render() { - if (this.props.created) - return ( - - ); - - return ( -
-

New Review

- - {this.props.loading && ( -
- Loading... -
- )} - {this.props.error && ( -
-
- )} - - - - Back to list - -
- ); - } -} - -const mapStateToProps = state => { - const { created, error, loading } = state.review.create; - return { created, error, loading }; -}; - -const mapDispatchToProps = dispatch => ({ - create: values => dispatch(create(values)), - reset: () => dispatch(reset()) -}); - -export default connect(mapStateToProps, mapDispatchToProps)(Create); diff --git a/client/src/components/review/Form.js b/client/src/components/review/Form.js deleted file mode 100644 index 304121a..0000000 --- a/client/src/components/review/Form.js +++ /dev/null @@ -1,96 +0,0 @@ -import React, { Component } from 'react'; -import { Field, reduxForm } from 'redux-form'; -import PropTypes from 'prop-types'; - -class Form extends Component { - static propTypes = { - handleSubmit: PropTypes.func.isRequired, - error: PropTypes.string - }; - - renderField = data => { - data.input.className = 'form-control'; - - const isInvalid = data.meta.touched && !!data.meta.error; - if (isInvalid) { - data.input.className += ' is-invalid'; - data.input['aria-invalid'] = true; - } - - if (this.props.error && data.meta.touched && !data.meta.error) { - data.input.className += ' is-valid'; - } - - return ( -
- - - {isInvalid &&
{data.meta.error}
} -
- ); - }; - - render() { - return ( - - parseFloat(v)} - /> - - - - - - - - ); - } -} - -export default reduxForm({ - form: 'review', - enableReinitialize: true, - keepDirtyOnReinitialize: true -})(Form); diff --git a/client/src/components/review/List.js b/client/src/components/review/List.js deleted file mode 100644 index 0e20cda..0000000 --- a/client/src/components/review/List.js +++ /dev/null @@ -1,180 +0,0 @@ -import React, { Component } from 'react'; -import { connect } from 'react-redux'; -import { Link } from 'react-router-dom'; -import PropTypes from 'prop-types'; -import { list, reset } from '../../actions/review/list'; - -class List extends Component { - static propTypes = { - retrieved: PropTypes.object, - loading: PropTypes.bool.isRequired, - error: PropTypes.string, - eventSource: PropTypes.instanceOf(EventSource), - deletedItem: PropTypes.object, - list: PropTypes.func.isRequired, - reset: PropTypes.func.isRequired - }; - - componentDidMount() { - this.props.list( - this.props.match.params.page && - decodeURIComponent(this.props.match.params.page) - ); - } - - componentWillReceiveProps(nextProps) { - if (this.props.match.params.page !== nextProps.match.params.page) - nextProps.list( - nextProps.match.params.page && - decodeURIComponent(nextProps.match.params.page) - ); - } - - componentWillUnmount() { - this.props.reset(this.props.eventSource); - } - - render() { - return ( -
-

Review List

- - {this.props.loading && ( -
Loading...
- )} - {this.props.deletedItem && ( -
- {this.props.deletedItem['@id']} deleted. -
- )} - {this.props.error && ( -
{this.props.error}
- )} - -

- - Create - -

- - - - - - - - - - - - - - {this.props.retrieved && - this.props.retrieved['hydra:member'].map(item => ( - - - - - - - - - - - ))} - -
idratingbodyauthorpublicationDatebook -
- - {item['@id']} - - {item['rating']}{item['body']}{item['author']}{item['publicationDate']}{this.renderLinks('books', item['book'])} - - - -
- - {this.pagination()} -
- ); - } - - pagination() { - const view = this.props.retrieved && this.props.retrieved['hydra:view']; - if (!view) return; - - const { - 'hydra:first': first, - 'hydra:previous': previous, - 'hydra:next': next, - 'hydra:last': last - } = view; - - return ( - - ); - } - - renderLinks = (type, items) => { - if (Array.isArray(items)) { - return items.map((item, i) => ( -
{this.renderLinks(type, item)}
- )); - } - - return ( - {items} - ); - }; -} - -const mapStateToProps = state => { - const { - retrieved, - loading, - error, - eventSource, - deletedItem - } = state.review.list; - return { retrieved, loading, error, eventSource, deletedItem }; -}; - -const mapDispatchToProps = dispatch => ({ - list: page => dispatch(list(page)), - reset: eventSource => dispatch(reset(eventSource)) -}); - -export default connect(mapStateToProps, mapDispatchToProps)(List); diff --git a/client/src/components/review/Show.js b/client/src/components/review/Show.js deleted file mode 100644 index 919d2ee..0000000 --- a/client/src/components/review/Show.js +++ /dev/null @@ -1,140 +0,0 @@ -import React, { Component } from 'react'; -import { connect } from 'react-redux'; -import { Link, Redirect } from 'react-router-dom'; -import PropTypes from 'prop-types'; -import { retrieve, reset } from '../../actions/review/show'; -import { del } from '../../actions/review/delete'; - -class Show extends Component { - static propTypes = { - retrieved: PropTypes.object, - loading: PropTypes.bool.isRequired, - error: PropTypes.string, - eventSource: PropTypes.instanceOf(EventSource), - retrieve: PropTypes.func.isRequired, - reset: PropTypes.func.isRequired, - deleteError: PropTypes.string, - deleteLoading: PropTypes.bool.isRequired, - deleted: PropTypes.object, - del: PropTypes.func.isRequired - }; - - componentDidMount() { - this.props.retrieve(decodeURIComponent(this.props.match.params.id)); - } - - componentWillUnmount() { - this.props.reset(this.props.eventSource); - } - - del = () => { - if (window.confirm('Are you sure you want to delete this item?')) - this.props.del(this.props.retrieved); - }; - - render() { - if (this.props.deleted) return ; - - const item = this.props.retrieved; - - return ( -
-

Show {item && item['@id']}

- - {this.props.loading && ( -
- Loading... -
- )} - {this.props.error && ( -
-
- )} - {this.props.deleteError && ( -
-
- )} - - {item && ( - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
FieldValue
rating{item['rating']}
body{item['body']}
author{item['author']}
publicationDate{item['publicationDate']}
book{this.renderLinks('books', item['book'])}
- )} - - Back to list - - {item && ( - - - - )} - -
- ); - } - - renderLinks = (type, items) => { - if (Array.isArray(items)) { - return items.map((item, i) => ( -
{this.renderLinks(type, item)}
- )); - } - - return ( - - {items} - - ); - }; -} - -const mapStateToProps = state => ({ - retrieved: state.review.show.retrieved, - error: state.review.show.error, - loading: state.review.show.loading, - eventSource: state.review.show.eventSource, - deleteError: state.review.del.error, - deleteLoading: state.review.del.loading, - deleted: state.review.del.deleted -}); - -const mapDispatchToProps = dispatch => ({ - retrieve: id => dispatch(retrieve(id)), - del: item => dispatch(del(item)), - reset: eventSource => dispatch(reset(eventSource)) -}); - -export default connect(mapStateToProps, mapDispatchToProps)(Show); diff --git a/client/src/components/review/Update.js b/client/src/components/review/Update.js deleted file mode 100644 index d6a3862..0000000 --- a/client/src/components/review/Update.js +++ /dev/null @@ -1,123 +0,0 @@ -import React, { Component } from 'react'; -import { connect } from 'react-redux'; -import { Link, Redirect } from 'react-router-dom'; -import PropTypes from 'prop-types'; -import Form from './Form'; -import { retrieve, update, reset } from '../../actions/review/update'; -import { del } from '../../actions/review/delete'; - -class Update extends Component { - static propTypes = { - retrieved: PropTypes.object, - retrieveLoading: PropTypes.bool.isRequired, - retrieveError: PropTypes.string, - updateLoading: PropTypes.bool.isRequired, - updateError: PropTypes.string, - deleteLoading: PropTypes.bool.isRequired, - deleteError: PropTypes.string, - updated: PropTypes.object, - deleted: PropTypes.object, - eventSource: PropTypes.instanceOf(EventSource), - retrieve: PropTypes.func.isRequired, - update: PropTypes.func.isRequired, - del: PropTypes.func.isRequired, - reset: PropTypes.func.isRequired - }; - - componentDidMount() { - this.props.retrieve(decodeURIComponent(this.props.match.params.id)); - } - - componentWillUnmount() { - this.props.reset(this.props.eventSource); - } - - del = () => { - if (window.confirm('Are you sure you want to delete this item?')) - this.props.del(this.props.retrieved); - }; - - render() { - if (this.props.deleted) return ; - - const item = this.props.updated ? this.props.updated : this.props.retrieved; - - return ( -
-

Edit {item && item['@id']}

- - {this.props.created && ( -
- {this.props.created['@id']} created. -
- )} - {this.props.updated && ( -
- {this.props.updated['@id']} updated. -
- )} - {(this.props.retrieveLoading || - this.props.updateLoading || - this.props.deleteLoading) && ( -
- Loading... -
- )} - {this.props.retrieveError && ( -
-
- )} - {this.props.updateError && ( -
-
- )} - {this.props.deleteError && ( -
-
- )} - - {item && ( -
this.props.update(item, values)} - initialValues={item} - /> - )} - - Back to list - - -
- ); - } -} - -const mapStateToProps = state => ({ - retrieved: state.review.update.retrieved, - retrieveError: state.review.update.retrieveError, - retrieveLoading: state.review.update.retrieveLoading, - updateError: state.review.update.updateError, - updateLoading: state.review.update.updateLoading, - deleteError: state.review.del.error, - deleteLoading: state.review.del.loading, - eventSource: state.review.update.eventSource, - created: state.review.create.created, - deleted: state.review.del.deleted, - updated: state.review.update.updated -}); - -const mapDispatchToProps = dispatch => ({ - retrieve: id => dispatch(retrieve(id)), - update: (item, values) => dispatch(update(item, values)), - del: item => dispatch(del(item)), - reset: eventSource => dispatch(reset(eventSource)) -}); - -export default connect(mapStateToProps, mapDispatchToProps)(Update); diff --git a/client/src/components/review/index.js b/client/src/components/review/index.js deleted file mode 100644 index e936e55..0000000 --- a/client/src/components/review/index.js +++ /dev/null @@ -1,6 +0,0 @@ -import Create from './Create'; -import List from './List'; -import Update from './Update'; -import Show from './Show'; - -export { Create, List, Update, Show }; diff --git a/client/src/homepage.js b/client/src/homepage.js index 2b6b5df..f9b7535 100644 --- a/client/src/homepage.js +++ b/client/src/homepage.js @@ -6,6 +6,16 @@ const homepage = () => (