From f62e032eeab978cb42feefde53f60959d32b6486 Mon Sep 17 00:00:00 2001 From: Sergey Sova Date: Fri, 24 May 2019 23:38:32 +0300 Subject: [PATCH 1/6] refactor(lib/fetching): add flow types --- src/lib/fetching/index.js | 78 +++++++++++++++++++++++++-------------- 1 file changed, 50 insertions(+), 28 deletions(-) diff --git a/src/lib/fetching/index.js b/src/lib/fetching/index.js index e1532dd..fb56b83 100644 --- a/src/lib/fetching/index.js +++ b/src/lib/fetching/index.js @@ -1,40 +1,62 @@ -import { createStore, createEvent } from "effector" - -export const createRequestState = (effect, initial = false) => - createStore(initial) - .on(effect, () => true) - .on(effect.done, () => false) - .on(effect.fail, () => false) - -/** - * @param {'initial'|'loading'|'done'|'fail'} initialStatus - */ -export const createFetching = ( - effect, - initialStatus = "initial", - { result: iresult = null, error: ierror = null, reset = createEvent() } = {}, -) => { - const result = createStore(iresult) +// @flow +import { + createStore, + createEvent, + type Effect, + type Event, + type Store, +} from "effector" + +// export const createRequestState = (effect, initial = false) => +// createStore(initial) +// .on(effect, () => true) +// .on(effect.done, () => false) +// .on(effect.fail, () => false) + +type Status = "initial" | "loading" | "done" | "fail" +type Params = { + result?: R, + error?: E, + reset?: Event, +} + +export type Fetching = { + result: Store, + error: Store, + status: Store, + isDone: Store, + isFailed: Store, + isLoading: Store, +} + +export function createFetching( + effect: Effect, + initialStatus: Status = "initial", + params?: Params = {}, +): Fetching { + const customReset = params.reset || createEvent() + + const result: Store = createStore(params.result || null) .reset(effect) .reset(effect.fail) - .reset(reset) - .on(effect.done, (_, value) => value) + .reset(customReset) + .on(effect.done, (_, { result: value }) => value) - const error = createStore(ierror) + const error: Store = createStore(params.error || null) .reset(effect) .reset(effect.done) - .reset(reset) - .on(effect.fail, (_, value) => value) + .reset(customReset) + .on(effect.fail, (_, { error: value }) => value) - const status = createStore(initialStatus) + const status: Store = createStore(initialStatus) .on(effect, () => "loading") .on(effect.done, () => "done") .on(effect.fail, () => "fail") - .reset(reset) + .on(customReset, () => "initial") - const isDone = status.map((state) => state === "done") - const isFailed = status.map((state) => state === "fail") - const isLoading = status.map((state) => state === "loading") + const isDone: Store = status.map((state) => state === "done") + const isFailed: Store = status.map((state) => state === "fail") + const isLoading: Store = status.map((state) => state === "loading") - return { status, result, error, isDone, isFailed, isLoading } + return { result, error, status, isDone, isFailed, isLoading } } From 58b3fb1f4955034725a2fbbb15f55c539b420a9d Mon Sep 17 00:00:00 2001 From: Sergey Sova Date: Fri, 24 May 2019 23:39:00 +0300 Subject: [PATCH 2/6] refactor(features/common): add types for common template --- src/features/common/templates/common-content.js | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/features/common/templates/common-content.js b/src/features/common/templates/common-content.js index 2da3e96..9643dc5 100644 --- a/src/features/common/templates/common-content.js +++ b/src/features/common/templates/common-content.js @@ -1,11 +1,17 @@ -import React from "react" +// @flow +import * as React from "react" import PropTypes from "prop-types" import styled from "styled-components" import { MainTemplate } from "@howtocards/ui/templates" import { Header } from "../organisms" -export const CommonContentTemplate = ({ header, children }) => ( +type Props = { + children: React.Node, + header?: React.Node, +} + +export const CommonContentTemplate = ({ header, children }: Props) => ( {children} From f7daf8fd12af8b9c7df9ea8b19ab8aee0c31a4d1 Mon Sep 17 00:00:00 2001 From: Sergey Sova Date: Fri, 24 May 2019 23:39:45 +0300 Subject: [PATCH 3/6] refactor(features/cards): fix fetching types and rename events --- src/features/cards/index.js | 5 +++++ src/features/cards/model/create.js | 8 ++++---- src/features/cards/model/edit.js | 22 +++++++++++++++------- src/features/cards/model/home.js | 7 +++++-- src/features/cards/model/view.js | 7 +++++-- src/features/cards/pages/create.js | 10 +++++----- 6 files changed, 39 insertions(+), 20 deletions(-) diff --git a/src/features/cards/index.js b/src/features/cards/index.js index d3cd495..5ebb81c 100644 --- a/src/features/cards/index.js +++ b/src/features/cards/index.js @@ -1,8 +1,13 @@ import "./model" +import { type Card } from "./types" + export { $registry as $cardsRegistry } from "./model/registry.store" +export { cardsToObject } from "./model/registry.model" export { actions as registryActions } from "./symbiotes/registry" export { CardItem, CardsList } from "./organisms" export { cardsRegistrySelector } from "./selectors" export { cardsRoutes } from "./routes" export { reducer as cardsReducer } from "./symbiotes" + +export { Card } diff --git a/src/features/cards/model/create.js b/src/features/cards/model/create.js index 5c78bde..7397395 100644 --- a/src/features/cards/model/create.js +++ b/src/features/cards/model/create.js @@ -11,7 +11,7 @@ import { cardsApi } from "../api" export const titleChanged = createEvent() export const contentChanged = createEvent() -export const submitButtonPressed = createEvent() +export const formSubmitted = createEvent() export const pageUnmounted = createEvent() const cardCreate = createEffect() @@ -32,12 +32,12 @@ $title.on(titleChanged.map(trimEvent), (_, title) => title) $content.on(contentChanged, (_, content) => content) $form.reset(pageUnmounted) -submitButtonPressed.watch(() => { +formSubmitted.watch(() => { cardCreate($form.getState()) }) cardCreate.use((form) => cardsApi.create(form)) -cardCreate.done.watch(() => { - history.push("/") +cardCreate.done.watch(({ result: card }) => { + history.push(`/open/${card.id}`) }) diff --git a/src/features/cards/model/edit.js b/src/features/cards/model/edit.js index 82fc72a..ecf8301 100644 --- a/src/features/cards/model/edit.js +++ b/src/features/cards/model/edit.js @@ -2,7 +2,7 @@ import { createEvent, createEffect, createStore } from "effector" import type { Effect, Store } from "effector" -import { createFetching } from "@lib/fetching" +import { createFetching, type Fetching } from "@lib/fetching" import { history } from "@lib/routing" import { cardsApi } from "../api" import type { Card } from "../types" @@ -13,15 +13,23 @@ export const contentChanged = createEvent() export const savePressed = createEvent() export const cardLoading: Effect = createEffect() -export const cardFetching = createFetching(cardLoading, "loading", { - reset: pageUnloaded, -}) +export const cardFetching: Fetching<*, void> = createFetching( + cardLoading, + "loading", + { + reset: pageUnloaded, + }, +) type SaveCard = { id: number, title: string, content: mixed } export const cardSaving: Effect = createEffect() -export const cardSaveFetching = createFetching(cardSaving, "initial", { - reset: pageUnloaded, -}) +export const cardSaveFetching: Fetching<*, void> = createFetching( + cardSaving, + "initial", + { + reset: pageUnloaded, + }, +) export const $card: Store = createStore(null) export const $title: Store = $card.map((card) => card && card.title) diff --git a/src/features/cards/model/home.js b/src/features/cards/model/home.js index 7d3ab3e..5d0bf73 100644 --- a/src/features/cards/model/home.js +++ b/src/features/cards/model/home.js @@ -2,7 +2,7 @@ import { createEvent, createEffect, createStore } from "effector" import type { Event, Effect, Store } from "effector" -import { createFetching } from "@lib/fetching" +import { createFetching, type Fetching } from "@lib/fetching" import { cardsApi } from "../api" import type { Card } from "../types" import { $registry } from "./registry.store" @@ -11,7 +11,10 @@ import { cardsToObject } from "./registry.model" export const pageReady: Event = createEvent() const homeCardsLoading: Effect = createEffect() -export const homeCardsFetching = createFetching(homeCardsLoading, "loading") +export const homeCardsFetching: Fetching<*, void> = createFetching( + homeCardsLoading, + "loading", +) export const $cardsIds: Store = createStore([]) diff --git a/src/features/cards/model/view.js b/src/features/cards/model/view.js index a810c84..7c2c8bc 100644 --- a/src/features/cards/model/view.js +++ b/src/features/cards/model/view.js @@ -2,7 +2,7 @@ import { createEffect, createStore, createEvent } from "effector" import type { Event, Effect, Store } from "effector" -import { createFetching } from "@lib/fetching" +import { createFetching, type Fetching } from "@lib/fetching" import { cardsApi } from "../api" import type { Card } from "../types" import { $registry } from "./registry.store" @@ -15,7 +15,10 @@ export const cardLoading: Effect< { card: Card }, void, > = createEffect() -export const cardFetching = createFetching(cardLoading, "loading") +export const cardFetching: Fetching<*, void> = createFetching( + cardLoading, + "loading", +) export const $card: Store = createStore(null) diff --git a/src/features/cards/pages/create.js b/src/features/cards/pages/create.js index 09a0335..5d4a235 100644 --- a/src/features/cards/pages/create.js +++ b/src/features/cards/pages/create.js @@ -12,14 +12,14 @@ import { contentChanged, titleChanged, pageUnmounted, - submitButtonPressed, + formSubmitted, } from "../model/create" import { CardsCommonTemplate } from "../templates/common" import { TitleInput } from "../atoms/title-input" -const onPressSubmit = (event) => { +const onFormSubmitted = (event) => { event.preventDefault() - submitButtonPressed() + formSubmitted() } export const CardCreatePage = () => { @@ -30,7 +30,7 @@ export const CardCreatePage = () => { ( -
+ <Content /> @@ -86,6 +86,6 @@ const Sidebar = () => ( </Row> <Row>Select text to use rich editor features.</Row> <Row>After creation your card will be available on the home page.</Row> - <ButtonPrimary onClick={onPressSubmit}>Create</ButtonPrimary> + <ButtonPrimary onClick={onFormSubmitted}>Create</ButtonPrimary> </Col> ) From 656d0338bd186d0f31d04deaede3751645998234 Mon Sep 17 00:00:00 2001 From: Sergey Sova <mail@sergeysova.com> Date: Fri, 24 May 2019 23:40:12 +0300 Subject: [PATCH 4/6] refactor(features/users): move to effector. remove redux --- src/features/users/api.js | 10 +- src/features/users/effects.js | 43 ------ src/features/users/index.js | 1 - src/features/users/model/current.js | 95 +++++++++++++ src/features/users/organisms/error.js | 23 ++-- src/features/users/organisms/loading.js | 3 +- src/features/users/pages/user.js | 138 ++++++++++--------- src/features/users/selectors.js | 28 ---- src/features/users/symbiotes/current.js | 26 ---- src/features/users/symbiotes/current.test.js | 83 ----------- src/features/users/symbiotes/index.js | 5 - src/features/users/templates/common.js | 10 +- src/features/users/types.js | 12 ++ src/reducers.js | 2 - 14 files changed, 206 insertions(+), 273 deletions(-) delete mode 100644 src/features/users/effects.js create mode 100644 src/features/users/model/current.js delete mode 100644 src/features/users/selectors.js delete mode 100644 src/features/users/symbiotes/current.js delete mode 100644 src/features/users/symbiotes/current.test.js delete mode 100644 src/features/users/symbiotes/index.js create mode 100644 src/features/users/types.js diff --git a/src/features/users/api.js b/src/features/users/api.js index 0c50ab6..51581b0 100644 --- a/src/features/users/api.js +++ b/src/features/users/api.js @@ -1,20 +1,24 @@ +// @flow import { request } from "@features/common" +import { type Card } from "@features/cards" +import { type User } from "./types" /** * Get info about user */ -const getInfo = (userId) => request("GET", `/users/${userId}/`) +const getInfo = (userId: number): Promise<User> => + request("GET", `/users/${userId}/`) /** * Get useful cards for user */ -const getUsefulCardsFor = (userId) => +const getUsefulCardsFor = (userId: number): Promise<{ cards: Card[] }> => request("GET", `/users/${userId}/cards/useful/`) /** * Get cards created by user */ -const getCardsCreatedBy = (userId) => +const getCardsCreatedBy = (userId: number): Promise<{ cards: Card[] }> => request("GET", `/users/${userId}/cards/authors/`) /** diff --git a/src/features/users/effects.js b/src/features/users/effects.js deleted file mode 100644 index 3333960..0000000 --- a/src/features/users/effects.js +++ /dev/null @@ -1,43 +0,0 @@ -import { handleFetching } from "symbiote-fetching" - -import { registryActions } from "@features/cards" - -import { usersApi } from "./api" -import { actions as currentActions } from "./symbiotes/current" - -/** - * @param {number} userId - */ -export const getUserWithCards = (userId) => - handleFetching(currentActions.fetch, { - noThrow: true, - async run(dispatch) { - const { user } = await dispatch(getUser, userId) - const [useful, created] = await dispatch(getCardsFor, userId) - - dispatch(registryActions.mergeById(useful.concat(created))) - dispatch( - currentActions.set({ - user, - useful: useful.map((c) => c.id), - created: created.map((c) => c.id), - }), - ) - - return { user, useful, created } - }, - }) - -const getCardsFor = (userId) => (dispatch) => { - const usefulCardsP = dispatch(usersApi.getUsefulCardsFor, userId) - .then(({ cards }) => cards) - .catch(() => []) - const createdCardsP = dispatch(usersApi.getCardsCreatedBy, userId) - .then(({ cards }) => cards) - .catch(() => []) - - return Promise.all([usefulCardsP, createdCardsP]) -} - -export const getUser = (userId) => (dispatch) => - dispatch(usersApi.getInfo, userId) diff --git a/src/features/users/index.js b/src/features/users/index.js index bde4999..90f187e 100644 --- a/src/features/users/index.js +++ b/src/features/users/index.js @@ -1,2 +1 @@ export { usersRoutes } from "./routes" -export { reducer as usersReducer } from "./symbiotes" diff --git a/src/features/users/model/current.js b/src/features/users/model/current.js new file mode 100644 index 0000000..eb9dc6a --- /dev/null +++ b/src/features/users/model/current.js @@ -0,0 +1,95 @@ +// @flow +import { + createEvent, + createStore, + createEffect, + type Effect, + type Store, + combine, +} from "effector" +import { createFetching, type Fetching } from "@lib/fetching" +import { $cardsRegistry, cardsToObject } from "@features/cards" +// TODO: fix type reexport +import { type Card } from "../../cards/types" +import { usersApi } from "../api" +import { type User } from "../types" + +export const pageMounted = createEvent<{ userId: number }>() + +const loadUser: Effect<number, User, void> = createEffect() +export const userFetching: Fetching<User, void> = createFetching( + loadUser, + "loading", +) + +type Cards = { + useful: Card[], + created: Card[], +} +const loadCards: Effect<number, Cards, void> = createEffect() +export const cardsFetching: Fetching<User, void> = createFetching( + loadCards, + "loading", +) + +export const $user: Store<?User> = createStore(null) +export const $cards: Store<{ + useful: number[], + created: number[], +}> = createStore({ + useful: [], + created: [], +}) + +pageMounted.watch(({ userId }) => { + loadUser(userId) + loadCards(userId) +}) + +loadUser.use((userId) => usersApi.getInfo(userId).then(({ user }) => user)) + +loadCards.use((userId) => + Promise.all([ + usersApi.getUsefulCardsFor(userId).then(({ cards }) => cards), + usersApi.getCardsCreatedBy(userId).then(({ cards }) => cards), + ]).then(([useful, created]) => ({ useful, created })), +) + +$user.on(loadUser.done, (_, { result: user }) => user) +$cards.on(loadCards.done, (_, { result: { useful, created } }) => ({ + useful: useful.map(({ id }) => id), + created: created.map(({ id }) => id), +})) + +$cardsRegistry.on( + loadCards.done, + (registry, { result: { useful, created } }) => ({ + ...registry, + ...cardsToObject(useful), + ...cardsToObject(created), + }), +) + +export const $isLoading: Store<boolean> = combine( + userFetching.isLoading, + cardsFetching.isLoading, + (userLoading, cardsLoading) => userLoading || cardsLoading, +) + +export const $isFailed: Store<boolean> = combine( + userFetching.isFailed, + cardsFetching.isFailed, + (userFailed, cardsFailed) => userFailed || cardsFailed, +) + +export const $error: Store<?string> = combine( + userFetching.isFailed, + userFetching.error, + cardsFetching.isFailed, + cardsFetching.error, + (userFailed, userError, cardsFailed, cardsError) => { + if (userFailed) return userError + if (cardsFailed) return cardsError + return undefined + }, +) diff --git a/src/features/users/organisms/error.js b/src/features/users/organisms/error.js index b06fff6..9192c6e 100644 --- a/src/features/users/organisms/error.js +++ b/src/features/users/organisms/error.js @@ -1,35 +1,36 @@ -import React from "react" +// @flow +import * as React from "react" import PropTypes from "prop-types" import { Card } from "@howtocards/ui" import { UsersCommonTemplate } from "../templates/common" -const messageFromError = (fetching) => { - switch (fetching.error) { +const messageFromError = (error) => { + switch (error) { case "user_not_found": return "Sorry! User not found" default: { if (process.env.NODE_ENV === "development") { - return `ERROR: ${fetching.error}` + return `ERROR: ${error}` } return "Unexpected error..." } } } -export const ErrorView = ({ fetching }) => ( +type Props = { + error: string, +} + +export const ErrorView = ({ error }: Props) => ( <UsersCommonTemplate> <Card> - <center style={{ padding: "2rem 0" }}> - {messageFromError(fetching)} - </center> + <center style={{ padding: "2rem 0" }}>{messageFromError(error)}</center> </Card> </UsersCommonTemplate> ) ErrorView.propTypes = { - fetching: PropTypes.shape({ - error: PropTypes.string, - }).isRequired, + error: PropTypes.string.isRequired, } diff --git a/src/features/users/organisms/loading.js b/src/features/users/organisms/loading.js index 624aebe..b9822dd 100644 --- a/src/features/users/organisms/loading.js +++ b/src/features/users/organisms/loading.js @@ -1,4 +1,5 @@ -import React from "react" +// @flow +import * as React from "react" import { Card } from "@howtocards/ui/atoms" import { UsersCommonTemplate } from "../templates/common" diff --git a/src/features/users/pages/user.js b/src/features/users/pages/user.js index 51c0e2b..a21ed8a 100644 --- a/src/features/users/pages/user.js +++ b/src/features/users/pages/user.js @@ -1,88 +1,90 @@ -import React from "react" +// @flow +import * as React from "react" import PropTypes from "prop-types" -import { fetchStatus } from "symbiote-fetching" -import { compose, withPropsOnChange, branch, renderComponent } from "recompose" -import { connect } from "react-redux" +import { useStore } from "effector-react" + import { Col, Row } from "@lib/styled-components-layout" import { H3, H1 } from "@howtocards/ui" import { CardsList, CardItem } from "@features/cards" import { UsersCommonTemplate } from "../templates/common" -import * as selectors from "../selectors" -import { getUserWithCards } from "../effects" import { LoadingView } from "../organisms/loading" import { ErrorView } from "../organisms/error" - -const mapStateToProps = (state, props) => ({ - user: selectors.currentUser(state), - fetching: selectors.userFetching(state), - useful: selectors.usefulCards(state), - created: selectors.createdCards(state), - userId: props.match.params.userId, -}) - -const mapDispatchToProps = (dispatch) => ({ - fetch: (userId) => dispatch(getUserWithCards, userId), -}) - -const enhance = compose( - connect( - mapStateToProps, - mapDispatchToProps, - ), - withPropsOnChange( - (props, next) => props.userId !== next.userId, - (props) => props.fetch(props.userId), - ), - branch((props) => isLoading(props.fetching), renderComponent(LoadingView)), - branch((props) => isFailed(props.fetching), renderComponent(ErrorView)), -) - -export const UserView = ({ user, created, useful }) => ( - <UsersCommonTemplate sidebar={<UserInfo user={user} />}> - <NamedCardsList - title={`Cards created by ${displayName(user)}`} - cards={created} - /> - <NamedCardsList - title={`Useful cards for ${displayName(user)}`} - cards={useful} - /> - </UsersCommonTemplate> -) - -UserView.propTypes = { - user: PropTypes.shape({ - id: PropTypes.number.isRequired, - email: PropTypes.string, - displayName: PropTypes.string, - }).isRequired, - created: PropTypes.arrayOf(PropTypes.number).isRequired, - useful: PropTypes.arrayOf(PropTypes.number).isRequired, +import { + $user, + $cards, + pageMounted, + $isLoading, + $isFailed, + $error, +} from "../model/current" + +type Props = { + match: { + params: { + userId: string, + }, + }, } -export const UserPage = enhance(UserView) - -const isLoading = (fetching) => - [fetchStatus.loading, fetchStatus.initial].includes(fetching.status) +export const UserPage = ({ match }: Props) => { + const userId = parseInt(match.params.userId, 10) + const user = useStore($user) + const { created, useful } = useStore($cards) + const isLoading = useStore($isLoading) + const isFailed = useStore($isFailed) + const error = useStore($error) + + React.useEffect(() => { + pageMounted({ userId }) + }, [userId]) + + if (isLoading) return <LoadingView /> + if (isFailed) + return <ErrorView error={error || "Cannot load. Please, try again later"} /> + + return ( + <UsersCommonTemplate sidebar={<UserInfo user={user} />}> + <NamedCardsList + title={`Cards created by ${displayName(user)}`} + cards={created} + /> + <NamedCardsList + title={`Useful cards for ${displayName(user)}`} + cards={useful} + /> + </UsersCommonTemplate> + ) +} -const isFailed = (fetching) => fetching.status === fetchStatus.failed +UserPage.propTypes = { + match: PropTypes.shape({ + params: PropTypes.shape({ + userId: PropTypes.string.isRequired, + }).isRequired, + }).isRequired, +} -const UserInfo = ({ user }) => ( - <Col gap="1rem"> - <Row> - <H3 narrow>{user.displayName || user.id}</H3> - </Row> - <CurrentUserInfo user={user} /> - </Col> -) +const UserInfo = ({ user }) => + user ? ( + <Col gap="1rem"> + <Row> + <H3 narrow>{user.displayName || user.id}</H3> + </Row> + <CurrentUserInfo user={user} /> + </Col> + ) : null UserInfo.propTypes = { user: PropTypes.shape({ id: PropTypes.number.isRequired, email: PropTypes.string, displayName: PropTypes.string, - }).isRequired, + }), +} + +UserInfo.defaultProps = { + user: null, } const CurrentUserInfo = ({ user }) => @@ -92,7 +94,7 @@ CurrentUserInfo.propTypes = { user: PropTypes.shape({ email: PropTypes.string }).isRequired, } -const displayName = (user) => user.displayName || "user" +const displayName = (user) => (user && user.displayName) || "user" const NamedCardsList = ({ cards, title }) => { if (cards && cards.length !== 0) { diff --git a/src/features/users/selectors.js b/src/features/users/selectors.js deleted file mode 100644 index b0260bc..0000000 --- a/src/features/users/selectors.js +++ /dev/null @@ -1,28 +0,0 @@ -import { createSelector } from "reselect" - -const rootSelector = (root) => root.users - -export const current = createSelector( - rootSelector, - (users) => users.current, -) - -export const currentUser = createSelector( - current, - (usersCurrent) => usersCurrent.model, -) - -export const userFetching = createSelector( - current, - (usersCurrent) => usersCurrent.fetching, -) - -export const usefulCards = createSelector( - current, - (usersCurrent) => usersCurrent.useful, -) - -export const createdCards = createSelector( - current, - (usersCurrent) => usersCurrent.created, -) diff --git a/src/features/users/symbiotes/current.js b/src/features/users/symbiotes/current.js deleted file mode 100644 index 64bcd85..0000000 --- a/src/features/users/symbiotes/current.js +++ /dev/null @@ -1,26 +0,0 @@ -import { createSymbiote } from "redux-symbiote" -import { initialFetching, createFetching } from "symbiote-fetching" - -const initialState = { - model: null, - useful: [], - created: [], - fetching: initialFetching, -} - -const symbiotes = { - fetch: createFetching("fetching"), - set: (state, { user, useful, created }) => ({ - ...state, - model: user, - useful, - created, - }), - reset: (state) => ({ ...state, model: null, useful: [], created: [] }), -} - -export const { actions, reducer } = createSymbiote( - initialState, - symbiotes, - "users/current", -) diff --git a/src/features/users/symbiotes/current.test.js b/src/features/users/symbiotes/current.test.js deleted file mode 100644 index 5accd86..0000000 --- a/src/features/users/symbiotes/current.test.js +++ /dev/null @@ -1,83 +0,0 @@ -import { initialFetching, fetchStatus } from "symbiote-fetching" -import { reducer, actions } from "./current" - -describe("actions.set", () => { - it("should set model, useful, created", () => { - const initial = { - model: null, - useful: [], - created: [], - fetching: initialFetching, - } - - const result = reducer( - initial, - actions.set({ - user: { id: 1 }, - useful: [{ id: 2 }], - created: [{ id: 3 }], - }), - ) - const expected = { - model: { id: 1 }, - useful: [{ id: 2 }], - created: [{ id: 3 }], - fetching: initialFetching, - } - - expect(result).toEqual(expected) - }) - - it("should overwrite model, useful, created if exists", () => { - const initial = { - model: { id: 900 }, - useful: [{ id: 200 }, { id: 300 }], - created: [{ id: 400 }, { id: 500 }], - fetching: initialFetching, - } - - const result = reducer( - initial, - actions.set({ - user: { id: 1 }, - useful: [{ id: 2 }], - created: [{ id: 3 }], - }), - ) - const expected = { - model: { id: 1 }, - useful: [{ id: 2 }], - created: [{ id: 3 }], - fetching: initialFetching, - } - - expect(result).toEqual(expected) - }) -}) - -describe("actions.reset", () => { - it("should clear model, useful, created", () => { - const initial = { - model: { id: 900 }, - useful: [{ id: 200 }, { id: 300 }], - created: [{ id: 400 }, { id: 500 }], - fetching: { - status: fetchStatus.loading, - error: null, - }, - } - - const result = reducer(initial, actions.reset()) - const expected = { - model: null, - useful: [], - created: [], - fetching: { - status: fetchStatus.loading, - error: null, - }, - } - - expect(result).toEqual(expected) - }) -}) diff --git a/src/features/users/symbiotes/index.js b/src/features/users/symbiotes/index.js deleted file mode 100644 index 56ce9df..0000000 --- a/src/features/users/symbiotes/index.js +++ /dev/null @@ -1,5 +0,0 @@ -import { combineReducers } from "redux" - -import { reducer as current } from "./current" - -export const reducer = combineReducers({ current }) diff --git a/src/features/users/templates/common.js b/src/features/users/templates/common.js index 8b9f06b..b6cb7d1 100644 --- a/src/features/users/templates/common.js +++ b/src/features/users/templates/common.js @@ -1,4 +1,5 @@ -import React from "react" +// @flow +import * as React from "react" import PropTypes from "prop-types" import { CommonContentTemplate } from "@features/common" @@ -9,7 +10,12 @@ import { SidebarTemplate, } from "@howtocards/ui" -export const UsersCommonTemplate = ({ children, sidebar }) => ( +type Props = { + children: React.Node, + sidebar?: React.Node, +} + +export const UsersCommonTemplate = ({ children, sidebar }: Props) => ( <CommonContentTemplate> <Container> <SidebarTemplate diff --git a/src/features/users/types.js b/src/features/users/types.js new file mode 100644 index 0000000..f49c351 --- /dev/null +++ b/src/features/users/types.js @@ -0,0 +1,12 @@ +export type CurrentUser = { + id: number, + displayName: string, + email: string, +} + +export type ExternalUser = { + id: number, + displayName: string, +} + +export type User = ExternalUser | CurrentUser diff --git a/src/reducers.js b/src/reducers.js index f0bb7bf..8ac20f7 100644 --- a/src/reducers.js +++ b/src/reducers.js @@ -2,11 +2,9 @@ import { combineReducers } from "redux" import { connectRouter } from "connected-react-router" import { cardsReducer as cards } from "@features/cards" -import { usersReducer as users } from "@features/users" export const createReducer = (history) => combineReducers({ router: connectRouter(history), cards, - users, }) From 4811bfded5098f4e2fb205adba3b180d2c0af81e Mon Sep 17 00:00:00 2001 From: Sergey Sova <mail@sergeysova.com> Date: Fri, 24 May 2019 23:55:05 +0300 Subject: [PATCH 5/6] chore(app): remove redux --- package.json | 7 - src/features/cards/effects.js | 85 -------- src/features/cards/index.js | 3 - src/features/cards/selectors.js | 34 --- src/features/cards/symbiotes/index.js | 6 - src/features/cards/symbiotes/page.js | 23 --- src/features/cards/symbiotes/page.test.js | 16 -- src/features/cards/symbiotes/registry.js | 47 ----- src/features/cards/symbiotes/registry.test.js | 195 ------------------ .../common/organisms/authenticated.js | 5 +- src/features/common/organisms/header.js | 1 + src/features/common/pages/not-found.js | 3 +- src/index.js | 21 +- src/lib/routing/index.js | 9 - src/reducers.js | 10 - src/store.js | 28 --- yarn.lock | 82 +------- 17 files changed, 19 insertions(+), 556 deletions(-) delete mode 100644 src/features/cards/effects.js delete mode 100644 src/features/cards/selectors.js delete mode 100644 src/features/cards/symbiotes/index.js delete mode 100644 src/features/cards/symbiotes/page.js delete mode 100644 src/features/cards/symbiotes/page.test.js delete mode 100644 src/features/cards/symbiotes/registry.js delete mode 100644 src/features/cards/symbiotes/registry.test.js delete mode 100644 src/reducers.js delete mode 100644 src/store.js diff --git a/package.json b/package.json index 9e36b64..df957a9 100644 --- a/package.json +++ b/package.json @@ -132,18 +132,12 @@ "react-dev-utils": "^7.0.3", "react-dom": "^16.8.3", "react-hot-loader": "^4.7.1", - "react-redux": "^6.0.1", "react-router": "^4.4.0-beta.8", "react-router-config": "^4.4.0-beta.8", "react-router-dom": "^4.4.0-beta.6", "react-select": "^2.4.1", "react-test-renderer": "^16.8.3", "react-testing-library": "^6.0.0", - "recompose": "^0.30.0", - "redux": "^4.0.1", - "redux-execute": "^2.0.1", - "redux-symbiote": "^3.0.2", - "reselect": "^4.0.0", "resolve": "1.10.0", "sass-loader": "7.1.0", "slate": "^0.44.10", @@ -154,7 +148,6 @@ "styled-components": "^4.1.3", "styled-icons": "^7.4.0", "styled-normalize": "^8.0.6", - "symbiote-fetching": "^0.7.0", "terser-webpack-plugin": "1.2.2", "typescript": "^3.4.1", "url-loader": "1.1.2", diff --git a/src/features/cards/effects.js b/src/features/cards/effects.js deleted file mode 100644 index 7ea1aed..0000000 --- a/src/features/cards/effects.js +++ /dev/null @@ -1,85 +0,0 @@ -import { handleFetching } from "symbiote-fetching" -import { push } from "connected-react-router" - -import { cardsApi } from "./api" -import { actions as page } from "./symbiotes/page" -import { actions as registry } from "./symbiotes/registry" -import { cardsRegistrySelector } from "./selectors" - -export const cardCreate = ({ title, content }) => async (dispatch) => { - try { - const { result, ok, error } = await dispatch(cardsApi.create, { - title, - content, - }) - - dispatch(push("/")) - return { ok, error, result } - } catch (error) { - return { ok: false, error: String(error) } - } -} - -export const cardEdit = ({ id, title, content }) => async (dispatch) => { - try { - const { result, ok, error } = await dispatch(cardsApi.edit, { - id, - title, - content, - }) - - dispatch(push("/")) - return { ok, error, result } - } catch (error) { - return { ok: false, error: String(error) } - } -} - -export const getAllCards = () => - handleFetching(page.fetchAll, { - noThrow: true, - async run(dispatch) { - const { ok, result, error } = await dispatch(cardsApi.getLatest) - - if (ok) { - dispatch(registry.mergeById(result)) - dispatch(page.setCardsIds(result.map((i) => i.id))) - } - - throw new Error(error) - }, - }) - -export const fetchFullCard = (id) => - handleFetching(page.fetchOne, { - noThrow: true, - async run(dispatch) { - const { ok, result, error } = await dispatch(cardsApi.getById, id) - - if (ok) { - dispatch(registry.setCard(result.card)) - } - - throw new Error(error) - }, - }) - -export const setUsefulMark = (cardId) => async (dispatch, getState) => { - const card = cardsRegistrySelector(getState())[cardId] - const isUseful = !card.meta.isUseful - const prom = dispatch(cardsApi.markUseful, cardId, isUseful) - - dispatch(registry.setUsefulMark({ cardId, isUseful })) - - try { - const { ok, error, result } = await prom - - if (!ok) { - throw new Error(error) - } - dispatch(registry.setCard(result.card)) - } catch (_error) { - // Rollback - dispatch(registry.setUsefulMark({ cardId, isUseful: !isUseful })) - } -} diff --git a/src/features/cards/index.js b/src/features/cards/index.js index 5ebb81c..c91b4cc 100644 --- a/src/features/cards/index.js +++ b/src/features/cards/index.js @@ -4,10 +4,7 @@ import { type Card } from "./types" export { $registry as $cardsRegistry } from "./model/registry.store" export { cardsToObject } from "./model/registry.model" -export { actions as registryActions } from "./symbiotes/registry" export { CardItem, CardsList } from "./organisms" -export { cardsRegistrySelector } from "./selectors" export { cardsRoutes } from "./routes" -export { reducer as cardsReducer } from "./symbiotes" export { Card } diff --git a/src/features/cards/selectors.js b/src/features/cards/selectors.js deleted file mode 100644 index 86295df..0000000 --- a/src/features/cards/selectors.js +++ /dev/null @@ -1,34 +0,0 @@ -import { createSelector } from "reselect" - -/** - * @root - */ -export const cardsRootSelector = createSelector( - (root) => root.cards, - (cards) => cards, -) - -export const cardsPageSelector = createSelector( - cardsRootSelector, - (cards) => cards.page, -) - -export const cardsPageFetchingAllSelector = createSelector( - cardsPageSelector, - (page) => page.fetchingAll, -) - -export const cardsPageFetchingOneSelector = createSelector( - cardsPageSelector, - (page) => page.fetchingOne, -) - -export const cardsPageCardsIdsSelector = createSelector( - cardsPageSelector, - (page) => page.cardsIds, -) - -export const cardsRegistrySelector = createSelector( - cardsRootSelector, - (cards) => cards.registry, -) diff --git a/src/features/cards/symbiotes/index.js b/src/features/cards/symbiotes/index.js deleted file mode 100644 index b8399b8..0000000 --- a/src/features/cards/symbiotes/index.js +++ /dev/null @@ -1,6 +0,0 @@ -import { combineReducers } from "redux" - -import { reducer as registry } from "./registry" -import { reducer as page } from "./page" - -export const reducer = combineReducers({ page, registry }) diff --git a/src/features/cards/symbiotes/page.js b/src/features/cards/symbiotes/page.js deleted file mode 100644 index 268229b..0000000 --- a/src/features/cards/symbiotes/page.js +++ /dev/null @@ -1,23 +0,0 @@ -import { createSymbiote } from "redux-symbiote" -import { initialFetching, createFetching } from "symbiote-fetching" - -export const initialState = { - fetchingAll: initialFetching, - fetchingOne: initialFetching, - cardsIds: [], -} - -const symbiotes = { - fetchAll: createFetching("fetchingAll"), - fetchOne: createFetching("fetchOne"), - setCardsIds: (state, cardsIds) => ({ - ...state, - cardsIds, - }), -} - -export const { actions, reducer } = createSymbiote( - initialState, - symbiotes, - "cards/page", -) diff --git a/src/features/cards/symbiotes/page.test.js b/src/features/cards/symbiotes/page.test.js deleted file mode 100644 index 9936bab..0000000 --- a/src/features/cards/symbiotes/page.test.js +++ /dev/null @@ -1,16 +0,0 @@ -import { initialFetching } from "symbiote-fetching" -import { initialState, reducer, actions } from "./page" -/* eslint-disable no-magic-numbers */ - -describe("actions.setCardsIds", () => { - it("should set cards ids", () => { - const result = reducer(initialState, actions.setCardsIds([1, 2, 3])) - const expected = { - fetchingAll: initialFetching, - fetchingOne: initialFetching, - cardsIds: [1, 2, 3], - } - - expect(result).toEqual(expected) - }) -}) diff --git a/src/features/cards/symbiotes/registry.js b/src/features/cards/symbiotes/registry.js deleted file mode 100644 index a04edd6..0000000 --- a/src/features/cards/symbiotes/registry.js +++ /dev/null @@ -1,47 +0,0 @@ -import { createSymbiote } from "redux-symbiote" - -const initialState = {} - -const symbiotes = { - reset: () => initialState, - merge: (state, cards) => ({ - ...state, - ...cards, - }), - mergeById: (state, cards) => ({ - ...state, - ...cards.reduce((accum, card) => { - // eslint-disable-next-line no-param-reassign - accum[card.id] = card - return accum - }, {}), - }), - setCard: (state, card) => ({ - ...state, - [card.id]: { ...state[card.id], ...card }, - }), - setUsefulMark: (state, { cardId, isUseful }) => - state[cardId] - ? { - ...state, - [cardId]: { - id: cardId, - ...state[cardId], - meta: { ...state[cardId].meta, isUseful }, - }, - } - : state, - delete: (state, cardId) => - state[cardId] - ? { - ...state, - [cardId]: undefined, - } - : state, -} - -export const { actions, reducer } = createSymbiote( - initialState, - symbiotes, - "cards/registry", -) diff --git a/src/features/cards/symbiotes/registry.test.js b/src/features/cards/symbiotes/registry.test.js deleted file mode 100644 index 9f49c7a..0000000 --- a/src/features/cards/symbiotes/registry.test.js +++ /dev/null @@ -1,195 +0,0 @@ -import { reducer, actions } from "./registry" -/* eslint-disable no-magic-numbers */ - -describe("actions.reset", () => { - it("should clear", () => { - const result = reducer({ 1: {}, 2: {} }, actions.reset()) - const expected = {} - - expect(result).toEqual(expected) - }) -}) - -describe("actions.merge", () => { - it("should add new cards to empty", () => { - const result = reducer({}, actions.merge({ 1: { id: 1 } })) - const expected = { - 1: { id: 1 }, - } - - expect(result).toEqual(expected) - }) - - it("should add new cards to exists", () => { - const initial = { 2: { id: 2 } } - - const result = reducer( - initial, - actions.merge({ 1: { id: 1 }, 3: { id: 3 } }), - ) - const expected = { - 1: { id: 1 }, - 2: { id: 2 }, - 3: { id: 3 }, - } - - expect(result).toEqual(expected) - }) - - it("should overwrite exists cards", () => { - const initial = { 1: { id: 1, value: "FOO" } } - - const result = reducer( - initial, - actions.merge({ 1: { id: 1, value: "BAR" } }), - ) - const expected = { - 1: { id: 1, value: "BAR" }, - } - - expect(result).toEqual(expected) - }) -}) - -describe("actions.mergeById", () => { - it("should merge array to object by id", () => { - const initial = { - 1: { id: 1, value: 1 }, - 2: { id: 2, value: 2 }, - } - - const result = reducer( - initial, - actions.mergeById([{ id: 3, value: 3 }, { id: 4, value: 4 }]), - ) - const expected = { - 1: { id: 1, value: 1 }, - 2: { id: 2, value: 2 }, - 3: { id: 3, value: 3 }, - 4: { id: 4, value: 4 }, - } - - expect(result).toEqual(expected) - }) - - it("should add new items from array", () => { - const initial = {} - - const result = reducer( - initial, - actions.mergeById([{ id: 1, value: 1 }, { id: 2, value: 2 }]), - ) - const expected = { - 1: { id: 1, value: 1 }, - 2: { id: 2, value: 2 }, - } - - expect(result).toEqual(expected) - }) - - it("should overwrite items by id", () => { - const initial = { - 1: { - id: 1, - value: "FOO", - }, - } - - const result = reducer( - initial, - actions.mergeById([{ id: 1, value: "BAR" }, { id: 2, value: "ZAF" }]), - ) - const expected = { - 1: { id: 1, value: "BAR" }, - 2: { id: 2, value: "ZAF" }, - } - - expect(result).toEqual(expected) - }) -}) - -describe("actions.setCard", () => { - it("should add one card by id", () => { - const initial = {} - const card = { id: 1, value: "TITLE" } - - const result = reducer(initial, actions.setCard(card)) - const expected = { - 1: card, - } - - expect(result).toEqual(expected) - }) - - it("should merge card data with exists", () => { - const initial = { 1: { id: 1, title: "FOO" } } - - const result = reducer(initial, actions.setCard({ id: 1, content: "BAR" })) - const expected = { - 1: { - id: 1, - title: "FOO", - content: "BAR", - }, - } - - expect(result).toEqual(expected) - }) -}) - -describe("actions.setUsefulMark", () => { - it("should set useful mark to exists card", () => { - const initial = { - 1: { - id: 1, - title: "FOO", - meta: { - isUseful: false, - isEditable: false, - }, - }, - } - - const result = reducer( - initial, - actions.setUsefulMark({ cardId: 1, isUseful: true }), - ) - const expected = { - 1: { - id: 1, - title: "FOO", - meta: { - isUseful: true, - isEditable: false, - }, - }, - } - - expect(result).toEqual(expected) - }) - - it("do nothing if not found", () => { - const initial = { 2: { id: 2 } } - - const result = reducer( - initial, - actions.setUsefulMark({ cardId: 1, isUseful: true }), - ) - const expected = { 2: { id: 2 } } - - expect(result).toEqual(expected) - }) -}) - -describe("actions.delete", () => { - it("should remove card if exists", () => { - const initial = { 1: { id: 1 }, 2: { id: 2 } } - - const result = reducer(initial, actions.delete(2)) - const expected = { - 1: { id: 1 }, - } - - expect(result).toEqual(expected) - }) -}) diff --git a/src/features/common/organisms/authenticated.js b/src/features/common/organisms/authenticated.js index cae4332..62b6e54 100644 --- a/src/features/common/organisms/authenticated.js +++ b/src/features/common/organisms/authenticated.js @@ -1,6 +1,5 @@ import React from "react" import PropTypes from "prop-types" -import { fetchStatus } from "symbiote-fetching" import { WithAccount } from "./with-account" @@ -9,8 +8,8 @@ export const Authenticated = ({ render }) => ( renderExists={render} render={({ fetching }) => { switch (fetching.status) { - case fetchStatus.initial: - case fetchStatus.failed: + case "initial": + case "failed": return <div>Authenticated only</div> default: diff --git a/src/features/common/organisms/header.js b/src/features/common/organisms/header.js index f00c59a..a073f93 100644 --- a/src/features/common/organisms/header.js +++ b/src/features/common/organisms/header.js @@ -2,6 +2,7 @@ import React from "react" import PropTypes from "prop-types" import styled from "styled-components" import { Link } from "react-router-dom" + import { WithThemeToggler } from "@lib/theme-context" import { Container } from "@howtocards/ui" import { WithAccount } from "./with-account" diff --git a/src/features/common/pages/not-found.js b/src/features/common/pages/not-found.js index 90722e9..971688c 100644 --- a/src/features/common/pages/not-found.js +++ b/src/features/common/pages/not-found.js @@ -1,4 +1,5 @@ -import React from "react" +// @flow +import * as React from "react" import styled from "styled-components" import { CommonContentTemplate } from "@features/common" diff --git a/src/index.js b/src/index.js index 4246224..14ac1e2 100644 --- a/src/index.js +++ b/src/index.js @@ -1,24 +1,21 @@ -import React from "react" +import * as React from "react" import ReactDom from "react-dom" -import { Provider } from "react-redux" -import { ConnectedRouter } from "connected-react-router" +import { Router } from "react-router" import { history } from "@lib/routing" import { App } from "./app" -import { configureStore } from "./store" const root = document.querySelector("#root") -const store = configureStore({ history }) const render = () => { - ReactDom.render( - <Provider store={store}> - <ConnectedRouter history={history}> + if (root) { + ReactDom.render( + <Router history={history}> <App /> - </ConnectedRouter> - </Provider>, - root, - ) + </Router>, + root, + ) + } } if (module.hot) { diff --git a/src/lib/routing/index.js b/src/lib/routing/index.js index 31ff80f..64ab126 100644 --- a/src/lib/routing/index.js +++ b/src/lib/routing/index.js @@ -1,12 +1,3 @@ import { createBrowserHistory } from "history" -import React from "react" -import { Redirect } from "react-router-dom" - -export const redirectTo = (path, key) => () => <Redirect key={key} to={path} /> -export const redirectFrom = (from, to) => ({ - path: from, - exact: true, - component: redirectTo(to), -}) export const history = createBrowserHistory() diff --git a/src/reducers.js b/src/reducers.js deleted file mode 100644 index 8ac20f7..0000000 --- a/src/reducers.js +++ /dev/null @@ -1,10 +0,0 @@ -import { combineReducers } from "redux" -import { connectRouter } from "connected-react-router" - -import { cardsReducer as cards } from "@features/cards" - -export const createReducer = (history) => - combineReducers({ - router: connectRouter(history), - cards, - }) diff --git a/src/store.js b/src/store.js deleted file mode 100644 index a7af1eb..0000000 --- a/src/store.js +++ /dev/null @@ -1,28 +0,0 @@ -import { createStore, applyMiddleware, compose } from "redux" -import { routerMiddleware } from "connected-react-router" -import { createExecute } from "redux-execute" - -import { createReducer } from "./reducers" - -const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose // eslint-disable-line no-underscore-dangle, max-len - -export function configureStore({ history, initialState = {} } = {}) { - const middlewares = [createExecute({ log: false }), routerMiddleware(history)] - - const store = createStore( - createReducer(history), - initialState, - composeEnhancers(applyMiddleware(...middlewares)), - ) - - if (module.hot) { - module.hot.accept("./reducers", () => { - // eslint-disable-next-line global-require - const next = require("./reducers") - - store.replaceReducer(next.createReducer(history)) - }) - } - - return store -} diff --git a/yarn.lock b/yarn.lock index fcd27fc..be3bb86 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3271,11 +3271,6 @@ change-case@^3.0.2: upper-case "^1.1.1" upper-case-first "^1.1.0" -change-emitter@^0.1.2: - version "0.1.6" - resolved "https://registry.yarnpkg.com/change-emitter/-/change-emitter-0.1.6.tgz#e8b2fe3d7f1ab7d69a32199aff91ea6931409515" - integrity sha1-6LL+PX8at9aaMhma/5HqaTFAlRU= - character-entities-html4@^1.0.0: version "1.1.2" resolved "https://registry.yarnpkg.com/character-entities-html4/-/character-entities-html4-1.1.2.tgz#c44fdde3ce66b52e8d321d6c1bf46101f0150610" @@ -4493,11 +4488,6 @@ depd@~1.1.2: resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.2.tgz#9bcd52e14c097763e749b274c4346ed2e560b5a9" integrity sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak= -deprecated@0.0.2: - version "0.0.2" - resolved "https://registry.yarnpkg.com/deprecated/-/deprecated-0.0.2.tgz#bc9dcf9bce9174fcf9090cf1295131c439c682fd" - integrity sha1-vJ3Pm86RdPz5CQzxKVExxDnGgv0= - des.js@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/des.js/-/des.js-1.0.0.tgz#c074d2e2aa6a8a9a07dbd61f9a15c2cd83ec8ecc" @@ -5727,7 +5717,7 @@ fb-watchman@^2.0.0: dependencies: bser "^2.0.0" -fbjs@^0.8.0, fbjs@^0.8.1: +fbjs@^0.8.0: version "0.8.17" resolved "https://registry.yarnpkg.com/fbjs/-/fbjs-0.8.17.tgz#c4d598ead6949112653d6588b01a5cdcd9f90fdd" integrity sha1-xNWY6taUkRJlPWWIsBpc3Nn5D90= @@ -6609,7 +6599,7 @@ hoek@4.x.x: resolved "https://registry.yarnpkg.com/hoek/-/hoek-4.2.1.tgz#9634502aa12c445dd5a7c5734b572bb8738aacbb" integrity sha512-QLg82fGkfnJ/4iy1xZ81/9SIJiq1NGFUMGs6ParyjBZr6jW2Ufj/snDqTHixNlHdPNwN2RLVD0Pi3igeK9+JfA== -hoist-non-react-statics@^2.3.1, hoist-non-react-statics@^2.5.0, hoist-non-react-statics@^2.5.5: +hoist-non-react-statics@^2.5.0, hoist-non-react-statics@^2.5.5: version "2.5.5" resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-2.5.5.tgz#c5903cf409c0dfd908f388e619d86b9c1174cb47" integrity sha512-rqcy4pJo55FTTLWt+bU8ukscqHeE/e9KWvsOW2b/a3afxQZhwkQdT1rPPCJ0rYXdj4vNcasY8zHTH+jF/qStxw== @@ -11216,12 +11206,12 @@ react-input-autosize@^2.2.1: dependencies: prop-types "^15.5.8" -react-is@^16.6.0, react-is@^16.7.0, react-is@^16.8.1, react-is@^16.8.2, react-is@^16.8.4, react-is@^16.8.6: +react-is@^16.6.0, react-is@^16.7.0, react-is@^16.8.1, react-is@^16.8.4, react-is@^16.8.6: version "16.8.6" resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.8.6.tgz#5bbc1e2d29141c9fbdfed456343fe2bc430a6a16" integrity sha512-aUk3bHfZ2bRSVFFbbeVS4i+lNPZr3/WM5jT2J5omUVV1zzcs1nAaf3l51ctA5FFvCRbhrH0bdAsRRQddFJZPtA== -react-lifecycles-compat@^3.0.2, react-lifecycles-compat@^3.0.4: +react-lifecycles-compat@^3.0.4: version "3.0.4" resolved "https://registry.yarnpkg.com/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz#4f1a273afdfc8f3488a8c516bfda78f872352362" integrity sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA== @@ -11254,18 +11244,6 @@ react-powerplug@^1.0.0: dependencies: "@babel/runtime" "^7.0.0" -react-redux@^6.0.1: - version "6.0.1" - resolved "https://registry.yarnpkg.com/react-redux/-/react-redux-6.0.1.tgz#0d423e2c1cb10ada87293d47e7de7c329623ba4d" - integrity sha512-T52I52Kxhbqy/6TEfBv85rQSDz6+Y28V/pf52vDWs1YRXG19mcFOGfHnY2HsNFHyhP+ST34Aih98fvt6tqwVcQ== - dependencies: - "@babel/runtime" "^7.3.1" - hoist-non-react-statics "^3.3.0" - invariant "^2.2.4" - loose-envify "^1.4.0" - prop-types "^15.7.2" - react-is "^16.8.2" - react-router-config@^4.4.0-beta.8: version "4.4.0-beta.8" resolved "https://registry.yarnpkg.com/react-router-config/-/react-router-config-4.4.0-beta.8.tgz#164fff4e91afad2c83a0b97544d2981628613801" @@ -11518,18 +11496,6 @@ rechoir@^0.6.2: dependencies: resolve "^1.1.6" -recompose@^0.30.0: - version "0.30.0" - resolved "https://registry.yarnpkg.com/recompose/-/recompose-0.30.0.tgz#82773641b3927e8c7d24a0d87d65aeeba18aabd0" - integrity sha512-ZTrzzUDa9AqUIhRk4KmVFihH0rapdCSMFXjhHbNrjAWxBuUD/guYlyysMnuHjlZC/KRiOKRtB4jf96yYSkKE8w== - dependencies: - "@babel/runtime" "^7.0.0" - change-emitter "^0.1.2" - fbjs "^0.8.1" - hoist-non-react-statics "^2.3.1" - react-lifecycles-compat "^3.0.2" - symbol-observable "^1.0.4" - recursive-readdir@2.2.2: version "2.2.2" resolved "https://registry.yarnpkg.com/recursive-readdir/-/recursive-readdir-2.2.2.tgz#9946fb3274e1628de6e36b2f6714953b4845094f" @@ -11545,27 +11511,6 @@ redent@^2.0.0: indent-string "^3.0.0" strip-indent "^2.0.0" -redux-execute@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/redux-execute/-/redux-execute-2.0.1.tgz#e56dba8c20612a736ec2f9bbe406bcf4933e0810" - integrity sha512-MhXHNZEWmzK3Vig+71cSp/8wOr2tSh2WVx9xfKRen85v68PTVzAb01t/wO7k6VXrw8/cbOOQM92O7TKzwlDCzA== - -redux-symbiote@^3.0.2: - version "3.1.0" - resolved "https://registry.yarnpkg.com/redux-symbiote/-/redux-symbiote-3.1.0.tgz#21e3528c3b524342b4f42766644b393547aad79b" - integrity sha512-16THhoM5bgRW00rwqJt5TgaElaTJcjcIvb+EQ73U2VHSxjUJmLZrUK4cbR2nSr8RtCLErq9e52SOaGcu2itN/w== - dependencies: - nanoid "^2.0.1" - symbiote-symbol "^3.0.0" - -redux@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/redux/-/redux-4.0.1.tgz#436cae6cc40fbe4727689d7c8fae44808f1bfef5" - integrity sha512-R7bAtSkk7nY6O/OYMVR9RiBI+XghjF9rlbl5806HJbQph0LJVHZrU5oaO4q70eUKiqMRqm4y07KLTlMZ2BlVmg== - dependencies: - loose-envify "^1.4.0" - symbol-observable "^1.2.0" - regenerate-unicode-properties@^8.0.2: version "8.0.2" resolved "https://registry.yarnpkg.com/regenerate-unicode-properties/-/regenerate-unicode-properties-8.0.2.tgz#7b38faa296252376d363558cfbda90c9ce709662" @@ -11911,11 +11856,6 @@ 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" @@ -13039,19 +12979,7 @@ swap-case@^1.1.0: lower-case "^1.1.1" upper-case "^1.1.1" -symbiote-fetching@^0.7.0: - version "0.7.0" - resolved "https://registry.yarnpkg.com/symbiote-fetching/-/symbiote-fetching-0.7.0.tgz#98f405f1e756dd4dfed0b62bc7be3afb7288f2af" - integrity sha512-nZ5Snrs3/CFnNLsP6Mh+3sYvDiUrYcG7TWpHO3Ti7k3wgWVgQ+/01afZU70RZiLGNYDGlZRlObjokBEeGR8eQg== - dependencies: - deprecated "0.0.2" - -symbiote-symbol@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/symbiote-symbol/-/symbiote-symbol-3.0.0.tgz#dcc63ec453581c12cfc0a4043b2307795e5adfad" - integrity sha512-kuThtzbNBZPJOd/rg4a0EXtnL4rB6Swxe6cSImMIcRiYG1vZajTeSs2RRdpE6ipyubHzCLgQ8/Un/+A/SKowAA== - -symbol-observable@^1.0.4, symbol-observable@^1.1.0, symbol-observable@^1.2.0: +symbol-observable@^1.1.0, symbol-observable@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/symbol-observable/-/symbol-observable-1.2.0.tgz#c22688aed4eab3cdc2dfeacbb561660560a00804" integrity sha512-e900nM8RRtGhlV36KGEU9k65K3mPb1WV70OdjfxlG2EAuM1noi/E/BaW/uMhL7bPEssK8QV57vN3esixjUvcXQ== From 407ae5b9e3332d628b51b10c761d01f12d185b5a Mon Sep 17 00:00:00 2001 From: Sergey Sova <mail@sergeysova.com> Date: Fri, 24 May 2019 23:58:23 +0300 Subject: [PATCH 6/6] fix(features/cards): title input should have corresponding bg color --- src/features/cards/atoms/title-input.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/features/cards/atoms/title-input.js b/src/features/cards/atoms/title-input.js index fe19f77..2ff8d83 100644 --- a/src/features/cards/atoms/title-input.js +++ b/src/features/cards/atoms/title-input.js @@ -2,10 +2,13 @@ import styled from "styled-components" export const TitleInput = styled.input` box-sizing: border-box; - background-color: none; + background-color: inherit; + color: currentColor; outline: none; box-shadow: none; border: none; font-size: 1.8em; margin-bottom: 1rem; + + ${({ theme }) => theme.embed.card} `