From c748ae6ce2a0e64160f5ca017385a638b2e9a832 Mon Sep 17 00:00:00 2001 From: Divyanshi Singh Date: Apr 02 2021 08:38:21 +0000 Subject: [PATCH 1/7] redux toolkit store configuration implemented --- diff --git a/package.json b/package.json index 20d0779..fab2975 100644 --- a/package.json +++ b/package.json @@ -4,6 +4,7 @@ "private": true, "homepage": ".", "dependencies": { + "@reduxjs/toolkit": "^1.5.1", "bootstrap": "^4.4.1", "dateformat": "^3.0.3", "react": "^16.5.2", diff --git a/src/configureStore.js b/src/configureStore.js new file mode 100644 index 0000000..2252549 --- /dev/null +++ b/src/configureStore.js @@ -0,0 +1,14 @@ +import { configureStore } from '@reduxjs/toolkit'; +import logger from 'redux-logger'; +import thunkMiddleware from 'redux-thunk'; +import reducer from './reducers'; + +export default function configureAppStore(initialState) { + const store = configureStore({ + reducer, + middleware: [ logger,thunkMiddleware], + devTools: process.env.NODE_ENV !== 'production', + initialState, + }) + return store; +} \ No newline at end of file diff --git a/src/index.js b/src/index.js index 35f417c..6a8df27 100644 --- a/src/index.js +++ b/src/index.js @@ -9,17 +9,11 @@ import 'typeface-open-sans' import App from './App'; import * as serviceWorker from './serviceWorker'; -import { createStore, applyMiddleware } from 'redux' -import thunkMiddleware from 'redux-thunk' -import { createLogger } from 'redux-logger' -import { Provider } from 'react-redux' -import reducer from './reducers' +import { Provider } from 'react-redux'; +import configureAppStore from './configureStore'; +import { defaultState } from './reducers'; -const loggerMiddleware = createLogger(); -const store = createStore(reducer, applyMiddleware( - thunkMiddleware, - loggerMiddleware -)); +const store= configureAppStore(defaultState); ReactDOM.render( diff --git a/src/reducers/index.js b/src/reducers/index.js index 5e628e0..4dfe6f1 100644 --- a/src/reducers/index.js +++ b/src/reducers/index.js @@ -1,6 +1,6 @@ import ActionTypes from "../constants" -const defaultState = { +export const defaultState = { landing_page: { blockerbugs: {}, devel: 0, diff --git a/yarn.lock b/yarn.lock index 85bfaa4..626a2c7 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1359,6 +1359,16 @@ resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-1.1.3.tgz#2b5a3ab3f918cca48a8c754c08168e3f03eba61b" integrity sha512-shAmDyaQC4H92APFoIaVDHCx5bStIocgvbwQyxPRrbUY20V1EYTbSDchWbuwlMG3V17cprZhA6+78JfB+3DTPw== +"@reduxjs/toolkit@^1.5.1": + version "1.5.1" + resolved "https://registry.yarnpkg.com/@reduxjs/toolkit/-/toolkit-1.5.1.tgz#05daa2f6eebc70dc18cd98a90421fab7fa565dc5" + integrity sha512-PngZKuwVZsd+mimnmhiOQzoD0FiMjqVks6ituO1//Ft5UEX5Ca9of13NEjo//pU22Jk7z/mdXVsmDfgsig1osA== + dependencies: + immer "^8.0.1" + redux "^4.0.0" + redux-thunk "^2.3.0" + reselect "^4.0.0" + "@svgr/babel-plugin-add-jsx-attribute@^4.2.0": version "4.2.0" resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-add-jsx-attribute/-/babel-plugin-add-jsx-attribute-4.2.0.tgz#dadcb6218503532d6884b210e7f3c502caaa44b1" @@ -5236,6 +5246,11 @@ immer@1.10.0: resolved "https://registry.yarnpkg.com/immer/-/immer-1.10.0.tgz#bad67605ba9c810275d91e1c2a47d4582e98286d" integrity sha512-O3sR1/opvCDGLEVcvrGTMtLac8GJ5IwZC4puPrLuRj3l7ICKvkmA0vGuU9OW8mV9WIBRnaxp5GJh9IEAaNOoYg== +immer@^8.0.1: + version "8.0.4" + resolved "https://registry.yarnpkg.com/immer/-/immer-8.0.4.tgz#3a21605a4e2dded852fb2afd208ad50969737b7a" + integrity sha512-jMfL18P+/6P6epANRvRk6q8t+3gGhqsJ9EuJ25AXE+9bNTYtssvzeYbEd0mXRYWCmmXSIbnlpz6vd6iJlmGGGQ== + import-cwd@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/import-cwd/-/import-cwd-2.1.0.tgz#aa6cf36e722761285cb371ec6519f53e2435b0a9" @@ -8837,7 +8852,7 @@ redux-thunk@^2.3.0: resolved "https://registry.yarnpkg.com/redux-thunk/-/redux-thunk-2.3.0.tgz#51c2c19a185ed5187aaa9a2d08b666d0d6467622" integrity sha512-km6dclyFnmcvxhAcrQV2AkZmPQjzPDjgVlQtR0EQjxZPyJ0BnMf3in1ryuR8A2qU0HldVRfxYXbFSKlI3N7Slw== -redux@^4.0.5: +redux@^4.0.0, redux@^4.0.5: version "4.0.5" resolved "https://registry.yarnpkg.com/redux/-/redux-4.0.5.tgz#4db5de5816e17891de8a80c424232d06f051d93f" integrity sha512-VSz1uMAH24DM6MF72vcojpYPtrTUu3ByVWfPL1nPfVRb5mZVTve5GnNCUV53QM/BZ66xfWrm0CTWoM+Xlz8V1w== @@ -9017,6 +9032,11 @@ requires-port@^1.0.0: resolved "https://registry.yarnpkg.com/requires-port/-/requires-port-1.0.0.tgz#925d2601d39ac485e091cf0da5c6e694dc3dcaff" integrity sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8= +reselect@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/reselect/-/reselect-4.0.0.tgz#f2529830e5d3d0e021408b246a206ef4ea4437f7" + integrity sha512-qUgANli03jjAyGlnbYVAV5vvnOmJnODyABz51RdBN7M4WaVu8mecZWgyQNkG8Yqe3KRGRt0l4K4B3XVEULC4CA== + resolve-cwd@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/resolve-cwd/-/resolve-cwd-2.0.0.tgz#00a9f7387556e27038eae232caa372a6a59b665a" From 8ac698fda28cb19aef47004023409ecd240cc3c9 Mon Sep 17 00:00:00 2001 From: Divyanshi Singh Date: Apr 02 2021 10:28:33 +0000 Subject: [PATCH 2/7] redux-toolkit: reducer splitting, actions implementation --- diff --git a/src/actions/reduxActions.js b/src/actions/reduxActions.js index 80a3461..306bca1 100644 --- a/src/actions/reduxActions.js +++ b/src/actions/reduxActions.js @@ -1,15 +1,8 @@ -import ActionTypes from '../constants'; +import { loadData, loadDataResp } from '../reducers/landingPageSlice'; +import { loadWizardDataResp, loadWizardData } from '../reducers/wizardSlice'; -export const loadDataResp = payload => ({ - type: ActionTypes.LOAD_DATA_RESP, - payload: payload -}) - -export const loadData = payload => dispatch => { - dispatch({ - type: ActionTypes.LOAD_DATA, - payload: payload - }); +export const fetchLandingPageData = (dispatch) => dispatch => { + dispatch(loadData()); fetch(window.env.ORACULUM_API_URL_v1 + "landing_page") .then(blob => blob.json()) @@ -21,17 +14,8 @@ export const loadData = payload => dispatch => { }); } -export const loadWizardDataResp = payload => ({ - type: ActionTypes.LOAD_WIZARD_DATA_RESP, - payload: payload -}) - -export const loadWizardData = payload => dispatch => { - dispatch({ - type: ActionTypes.LOAD_WIZARD_DATA, - payload: payload - }); - +export const fetchWizardData = payload => dispatch => { + dispatch(loadWizardData()) fetch(window.env.ORACULUM_API_URL_v1 + "actions/all") .then(blob => blob.json()) .then(data => { diff --git a/src/configureStore.js b/src/configureStore.js index 2252549..70c6cd6 100644 --- a/src/configureStore.js +++ b/src/configureStore.js @@ -1,7 +1,13 @@ -import { configureStore } from '@reduxjs/toolkit'; +import { configureStore, combineReducers } from '@reduxjs/toolkit'; import logger from 'redux-logger'; import thunkMiddleware from 'redux-thunk'; -import reducer from './reducers'; +import landingPageReducer from './reducers/landingPageSlice'; +import wizardReducer from './reducers/wizardSlice'; + +const reducer = combineReducers({ + landing_page: landingPageReducer, + wizard: wizardReducer +}) export default function configureAppStore(initialState) { const store = configureStore({ diff --git a/src/landingpage/LandingPage.js b/src/landingpage/LandingPage.js index b1bee82..aec079a 100644 --- a/src/landingpage/LandingPage.js +++ b/src/landingpage/LandingPage.js @@ -11,7 +11,7 @@ import Hideable from "./Hideable" import _ from "lodash" import { connect } from "react-redux" -import { loadData } from "../actions/reduxActions" +import { fetchLandingPageData } from "../actions/reduxActions" import Cookies from "universal-cookie" @@ -38,7 +38,7 @@ class LandingPage extends Component { } componentDidMount() { - this.props.dispatch(loadData()) + this.props.dispatch(fetchLandingPageData()) } toggle_config_mode(e) { diff --git a/src/reducers/landingPageSlice.js b/src/reducers/landingPageSlice.js new file mode 100644 index 0000000..d1e2cbb --- /dev/null +++ b/src/reducers/landingPageSlice.js @@ -0,0 +1,28 @@ +import { createSlice } from "@reduxjs/toolkit"; + +const landingPageReducer = createSlice({ + name: "landing_page", + initialState: { + blockerbugs: {}, + devel: 0, + meetings: [], + schedule: [], + last_qa_meeting: {}, + stable: 0, + config_mode: false, + enabled_components: ["events", "blockers", "minutes"], + + loading: false + }, + reducers: { + loadData(state, action) { + if (!state.loading) state.loading = true; + }, + loadDataResp(state, action) { + state.loading = false; + Object.assign(state, { ...action.payload }); + } + } +}); +export const { loadData, loadDataResp } = landingPageReducer.actions; +export default landingPageReducer.reducer; diff --git a/src/reducers/wizardSlice.js b/src/reducers/wizardSlice.js new file mode 100644 index 0000000..f48032b --- /dev/null +++ b/src/reducers/wizardSlice.js @@ -0,0 +1,24 @@ +import { createSlice } from "@reduxjs/toolkit"; + +const wizardReducer = createSlice({ + name: "wizard", + initialState: { + actions: [], + providers: [], + all_actions: [], + + loading: false + }, + reducers: { + loadWizardData(state, action) { + if (!state.loading) state.loading = true; + }, + loadWizardDataResp(state, action) { + state.loading = false; + state.providers = action.payload.providers; + state.all_actions = action.payload.actions; + } + } +}); +export const { loadWizardData, loadWizardDataResp } = wizardReducer.actions; +export default wizardReducer.reducer; diff --git a/src/wizard/Wizard.js b/src/wizard/Wizard.js index a9ecb3e..1b136bd 100644 --- a/src/wizard/Wizard.js +++ b/src/wizard/Wizard.js @@ -6,7 +6,7 @@ import Actions from "./Actions" import { Container, Row } from "reactstrap" import { connect } from "react-redux" -import { loadWizardData } from "../actions/reduxActions" +import { fetchWizardData } from "../actions/reduxActions" class Wizard extends Component { constructor(props) { @@ -26,7 +26,7 @@ class Wizard extends Component { }) }) - this.props.dispatch(loadWizardData()) + this.props.dispatch(fetchWizardData()) } show_actions(actions) { From 042f3e751f7c8f89220c4437ce6716d36f952dcd Mon Sep 17 00:00:00 2001 From: Divyanshi Singh Date: Apr 04 2021 08:18:28 +0000 Subject: [PATCH 3/7] code splitting and project structure modification --- diff --git a/src/App.js b/src/App.js index b782aa0..3f55033 100644 --- a/src/App.js +++ b/src/App.js @@ -4,7 +4,7 @@ import { Route, Switch } from 'react-router'; import { BrowserRouter } from 'react-router-dom' import Wizard from './wizard/Wizard'; -import LandingPage from './landingpage/LandingPage'; +import LandingPage from './Containers/LandingPage'; import NotFound from './NotFound'; diff --git a/src/Components/Blockers/index.js b/src/Components/Blockers/index.js new file mode 100644 index 0000000..3466cab --- /dev/null +++ b/src/Components/Blockers/index.js @@ -0,0 +1,61 @@ +import React, { Component } from "react"; +import { Row } from "reactstrap"; +import SourceLink from "../SourceLinks"; +import Header from "../Header"; +import Table from "../Table"; + +class Blockers extends Component { + constructor(props) { + super(props); + this.state = { blockerbugs: {}, release: 0 }; + } + + render() { + const { data } = this.props; + const tableContentBeta = [ + ["Proposed Blockers", data.beta_blockers_proposed], + ["Accepted Blockers", data.beta_blockers], + ["Proposed FEs", data.beta_fe_proposed], + ["Accepted FEs", data.beta_fe] + ]; + + const tableContentFinal = [ + ["Proposed Blockers", data.final_blockers_proposed], + ["Accepted Blockers", data.final_blockers], + ["Proposed FEs", data.final_fe_proposed], + ["Accepted FEs", data.final_fe] + ]; + if (this.props.data) + return ( +
+
+ + +
+ + + +
+
+ + + + ); + } +} + +export default Blockers; diff --git a/src/Components/EventItems/index.js b/src/Components/EventItems/index.js new file mode 100644 index 0000000..09a6d47 --- /dev/null +++ b/src/Components/EventItems/index.js @@ -0,0 +1,15 @@ +import React from 'react'; + +const EventItems = ({ start, summary, link, info }) => { + return ( +
  • + {start} +
    + + {summary} + +
    +
  • + ); +}; +export default EventItems; diff --git a/src/Components/Events/index.js b/src/Components/Events/index.js new file mode 100644 index 0000000..427e865 --- /dev/null +++ b/src/Components/Events/index.js @@ -0,0 +1,47 @@ +import React, { Component } from "react"; +import dateFormat from "dateformat"; +import Header from "../Header"; +import EventItems from "../EventItems"; + +class Events extends Component { + constructor(props) { + super(props); + this.state = { meetings: [] }; + } + + render() { + const meetings = this.props.data.map(meeting => { + const old = new Date(meeting.start); + var meeting_start = dateFormat( + new Date(old.getTime() - old.getTimezoneOffset() * 60000), + "d mmm yyyy - HH:MM" + ); + if (meeting.fullday) { + meeting_start = meeting_start.slice(0, -5) + "All day"; + } + return ( + + ); + }); + return ( +
    +
    + +
      {meetings}
    +
    + ); + } +} + + + +export default Events; diff --git a/src/Components/Header/index.js b/src/Components/Header/index.js new file mode 100644 index 0000000..b4d9a66 --- /dev/null +++ b/src/Components/Header/index.js @@ -0,0 +1,12 @@ +import React from "react"; +import SourceLink from "../SourceLinks"; + +const Header = ({ headerText, headerLink }) => { + return ( +

    + {headerText} + {headerLink && } +

    + ); +}; +export default Header; diff --git a/src/Components/Hideable/index.js b/src/Components/Hideable/index.js new file mode 100644 index 0000000..aac075a --- /dev/null +++ b/src/Components/Hideable/index.js @@ -0,0 +1,37 @@ +import React, { Component } from "react" +import _ from "lodash" + +class Hideable extends Component { + constructor(props) { + super(props) + this.id = _.uniqueId("hideable-id-") + } + + render() { + if (this.props.component_name === undefined) { + return
    + } + return ( + + ) + } +} + +export default Hideable diff --git a/src/Components/Line/index.js b/src/Components/Line/index.js new file mode 100644 index 0000000..17f4d3e --- /dev/null +++ b/src/Components/Line/index.js @@ -0,0 +1,17 @@ +import React, {Component} from 'react'; + +const Line = ({ color, strokeWidth }) => { + const lineStyle={ + stroke: color, + strokeWidth, + +}; + + return ( + + + + + ); +}; +export default Line; \ No newline at end of file diff --git a/src/Components/Minutes/index.js b/src/Components/Minutes/index.js new file mode 100644 index 0000000..26f7f69 --- /dev/null +++ b/src/Components/Minutes/index.js @@ -0,0 +1,33 @@ +import React, { Component } from "react" +import Header from "../Header"; + +const Minutes = ( props ) => { + + return ( +
    +
    + +
    + + Latest minutes from {props.data.date} + +
    + Visit{" "} + + meetbot + {" "} + to see older. +
    +
    +
    + ) + +} + +export default Minutes; diff --git a/src/Components/SourceLinks/index.js b/src/Components/SourceLinks/index.js new file mode 100644 index 0000000..76cfa0b --- /dev/null +++ b/src/Components/SourceLinks/index.js @@ -0,0 +1,17 @@ +import React, {Component} from 'react' + +class SourceLink extends Component { + render() { + return ( + + + + ) + } +} + +export default SourceLink diff --git a/src/Components/Table/index.js b/src/Components/Table/index.js new file mode 100644 index 0000000..4cec938 --- /dev/null +++ b/src/Components/Table/index.js @@ -0,0 +1,27 @@ +import React from "react"; + +const Table = ({ className, tableHead, tableContent, customClass }) => { + return ( +
    + + + {tableHead.map((item, index) => ( + + ))} + + + + {tableContent.map((columns, i) => ( + + {columns.map(column => ( + + ))} + + ))} + +
    + {item} +
    {column}
    + ); +}; +export default Table; diff --git a/src/Components/Timeline/index.js b/src/Components/Timeline/index.js new file mode 100644 index 0000000..98b19de --- /dev/null +++ b/src/Components/Timeline/index.js @@ -0,0 +1,62 @@ +import React, { Component } from "react" +import SourceLink from '../SourceLinks' +import { get_title } from "./utils"; +import Line from "../Line"; + + +class Timeline extends Component { + constructor(props) { + super(props) + this.state = { schedule: [] } + } + + render() { + const { data } = this.props; + const line = data.map((milestone) => { + return ( + + + + ) + }) + + const dates = data.map((milestone) => { + return ( + + {milestone.date} + + ) + }) + + const schedule = data.map((milestone) => { + return ( + + {milestone.summary} + + ) + }) + return ( +
    +

    + Current development schedule{" "} + +

    +
    + + + {line} + {dates} + {schedule} + +
    +
    +
    + ) + } +} + + +export default Timeline diff --git a/src/Components/Timeline/utils.js b/src/Components/Timeline/utils.js new file mode 100644 index 0000000..e2b25bc --- /dev/null +++ b/src/Components/Timeline/utils.js @@ -0,0 +1,11 @@ +export const get_title = (summary) => { + summary = summary.toLowerCase() + if (summary.includes("freeze")) + return "At the milestone freeze, pushes from the updates-testing to the stable repository are suspended until the release candidate is accepted." + if (summary === "rawhide") + return "Next Fedora release hasn't been branched yet from rolling release branch." + if (summary.includes("branch")) + return "Next version of Fedora that was 'branched' from the rolling Rawhide tree and in the future will become the next stable Fedora release." + if (summary.includes("release")) + return "Release candidate was accepted (violating no milestone criteria) and was released." + } \ No newline at end of file diff --git a/src/Containers/LandingPage/actions.js b/src/Containers/LandingPage/actions.js new file mode 100644 index 0000000..00a0d1c --- /dev/null +++ b/src/Containers/LandingPage/actions.js @@ -0,0 +1,14 @@ +import { loadData, loadDataResp } from "./reducer"; + +export const fetchLandingPageData = (dispatch) => dispatch => { + dispatch(loadData()); + + fetch(window.env.ORACULUM_API_URL_v1 + "landing_page") + .then(blob => blob.json()) + .then(data => { + dispatch(loadDataResp(data)) + }) + .catch((error) => { + console.error('Error:', error); + }); +} \ No newline at end of file diff --git a/src/Containers/LandingPage/index.js b/src/Containers/LandingPage/index.js new file mode 100644 index 0000000..d10d133 --- /dev/null +++ b/src/Containers/LandingPage/index.js @@ -0,0 +1,141 @@ +import React, { Component } from "react" +import { Container, Row } from "reactstrap" +import { Link } from "react-router-dom" +import Layout from "../../layout/Layout" +import Timeline from "../../Components/Timeline" +import Events from "../../Components/Events" +import Blockers from "../../Components/Blockers" +import Minutes from "../../Components/Minutes" +import Hideable from "../../Components/Hideable" + +import _ from "lodash" + +import { connect } from "react-redux" +import { fetchLandingPageData } from "./actions" + +import Cookies from "universal-cookie" + +class LandingPage extends Component { + constructor(props) { + super(props) + this.cookies = new Cookies() + this.available_components = ["events", "blockers", "minutes"] + let enabled_components = this.cookies.get("landingpage_enabled_components") + if (enabled_components === undefined) { + enabled_components = this.available_components.slice() + this.cookies.set("landingpage_enabled_components", enabled_components, { path: "/" }) + } + this.state = { + blockerbugs: {}, + devel: 0, + meetings: [], + schedule: [], + last_qa_meeting: {}, + stable: 0, + config_mode: false, + enabled_components: enabled_components, + } + } + + componentDidMount() { + this.props.dispatch(fetchLandingPageData()) + } + + toggle_config_mode(e) { + let config_mode = !this.state.config_mode + this.setState({ config_mode: config_mode }) + e.preventDefault() + } + + toggle_component_visibility(e, name) { + if (name === undefined) { + e.preventDefault() + return + } + let enabled_components = this.state.enabled_components + if (enabled_components.includes(name)) { + enabled_components.splice(enabled_components.indexOf(name), 1) + } else { + enabled_components.push(name) + enabled_components = this.available_components.filter((c) => enabled_components.includes(c)) + } + this.cookies.set("landingpage_enabled_components", enabled_components, { path: "/" }) + this.setState({ enabled_components: enabled_components }) + e.preventDefault() + } + + render() { + const available_components = { + events: , + blockers: , + minutes: , + } + let components = _.chunk( + this.state.config_mode ? this.available_components : this.state.enabled_components, + 2 + ) + components = components.map((row) => ( + + {row.map((item) => ( +
    + + {available_components[item]} + +
    + ))} +
    + )) + return ( + +
    + + +
    + +
    +
    +
    +
    + + {components} + + + + +
    + + Do you have some spare time? Feeling like helping others? Wanna improve Fedora? + Click here! + +
    +
    +
    +
    + ) + } +} + +const mapStateToProps = (state) => { + return { + ...state.landing_page, + } +} + +export default connect(mapStateToProps)(LandingPage) diff --git a/src/Containers/LandingPage/reducer.js b/src/Containers/LandingPage/reducer.js new file mode 100644 index 0000000..d1e2cbb --- /dev/null +++ b/src/Containers/LandingPage/reducer.js @@ -0,0 +1,28 @@ +import { createSlice } from "@reduxjs/toolkit"; + +const landingPageReducer = createSlice({ + name: "landing_page", + initialState: { + blockerbugs: {}, + devel: 0, + meetings: [], + schedule: [], + last_qa_meeting: {}, + stable: 0, + config_mode: false, + enabled_components: ["events", "blockers", "minutes"], + + loading: false + }, + reducers: { + loadData(state, action) { + if (!state.loading) state.loading = true; + }, + loadDataResp(state, action) { + state.loading = false; + Object.assign(state, { ...action.payload }); + } + } +}); +export const { loadData, loadDataResp } = landingPageReducer.actions; +export default landingPageReducer.reducer; diff --git a/src/actions/reduxActions.js b/src/actions/reduxActions.js index 306bca1..084894f 100644 --- a/src/actions/reduxActions.js +++ b/src/actions/reduxActions.js @@ -1,19 +1,5 @@ -import { loadData, loadDataResp } from '../reducers/landingPageSlice'; import { loadWizardDataResp, loadWizardData } from '../reducers/wizardSlice'; -export const fetchLandingPageData = (dispatch) => dispatch => { - dispatch(loadData()); - - fetch(window.env.ORACULUM_API_URL_v1 + "landing_page") - .then(blob => blob.json()) - .then(data => { - dispatch(loadDataResp(data)) - }) - .catch((error) => { - console.error('Error:', error); - }); -} - export const fetchWizardData = payload => dispatch => { dispatch(loadWizardData()) fetch(window.env.ORACULUM_API_URL_v1 + "actions/all") diff --git a/src/api/api.users.js b/src/api/api.users.js new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/src/api/api.users.js diff --git a/src/configureStore.js b/src/configureStore.js index 70c6cd6..29d33ad 100644 --- a/src/configureStore.js +++ b/src/configureStore.js @@ -1,20 +1,38 @@ -import { configureStore, combineReducers } from '@reduxjs/toolkit'; -import logger from 'redux-logger'; -import thunkMiddleware from 'redux-thunk'; -import landingPageReducer from './reducers/landingPageSlice'; -import wizardReducer from './reducers/wizardSlice'; +import { configureStore, combineReducers } from "@reduxjs/toolkit"; +import logger from "redux-logger"; +import thunkMiddleware from "redux-thunk"; +import landingPageReducer from "./Containers/LandingPage/reducer"; +import wizardReducer from "./reducers/wizardSlice"; + +export const defaultState = { + landing_page: { + blockerbugs: {}, + devel: 0, + meetings: [], + schedule: [], + last_qa_meeting: {}, + stable: 0, + config_mode: false, + enabled_components: ["events", "blockers", "minutes"] + }, + wizard: { + actions: [], + providers: [], + all_actions: [] + } +}; const reducer = combineReducers({ - landing_page: landingPageReducer, - wizard: wizardReducer -}) + landing_page: landingPageReducer, + wizard: wizardReducer +}); export default function configureAppStore(initialState) { - const store = configureStore({ - reducer, - middleware: [ logger,thunkMiddleware], - devTools: process.env.NODE_ENV !== 'production', - initialState, - }) - return store; -} \ No newline at end of file + const store = configureStore({ + reducer, + middleware: [logger, thunkMiddleware], + devTools: process.env.NODE_ENV !== "production", + initialState + }); + return store; +} diff --git a/src/index.css b/src/index.css index 27f6835..7bdb2de 100644 --- a/src/index.css +++ b/src/index.css @@ -82,7 +82,7 @@ h1 { } .bugscount { - padding-left: 2em; + padding-right: 2em; } .smallsuper { diff --git a/src/index.js b/src/index.js index 6a8df27..7bf6062 100644 --- a/src/index.js +++ b/src/index.js @@ -11,7 +11,7 @@ import * as serviceWorker from './serviceWorker'; import { Provider } from 'react-redux'; import configureAppStore from './configureStore'; -import { defaultState } from './reducers'; +import { defaultState } from './configureStore'; const store= configureAppStore(defaultState); diff --git a/src/landingpage/Blockers.js b/src/landingpage/Blockers.js deleted file mode 100644 index 30b923a..0000000 --- a/src/landingpage/Blockers.js +++ /dev/null @@ -1,85 +0,0 @@ -import React, { Component } from "react" -import { Row } from "reactstrap" -import SourceLink from "./SourceLink" - -class Blockers extends Component { - constructor(props) { - super(props) - this.state = { blockerbugs: {}, release: 0 } - } - - render() { - if (this.props.data) - return ( -
    -

    - Fedora {this.props.release} blockers and FEs{" "} - -

    - -
    - - - - - - - - - - - - - - - - - - - - - - - - -
    - Beta -
    Proposed Blockers{this.props.data.beta_blockers_proposed}
    Accepted Blockers{this.props.data.beta_blockers}
    Proposed FEs{this.props.data.beta_fe_proposed}
    Accepted FEs{this.props.data.beta_fe}
    -
    - -
    - - - - - - - - - - - - - - - - - - - - - - - - -
    - Final -
    Proposed Blockers{this.props.data.final_blockers_proposed}
    Accepted Blockers{this.props.data.final_blockers}
    Proposed FEs{this.props.data.final_fe_proposed}
    Accepted FEs{this.props.data.final_fe}
    -
    -
    -
    - ) - } -} - -export default Blockers diff --git a/src/landingpage/Events.js b/src/landingpage/Events.js deleted file mode 100644 index 54eb80b..0000000 --- a/src/landingpage/Events.js +++ /dev/null @@ -1,58 +0,0 @@ -import React, { Component } from "react" -import dateFormat from "dateformat" -import SourceLink from './SourceLink' - -class Events extends Component { - constructor(props) { - super(props) - this.state = { meetings: [] } - } - - render() { - const meetings = this.props.data.map((meeting) => { - const old = new Date(meeting.start) - var meeting_start = dateFormat( - new Date(old.getTime() - old.getTimezoneOffset() * 60000), - "d mmm yyyy - HH:MM" - ) - if (meeting.fullday) { - meeting_start = meeting_start.slice(0, -5) + "All day" - } - return ( - - ) - }) - return ( -
    -

    - Meetings and testdays in the next 7 days{" "} - -

    -
      {meetings}
    -
    - ) - } -} - -class Event extends Component { - render() { - return ( -
  • - {this.props.start} -
    - - {this.props.summary} - -
    -
  • - ) - } -} - -export default Events diff --git a/src/landingpage/Hideable.js b/src/landingpage/Hideable.js deleted file mode 100644 index aac075a..0000000 --- a/src/landingpage/Hideable.js +++ /dev/null @@ -1,37 +0,0 @@ -import React, { Component } from "react" -import _ from "lodash" - -class Hideable extends Component { - constructor(props) { - super(props) - this.id = _.uniqueId("hideable-id-") - } - - render() { - if (this.props.component_name === undefined) { - return
    - } - return ( - - ) - } -} - -export default Hideable diff --git a/src/landingpage/LandingPage.js b/src/landingpage/LandingPage.js deleted file mode 100644 index aec079a..0000000 --- a/src/landingpage/LandingPage.js +++ /dev/null @@ -1,141 +0,0 @@ -import React, { Component } from "react" -import { Container, Row } from "reactstrap" -import { Link } from "react-router-dom" -import Layout from "../layout/Layout" -import Timeline from "./Timeline" -import Events from "./Events" -import Blockers from "./Blockers" -import Minutes from "./Minutes" -import Hideable from "./Hideable" - -import _ from "lodash" - -import { connect } from "react-redux" -import { fetchLandingPageData } from "../actions/reduxActions" - -import Cookies from "universal-cookie" - -class LandingPage extends Component { - constructor(props) { - super(props) - this.cookies = new Cookies() - this.available_components = ["events", "blockers", "minutes"] - let enabled_components = this.cookies.get("landingpage_enabled_components") - if (enabled_components === undefined) { - enabled_components = this.available_components.slice() - this.cookies.set("landingpage_enabled_components", enabled_components, { path: "/" }) - } - this.state = { - blockerbugs: {}, - devel: 0, - meetings: [], - schedule: [], - last_qa_meeting: {}, - stable: 0, - config_mode: false, - enabled_components: enabled_components, - } - } - - componentDidMount() { - this.props.dispatch(fetchLandingPageData()) - } - - toggle_config_mode(e) { - let config_mode = !this.state.config_mode - this.setState({ config_mode: config_mode }) - e.preventDefault() - } - - toggle_component_visibility(e, name) { - if (name === undefined) { - e.preventDefault() - return - } - let enabled_components = this.state.enabled_components - if (enabled_components.includes(name)) { - enabled_components.splice(enabled_components.indexOf(name), 1) - } else { - enabled_components.push(name) - enabled_components = this.available_components.filter((c) => enabled_components.includes(c)) - } - this.cookies.set("landingpage_enabled_components", enabled_components, { path: "/" }) - this.setState({ enabled_components: enabled_components }) - e.preventDefault() - } - - render() { - const available_components = { - events: , - blockers: , - minutes: , - } - let components = _.chunk( - this.state.config_mode ? this.available_components : this.state.enabled_components, - 2 - ) - components = components.map((row) => ( - - {row.map((item) => ( -
    - - {available_components[item]} - -
    - ))} -
    - )) - return ( - -
    - - -
    - -
    -
    -
    -
    - - {components} - - - - -
    - - Do you have some spare time? Feeling like helping others? Wanna improve Fedora? - Click here! - -
    -
    -
    -
    - ) - } -} - -const mapStateToProps = (state) => { - return { - ...state.landing_page, - } -} - -export default connect(mapStateToProps)(LandingPage) diff --git a/src/landingpage/Minutes.js b/src/landingpage/Minutes.js deleted file mode 100644 index 4f88f2b..0000000 --- a/src/landingpage/Minutes.js +++ /dev/null @@ -1,28 +0,0 @@ -import React, { Component } from "react" - -class Events extends Component { - render() { - return ( -
    -

    Fedora QA Meeting Minutes

    -
    - - Latest minutes from {this.props.data.date} - -
    - Visit{" "} - - meetbot - {" "} - to see older. -
    -
    -
    - ) - } -} - -export default Events diff --git a/src/landingpage/SourceLink.js b/src/landingpage/SourceLink.js deleted file mode 100644 index 76cfa0b..0000000 --- a/src/landingpage/SourceLink.js +++ /dev/null @@ -1,17 +0,0 @@ -import React, {Component} from 'react' - -class SourceLink extends Component { - render() { - return ( - - - - ) - } -} - -export default SourceLink diff --git a/src/landingpage/Timeline.js b/src/landingpage/Timeline.js deleted file mode 100644 index 1de10c5..0000000 --- a/src/landingpage/Timeline.js +++ /dev/null @@ -1,84 +0,0 @@ -import React, { Component } from "react" -import SourceLink from './SourceLink' - -class Timeline extends Component { - constructor(props) { - super(props) - this.state = { schedule: [] } - } - - get_title(summary) { - summary = summary.toLowerCase() - if (summary.includes("freeze")) - return "At the milestone freeze, pushes from the updates-testing to the stable repository are suspended until the release candidate is accepted." - if (summary === "rawhide") - return "Next Fedora release hasn't been branched yet from rolling release branch." - if (summary.includes("branch")) - return "Next version of Fedora that was 'branched' from the rolling Rawhide tree and in the future will become the next stable Fedora release." - if (summary.includes("release")) - return "Release candidate was accepted (violating no milestone criteria) and was released." - } - - render() { - const line = this.props.data.map((milestone) => { - return ( - - - - ) - }) - - const dates = this.props.data.map((milestone) => { - return ( - - {milestone.date} - - ) - }) - - const schedule = this.props.data.map((milestone) => { - return ( - - {milestone.summary} - - ) - }) - return ( -
    -

    - Current development schedule{" "} - -

    -
    - - - {line} - {dates} - {schedule} - -
    -
    -
    - ) - } -} - -class Line extends Component { - render() { - const lineStyle = { - stroke: this.props.color, - strokeWidth: "3", - } - return ( - - - - - ) - } -} - -export default Timeline diff --git a/src/reducers/index.js b/src/reducers/index.js deleted file mode 100644 index 4dfe6f1..0000000 --- a/src/reducers/index.js +++ /dev/null @@ -1,44 +0,0 @@ -import ActionTypes from "../constants" - -export const defaultState = { - landing_page: { - blockerbugs: {}, - devel: 0, - meetings: [], - schedule: [], - last_qa_meeting: {}, - stable: 0, - config_mode: false, - enabled_components: ["events", "blockers", "minutes"], - }, - wizard: { - actions: [], - providers: [], - all_actions: [], - }, -} - -export default (state = defaultState, action) => { - switch (action.type) { - case ActionTypes.LOAD_DATA_RESP: - return { - ...state, - landing_page: action.payload, - } - - case ActionTypes.LOAD_WIZARD_DATA_RESP: - return { - ...state, - wizard: { - ...state.wizard, - providers: action.payload.providers, - all_actions: action.payload.actions, - }, - } - - default: - return { - ...state, - } - } -} diff --git a/src/reducers/landingPageSlice.js b/src/reducers/landingPageSlice.js deleted file mode 100644 index d1e2cbb..0000000 --- a/src/reducers/landingPageSlice.js +++ /dev/null @@ -1,28 +0,0 @@ -import { createSlice } from "@reduxjs/toolkit"; - -const landingPageReducer = createSlice({ - name: "landing_page", - initialState: { - blockerbugs: {}, - devel: 0, - meetings: [], - schedule: [], - last_qa_meeting: {}, - stable: 0, - config_mode: false, - enabled_components: ["events", "blockers", "minutes"], - - loading: false - }, - reducers: { - loadData(state, action) { - if (!state.loading) state.loading = true; - }, - loadDataResp(state, action) { - state.loading = false; - Object.assign(state, { ...action.payload }); - } - } -}); -export const { loadData, loadDataResp } = landingPageReducer.actions; -export default landingPageReducer.reducer; From ed8426bec4a732bb2329a60d98c84a5f0e52ff29 Mon Sep 17 00:00:00 2001 From: Divyanshi Singh Date: Apr 04 2021 17:14:19 +0000 Subject: [PATCH 4/7] common api function, http error handling --- diff --git a/src/Containers/LandingPage/actions.js b/src/Containers/LandingPage/actions.js index 00a0d1c..1f4a0aa 100644 --- a/src/Containers/LandingPage/actions.js +++ b/src/Containers/LandingPage/actions.js @@ -1,14 +1,14 @@ import { loadData, loadDataResp } from "./reducer"; +import { fetchAPI } from "../../api/api.common"; -export const fetchLandingPageData = (dispatch) => dispatch => { +export const fetchLandingPageData = () => async dispatch => { dispatch(loadData()); - - fetch(window.env.ORACULUM_API_URL_v1 + "landing_page") - .then(blob => blob.json()) - .then(data => { + try{ + const url = window.env.ORACULUM_API_URL_v1 + "landing_page"; + const data = await fetchAPI(url); dispatch(loadDataResp(data)) - }) - .catch((error) => { - console.error('Error:', error); - }); + } catch(err) { + console.error(err); + } + } \ No newline at end of file diff --git a/src/Errors/HttpApiCallError.js b/src/Errors/HttpApiCallError.js new file mode 100644 index 0000000..14087fe --- /dev/null +++ b/src/Errors/HttpApiCallError.js @@ -0,0 +1,9 @@ +export default class HttpApiCallError extends Error { + constructor(message, statusCode) { + super(message); + this.message = message; + this.statusCode = statusCode; + this.stack = new Error(message).stack; + this.name = 'HttpApiCallError'; + } +} \ No newline at end of file diff --git a/src/api/api.common.js b/src/api/api.common.js new file mode 100644 index 0000000..d40dfa6 --- /dev/null +++ b/src/api/api.common.js @@ -0,0 +1,13 @@ +import HttpApiCallError from "../Errors/HttpApiCallError"; + +export const fetchAPI = async url => { + const response = await fetch(url); + const responseBody = await response.json(); + const isSuccess = response.status === 200; + if ( isSuccess ) { + return responseBody; + } + const error = HttpApiCallError(response.statusText, response.status); + error.response = response; + throw error; +} \ No newline at end of file diff --git a/src/api/api.users.js b/src/api/api.users.js deleted file mode 100644 index e69de29..0000000 --- a/src/api/api.users.js +++ /dev/null From 082ea05fbaf3752d015992a18278af10bb4d0f56 Mon Sep 17 00:00:00 2001 From: Divyanshi Singh Date: Apr 04 2021 17:35:43 +0000 Subject: [PATCH 5/7] wizard component --- diff --git a/src/App.js b/src/App.js index 3f55033..6f9cdb9 100644 --- a/src/App.js +++ b/src/App.js @@ -3,7 +3,7 @@ import React, { Component } from 'react'; import { Route, Switch } from 'react-router'; import { BrowserRouter } from 'react-router-dom' -import Wizard from './wizard/Wizard'; +import Wizard from './Containers/Wizard'; import LandingPage from './Containers/LandingPage'; import NotFound from './NotFound'; diff --git a/src/Containers/Wizard/actions.js b/src/Containers/Wizard/actions.js new file mode 100644 index 0000000..b092d00 --- /dev/null +++ b/src/Containers/Wizard/actions.js @@ -0,0 +1,14 @@ +import { loadWizardDataResp, loadWizardData } from './reducer'; +import { fetchAPI } from '../../api/api.common'; + +export const fetchWizardData = () => async dispatch => { + dispatch(loadWizardData()) + try{ + const url = window.env.ORACULUM_API_URL_v1 + "actions/all"; + const data = await fetchAPI(url); + dispatch(loadWizardDataResp(data)) + } catch(err) { + console.error(err); + } +} + diff --git a/src/Containers/Wizard/index.js b/src/Containers/Wizard/index.js new file mode 100644 index 0000000..4918d34 --- /dev/null +++ b/src/Containers/Wizard/index.js @@ -0,0 +1,71 @@ +import React, { Component } from "react" +import WizardForm from "../../wizard/WizardForm" +import Layout from "../../layout/Layout" +import { oraculumApiUrl_v1 } from "../../config" +import Actions from "../../wizard/Actions" +import { Container, Row } from "reactstrap" + +import { connect } from "react-redux" +import { fetchWizardData } from "./actions" + +class Wizard extends Component { + constructor(props) { + super(props) + this.state = { + actions: [], + } + } + + componentDidMount() { + fetch(oraculumApiUrl_v1 + "actions/all") + .then((resp) => resp.json()) + .then((data) => { + this.setState({ + providers: data.providers, + all_actions: data.actions, + }) + }) + + this.props.dispatch(fetchWizardData()) + } + + show_actions(actions) { + this.setState({ actions }) + } + + render() { + return ( + +
    + + +

    Nothing sparked joy?

    +
    + None of the above looks interesting to you? We'd be happy if you looked around at{" "} + https://whatcanidoforfedora.org/! +
    +
    +
    + + +
    + +
    +
    +
    +
    + ) + } +} + +const mapStateToProps = (state) => { + return { + ...state.wizard, + } +} + +export default connect(mapStateToProps)(Wizard) diff --git a/src/Containers/Wizard/reducer.js b/src/Containers/Wizard/reducer.js new file mode 100644 index 0000000..f48032b --- /dev/null +++ b/src/Containers/Wizard/reducer.js @@ -0,0 +1,24 @@ +import { createSlice } from "@reduxjs/toolkit"; + +const wizardReducer = createSlice({ + name: "wizard", + initialState: { + actions: [], + providers: [], + all_actions: [], + + loading: false + }, + reducers: { + loadWizardData(state, action) { + if (!state.loading) state.loading = true; + }, + loadWizardDataResp(state, action) { + state.loading = false; + state.providers = action.payload.providers; + state.all_actions = action.payload.actions; + } + } +}); +export const { loadWizardData, loadWizardDataResp } = wizardReducer.actions; +export default wizardReducer.reducer; diff --git a/src/actions/reduxActions.js b/src/actions/reduxActions.js deleted file mode 100644 index 084894f..0000000 --- a/src/actions/reduxActions.js +++ /dev/null @@ -1,13 +0,0 @@ -import { loadWizardDataResp, loadWizardData } from '../reducers/wizardSlice'; - -export const fetchWizardData = payload => dispatch => { - dispatch(loadWizardData()) - fetch(window.env.ORACULUM_API_URL_v1 + "actions/all") - .then(blob => blob.json()) - .then(data => { - dispatch(loadWizardDataResp(data)) - }) - .catch((error) => { - console.error('Error:', error); - }); -} diff --git a/src/configureStore.js b/src/configureStore.js index 29d33ad..febe607 100644 --- a/src/configureStore.js +++ b/src/configureStore.js @@ -2,7 +2,7 @@ import { configureStore, combineReducers } from "@reduxjs/toolkit"; import logger from "redux-logger"; import thunkMiddleware from "redux-thunk"; import landingPageReducer from "./Containers/LandingPage/reducer"; -import wizardReducer from "./reducers/wizardSlice"; +import wizardReducer from "./Containers/Wizard/reducer"; export const defaultState = { landing_page: { diff --git a/src/reducers/wizardSlice.js b/src/reducers/wizardSlice.js deleted file mode 100644 index f48032b..0000000 --- a/src/reducers/wizardSlice.js +++ /dev/null @@ -1,24 +0,0 @@ -import { createSlice } from "@reduxjs/toolkit"; - -const wizardReducer = createSlice({ - name: "wizard", - initialState: { - actions: [], - providers: [], - all_actions: [], - - loading: false - }, - reducers: { - loadWizardData(state, action) { - if (!state.loading) state.loading = true; - }, - loadWizardDataResp(state, action) { - state.loading = false; - state.providers = action.payload.providers; - state.all_actions = action.payload.actions; - } - } -}); -export const { loadWizardData, loadWizardDataResp } = wizardReducer.actions; -export default wizardReducer.reducer; diff --git a/src/wizard/Wizard.js b/src/wizard/Wizard.js deleted file mode 100644 index 1b136bd..0000000 --- a/src/wizard/Wizard.js +++ /dev/null @@ -1,71 +0,0 @@ -import React, { Component } from "react" -import WizardForm from "./WizardForm" -import Layout from "../layout/Layout" -import { oraculumApiUrl_v1 } from "../config" -import Actions from "./Actions" -import { Container, Row } from "reactstrap" - -import { connect } from "react-redux" -import { fetchWizardData } from "../actions/reduxActions" - -class Wizard extends Component { - constructor(props) { - super(props) - this.state = { - actions: [], - } - } - - componentDidMount() { - fetch(oraculumApiUrl_v1 + "actions/all") - .then((resp) => resp.json()) - .then((data) => { - this.setState({ - providers: data.providers, - all_actions: data.actions, - }) - }) - - this.props.dispatch(fetchWizardData()) - } - - show_actions(actions) { - this.setState({ actions }) - } - - render() { - return ( - -
    - - -

    Nothing sparked joy?

    -
    - None of the above looks interesting to you? We'd be happy if you looked around at{" "} - https://whatcanidoforfedora.org/! -
    -
    -
    - - -
    - -
    -
    -
    -
    - ) - } -} - -const mapStateToProps = (state) => { - return { - ...state.wizard, - } -} - -export default connect(mapStateToProps)(Wizard) From 8388eaf94d23cd21ce9f3f6eeda3c49c2dbfbab9 Mon Sep 17 00:00:00 2001 From: Divyanshi Singh Date: Apr 07 2021 11:12:40 +0000 Subject: [PATCH 6/7] redux toolkit implemented --- diff --git a/package.json b/package.json index 20d0779..fab2975 100644 --- a/package.json +++ b/package.json @@ -4,6 +4,7 @@ "private": true, "homepage": ".", "dependencies": { + "@reduxjs/toolkit": "^1.5.1", "bootstrap": "^4.4.1", "dateformat": "^3.0.3", "react": "^16.5.2", diff --git a/src/actions/reduxActions.js b/src/actions/reduxActions.js index 80a3461..306bca1 100644 --- a/src/actions/reduxActions.js +++ b/src/actions/reduxActions.js @@ -1,15 +1,8 @@ -import ActionTypes from '../constants'; +import { loadData, loadDataResp } from '../reducers/landingPageSlice'; +import { loadWizardDataResp, loadWizardData } from '../reducers/wizardSlice'; -export const loadDataResp = payload => ({ - type: ActionTypes.LOAD_DATA_RESP, - payload: payload -}) - -export const loadData = payload => dispatch => { - dispatch({ - type: ActionTypes.LOAD_DATA, - payload: payload - }); +export const fetchLandingPageData = (dispatch) => dispatch => { + dispatch(loadData()); fetch(window.env.ORACULUM_API_URL_v1 + "landing_page") .then(blob => blob.json()) @@ -21,17 +14,8 @@ export const loadData = payload => dispatch => { }); } -export const loadWizardDataResp = payload => ({ - type: ActionTypes.LOAD_WIZARD_DATA_RESP, - payload: payload -}) - -export const loadWizardData = payload => dispatch => { - dispatch({ - type: ActionTypes.LOAD_WIZARD_DATA, - payload: payload - }); - +export const fetchWizardData = payload => dispatch => { + dispatch(loadWizardData()) fetch(window.env.ORACULUM_API_URL_v1 + "actions/all") .then(blob => blob.json()) .then(data => { diff --git a/src/configureStore.js b/src/configureStore.js new file mode 100644 index 0000000..4ac50f4 --- /dev/null +++ b/src/configureStore.js @@ -0,0 +1,19 @@ +import { configureStore, combineReducers } from '@reduxjs/toolkit'; +import logger from 'redux-logger'; +import thunkMiddleware from 'redux-thunk'; +import landingPageReducer from './reducers/landingPageSlice'; +import wizardReducer from './reducers/wizardSlice'; + +const reducer = combineReducers({ + landing_page: landingPageReducer, + wizard: wizardReducer +}) + +export default function configureAppStore() { + const store = configureStore({ + reducer, + middleware: [ thunkMiddleware, logger ], + devTools: process.env.NODE_ENV !== 'production', + }) + return store; +} \ No newline at end of file diff --git a/src/index.js b/src/index.js index 35f417c..5c27953 100644 --- a/src/index.js +++ b/src/index.js @@ -9,17 +9,10 @@ import 'typeface-open-sans' import App from './App'; import * as serviceWorker from './serviceWorker'; -import { createStore, applyMiddleware } from 'redux' -import thunkMiddleware from 'redux-thunk' -import { createLogger } from 'redux-logger' -import { Provider } from 'react-redux' -import reducer from './reducers' +import { Provider } from 'react-redux'; +import configureAppStore from './configureStore'; -const loggerMiddleware = createLogger(); -const store = createStore(reducer, applyMiddleware( - thunkMiddleware, - loggerMiddleware -)); +const store= configureAppStore(); ReactDOM.render( diff --git a/src/landingpage/LandingPage.js b/src/landingpage/LandingPage.js index b1bee82..aec079a 100644 --- a/src/landingpage/LandingPage.js +++ b/src/landingpage/LandingPage.js @@ -11,7 +11,7 @@ import Hideable from "./Hideable" import _ from "lodash" import { connect } from "react-redux" -import { loadData } from "../actions/reduxActions" +import { fetchLandingPageData } from "../actions/reduxActions" import Cookies from "universal-cookie" @@ -38,7 +38,7 @@ class LandingPage extends Component { } componentDidMount() { - this.props.dispatch(loadData()) + this.props.dispatch(fetchLandingPageData()) } toggle_config_mode(e) { diff --git a/src/reducers/index.js b/src/reducers/index.js deleted file mode 100644 index 5e628e0..0000000 --- a/src/reducers/index.js +++ /dev/null @@ -1,44 +0,0 @@ -import ActionTypes from "../constants" - -const defaultState = { - landing_page: { - blockerbugs: {}, - devel: 0, - meetings: [], - schedule: [], - last_qa_meeting: {}, - stable: 0, - config_mode: false, - enabled_components: ["events", "blockers", "minutes"], - }, - wizard: { - actions: [], - providers: [], - all_actions: [], - }, -} - -export default (state = defaultState, action) => { - switch (action.type) { - case ActionTypes.LOAD_DATA_RESP: - return { - ...state, - landing_page: action.payload, - } - - case ActionTypes.LOAD_WIZARD_DATA_RESP: - return { - ...state, - wizard: { - ...state.wizard, - providers: action.payload.providers, - all_actions: action.payload.actions, - }, - } - - default: - return { - ...state, - } - } -} diff --git a/src/reducers/landingPageSlice.js b/src/reducers/landingPageSlice.js new file mode 100644 index 0000000..d1e2cbb --- /dev/null +++ b/src/reducers/landingPageSlice.js @@ -0,0 +1,28 @@ +import { createSlice } from "@reduxjs/toolkit"; + +const landingPageReducer = createSlice({ + name: "landing_page", + initialState: { + blockerbugs: {}, + devel: 0, + meetings: [], + schedule: [], + last_qa_meeting: {}, + stable: 0, + config_mode: false, + enabled_components: ["events", "blockers", "minutes"], + + loading: false + }, + reducers: { + loadData(state, action) { + if (!state.loading) state.loading = true; + }, + loadDataResp(state, action) { + state.loading = false; + Object.assign(state, { ...action.payload }); + } + } +}); +export const { loadData, loadDataResp } = landingPageReducer.actions; +export default landingPageReducer.reducer; diff --git a/src/reducers/wizardSlice.js b/src/reducers/wizardSlice.js new file mode 100644 index 0000000..f48032b --- /dev/null +++ b/src/reducers/wizardSlice.js @@ -0,0 +1,24 @@ +import { createSlice } from "@reduxjs/toolkit"; + +const wizardReducer = createSlice({ + name: "wizard", + initialState: { + actions: [], + providers: [], + all_actions: [], + + loading: false + }, + reducers: { + loadWizardData(state, action) { + if (!state.loading) state.loading = true; + }, + loadWizardDataResp(state, action) { + state.loading = false; + state.providers = action.payload.providers; + state.all_actions = action.payload.actions; + } + } +}); +export const { loadWizardData, loadWizardDataResp } = wizardReducer.actions; +export default wizardReducer.reducer; diff --git a/src/wizard/Wizard.js b/src/wizard/Wizard.js index a9ecb3e..1b136bd 100644 --- a/src/wizard/Wizard.js +++ b/src/wizard/Wizard.js @@ -6,7 +6,7 @@ import Actions from "./Actions" import { Container, Row } from "reactstrap" import { connect } from "react-redux" -import { loadWizardData } from "../actions/reduxActions" +import { fetchWizardData } from "../actions/reduxActions" class Wizard extends Component { constructor(props) { @@ -26,7 +26,7 @@ class Wizard extends Component { }) }) - this.props.dispatch(loadWizardData()) + this.props.dispatch(fetchWizardData()) } show_actions(actions) { diff --git a/yarn.lock b/yarn.lock index 85bfaa4..626a2c7 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1359,6 +1359,16 @@ resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-1.1.3.tgz#2b5a3ab3f918cca48a8c754c08168e3f03eba61b" integrity sha512-shAmDyaQC4H92APFoIaVDHCx5bStIocgvbwQyxPRrbUY20V1EYTbSDchWbuwlMG3V17cprZhA6+78JfB+3DTPw== +"@reduxjs/toolkit@^1.5.1": + version "1.5.1" + resolved "https://registry.yarnpkg.com/@reduxjs/toolkit/-/toolkit-1.5.1.tgz#05daa2f6eebc70dc18cd98a90421fab7fa565dc5" + integrity sha512-PngZKuwVZsd+mimnmhiOQzoD0FiMjqVks6ituO1//Ft5UEX5Ca9of13NEjo//pU22Jk7z/mdXVsmDfgsig1osA== + dependencies: + immer "^8.0.1" + redux "^4.0.0" + redux-thunk "^2.3.0" + reselect "^4.0.0" + "@svgr/babel-plugin-add-jsx-attribute@^4.2.0": version "4.2.0" resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-add-jsx-attribute/-/babel-plugin-add-jsx-attribute-4.2.0.tgz#dadcb6218503532d6884b210e7f3c502caaa44b1" @@ -5236,6 +5246,11 @@ immer@1.10.0: resolved "https://registry.yarnpkg.com/immer/-/immer-1.10.0.tgz#bad67605ba9c810275d91e1c2a47d4582e98286d" integrity sha512-O3sR1/opvCDGLEVcvrGTMtLac8GJ5IwZC4puPrLuRj3l7ICKvkmA0vGuU9OW8mV9WIBRnaxp5GJh9IEAaNOoYg== +immer@^8.0.1: + version "8.0.4" + resolved "https://registry.yarnpkg.com/immer/-/immer-8.0.4.tgz#3a21605a4e2dded852fb2afd208ad50969737b7a" + integrity sha512-jMfL18P+/6P6epANRvRk6q8t+3gGhqsJ9EuJ25AXE+9bNTYtssvzeYbEd0mXRYWCmmXSIbnlpz6vd6iJlmGGGQ== + import-cwd@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/import-cwd/-/import-cwd-2.1.0.tgz#aa6cf36e722761285cb371ec6519f53e2435b0a9" @@ -8837,7 +8852,7 @@ redux-thunk@^2.3.0: resolved "https://registry.yarnpkg.com/redux-thunk/-/redux-thunk-2.3.0.tgz#51c2c19a185ed5187aaa9a2d08b666d0d6467622" integrity sha512-km6dclyFnmcvxhAcrQV2AkZmPQjzPDjgVlQtR0EQjxZPyJ0BnMf3in1ryuR8A2qU0HldVRfxYXbFSKlI3N7Slw== -redux@^4.0.5: +redux@^4.0.0, redux@^4.0.5: version "4.0.5" resolved "https://registry.yarnpkg.com/redux/-/redux-4.0.5.tgz#4db5de5816e17891de8a80c424232d06f051d93f" integrity sha512-VSz1uMAH24DM6MF72vcojpYPtrTUu3ByVWfPL1nPfVRb5mZVTve5GnNCUV53QM/BZ66xfWrm0CTWoM+Xlz8V1w== @@ -9017,6 +9032,11 @@ requires-port@^1.0.0: resolved "https://registry.yarnpkg.com/requires-port/-/requires-port-1.0.0.tgz#925d2601d39ac485e091cf0da5c6e694dc3dcaff" integrity sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8= +reselect@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/reselect/-/reselect-4.0.0.tgz#f2529830e5d3d0e021408b246a206ef4ea4437f7" + integrity sha512-qUgANli03jjAyGlnbYVAV5vvnOmJnODyABz51RdBN7M4WaVu8mecZWgyQNkG8Yqe3KRGRt0l4K4B3XVEULC4CA== + resolve-cwd@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/resolve-cwd/-/resolve-cwd-2.0.0.tgz#00a9f7387556e27038eae232caa372a6a59b665a" From aab55ff8c280df6528aafe2f26dc1494ba4c35f1 Mon Sep 17 00:00:00 2001 From: Divyanshi Singh Date: Apr 08 2021 13:37:50 +0000 Subject: [PATCH 7/7] rebased --- diff --git a/src/configureStore.js b/src/configureStore.js index febe607..9d817e1 100644 --- a/src/configureStore.js +++ b/src/configureStore.js @@ -1,38 +1,19 @@ -import { configureStore, combineReducers } from "@reduxjs/toolkit"; -import logger from "redux-logger"; -import thunkMiddleware from "redux-thunk"; -import landingPageReducer from "./Containers/LandingPage/reducer"; -import wizardReducer from "./Containers/Wizard/reducer"; - -export const defaultState = { - landing_page: { - blockerbugs: {}, - devel: 0, - meetings: [], - schedule: [], - last_qa_meeting: {}, - stable: 0, - config_mode: false, - enabled_components: ["events", "blockers", "minutes"] - }, - wizard: { - actions: [], - providers: [], - all_actions: [] - } -}; +import { configureStore, combineReducers } from '@reduxjs/toolkit'; +import logger from 'redux-logger'; +import thunkMiddleware from 'redux-thunk'; +import landingPageReducer from './reducers/landingPageSlice'; +import wizardReducer from './reducers/wizardSlice'; const reducer = combineReducers({ - landing_page: landingPageReducer, - wizard: wizardReducer -}); + landing_page: landingPageReducer, + wizard: wizardReducer +}) -export default function configureAppStore(initialState) { - const store = configureStore({ - reducer, - middleware: [logger, thunkMiddleware], - devTools: process.env.NODE_ENV !== "production", - initialState - }); - return store; +export default function configureAppStore() { + const store = configureStore({ + reducer, + middleware: [ thunkMiddleware, logger ], + devTools: process.env.NODE_ENV !== 'production', + }) + return store; } diff --git a/src/index.js b/src/index.js index 7bf6062..5c27953 100644 --- a/src/index.js +++ b/src/index.js @@ -11,9 +11,8 @@ import * as serviceWorker from './serviceWorker'; import { Provider } from 'react-redux'; import configureAppStore from './configureStore'; -import { defaultState } from './configureStore'; -const store= configureAppStore(defaultState); +const store= configureAppStore(); ReactDOM.render( diff --git a/src/reducers/landingPageSlice.js b/src/reducers/landingPageSlice.js new file mode 100644 index 0000000..d1e2cbb --- /dev/null +++ b/src/reducers/landingPageSlice.js @@ -0,0 +1,28 @@ +import { createSlice } from "@reduxjs/toolkit"; + +const landingPageReducer = createSlice({ + name: "landing_page", + initialState: { + blockerbugs: {}, + devel: 0, + meetings: [], + schedule: [], + last_qa_meeting: {}, + stable: 0, + config_mode: false, + enabled_components: ["events", "blockers", "minutes"], + + loading: false + }, + reducers: { + loadData(state, action) { + if (!state.loading) state.loading = true; + }, + loadDataResp(state, action) { + state.loading = false; + Object.assign(state, { ...action.payload }); + } + } +}); +export const { loadData, loadDataResp } = landingPageReducer.actions; +export default landingPageReducer.reducer; diff --git a/src/reducers/wizardSlice.js b/src/reducers/wizardSlice.js new file mode 100644 index 0000000..f48032b --- /dev/null +++ b/src/reducers/wizardSlice.js @@ -0,0 +1,24 @@ +import { createSlice } from "@reduxjs/toolkit"; + +const wizardReducer = createSlice({ + name: "wizard", + initialState: { + actions: [], + providers: [], + all_actions: [], + + loading: false + }, + reducers: { + loadWizardData(state, action) { + if (!state.loading) state.loading = true; + }, + loadWizardDataResp(state, action) { + state.loading = false; + state.providers = action.payload.providers; + state.all_actions = action.payload.actions; + } + } +}); +export const { loadWizardData, loadWizardDataResp } = wizardReducer.actions; +export default wizardReducer.reducer;