Dwayne Harris 5 years ago
parent
commit
9d13a01dfb
  1. 10
      src/components/app/app.scss
  2. 2
      src/components/app/app.tsx
  3. 7
      src/components/pages/group-admin/group-admin.tsx
  4. 10
      src/components/pages/self/index.ts
  5. 144
      src/components/pages/self/self.tsx
  6. 5
      src/types/index.ts
  7. 4
      src/utils/normalization.ts

10
src/components/app/app.scss

@ -15,7 +15,7 @@ $white-ter: hsl(0, 0%, 96%);
$family-sans-serif: "Open Sans", sans-serif;
$primary: $blue;
$title-weight: 400;
// $title-weight: 400;
$body-background-color: $white-ter;
$body-size: 14px;
@ -37,7 +37,6 @@ $body-size: 14px;
div#main-menu {
background: linear-gradient(135deg, $primary, darken($primary, 20%));
// border-left: 1px solid $grey-lighter;
bottom: 0;
display: flex;
flex-direction: column;
@ -59,7 +58,7 @@ div.centered-content {
border-radius: $radius;
margin: 1rem auto;
padding: 2rem;
width: 80%;
width: 95%;
div.centered-content-icon {
border-radius: 100px;
@ -70,6 +69,11 @@ div.centered-content {
}
}
.centered-content-narrow {
@extend div.centered-content;
width: 75%;
}
div#navigation {
flex-grow: 1;

2
src/components/app/app.tsx

@ -65,7 +65,7 @@ const App: FC<Props> = ({ collapsed, fetching, fetchSelf, setChecked }) => {
<Route path="/c/:id/admin/:tab?" component={GroupAdmin} />
<Route path="/c/:id/register" component={RegisterGroup} />
<Route path="/communities" component={Directory} />
<Route path="/self" component={Self} />
<Route path="/self/:tab?" component={Self} />
<Route path="/developers" component={Developers} />
<Route path="/about" component={About} />
</div>

7
src/components/pages/group-admin/group-admin.tsx

@ -6,7 +6,7 @@ import { faCheckCircle } from '@fortawesome/free-solid-svg-icons'
import { useDeepCompareEffect } from 'src/hooks'
import { setTitle } from 'src/utils'
import { Group, GroupMembershipType } from 'src/types'
import { Group, GroupMembershipType, Tab } from 'src/types'
import PageHeader from 'src/components/page-header'
import TextareaField from 'src/components/forms/textarea-field'
@ -15,11 +15,6 @@ import GroupInvitations from 'src/components/group-invitations'
import GroupLogs from 'src/components/group-logs'
import Loading from 'src/components/pages/loading'
interface Tab {
id: string
label: string
}
interface Params {
id: string
tab: string

10
src/components/pages/self/index.ts

@ -2,9 +2,10 @@ import { Dispatch } from 'redux'
import { connect } from 'react-redux'
import { unauthenticate } from 'src/actions/authentication'
import { getAuthenticated, getChecked, getAuthenticatedUser } from 'src/selectors/authentication'
import { AppState } from 'src/types'
import { AppState, User } from 'src/types'
import Self from './self'
import { initForm, initField, setFieldValue } from 'src/actions/forms'
const mapStateToProps = (state: AppState) => ({
checked: getChecked(state),
@ -13,6 +14,13 @@ const mapStateToProps = (state: AppState) => ({
})
const mapDispatchToProps = (dispatch: Dispatch) => ({
initForm: (user: User) => {
dispatch(initForm())
dispatch(initField('name'))
dispatch(initField('about'))
dispatch(setFieldValue('name', user.name as string))
dispatch(setFieldValue('about', user.about as string))
},
logout: async () => {
localStorage.clear()
dispatch(unauthenticate())

144
src/components/pages/self/self.tsx

@ -1,37 +1,57 @@
import React, { FC, useEffect } from 'react'
import { RouteComponentProps } from 'react-router-dom'
import React, { FC } from 'react'
import { Link, RouteComponentProps } from 'react-router-dom'
import moment from 'moment'
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
import { faDoorOpen } from '@fortawesome/free-solid-svg-icons'
import { faDoorOpen, faCheckCircle, faPlusCircle, faIdCard, faEnvelope } from '@fortawesome/free-solid-svg-icons'
import { useAuthenticationCheck } from 'src/hooks'
import { useAuthenticationCheck, useDeepCompareEffect } from 'src/hooks'
import { setTitle } from 'src/utils'
import { User } from 'src/types'
import { User, Tab } from 'src/types'
import PageHeader from 'src/components/page-header'
import Loading from 'src/components/pages/loading'
import TextField from 'src/components/forms/text-field'
import TextareaField from 'src/components/forms/textarea-field'
export interface Props extends RouteComponentProps {
interface Params {
tab: string
}
export interface Props extends RouteComponentProps<Params> {
checked: boolean
authenticated: boolean
user?: User
initForm: (user: User) => void
logout: () => void
}
const Self: FC<Props> = ({ checked, authenticated, user, logout, history }) => {
const Self: FC<Props> = ({ checked, authenticated, user, initForm, logout, history, match }) => {
useAuthenticationCheck(checked, authenticated, history)
useEffect(() => {
if (user) setTitle(`${user.name} (@${user.id})`)
const tab = match.params.tab || ''
const tabs: Tab[] = [
{
id: '',
label: 'Posts',
},
{
id: 'settings',
label: 'Settings',
},
{
id: 'apps',
label: 'Apps',
},
]
useDeepCompareEffect(() => {
if (user) {
setTitle(`${user.name} (@${user.id})`)
initForm(user)
}
}, [user])
if (!user) {
return (
<div>
<PageHeader title="Self" />
<div className="main-content"></div>
</div>
)
}
if (!user) return <Loading />
return (
<div>
@ -47,14 +67,88 @@ const Self: FC<Props> = ({ checked, authenticated, user, logout, history }) => {
</div>
</nav>
<p>
<button className="button is-danger" onClick={() => logout()}>
<span className="icon is-small">
<FontAwesomeIcon icon={faDoorOpen} />
</span>
<span>Log Out</span>
</button>
</p>
<div className="centered-content">
<div className="tabs is-large">
<ul>
{tabs.map(t => (
<li key={t.id} className={tab === t.id ? 'is-active': ''}>
<Link to={`/self/${t.id}`}>
{t.label}
</Link>
</li>
))}
</ul>
</div>
<div className="container">
{tab === '' &&
<p>No Posts.</p>
}
{tab === 'settings' &&
<div>
<div className="field">
<label className="label">ID</label>
<div className="control has-icons-left">
<input className="input" type="text" value={user.id} readOnly />
<span className="icon is-small is-left">
<FontAwesomeIcon icon={faIdCard} />
</span>
</div>
</div>
<br />
<div className="field">
<label className="label">Email</label>
<div className="control has-icons-left">
<input className="input" type="email" value={user.email} readOnly />
<span className="icon is-small is-left">
<FontAwesomeIcon icon={faEnvelope} />
</span>
</div>
</div>
<br />
<TextField name="name" label="Name" placeholder="Your Display Name" />
<br />
<TextareaField name="about" label="About" placeholder="Your Bio" />
<br />
<button className="button is-primary">
<span className="icon is-small">
<FontAwesomeIcon icon={faCheckCircle} />
</span>
<span>Save</span>
</button>
<hr />
<button className="button is-danger" onClick={() => logout()}>
<span className="icon is-small">
<FontAwesomeIcon icon={faDoorOpen} />
</span>
<span>Log Out</span>
</button>
</div>
}
{tab === 'apps' &&
<div>
<p>No Apps.</p>
<br />
<button className="button is-primary">
<span className="icon is-small">
<FontAwesomeIcon icon={faPlusCircle} />
</span>
<span>Create a new App</span>
</button>
</div>
}
</div>
</div>
</div>
</div>
)

5
src/types/index.ts

@ -15,6 +15,11 @@ export interface ClassDictionary {
[name: string]: boolean
}
export interface Tab {
id: string
label: string
}
export * from './entities'
export * from './store'

4
src/utils/normalization.ts

@ -61,7 +61,7 @@ export function normalize(entities: Entity[], type: EntityType): NormalizeResult
return set(type, newStore, {
...invitation,
user: set(EntityType.Group, newStore, invitation.user),
user: set(EntityType.User, newStore, invitation.user),
})
})
@ -72,7 +72,7 @@ export function normalize(entities: Entity[], type: EntityType): NormalizeResult
return set(type, newStore, {
...log,
user: set(EntityType.Group, newStore, log.user),
user: set(EntityType.User, newStore, log.user),
})
})

Loading…
Cancel
Save