Skip to content
This repository was archived by the owner on Mar 19, 2021. It is now read-only.

add settings page with displayName change logic #89

Merged
merged 6 commits into from
Aug 18, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,5 +15,13 @@ module.exports = {
],
quotes: "off",
"react/sort-comp": "off",
"sort-imports": [
"warn",
{
ignoreCase: false,
ignoreDeclarationSort: true,
ignoreMemberSort: false,
},
],
},
}
6 changes: 5 additions & 1 deletion babel.config.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
module.exports = {
presets: ["react-app"],
plugins: ["react-hot-loader/babel", "styled-components"],
plugins: [
"react-hot-loader/babel",
"styled-components",
"@babel/proposal-optional-chaining",
],
env: {
development: {
plugins: [
Expand Down
4 changes: 3 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,6 @@
"browser-cookies": "^1.2.0",
"case-sensitive-paths-webpack-plugin": "2.2.0",
"commitizen": "^3.0.7",
"connected-react-router": "^6.3.1",
"css-loader": "1.0.0",
"cz-customizable": "^5.3.0",
"date-fns": "^1.30.1",
Expand Down Expand Up @@ -158,5 +157,8 @@
"webpack-manifest-plugin": "2.0.4",
"webpackbar": "^3.1.5",
"workbox-webpack-plugin": "3.6.3"
},
"devDependencies": {
"@babel/plugin-proposal-optional-chaining": "^7.2.0"
}
}
36 changes: 34 additions & 2 deletions src/api/account.js
Original file line number Diff line number Diff line change
@@ -1,16 +1,48 @@
// @flow
import { request } from "@features/common"

type RegisterData = {
export type CurrentUser = {|
id: number,
displayName: string,
email: string,
|}

export type ExternalUser = {|
id: number,
displayName: string,
|}

export type User = ExternalUser | CurrentUser

type RegisterData = {|
email: string,
password: string,
}
|}
/**
* https://github.com/howtocards/frontend/tree/master/mock-server/server#post-account-create-user-account
*/
const createAccount = (registerData: RegisterData): Promise<number> =>
request("POST", "/account/", { body: registerData })

export type Settings = {|
displayName: string | null,
gravatarEmail: string | null,
|}

export type UpdateSettings = {|
displayName?: string,
|}

const updateSettings = (
data: UpdateSettings,
): Promise<{ settings: Settings }> =>
request("PUT", "/account/settings/", { body: data })

const getSettings = (): Promise<{ settings: Settings }> =>
request("GET", "/account/settings/")

export const accountApi = {
createAccount,
updateSettings,
getSettings,
}
2 changes: 1 addition & 1 deletion src/features/cards/model/registry.events.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// @flow
import { createEvent, createEffect, type Effect } from "effector"
import { type Effect, createEffect, createEvent } from "effector"
import type { Card } from "../types"

export const clearRegistry = createEvent<void>()
Expand Down
4 changes: 2 additions & 2 deletions src/features/cards/model/registry.store.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// @flow
import { createStore, sample, type Store } from "effector"
import { cardsApi, type Card } from "@api/cards"
import { type Store, createStore, sample } from "effector"
import { type Card, cardsApi } from "@api/cards"
import {
clearRegistry,
setUsefulMark,
Expand Down
3 changes: 2 additions & 1 deletion src/features/cards/organisms/card-item.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
/* eslint-disable react/prop-types */
import React, { useState } from "react"
import styled, { css } from "styled-components"
import PropTypes from "prop-types"
Expand All @@ -7,7 +8,7 @@ import { Link as RouterLink } from "react-router-dom"
import { RichEditor } from "@lib/rich-text"
import { Row } from "@lib/styled-components-layout"
import * as Menu from "@lib/context-menu"
import { Link, H2, Icon, Text, Modal, CardNarrow } from "@howtocards/ui"
import { CardNarrow, H2, Icon, Link, Modal, Text } from "@howtocards/ui"

export const CardItem = ({ onUsefulClick, card, maximized }) => (
<CardNarrow>
Expand Down
2 changes: 1 addition & 1 deletion src/features/cards/organisms/card-skeleton.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import React from "react"
import styled, { css } from "styled-components"

import { Row } from "@lib/styled-components-layout"
import { H2, Icon, CardNarrow } from "@howtocards/ui"
import { CardNarrow, H2, Icon } from "@howtocards/ui"

export const CardSkeleton = () => (
<SkeletonCard>
Expand Down
2 changes: 1 addition & 1 deletion src/features/cards/templates/common.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@ import * as React from "react"

import { CommonContentTemplate } from "@features/common"
import {
Container,
FooterContent,
Sidebar,
Container,
SidebarTemplate,
} from "@howtocards/ui"

Expand Down
2 changes: 1 addition & 1 deletion src/features/common/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,5 @@ export { CommonContentTemplate } from "./templates"
export { Header, AccountLoader, Authenticated } from "./organisms"
export { NotFoundPage } from "./pages/not-found"
export { request } from "./lib/request"
export { sessionDropped } from "./model/session.events"
export { sessionDropped, loadSession } from "./model/session.events"
export { tokenChanged } from "./model/token"
6 changes: 3 additions & 3 deletions src/features/common/model/session.events.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { createEvent, createEffect, type Event, type Effect } from "effector"
import { type Effect, type Event, createEffect, createEvent } from "effector"
import { createFetching } from "@lib/fetching"
import { type Session } from "./session.store"

export const sessionDropped: Event<*> = createEvent()

export const sessionFetchProcessing: Effect<void, Session, *> = createEffect()
export const sessionFetching = createFetching(sessionFetchProcessing)
export const loadSession: Effect<void, Session, *> = createEffect()
export const loadSessionFetching = createFetching(loadSession)
10 changes: 5 additions & 5 deletions src/features/common/model/session.model.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,14 @@ import { forward } from "effector"
import { commonApi } from "../api"
import { tokenDropped } from "./token"
import { $session } from "./session.store"
import { sessionFetchProcessing, sessionDropped } from "./session.events"
import { loadSession, sessionDropped } from "./session.events"

sessionFetchProcessing.use(() => commonApi.getCurrentAccount())
loadSession.use(() => commonApi.getCurrentAccount())

$session
.reset(sessionDropped)
.on(sessionFetchProcessing.done, (_, { result }) => result.user)
.on(sessionFetchProcessing.fail, () => null)
.on(loadSession.done, (_, { result }) => result.user)
.on(loadSession.fail, () => null)

forward({ from: sessionFetchProcessing.fail, to: tokenDropped })
forward({ from: loadSession.fail, to: tokenDropped })
forward({ from: sessionDropped, to: tokenDropped })
2 changes: 1 addition & 1 deletion src/features/common/model/session.store.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// @flow
import { createStore, type Store } from "effector"
import { type Store, createStore } from "effector"

export type Session = {
id: number,
Expand Down
6 changes: 3 additions & 3 deletions src/features/common/model/token.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// @flow
import Cookies from "browser-cookies"
import { createStore, createEvent } from "effector"
import { sessionFetchProcessing } from "./session.events"
import { createEvent, createStore } from "effector"
import { loadSession } from "./session.events"

const TOKEN_ID = "hw-token"

Expand All @@ -16,7 +16,7 @@ $token.on(tokenDropped, () => null)
$token.watch((token) => {
if (token) {
Cookies.set(TOKEN_ID, token)
setTimeout(() => sessionFetchProcessing(), 0)
setTimeout(() => loadSession(), 0)
}
})

Expand Down
4 changes: 2 additions & 2 deletions src/features/common/organisms/account-loader.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,15 @@ import { useEffect } from "react"
import { useStore } from "effector-react"

import { $session } from "../model/session.store"
import { sessionFetchProcessing } from "../model/session.events"
import { loadSession } from "../model/session.events"
import { $token } from "../model/token"

export const AccountLoader = ({ children }) => {
const session = useStore($session)
const token = useStore($token)

useEffect(() => {
sessionFetchProcessing()
loadSession()
}, [])

if (token && !session) return null
Expand Down
5 changes: 3 additions & 2 deletions src/features/common/organisms/header.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
// @flow
/* eslint-disable react/prop-types */
import * as React from "react"
import PropTypes from "prop-types"
import styled from "styled-components"
Expand Down Expand Up @@ -34,11 +35,11 @@ const linksForUser = ({ account }) => (
<NavLink to="/new/card">+ New</NavLink>
<Menu.Context
as={NavItem}
trigger={<span>Profile</span>}
trigger={<span>{account.displayName || "Profile"}</span>}
menu={({ close }) => (
<>
<Menu.Item as={Link} to={`/user/${account.id}`} onClick={close}>
{account.email}
Profile: {account.email}
</Menu.Item>
<Menu.Item as={Link} to="/settings" onClick={close}>
Settings
Expand Down
2 changes: 1 addition & 1 deletion src/features/join/model/logout.model.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { sessionDropped } from "@features/common"
import { history } from "@lib/routing"
import { logoutPressed, cancelPressed } from "./logout.events"
import { cancelPressed, logoutPressed } from "./logout.events"

logoutPressed.watch(() => {
sessionDropped()
Expand Down
6 changes: 3 additions & 3 deletions src/features/join/pages/logout.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@ import React from "react"

import { Col, Row } from "@lib/styled-components-layout"

import { Card, ButtonPrimary, Button } from "@howtocards/ui/atoms"
import { Button, ButtonPrimary, Card } from "@howtocards/ui/atoms"
import { PrimitiveFooter } from "@howtocards/ui/organisms"
import { Container, CenterContentTemplate } from "@howtocards/ui/templates"
import { CenterContentTemplate, Container } from "@howtocards/ui/templates"

import { logoutPressed, cancelPressed } from "../model/logout.events"
import { cancelPressed, logoutPressed } from "../model/logout.events"

export const LogoutPage = () => (
<CenterContentTemplate footer={<PrimitiveFooter />}>
Expand Down
6 changes: 3 additions & 3 deletions src/features/search/model/main.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
// @flow
import { createEvent, createEffect, createStore, forward } from "effector"
import { createEffect, createEvent, createStore, forward } from "effector"

import { createFetching, type Fetching } from "@lib/fetching"
import { cardsToObject, $cardsRegistry } from "@features/cards"
import { type Fetching, createFetching } from "@lib/fetching"
import { $cardsRegistry, cardsToObject } from "@features/cards"
import type { Card } from "@features/common"

import { searchApi } from "../api"
Expand Down
2 changes: 1 addition & 1 deletion src/features/search/model/search-history.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// @flow
import { createStore, createEvent } from "effector"
import { createEvent, createStore } from "effector"

export const $searchHistory = createStore<string[]>([])

Expand Down
2 changes: 1 addition & 1 deletion src/features/search/pages/main.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import React from "react"
import { useStore } from "effector-react"

import { CardsList, CardsCommonTemplate } from "@features/cards"
import { CardsCommonTemplate, CardsList } from "@features/cards"
import { $searchCardsIds } from "../model/main"

export const SearchMainPage = () => {
Expand Down
2 changes: 2 additions & 0 deletions src/features/settings/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
// @flow
export * from "./templates"
2 changes: 2 additions & 0 deletions src/features/settings/templates/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
// @flow
export { SettingsTemplate } from "./settings"
47 changes: 47 additions & 0 deletions src/features/settings/templates/settings.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
// @flow
import * as React from "react"
// TODO: remove styles
import styled from "styled-components"

import { CommonContentTemplate } from "@features/common"
import { Card, Container, H1 } from "@howtocards/ui"

type Props = {
children: React.Node,
title?: string,
}

export const SettingsTemplate = ({ children, title }: Props) => (
<CommonContentTemplate>
<Container>
<Main>
<Card>
{title && <H1>{title}</H1>}
{children}
</Card>
</Main>
</Container>
</CommonContentTemplate>
)

SettingsTemplate.defaultProps = {
title: undefined,
}

const Main = styled.main`
display: flex;
flex-direction: column;
margin-top: 2rem;
flex-grow: 1;
align-items: center;

${Card} {
max-width: 60rem;
width: 100%;
}

${H1} {
margin-top: 0;
margin-bottom: 0;
}
`
12 changes: 6 additions & 6 deletions src/features/users/model/current.js
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
// @flow
import {
createEvent,
createStore,
createEffect,
type Effect,
type Store,
combine,
createEffect,
createEvent,
createStore,
} from "effector"
import { createFetching, type Fetching } from "@lib/fetching"
import { type User } from "@api/account"
import { type Fetching, createFetching } 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 }>()

Expand All @@ -27,7 +27,7 @@ type Cards = {
created: Card[],
}
const loadCards: Effect<number, Cards, void> = createEffect()
export const cardsFetching: Fetching<User, void> = createFetching(
export const cardsFetching: Fetching<Cards, void> = createFetching(
loadCards,
"loading",
)
Expand Down
Loading