From 8eab4503dfe4827a40e07af157605e2db5a3f61b Mon Sep 17 00:00:00 2001 From: Femi Balogun Date: Sun, 25 Aug 2019 21:56:23 +0100 Subject: [PATCH 1/4] bug: fix signup loader - [Finishes #168098099] --- _test_/registerErrorsReducer.spec.js | 2 +- _test_/signupAction.spec.test.js | 6 +++--- src/actions/registerActions.js | 4 ++-- src/actions/types.js | 1 + src/reducers/registerErrorsReducer.js | 4 ++-- 5 files changed, 9 insertions(+), 8 deletions(-) diff --git a/_test_/registerErrorsReducer.spec.js b/_test_/registerErrorsReducer.spec.js index e5d5c2e..0e901c3 100644 --- a/_test_/registerErrorsReducer.spec.js +++ b/_test_/registerErrorsReducer.spec.js @@ -13,7 +13,7 @@ describe('Register Errors reducer', () => { it('should load before getting errors', () => { expect(reducer(initialState, { - type: actionTypes.SET_LOADING, + type: actionTypes.SIGNUP_LOADING, })).toEqual({ ...initialState, loading: true, diff --git a/_test_/signupAction.spec.test.js b/_test_/signupAction.spec.test.js index 6f0cc16..a0e1438 100644 --- a/_test_/signupAction.spec.test.js +++ b/_test_/signupAction.spec.test.js @@ -1,7 +1,7 @@ import moxios from 'moxios'; import thunk from 'redux-thunk'; import configureMockStore from 'redux-mock-store'; -import { GET_ERRS, SET_LOADING, SUCCESS } from '../src/actions/types'; +import { GET_ERRS, SIGNUP_LOADING, SUCCESS } from '../src/actions/types'; import mockRegisterData from '../src/utils/registerMockStore'; import { registerUser } from '../src/actions/registerActions'; import axios from '../src/config/axiosInstance'; @@ -25,7 +25,7 @@ describe('Register actions', () => { }); const expectedActions = [ { - type: SET_LOADING, + type: SIGNUP_LOADING, }, { payload: errorResponse.message, @@ -50,7 +50,7 @@ describe('Register actions', () => { }); const expectedActions = [ { - type: SET_LOADING, + type: SIGNUP_LOADING, }, { type: SUCCESS, diff --git a/src/actions/registerActions.js b/src/actions/registerActions.js index 05bce96..c46c95e 100644 --- a/src/actions/registerActions.js +++ b/src/actions/registerActions.js @@ -1,6 +1,6 @@ import axios from '../config/axiosInstance'; import setAuthToken from '../utils/setAuthToken'; -import { GET_ERRS, SET_LOADING, SUCCESS } from './types'; +import { GET_ERRS, SIGNUP_LOADING, SUCCESS } from './types'; export const success = () => ({ type: SUCCESS, @@ -8,7 +8,7 @@ export const success = () => ({ export const registerUser = (newUserDetails, history) => (dispatch) => { dispatch({ - type: SET_LOADING, + type: SIGNUP_LOADING, }); return axios.post('/auth/signup', newUserDetails) .then((res) => { diff --git a/src/actions/types.js b/src/actions/types.js index 3abfed2..41cfecc 100644 --- a/src/actions/types.js +++ b/src/actions/types.js @@ -20,3 +20,4 @@ export const CREATE_ARTICLE_SUCCESS = 'CREATE_ARTICLE_SUCCESS'; export const CREATE_ARTICLE_FAILURE = 'CREATE_ARTICLE_FAILURE'; export const LOGIN_LOADING = 'LOGGIN_LOADING'; export const SUCCESS = 'SUCCESS'; +export const SIGNUP_LOADING = 'SIGNUP_LOADING'; diff --git a/src/reducers/registerErrorsReducer.js b/src/reducers/registerErrorsReducer.js index e422bbf..a41eef9 100644 --- a/src/reducers/registerErrorsReducer.js +++ b/src/reducers/registerErrorsReducer.js @@ -1,10 +1,10 @@ -import { GET_ERRS, SET_LOADING } from '../actions/types'; +import { GET_ERRS, SIGNUP_LOADING } from '../actions/types'; const initialState = { loading: false, errors: {} }; export default function (state = initialState, action) { switch (action.type) { - case SET_LOADING: + case SIGNUP_LOADING: return { ...state, loading: true, From bae3cd1ce0e39c129a5d185db46ee13bb6737c65 Mon Sep 17 00:00:00 2001 From: Femi Balogun Date: Fri, 23 Aug 2019 01:35:03 +0100 Subject: [PATCH 2/4] feature(article): read single article - enable user to read a specific article - [Finishes #167756361] --- .codeclimate.yml | 4 +- _test_/App.spec.js | 2 +- _test_/ArticleActions.spec.js | 1 - _test_/Comments.spec.js | 24 ++++++ _test_/CommentsBtn.spec.js | 25 ++++++ _test_/FeaturedArticle.spec.js | 8 -- _test_/Homepage.spec.js | 1 - _test_/MainArticle.spec.js | 48 +++++++++++ _test_/RecommendedArticles.spec.js | 64 +++++++++++++++ _test_/SingleArticle.spec.js | 63 ++++++++++++++ _test_/SingleArticleMapState.spec.js | 13 +++ _test_/Tags.spec.js | 34 ++++++++ _test_/__mocks__/fileMock.js | 2 +- _test_/singleArticleAction.spec.js | 75 +++++++++++++++++ _test_/singleArticleReducer.spec.js | 36 ++++++++ browserMock.js | 19 ----- config/jest/assetsTransformer.js | 7 ++ jest.config.js | 2 +- src/actions/ArticleActions.js | 34 ++++++++ src/actions/types.js | 1 + src/components/App.js | 6 +- src/components/ArticleCard/ArticleCard.scss | 26 ++++++ src/components/ArticleCard/Index.jsx | 37 +++++---- src/components/Comments/Comments.scss | 3 + src/components/Comments/index.jsx | 10 +++ src/components/Error/Error.scss | 2 +- src/components/FeaturedArticle/Index.jsx | 11 ++- src/components/FeaturedSection/Index.jsx | 5 ++ src/components/Loader/index.jsx | 12 +-- .../CommentsBtn/CommentsBtn.scss | 16 ++++ .../SingleArticle/CommentsBtn/index.jsx | 13 +++ .../MainArticle/MainArticle.scss | 54 ++++++++++++ .../SingleArticle/MainArticle/index.jsx | 82 +++++++++++++++++++ .../Recommended/Recommended.scss | 33 ++++++++ .../SingleArticle/Recommended/index.jsx | 57 +++++++++++++ src/components/SingleArticle/Tags/Tags.scss | 15 ++++ src/components/SingleArticle/Tags/index.jsx | 35 ++++++++ src/components/SingleArticle/index.jsx | 65 +++++++++++++++ src/components/SingleArticle/index.scss | 3 + src/components/TrendingSection/Index.jsx | 2 + src/components/articleLayout/index.jsx | 9 +- src/components/articleLayout/index.scss | 4 + src/helpers/helpers.js | 1 - src/index.html | 2 +- src/reducers/index.js | 2 + src/reducers/singleArticleReducer.js | 21 +++++ src/utils/singleArticleMockStore.js | 42 ++++++++++ src/views/Homepage.jsx | 4 +- webpack.config.js | 1 + 49 files changed, 972 insertions(+), 64 deletions(-) create mode 100644 _test_/Comments.spec.js create mode 100644 _test_/CommentsBtn.spec.js create mode 100644 _test_/MainArticle.spec.js create mode 100644 _test_/RecommendedArticles.spec.js create mode 100644 _test_/SingleArticle.spec.js create mode 100644 _test_/SingleArticleMapState.spec.js create mode 100644 _test_/Tags.spec.js create mode 100644 _test_/singleArticleAction.spec.js create mode 100644 _test_/singleArticleReducer.spec.js delete mode 100644 browserMock.js create mode 100644 config/jest/assetsTransformer.js create mode 100644 src/components/Comments/Comments.scss create mode 100644 src/components/Comments/index.jsx create mode 100644 src/components/SingleArticle/CommentsBtn/CommentsBtn.scss create mode 100644 src/components/SingleArticle/CommentsBtn/index.jsx create mode 100644 src/components/SingleArticle/MainArticle/MainArticle.scss create mode 100644 src/components/SingleArticle/MainArticle/index.jsx create mode 100644 src/components/SingleArticle/Recommended/Recommended.scss create mode 100644 src/components/SingleArticle/Recommended/index.jsx create mode 100644 src/components/SingleArticle/Tags/Tags.scss create mode 100644 src/components/SingleArticle/Tags/index.jsx create mode 100644 src/components/SingleArticle/index.jsx create mode 100644 src/components/SingleArticle/index.scss create mode 100644 src/reducers/singleArticleReducer.js create mode 100644 src/utils/singleArticleMockStore.js diff --git a/.codeclimate.yml b/.codeclimate.yml index fb7d521..d14a4bd 100644 --- a/.codeclimate.yml +++ b/.codeclimate.yml @@ -12,4 +12,6 @@ checks: enabled: false identical-code: enabled: true - \ No newline at end of file + method-complexity: + config: + threshold: 10 diff --git a/_test_/App.spec.js b/_test_/App.spec.js index 7900594..6e8681b 100644 --- a/_test_/App.spec.js +++ b/_test_/App.spec.js @@ -26,6 +26,6 @@ describe('App', () => { expect(app.find('Switch').length).toBe(1); }); it('renders a Route component', () => { - expect(app.find('Route').length).toBe(12); + expect(app.find('Route').length).toBe(14); }); }); diff --git a/_test_/ArticleActions.spec.js b/_test_/ArticleActions.spec.js index aee88cb..2f6f601 100644 --- a/_test_/ArticleActions.spec.js +++ b/_test_/ArticleActions.spec.js @@ -1,7 +1,6 @@ import moxios from 'moxios'; import makeMockStore from './Utils/makeMockStore'; import { fetchResponseData, mockData } from './testData/articleData'; - import ArticleActions from '../src/actions/ArticleActions'; import { SET_LOADING, diff --git a/_test_/Comments.spec.js b/_test_/Comments.spec.js new file mode 100644 index 0000000..410efbf --- /dev/null +++ b/_test_/Comments.spec.js @@ -0,0 +1,24 @@ +import React from 'react'; +import expect from 'expect'; +import { shallow } from 'enzyme'; +import Comments from '../src/components/Comments'; + +describe('Main Article', () => { + let component; + + beforeEach(() => { + component = shallow(); + }); + + it('renders successfully', () => { + expect(component).toBeDefined(); + }); + + it('renders a div tag', () => { + expect(component.find('div').length).toBe(1); + }); + + it('renders an h1 tag', () => { + expect(component.find('h1').length).toBe(1); + }); +}); diff --git a/_test_/CommentsBtn.spec.js b/_test_/CommentsBtn.spec.js new file mode 100644 index 0000000..8b04f04 --- /dev/null +++ b/_test_/CommentsBtn.spec.js @@ -0,0 +1,25 @@ +import React from 'react'; +import expect from 'expect'; +import { shallow } from 'enzyme'; +import CommentsBtn from '../src/components/SingleArticle/CommentsBtn'; + + +describe('Single Article', () => { + let component; + + beforeEach(() => { + component = shallow(); + }); + + it('renders successfully', () => { + expect(component).toBeDefined(); + }); + + it('renders a div component', () => { + expect(component.find('div').length).toBe(1); + }); + + it('renders a Link component', () => { + expect(component.find('Link').length).toBe(1); + }); +}); diff --git a/_test_/FeaturedArticle.spec.js b/_test_/FeaturedArticle.spec.js index df00a68..081bf8e 100644 --- a/_test_/FeaturedArticle.spec.js +++ b/_test_/FeaturedArticle.spec.js @@ -23,14 +23,6 @@ describe('FeaturedArticle', () => { expect(app).toBeDefined(); }); - it('renders a div component', () => { - expect(app.find('div').length).toBe(1); - }); - - it('renders an img component', () => { - expect(app.find('img').length).toBe(1); - }); - it('renders a h3 component', () => { expect(app.find('h3').length).toBe(1); }); diff --git a/_test_/Homepage.spec.js b/_test_/Homepage.spec.js index 71c2cd1..999093d 100644 --- a/_test_/Homepage.spec.js +++ b/_test_/Homepage.spec.js @@ -16,7 +16,6 @@ describe('Homepage', () => { const comp = shallow(); const inst = comp.instance(); inst.loadItems(); - // console.log(inst.debug()); }); it('componentWillUnmount should be called on unmount', () => { diff --git a/_test_/MainArticle.spec.js b/_test_/MainArticle.spec.js new file mode 100644 index 0000000..90dc2b6 --- /dev/null +++ b/_test_/MainArticle.spec.js @@ -0,0 +1,48 @@ +import React from 'react'; +import expect from 'expect'; +import { shallow } from 'enzyme'; +import MainArticle from '../src/components/SingleArticle/MainArticle'; +import image from '../src/assets/articleImage.png'; + +describe('Main Article', () => { + let component; + + const props = { + views: 1, + imageUrl: '', + }; + + beforeEach(() => { + component = shallow(); + }); + + it('renders successfully', () => { + expect(component).toBeDefined(); + }); + + it('renders three div tags', () => { + expect(component.find('div').length).toBe(3); + component.setProps({ views: 2 }); + component.setProps({ imageUrl: image }); + }); + + it('renders an h1 tag', () => { + expect(component.find('h1').length).toBe(1); + }); + + it('renders an Link tag', () => { + expect(component.find('Link').length).toBe(1); + }); + + it('renders a p tag', () => { + expect(component.find('p').length).toBe(3); + }); + + it('renders a span tag', () => { + expect(component.find('span').length).toBe(3); + }); + + it('renders an image tag', () => { + expect(component.find('img').length).toBe(1); + }); +}); diff --git a/_test_/RecommendedArticles.spec.js b/_test_/RecommendedArticles.spec.js new file mode 100644 index 0000000..ca30c87 --- /dev/null +++ b/_test_/RecommendedArticles.spec.js @@ -0,0 +1,64 @@ +import React from 'react'; +import expect from 'expect'; +import { shallow } from 'enzyme'; +import Recommended from '../src/components/SingleArticle/Recommended'; +import image from '../src/assets/articleImage.png'; + +describe('Main Article', () => { + let component; + + const props = { + allArticles: [{ + title: 'Hello', + article: { slug: 'hello-1', imageUrl: '' }, + }, + { + title: 'Hellos', + article: { slug: 'hello-2', imageUrl: '' }, + }, + { + title: 'Helloey', + article: { slug: 'hello-3', imageUrl: '' }, + }], + }; + + beforeEach(() => { + component = shallow(); + }); + + it('renders successfully', () => { + expect(component).toBeDefined(); + }); + + it('renders a div tag', () => { + expect(component.find('div').length).toBe(2); + }); + + it('renders an h3 tag', () => { + expect(component.find('h3').length).toBe(1); + }); + + it('renders three h4 tags', () => { + expect(component.find('h4').length).toBe(3); + }); + + it('renders three image tags', () => { + expect(component.find('img').length).toBe(3); + component.setProps({ + allArticles: { + 0: { article: { slug: 'hello-1', imageUrl: image } }, + 1: { article: { slug: 'hello-2', imageUrl: image } }, + 2: { article: { slug: 'hello-3', imageUrl: image } }, + }, + }); + }); + + it('renders three Link tags', () => { + expect(component.find('Link').length).toBe(3); + }); + + it('returns null', () => { + component.setProps({ allArticles: [] }); + expect(component).toEqual({}); + }); +}); diff --git a/_test_/SingleArticle.spec.js b/_test_/SingleArticle.spec.js new file mode 100644 index 0000000..61e8274 --- /dev/null +++ b/_test_/SingleArticle.spec.js @@ -0,0 +1,63 @@ +import React from 'react'; +import expect from 'expect'; +import { shallow } from 'enzyme'; +import Loader from '../src/components/Loader'; +import { SingleArticle } from '../src/components/SingleArticle'; +import MainArticle from '../src/components/SingleArticle/MainArticle'; +import Tags from '../src/components/SingleArticle/Tags'; +import Recommended from '../src/components/SingleArticle/Recommended'; +import CommentsBtn from '../src/components/SingleArticle/CommentsBtn'; + + +describe('Single Article', () => { + let component; + let prevProps; + + const props = { + prevProps: { match: { params: { slug: 'hello' } } }, + match: { params: { slug: '' } }, + viewArticle: jest.fn(), + fetchArticles: jest.fn(), + loading: false, + componentDidUpdate: jest.fn(prevProps), + }; + + beforeEach(() => { + component = shallow(); + }); + + it('renders successfully', () => { + expect(component).toBeDefined(); + }); + + it('renders a div component', () => { + expect(component.find('div').length).toBe(1); + }); + + it('renders a MainArticle component', () => { + expect(component.find(MainArticle).length).toBe(1); + }); + + it('renders a Recommended component', () => { + expect(component.find(Recommended).length).toBe(1); + }); + + it('renders a Tags component', () => { + expect(component.find(Tags).length).toBe(1); + }); + + it('renders a CommentsBtn component', () => { + expect(component.find(CommentsBtn).length).toBe(1); + }); + + it('renders a Loader component', () => { + component.setProps({ loading: true }); + expect(component.find(Loader).length).toBe(1); + }); + + it('Click on recommended article', () => { + component.instance().componentDidUpdate(props.prevProps); + const render = jest.spyOn(component.instance(), 'render'); + expect(render).toHaveBeenCalledTimes(0); + }); +}); diff --git a/_test_/SingleArticleMapState.spec.js b/_test_/SingleArticleMapState.spec.js new file mode 100644 index 0000000..36272bd --- /dev/null +++ b/_test_/SingleArticleMapState.spec.js @@ -0,0 +1,13 @@ +import { mapStateToProps } from '../src/components/SingleArticle'; + +const state = { + singleArticle: {}, + loading: false, + recommendedArticles: {}, +}; + +describe('mapStateToProps', () => { + it('return the right object', () => { + expect(mapStateToProps(state)).toBeDefined(); + }); +}); diff --git a/_test_/Tags.spec.js b/_test_/Tags.spec.js new file mode 100644 index 0000000..6e4495a --- /dev/null +++ b/_test_/Tags.spec.js @@ -0,0 +1,34 @@ +import React from 'react'; +import expect from 'expect'; +import { shallow } from 'enzyme'; +import Tags from '../src/components/SingleArticle/Tags'; + +describe('Tags', () => { + let component; + + const props = { + tags: ['hello', 'bikes', 'food'], + }; + + beforeEach(() => { + component = shallow(); + }); + + it('renders successfully', () => { + expect(component).toBeDefined(); + }); + + it('renders three div components', () => { + expect(component.find('div').length).toBe(3); + }); + + it('renders no div component', () => { + component.setProps({ tags: null }); + expect(component.find('div').length).toBe(0); + }); + + it('renders zero div component', () => { + component.setProps({ tags: [''] }); + expect(component.find('div').length).toBe(0); + }); +}); diff --git a/_test_/__mocks__/fileMock.js b/_test_/__mocks__/fileMock.js index af69d3e..b39af97 100644 --- a/_test_/__mocks__/fileMock.js +++ b/_test_/__mocks__/fileMock.js @@ -1 +1 @@ -export default 'test-file-stub'; \ No newline at end of file +'test-file-stub'; diff --git a/_test_/singleArticleAction.spec.js b/_test_/singleArticleAction.spec.js new file mode 100644 index 0000000..0794d81 --- /dev/null +++ b/_test_/singleArticleAction.spec.js @@ -0,0 +1,75 @@ +import moxios from 'moxios'; +import thunk from 'redux-thunk'; +import configureMockStore from 'redux-mock-store'; +import { VIEW_SINGLE_ARTICLE, SET_LOADING } from '../src/actions/types'; +import { successResponse, errorResponse } from '../src/utils/singleArticleMockStore'; +import articleActions from '../src/actions/ArticleActions'; +import axios from '../src/config/axiosInstance'; + +const { viewArticle } = articleActions; + +const mockStore = configureMockStore([thunk]); +let store = mockStore(); + +describe('Register actions', () => { + beforeEach(() => { + moxios.install(); + store.clearActions(); + }); + + afterEach(() => moxios.uninstall(axios)); + + it('Returns success if article fetch was successful', (done) => { + moxios.wait(() => { + const request = moxios.requests.mostRecent(); + request.respondWith({ status: 200, response: successResponse }); + }); + const expectedActions = [ + { + type: SET_LOADING, + }, + { + payload: successResponse.data.body, + type: VIEW_SINGLE_ARTICLE, + }, + ]; + + store = mockStore({}); + const history = { push: jest.fn() }; + + return store.dispatch(viewArticle('article-3', history)) + .then(() => { + const actions = store.getActions(); + expect(actions[0]).toEqual(expectedActions[0]); + expect(actions[1].type).toEqual(expectedActions[1].type); + done(); + }); + }); + + it('Returns error if article fetch was successful', (done) => { + moxios.wait(() => { + const request = moxios.requests.mostRecent(); + request.respondWith({ status: 404, response: errorResponse }); + }); + const expectedActions = [ + { + type: SET_LOADING, + }, + { + payload: errorResponse.message, + type: VIEW_SINGLE_ARTICLE, + }, + ]; + + store = mockStore({}); + const history = { push: jest.fn() }; + + return store.dispatch(viewArticle('article-50-487263', history)) + .then(() => { + const actions = store.getActions(); + expect(actions[0]).toEqual(expectedActions[0]); + // expect(store.getActions()).toEqual(expectedActions); + done(); + }); + }); +}); diff --git a/_test_/singleArticleReducer.spec.js b/_test_/singleArticleReducer.spec.js new file mode 100644 index 0000000..c91b9bd --- /dev/null +++ b/_test_/singleArticleReducer.spec.js @@ -0,0 +1,36 @@ +import reducer from '../src/reducers/singleArticleReducer'; +import * as actionTypes from '../src/actions/types'; + +describe('Login reducer', () => { + let initialState; + + beforeEach(() => { + initialState = { + article: {}, + loading: false, + }; + }); + it('should return the initial state', () => { + expect(reducer(undefined, {})).toEqual(initialState); + }); + + it('should load before fetching article', () => { + expect(reducer(initialState, { + type: actionTypes.SET_LOADING, + })).toEqual({ + ...initialState, + loading: true, + }); + }); + + it('should successfully return an article', () => { + expect(reducer(initialState, { + type: actionTypes.VIEW_SINGLE_ARTICLE, + payload: 'Some random article', + })).toEqual({ + ...initialState, + loading: false, + article: 'Some random article', + }); + }); +}); diff --git a/browserMock.js b/browserMock.js deleted file mode 100644 index 301da54..0000000 --- a/browserMock.js +++ /dev/null @@ -1,19 +0,0 @@ -const localStorageMock = (function () { - const store = {}; - - return { - getItem(key) { - return store[key] || null; - }, - setItem(key, value) { - store[key] = value.toString(); - }, - clear() { - store = {}; - }, - }; -}()); - -Object.defineProperty(window, 'localStorage', { - value: localStorageMock, -}); diff --git a/config/jest/assetsTransformer.js b/config/jest/assetsTransformer.js new file mode 100644 index 0000000..dee01da --- /dev/null +++ b/config/jest/assetsTransformer.js @@ -0,0 +1,7 @@ +const path = require('path'); + +module.exports = { + process(src, filename) { + return `module.exports = ${JSON.stringify(path.basename(filename))};`; + }, +}; diff --git a/jest.config.js b/jest.config.js index aab986a..585e199 100644 --- a/jest.config.js +++ b/jest.config.js @@ -32,7 +32,7 @@ module.exports = { errorOnDeprecated: true, moduleFileExtensions: ['js', 'json', 'jsx'], moduleNameMapper: { - '\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$': '/_test_/__mocks__/fileMock.js', + '\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$': 'config/jest/assetsTransformer.js', '\\.(css|scss)$': '/_test_/__mocks__/styleMock.js', }, setupFilesAfterEnv: ['./tests.setup.js'], diff --git a/src/actions/ArticleActions.js b/src/actions/ArticleActions.js index 5b1a6f1..582a9cb 100644 --- a/src/actions/ArticleActions.js +++ b/src/actions/ArticleActions.js @@ -4,6 +4,7 @@ import { SET_LOADING, GET_ERRORS, SET_CURRENT_ARTICLES, + VIEW_SINGLE_ARTICLE, } from './types'; class ArticleActions { @@ -34,6 +35,39 @@ class ArticleActions { static setLoading = () => ({ type: SET_LOADING, }); + + static viewArticle = (slug, history) => (dispatch) => { + dispatch({ + type: SET_LOADING, + }); + return axios.get(`https://ah-nyati-backend-staging.herokuapp.com/api/v1/articles/${slug}`) + .then((res) => { + dispatch({ + type: VIEW_SINGLE_ARTICLE, + payload: { + articleBody: res.data.data[0].article.body, + title: res.data.data[0].article.title, + slug: res.data.data[0].article.slug, + imageUrl: res.data.data[0].article.imageUrl, + views: res.data.data[0].article.views, + read: res.data.data[0].article.read, + readTime: res.data.data[0].readTime, + author: res.data.data[0].article.User.userName, + userId: res.data.data[0].article.userId, + tags: res.data.data[0].tag, + }, + }); + }) + .catch((err) => { + if (err.response.status === 404) { + return history.push('/*'); + } + return dispatch({ + type: GET_ERRORS, + payload: err.message, + }); + }); + } } export default ArticleActions; diff --git a/src/actions/types.js b/src/actions/types.js index 41cfecc..920eecf 100644 --- a/src/actions/types.js +++ b/src/actions/types.js @@ -21,3 +21,4 @@ export const CREATE_ARTICLE_FAILURE = 'CREATE_ARTICLE_FAILURE'; export const LOGIN_LOADING = 'LOGGIN_LOADING'; export const SUCCESS = 'SUCCESS'; export const SIGNUP_LOADING = 'SIGNUP_LOADING'; +export const VIEW_SINGLE_ARTICLE = 'VIEW_SINGLE_ARTICLE'; diff --git a/src/components/App.js b/src/components/App.js index 3322159..33f8125 100644 --- a/src/components/App.js +++ b/src/components/App.js @@ -19,6 +19,8 @@ import store from '../store'; import setAuthToken from '../utils/setAuthToken'; import { setCurrentUser } from '../actions/authActions'; import CreateArticlePage from './article/CreateArticlePage'; +import SingleArticle from './SingleArticle'; +import Comments from './Comments'; const token = localStorage.jwtToken; let loggedInUser = {}; @@ -55,7 +57,9 @@ const App = () => ( - + + + diff --git a/src/components/ArticleCard/ArticleCard.scss b/src/components/ArticleCard/ArticleCard.scss index f03ebd3..976c082 100644 --- a/src/components/ArticleCard/ArticleCard.scss +++ b/src/components/ArticleCard/ArticleCard.scss @@ -49,6 +49,32 @@ font-weight: 900; } +.linky { + color: inherit; + transition: .4s transform ease-in-out; +} + +.linky-2 { + color: inherit; + text-decoration: none; +} + +.linky-2:hover { + color: inherit; + text-decoration: none; +} + +.linky:hover { + color: inherit; + border-radius: 5px; + text-decoration: none; + transform: scale(1.025) !important; +} + +.art-card { + display: inherit; +} + @media only screen and (min-width: 870px) and (max-width: 1000px) { .article-card__aside { padding: 0 8px; diff --git a/src/components/ArticleCard/Index.jsx b/src/components/ArticleCard/Index.jsx index bb05ac3..23cb231 100644 --- a/src/components/ArticleCard/Index.jsx +++ b/src/components/ArticleCard/Index.jsx @@ -1,5 +1,6 @@ import React from 'react'; import PropTypes from 'prop-types'; +import { Link } from 'react-router-dom'; import './ArticleCard.scss'; const ArticleCard = (props) => { @@ -12,35 +13,40 @@ const ArticleCard = (props) => { likeCount, viewCount, count, + slug, } = props; + const truncText = text.slice(0, count); + const URL = `articles/${slug}`; return ( -
-
- -
-

{title}

-

{`${truncText}...`}

-

- {date} + +

+
+ +
+

{title}

+

{`${truncText}...`}

+

+ {date}  /  - {readTime} -

-
- {likeCount} + {readTime} +

+
+ {likeCount}   - +     - {viewCount} + {viewCount}   Views +
-
+ ); }; @@ -53,6 +59,7 @@ ArticleCard.propTypes = { likeCount: PropTypes.number.isRequired, viewCount: PropTypes.number.isRequired, count: PropTypes.number.isRequired, + slug: PropTypes.string.isRequired, }; ArticleCard.defaultProps = { diff --git a/src/components/Comments/Comments.scss b/src/components/Comments/Comments.scss new file mode 100644 index 0000000..89c25db --- /dev/null +++ b/src/components/Comments/Comments.scss @@ -0,0 +1,3 @@ +.comms { + margin-top: 60px; +} diff --git a/src/components/Comments/index.jsx b/src/components/Comments/index.jsx new file mode 100644 index 0000000..39f2773 --- /dev/null +++ b/src/components/Comments/index.jsx @@ -0,0 +1,10 @@ +import React from 'react'; +import './Comments.scss'; + +const comments = () => ( +
+

Comments Page

+
+); + +export default comments; diff --git a/src/components/Error/Error.scss b/src/components/Error/Error.scss index a841a66..b967b60 100644 --- a/src/components/Error/Error.scss +++ b/src/components/Error/Error.scss @@ -1,7 +1,7 @@ .Container { width: 100%; height: 100vh; - background-image: url("../../assets/defaultBg.jpeg"); + background-image: url(https://res.cloudinary.com/free-spirit/image/upload/v1565357741/AH-assets/defaultBg.jpg); background-repeat: no-repeat; background-size: 100% 100%; display: flex; diff --git a/src/components/FeaturedArticle/Index.jsx b/src/components/FeaturedArticle/Index.jsx index 9d4381b..ec822d2 100644 --- a/src/components/FeaturedArticle/Index.jsx +++ b/src/components/FeaturedArticle/Index.jsx @@ -1,5 +1,6 @@ import React from 'react'; import PropTypes from 'prop-types'; +import { Link } from 'react-router-dom'; import './FeaturedArticle.scss'; const FeaturedArticle = (props) => { @@ -7,29 +8,35 @@ const FeaturedArticle = (props) => { title, imageUrl, customClass, + slug, } = props; const { wrapperClass, imageClass, titleClass, } = customClass; + + const URL = `articles/${slug}`; + return ( -
+

{title}

-
+ ); }; FeaturedArticle.propTypes = { title: PropTypes.string.isRequired, imageUrl: PropTypes.string, + slug: PropTypes.string, customClass: PropTypes.objectOf(PropTypes.string), }; FeaturedArticle.defaultProps = { customClass: { }, imageUrl: '', + slug: '', }; export default FeaturedArticle; diff --git a/src/components/FeaturedSection/Index.jsx b/src/components/FeaturedSection/Index.jsx index 895b5a5..ce7eee3 100644 --- a/src/components/FeaturedSection/Index.jsx +++ b/src/components/FeaturedSection/Index.jsx @@ -47,6 +47,7 @@ const FeaturedSection = ({ data }) => { @@ -55,11 +56,13 @@ const FeaturedSection = ({ data }) => { @@ -67,11 +70,13 @@ const FeaturedSection = ({ data }) => { diff --git a/src/components/Loader/index.jsx b/src/components/Loader/index.jsx index 298bb1d..8c0a43b 100644 --- a/src/components/Loader/index.jsx +++ b/src/components/Loader/index.jsx @@ -17,12 +17,14 @@ export default class Index extends React.Component { timeOut = () => { setTimeout(() => { this.setState({ - reload:
+ reload: ( +
Ooops! Check your network and - - Try Again - -
, + + Try Again + +
+ ), }); }, 6000); } diff --git a/src/components/SingleArticle/CommentsBtn/CommentsBtn.scss b/src/components/SingleArticle/CommentsBtn/CommentsBtn.scss new file mode 100644 index 0000000..e31a517 --- /dev/null +++ b/src/components/SingleArticle/CommentsBtn/CommentsBtn.scss @@ -0,0 +1,16 @@ +.com-btn { + color: #2e99d6; + text-align: center; + margin-top: 50px; + font-size: 40px; + border: 1px solid rgba(0, 0, 0, .4); + padding: 8px; + cursor: pointer; +} + +@media(max-width: 1024px) { + .com-btn { + font-size: 25px; + padding: 5px; + } +} diff --git a/src/components/SingleArticle/CommentsBtn/index.jsx b/src/components/SingleArticle/CommentsBtn/index.jsx new file mode 100644 index 0000000..de1ae4d --- /dev/null +++ b/src/components/SingleArticle/CommentsBtn/index.jsx @@ -0,0 +1,13 @@ +import React from 'react'; +import { Link } from 'react-router-dom'; +import './CommentsBtn.scss'; + +const commentBtn = () => ( + +
+ View comments +
+ +); + +export default commentBtn; diff --git a/src/components/SingleArticle/MainArticle/MainArticle.scss b/src/components/SingleArticle/MainArticle/MainArticle.scss new file mode 100644 index 0000000..9c94f72 --- /dev/null +++ b/src/components/SingleArticle/MainArticle/MainArticle.scss @@ -0,0 +1,54 @@ +.main-article { + margin-top: 40px; +} + +.article-title { + text-transform: capitalize; +} + +.article-stats { + display: inline-block; + margin-top: 10px; + padding-left: 50px; + padding-right: 50px; + padding-bottom: 10px; +} + +.stat-num, .author-key, .time-key { + font-weight: 700; + display: block; + text-align: center; +} + +.views-stat { + border-right: 1.5px solid rgba(0, 0, 0, .4); + border-left: 1.5px solid rgba(0, 0, 0, .4); +} + +.main-img { + width: 100%; + object-fit: cover; + object-position: 0 0; +} + +.write-up { + margin-top: 50px; + font-size: 20px; +} + +@media (max-width: 1024px) { + .main-img { + height: 100%; + width: 100%; + } + + .article-title { + font-size: 1.5rem; + } + + .article-stats { + padding-left: 20px; + padding-right: 20px; + } +} + diff --git a/src/components/SingleArticle/MainArticle/index.jsx b/src/components/SingleArticle/MainArticle/index.jsx new file mode 100644 index 0000000..6fc7966 --- /dev/null +++ b/src/components/SingleArticle/MainArticle/index.jsx @@ -0,0 +1,82 @@ +import React from 'react'; +import './MainArticle.scss'; +import { Link } from 'react-router-dom'; +import PropTypes from 'prop-types'; + +const mainArticle = (props) => { + const { + title, articleBody, views, readTime, author, userId, + } = props; + + let viewInfo = 'Views'; + const URL = `/profile/${userId}`; + + if (views < 2) { + viewInfo = 'View'; + } + + let { imageUrl } = props; + + const backupImage = 'https://i1.wp.com/www.africanbusinesscentral.com/wp-content/uploads/2018/07/Andela.jpeg'; + + if (imageUrl === '') { + imageUrl = backupImage; + } + + return ( +
+

{title}

+

+ + {`${readTime} `} + + min read +

+ +

+ + {views} + + {viewInfo} +

+ + +

+ + Author + + {` ${author}`} +

+ + +
+ article +
+ +
+ {articleBody} +
+
+ ); +}; + +mainArticle.propTypes = { + title: PropTypes.string, + articleBody: PropTypes.string, + imageUrl: PropTypes.string, + views: PropTypes.number, + author: PropTypes.string, + readTime: PropTypes.number, + userId: PropTypes.number.isRequired, +}; + +mainArticle.defaultProps = { + imageUrl: '', + title: '', + articleBody: '', + views: 0, + author: '', + readTime: 0, +}; + +export default mainArticle; diff --git a/src/components/SingleArticle/Recommended/Recommended.scss b/src/components/SingleArticle/Recommended/Recommended.scss new file mode 100644 index 0000000..03ebd2c --- /dev/null +++ b/src/components/SingleArticle/Recommended/Recommended.scss @@ -0,0 +1,33 @@ +.recommended { + margin-top: 50px; + margin-bottom: 30px; + margin-left: 30px; +} + +.rec-img { + width: 300px; + height: 250px; + object-fit: cover; +} + +.rec { + text-align: center; +} + +.rec-title { + margin-top: 20px; + text-transform: capitalize; +} + +@media(max-width: 1024px) { + .recommended{ + text-align: center; + margin-left: 0; + margin-bottom: 15px; + } + + .rec-title { + font-size: 1.3rem; + margin-bottom: 20px; + } +} diff --git a/src/components/SingleArticle/Recommended/index.jsx b/src/components/SingleArticle/Recommended/index.jsx new file mode 100644 index 0000000..a0b4b89 --- /dev/null +++ b/src/components/SingleArticle/Recommended/index.jsx @@ -0,0 +1,57 @@ +import React from 'react'; +import './Recommended.scss'; +import PropTypes from 'prop-types'; +import { Link } from 'react-router-dom'; + +const articleImage = 'https://i1.wp.com/www.africanbusinesscentral.com/wp-content/uploads/2018/07/Andela.jpeg'; + +const recommended = (props) => { + const { + allArticles, + } = props; + + if (allArticles[0]) { + const URL1 = `/articles/${allArticles[0].article.slug}`; + const URL2 = `/articles/${allArticles[1].article.slug}`; + const URL3 = `/articles/${allArticles[2].article.slug}`; + + let image1 = allArticles[0].article.imageUrl; + if (image1 === '') image1 = articleImage; + + let image2 = allArticles[1].article.imageUrl; + if (image2 === '') image2 = articleImage; + + let image3 = allArticles[2].article.imageUrl; + if (image3 === '') image3 = articleImage; + + + return ( +
+

Recommended Articles

+
+ + +

{allArticles[0].article.title}

+ + + + +

{allArticles[1].article.title}

+ + + + +

{allArticles[2].article.title}

+ +
+
+ ); + } + return null; +}; + +recommended.propTypes = { + allArticles: PropTypes.arrayOf(PropTypes.object).isRequired, +}; + +export default recommended; diff --git a/src/components/SingleArticle/Tags/Tags.scss b/src/components/SingleArticle/Tags/Tags.scss new file mode 100644 index 0000000..439bafd --- /dev/null +++ b/src/components/SingleArticle/Tags/Tags.scss @@ -0,0 +1,15 @@ +.tags-container { + margin-top: 15px; +} + +.tags { + font-size: 20px; + display: inline-block; + margin: 10px; + margin-left: 0; + padding: 5px; + padding-right: 30px; + padding-left: 30px; + background: #f2f2f2; + cursor: pointer; +} diff --git a/src/components/SingleArticle/Tags/index.jsx b/src/components/SingleArticle/Tags/index.jsx new file mode 100644 index 0000000..1ef234b --- /dev/null +++ b/src/components/SingleArticle/Tags/index.jsx @@ -0,0 +1,35 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import './Tags.scss'; + +const articleTags = (props) => { + const { + tags, + } = props; + + if (tags) { + if (tags[0] !== '') { + return ( + <> + {tags.map(tag => ( +
+ {tag} +
+ ))} + + ); + } + } + + return null; +}; + +articleTags.propTypes = { + tags: PropTypes.arrayOf(PropTypes.string), +}; + +articleTags.defaultProps = { + tags: [''], +}; + +export default articleTags; diff --git a/src/components/SingleArticle/index.jsx b/src/components/SingleArticle/index.jsx new file mode 100644 index 0000000..ccbe595 --- /dev/null +++ b/src/components/SingleArticle/index.jsx @@ -0,0 +1,65 @@ +import React, { Component } from 'react'; +import { connect } from 'react-redux'; +import PropTypes from 'prop-types'; +import MainArticle from './MainArticle'; +import articleActions from '../../actions/ArticleActions'; +import Tags from './Tags'; +import Recommended from './Recommended'; +import CommentsBtn from './CommentsBtn'; +import Loader from '../Loader'; +import './index.scss'; + +const { viewArticle, fetchArticles } = articleActions; + +export class SingleArticle extends Component { + state = {} + + componentDidMount() { + const { slug } = this.props.match.params; + this.props.viewArticle(slug, this.props.history); + this.props.fetchArticles(10, 1); + } + + componentDidUpdate(prevProps) { + if (prevProps.match.params.slug !== this.props.match.params.slug) { + const { slug } = this.props.match.params; + this.props.viewArticle(slug); + } + } + + render() { + if (this.props.article === {} || this.props.loading) { + return ; + } + return ( +
+ + + + +
+ ); + } +} + +export const mapStateToProps = state => ({ + article: state.singleArticle.article, + loading: state.singleArticle.loading, + recommendedArticles: state.article, +}); + +SingleArticle.propTypes = { + match: PropTypes.shape({ + params: PropTypes.shape({ + slug: PropTypes.string, + }), + }).isRequired, + viewArticle: PropTypes.func.isRequired, + fetchArticles: PropTypes.func.isRequired, + article: PropTypes.shape({}).isRequired, + recommendedArticles: PropTypes.shape({}).isRequired, + loading: PropTypes.bool.isRequired, + history: PropTypes.shape({}).isRequired, +}; + +export default connect(mapStateToProps, { viewArticle, fetchArticles })(SingleArticle); diff --git a/src/components/SingleArticle/index.scss b/src/components/SingleArticle/index.scss new file mode 100644 index 0000000..e53846b --- /dev/null +++ b/src/components/SingleArticle/index.scss @@ -0,0 +1,3 @@ +.article-container { + padding-bottom: 100px; +} diff --git a/src/components/TrendingSection/Index.jsx b/src/components/TrendingSection/Index.jsx index b7920f0..56bfb69 100644 --- a/src/components/TrendingSection/Index.jsx +++ b/src/components/TrendingSection/Index.jsx @@ -32,6 +32,7 @@ const TrendingSection = (props) => { title, body, views, + slug, } = article.article; const { likes } = article; @@ -43,6 +44,7 @@ const TrendingSection = (props) => { imageUrl={imageUrl} text={body} date={date} + slug={slug} readTime={readTime} likeCount={likes} viewCount={views} diff --git a/src/components/articleLayout/index.jsx b/src/components/articleLayout/index.jsx index 243afa2..85269c9 100644 --- a/src/components/articleLayout/index.jsx +++ b/src/components/articleLayout/index.jsx @@ -1,6 +1,7 @@ import React from 'react'; import PropType from 'prop-types'; import { Trail } from 'react-spring/renderprops.cjs'; +import { Link } from 'react-router-dom'; import './index.scss'; const ArticleLayout = (props) => { @@ -16,6 +17,8 @@ const ArticleLayout = (props) => { ); } + const URL = '/articles/'; + /* istanbul ignore next */ return ( { > {singleArticle => prop => (
-
+
{ />
-

{singleArticle.article.title}

+

{singleArticle.article.title}

{`${singleArticle.article.body.substring(0, 150)}...`}

@@ -58,7 +61,7 @@ const ArticleLayout = (props) => {

-
+
)}
diff --git a/src/components/articleLayout/index.scss b/src/components/articleLayout/index.scss index 97e1a1a..d1282b7 100644 --- a/src/components/articleLayout/index.scss +++ b/src/components/articleLayout/index.scss @@ -6,6 +6,10 @@ cursor: pointer; } + &-title { + text-transform: capitalize; + } + &-article { border-bottom: $font-size-1 solid $color-grey; padding-bottom: 1.5rem; diff --git a/src/helpers/helpers.js b/src/helpers/helpers.js index ae3fcc8..f27727b 100644 --- a/src/helpers/helpers.js +++ b/src/helpers/helpers.js @@ -42,7 +42,6 @@ class Helpers { */ static checkDuplicate(array, property) { const unique = _.uniqBy(array, property); - // console.log(array); return unique.length < array.length; } diff --git a/src/index.html b/src/index.html index 58acc32..2e597ea 100644 --- a/src/index.html +++ b/src/index.html @@ -7,7 +7,7 @@ - Author's Haven + Authors Haven diff --git a/src/reducers/index.js b/src/reducers/index.js index 501bb12..0f2c889 100644 --- a/src/reducers/index.js +++ b/src/reducers/index.js @@ -8,6 +8,7 @@ import registerErrorsReducer from './registerErrorsReducer'; import articles from './articlesReducer'; import user from './getUserReducer'; import success from './success'; +import singleArticleReducer from './singleArticleReducer'; import createArticleReducer from './article/article'; import fetchCategoryReducer from './category/category'; @@ -17,6 +18,7 @@ export default combineReducers({ err: errorReducer, reset: resetReducer, article: articleReducer, + singleArticle: singleArticleReducer, signupErrors: registerErrorsReducer, success, articles, diff --git a/src/reducers/singleArticleReducer.js b/src/reducers/singleArticleReducer.js new file mode 100644 index 0000000..663daec --- /dev/null +++ b/src/reducers/singleArticleReducer.js @@ -0,0 +1,21 @@ +import { VIEW_SINGLE_ARTICLE, SET_LOADING } from '../actions/types'; + +const initialState = { article: {}, loading: false }; + +export default function (state = initialState, action) { + switch (action.type) { + case SET_LOADING: + return { + ...state, + loading: true, + }; + case VIEW_SINGLE_ARTICLE: + return { + ...state, + loading: false, + article: action.payload, + }; + default: + return state; + } +} diff --git a/src/utils/singleArticleMockStore.js b/src/utils/singleArticleMockStore.js new file mode 100644 index 0000000..26846a7 --- /dev/null +++ b/src/utils/singleArticleMockStore.js @@ -0,0 +1,42 @@ +export const successResponse = { + status: 200, + message: "This article's read time is 1 mins", + data: [ + { + article: { + id: 3, + title: 'Article 3', + slug: 'article-3', + description: '', + body: "Don't forth, upon sea of firmament and together good beast abundantly beginning called night let seas behold called place fruitful was fly deep cattle grass creeping won't us very day thing. Sea third fly place signs fill open our meat a. Our he, our also fowl firmament wherein you're light can't so firmament give. Also tree seed dominion created dry. You'll behold given the. Grass herb waters day forth, face seed seasons. Open don't gathered, very fowl over. Abundantly said tree. A herb air sea fly upon signs he together they're days there you Is lights darkness night divided. Hath.", + imageUrl: '', + isDraft: true, + views: 68, + read: 68, + readRatio: 0, + userId: 1, + catId: 1, + Category: { + id: 1, + name: 'Education', + }, + User: { + id: 1, + firstName: null, + lastName: null, + userName: 'Alpha', + bio: null, + imageUrl: null, + }, + updatedAt: '2019-08-23T15:33:22.265Z', + }, + tag: [], + readTime: 1, + }, + ], +}; + +export const errorResponse = { + status: 404, + message: 'Article not found', +}; diff --git a/src/views/Homepage.jsx b/src/views/Homepage.jsx index bc6dbbc..1a1bfe6 100644 --- a/src/views/Homepage.jsx +++ b/src/views/Homepage.jsx @@ -8,7 +8,7 @@ import ArticleActions from '../actions/ArticleActions'; import Loader from '../components/Loader'; import Helpers from '../helpers/helpers'; -const { fetchArticles, getMoreArticles } = ArticleActions; +const { fetchArticles, getMoreArticles, viewArticle } = ArticleActions; const { setCount, removeDuplicate, @@ -96,4 +96,4 @@ const mapStateToProps = (state) => { }; }; -export default connect(mapStateToProps, { fetchArticles, getMoreArticles })(Homepage); +export default connect(mapStateToProps, { fetchArticles, getMoreArticles, viewArticle })(Homepage); diff --git a/webpack.config.js b/webpack.config.js index 67ccece..2222701 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -7,6 +7,7 @@ module.exports = { output: { path: path.join(__dirname, '/dist'), filename: 'bundle.js', + publicPath: '/', }, resolve: { extensions: ['.js', '.jsx', '.scss', '.css'], From 1aa1f96d25f7b65b4eb77c7d9f61b8816aa42b0a Mon Sep 17 00:00:00 2001 From: Emmanuel Ihemegbulam Date: Mon, 26 Aug 2019 17:01:04 +0100 Subject: [PATCH 3/4] bug(homepage): fix inconsistent article card height - Remove wrapper div from tranding article cards - Refactor article card test [Delivers #168113071] --- _test_/ArticleCard.spec.js | 2 +- src/components/ArticleCard/Index.jsx | 42 +++++++++++++--------------- 2 files changed, 21 insertions(+), 23 deletions(-) diff --git a/_test_/ArticleCard.spec.js b/_test_/ArticleCard.spec.js index 936e31b..d555742 100644 --- a/_test_/ArticleCard.spec.js +++ b/_test_/ArticleCard.spec.js @@ -35,7 +35,7 @@ describe('ArticleCard', () => { }); it('renders a div component', () => { - expect(app.find('div').length).toBe(4); + expect(app.find('div').length).toBe(3); }); it('renders an img component', () => { diff --git a/src/components/ArticleCard/Index.jsx b/src/components/ArticleCard/Index.jsx index 23cb231..9afd56b 100644 --- a/src/components/ArticleCard/Index.jsx +++ b/src/components/ArticleCard/Index.jsx @@ -21,28 +21,26 @@ const ArticleCard = (props) => { const URL = `articles/${slug}`; return ( - -
-
- -
-

{title}

-

{`${truncText}...`}

-

- {date} -  /  - {readTime} -

-
- {likeCount} -   - -   -   - {viewCount} -   - Views -
+ +
+ +
+

{title}

+

{`${truncText}...`}

+

+ {date} +  /  + {readTime} +

+
+ {likeCount} +   + +   +   + {viewCount} +   + Views
From a3b6b8f0cafce7ec7a8f8bb80fd757d3ce2f47f3 Mon Sep 17 00:00:00 2001 From: Emmanuel Ihemegbulam Date: Mon, 26 Aug 2019 16:39:19 +0100 Subject: [PATCH 4/4] bug(homepage): add default image for homepage articles - Add default image url to article components [Delivers #168111066] --- package-lock.json | 132 +++++++++++------------ src/components/ArticleCard/Index.jsx | 2 +- src/components/FeaturedArticle/Index.jsx | 3 +- src/components/FeaturedSection/Index.jsx | 8 +- src/components/TrendingSection/Index.jsx | 2 +- 5 files changed, 74 insertions(+), 73 deletions(-) diff --git a/package-lock.json b/package-lock.json index 7a57a3f..b539dab 100644 --- a/package-lock.json +++ b/package-lock.json @@ -5824,28 +5824,28 @@ "dependencies": { "abbrev": { "version": "1.1.1", - "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", + "resolved": false, "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", "dev": true, "optional": true }, "ansi-regex": { "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "resolved": false, "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", "dev": true, "optional": true }, "aproba": { "version": "1.2.0", - "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", + "resolved": false, "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==", "dev": true, "optional": true }, "are-we-there-yet": { "version": "1.1.5", - "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.5.tgz", + "resolved": false, "integrity": "sha512-5hYdAkZlcG8tOLujVDTgCT+uPX0VnpAH28gWsLfzpXYm7wP6mp5Q/gYyR7YQ0cKVJcXJnl3j2kpBan13PtQf6w==", "dev": true, "optional": true, @@ -5856,14 +5856,14 @@ }, "balanced-match": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "resolved": false, "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", "dev": true, "optional": true }, "brace-expansion": { "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "resolved": false, "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", "dev": true, "optional": true, @@ -5874,42 +5874,42 @@ }, "chownr": { "version": "1.1.1", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.1.tgz", + "resolved": false, "integrity": "sha512-j38EvO5+LHX84jlo6h4UzmOwi0UgW61WRyPtJz4qaadK5eY3BTS5TY/S1Stc3Uk2lIM6TPevAlULiEJwie860g==", "dev": true, "optional": true }, "code-point-at": { "version": "1.1.0", - "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", + "resolved": false, "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", "dev": true, "optional": true }, "concat-map": { "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "resolved": false, "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", "dev": true, "optional": true }, "console-control-strings": { "version": "1.1.0", - "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", + "resolved": false, "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=", "dev": true, "optional": true }, "core-util-is": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "resolved": false, "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", "dev": true, "optional": true }, "debug": { "version": "4.1.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "resolved": false, "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", "dev": true, "optional": true, @@ -5919,28 +5919,28 @@ }, "deep-extend": { "version": "0.6.0", - "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "resolved": false, "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", "dev": true, "optional": true }, "delegates": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", + "resolved": false, "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=", "dev": true, "optional": true }, "detect-libc": { "version": "1.0.3", - "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz", + "resolved": false, "integrity": "sha1-+hN8S9aY7fVc1c0CrFWfkaTEups=", "dev": true, "optional": true }, "fs-minipass": { "version": "1.2.5", - "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-1.2.5.tgz", + "resolved": false, "integrity": "sha512-JhBl0skXjUPCFH7x6x61gQxrKyXsxB5gcgePLZCwfyCGGsTISMoIeObbrvVeP6Xmyaudw4TT43qV2Gz+iyd2oQ==", "dev": true, "optional": true, @@ -5950,14 +5950,14 @@ }, "fs.realpath": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "resolved": false, "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", "dev": true, "optional": true }, "gauge": { "version": "2.7.4", - "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", + "resolved": false, "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=", "dev": true, "optional": true, @@ -5974,7 +5974,7 @@ }, "glob": { "version": "7.1.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz", + "resolved": false, "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==", "dev": true, "optional": true, @@ -5989,14 +5989,14 @@ }, "has-unicode": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", + "resolved": false, "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=", "dev": true, "optional": true }, "iconv-lite": { "version": "0.4.24", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "resolved": false, "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", "dev": true, "optional": true, @@ -6006,7 +6006,7 @@ }, "ignore-walk": { "version": "3.0.1", - "resolved": "https://registry.npmjs.org/ignore-walk/-/ignore-walk-3.0.1.tgz", + "resolved": false, "integrity": "sha512-DTVlMx3IYPe0/JJcYP7Gxg7ttZZu3IInhuEhbchuqneY9wWe5Ojy2mXLBaQFUQmo0AW2r3qG7m1mg86js+gnlQ==", "dev": true, "optional": true, @@ -6016,7 +6016,7 @@ }, "inflight": { "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "resolved": false, "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", "dev": true, "optional": true, @@ -6027,21 +6027,21 @@ }, "inherits": { "version": "2.0.3", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "resolved": false, "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", "dev": true, "optional": true }, "ini": { "version": "1.3.5", - "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz", + "resolved": false, "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==", "dev": true, "optional": true }, "is-fullwidth-code-point": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "resolved": false, "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", "dev": true, "optional": true, @@ -6051,14 +6051,14 @@ }, "isarray": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "resolved": false, "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", "dev": true, "optional": true }, "minimatch": { "version": "3.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "resolved": false, "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", "dev": true, "optional": true, @@ -6068,14 +6068,14 @@ }, "minimist": { "version": "0.0.8", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", + "resolved": false, "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", "dev": true, "optional": true }, "minipass": { "version": "2.3.5", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-2.3.5.tgz", + "resolved": false, "integrity": "sha512-Gi1W4k059gyRbyVUZQ4mEqLm0YIUiGYfvxhF6SIlk3ui1WVxMTGfGdQ2SInh3PDrRTVvPKgULkpJtT4RH10+VA==", "dev": true, "optional": true, @@ -6086,7 +6086,7 @@ }, "minizlib": { "version": "1.2.1", - "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-1.2.1.tgz", + "resolved": false, "integrity": "sha512-7+4oTUOWKg7AuL3vloEWekXY2/D20cevzsrNT2kGWm+39J9hGTCBv8VI5Pm5lXZ/o3/mdR4f8rflAPhnQb8mPA==", "dev": true, "optional": true, @@ -6096,7 +6096,7 @@ }, "mkdirp": { "version": "0.5.1", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", + "resolved": false, "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", "dev": true, "optional": true, @@ -6106,14 +6106,14 @@ }, "ms": { "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", + "resolved": false, "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", "dev": true, "optional": true }, "needle": { "version": "2.3.0", - "resolved": "https://registry.npmjs.org/needle/-/needle-2.3.0.tgz", + "resolved": false, "integrity": "sha512-QBZu7aAFR0522EyaXZM0FZ9GLpq6lvQ3uq8gteiDUp7wKdy0lSd2hPlgFwVuW1CBkfEs9PfDQsQzZghLs/psdg==", "dev": true, "optional": true, @@ -6125,7 +6125,7 @@ }, "node-pre-gyp": { "version": "0.12.0", - "resolved": "https://registry.npmjs.org/node-pre-gyp/-/node-pre-gyp-0.12.0.tgz", + "resolved": false, "integrity": "sha512-4KghwV8vH5k+g2ylT+sLTjy5wmUOb9vPhnM8NHvRf9dHmnW/CndrFXy2aRPaPST6dugXSdHXfeaHQm77PIz/1A==", "dev": true, "optional": true, @@ -6144,7 +6144,7 @@ }, "nopt": { "version": "4.0.1", - "resolved": "https://registry.npmjs.org/nopt/-/nopt-4.0.1.tgz", + "resolved": false, "integrity": "sha1-0NRoWv1UFRk8jHUFYC0NF81kR00=", "dev": true, "optional": true, @@ -6155,14 +6155,14 @@ }, "npm-bundled": { "version": "1.0.6", - "resolved": "https://registry.npmjs.org/npm-bundled/-/npm-bundled-1.0.6.tgz", + "resolved": false, "integrity": "sha512-8/JCaftHwbd//k6y2rEWp6k1wxVfpFzB6t1p825+cUb7Ym2XQfhwIC5KwhrvzZRJu+LtDE585zVaS32+CGtf0g==", "dev": true, "optional": true }, "npm-packlist": { "version": "1.4.1", - "resolved": "https://registry.npmjs.org/npm-packlist/-/npm-packlist-1.4.1.tgz", + "resolved": false, "integrity": "sha512-+TcdO7HJJ8peiiYhvPxsEDhF3PJFGUGRcFsGve3vxvxdcpO2Z4Z7rkosRM0kWj6LfbK/P0gu3dzk5RU1ffvFcw==", "dev": true, "optional": true, @@ -6173,7 +6173,7 @@ }, "npmlog": { "version": "4.1.2", - "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz", + "resolved": false, "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", "dev": true, "optional": true, @@ -6186,21 +6186,21 @@ }, "number-is-nan": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", + "resolved": false, "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", "dev": true, "optional": true }, "object-assign": { "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "resolved": false, "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", "dev": true, "optional": true }, "once": { "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "resolved": false, "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", "dev": true, "optional": true, @@ -6210,21 +6210,21 @@ }, "os-homedir": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", + "resolved": false, "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=", "dev": true, "optional": true }, "os-tmpdir": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", + "resolved": false, "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", "dev": true, "optional": true }, "osenv": { "version": "0.1.5", - "resolved": "https://registry.npmjs.org/osenv/-/osenv-0.1.5.tgz", + "resolved": false, "integrity": "sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g==", "dev": true, "optional": true, @@ -6235,21 +6235,21 @@ }, "path-is-absolute": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "resolved": false, "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", "dev": true, "optional": true }, "process-nextick-args": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz", + "resolved": false, "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==", "dev": true, "optional": true }, "rc": { "version": "1.2.8", - "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", + "resolved": false, "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", "dev": true, "optional": true, @@ -6262,7 +6262,7 @@ "dependencies": { "minimist": { "version": "1.2.0", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "resolved": false, "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", "dev": true, "optional": true @@ -6271,7 +6271,7 @@ }, "readable-stream": { "version": "2.3.6", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", + "resolved": false, "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", "dev": true, "optional": true, @@ -6287,7 +6287,7 @@ }, "rimraf": { "version": "2.6.3", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", + "resolved": false, "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", "dev": true, "optional": true, @@ -6297,49 +6297,49 @@ }, "safe-buffer": { "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "resolved": false, "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", "dev": true, "optional": true }, "safer-buffer": { "version": "2.1.2", - "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "resolved": false, "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", "dev": true, "optional": true }, "sax": { "version": "1.2.4", - "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", + "resolved": false, "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==", "dev": true, "optional": true }, "semver": { "version": "5.7.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.0.tgz", + "resolved": false, "integrity": "sha512-Ya52jSX2u7QKghxeoFGpLwCtGlt7j0oY9DYb5apt9nPlJ42ID+ulTXESnt/qAQcoSERyZ5sl3LDIOw0nAn/5DA==", "dev": true, "optional": true }, "set-blocking": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "resolved": false, "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", "dev": true, "optional": true }, "signal-exit": { "version": "3.0.2", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", + "resolved": false, "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=", "dev": true, "optional": true }, "string-width": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "resolved": false, "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", "dev": true, "optional": true, @@ -6351,7 +6351,7 @@ }, "string_decoder": { "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "resolved": false, "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", "dev": true, "optional": true, @@ -6361,7 +6361,7 @@ }, "strip-ansi": { "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "resolved": false, "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", "dev": true, "optional": true, @@ -6371,14 +6371,14 @@ }, "strip-json-comments": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "resolved": false, "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", "dev": true, "optional": true }, "tar": { "version": "4.4.8", - "resolved": "https://registry.npmjs.org/tar/-/tar-4.4.8.tgz", + "resolved": false, "integrity": "sha512-LzHF64s5chPQQS0IYBn9IN5h3i98c12bo4NCO7e0sGM2llXQ3p2FGC5sdENN4cTW48O915Sh+x+EXx7XW96xYQ==", "dev": true, "optional": true, @@ -6394,14 +6394,14 @@ }, "util-deprecate": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "resolved": false, "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", "dev": true, "optional": true }, "wide-align": { "version": "1.1.3", - "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz", + "resolved": false, "integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==", "dev": true, "optional": true, @@ -6411,14 +6411,14 @@ }, "wrappy": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "resolved": false, "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", "dev": true, "optional": true }, "yallist": { "version": "3.0.3", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.0.3.tgz", + "resolved": false, "integrity": "sha512-S+Zk8DEWE6oKpV+vI3qWkaK+jSbIK86pCwe2IF/xwIpQ8jEuxpw9NyaGjmp9+BoJv5FV2piqCDcoCtStppiq2A==", "dev": true, "optional": true diff --git a/src/components/ArticleCard/Index.jsx b/src/components/ArticleCard/Index.jsx index 9afd56b..e979cba 100644 --- a/src/components/ArticleCard/Index.jsx +++ b/src/components/ArticleCard/Index.jsx @@ -23,7 +23,7 @@ const ArticleCard = (props) => { return (
- +

{title}

{`${truncText}...`}

diff --git a/src/components/FeaturedArticle/Index.jsx b/src/components/FeaturedArticle/Index.jsx index ec822d2..6d519f0 100644 --- a/src/components/FeaturedArticle/Index.jsx +++ b/src/components/FeaturedArticle/Index.jsx @@ -10,6 +10,7 @@ const FeaturedArticle = (props) => { customClass, slug, } = props; + const { wrapperClass, imageClass, @@ -20,7 +21,7 @@ const FeaturedArticle = (props) => { return ( - +

{title}

); diff --git a/src/components/FeaturedSection/Index.jsx b/src/components/FeaturedSection/Index.jsx index ce7eee3..8ce0f1b 100644 --- a/src/components/FeaturedSection/Index.jsx +++ b/src/components/FeaturedSection/Index.jsx @@ -57,13 +57,13 @@ const FeaturedSection = ({ data }) => { customClass={smallCustomClass} title={data[1].article.title} slug={data[1].article.slug} - imageUrl={featuredArticles[0].imageUrl} + imageUrl={data[1].article.imageUrl} /> @@ -71,13 +71,13 @@ const FeaturedSection = ({ data }) => { customClass={smallCustomClass} title={data[3].article.title} slug={data[3].article.slug} - imageUrl={featuredArticles[2].imageUrl} + imageUrl={data[3].article.imageUrl} /> diff --git a/src/components/TrendingSection/Index.jsx b/src/components/TrendingSection/Index.jsx index 56bfb69..ae90d8a 100644 --- a/src/components/TrendingSection/Index.jsx +++ b/src/components/TrendingSection/Index.jsx @@ -24,12 +24,12 @@ const TrendingSection = (props) => { { data.map((article, index) => { const { - imageUrl, date, readTime, } = trendingArticles[index % 5]; const { title, + imageUrl, body, views, slug,