Skip to content

Commit

Permalink
Merge pull request #668 from Khaalid-oh/trendingtopics
Browse files Browse the repository at this point in the history
Add `User Permissions` tab to Settings
  • Loading branch information
Rassl authored Dec 11, 2023
2 parents 06ddc2b + 6d9e7d8 commit 897b4fa
Show file tree
Hide file tree
Showing 9 changed files with 254 additions and 49 deletions.
4 changes: 2 additions & 2 deletions build/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,8 @@
<noscript>You need to enable JavaScript to run this app.</noscript>
<div id="root"></div>
<!-- Add entry point 👇 -->


<!--
This HTML file is a template.
If you open it directly in the browser, you will see an empty page.
Expand Down
3 changes: 3 additions & 0 deletions public/svg-icons/PersonAdd.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ export const TypeTweet = ({ text, imageUrl, date, twitterHandle, name, verified
const PictureWrapper = styled(Flex)`
img {
width: 64px;
height: 64px
height: 64px;
border-radius: 50%;
object-fit: cover;
}
Expand Down
6 changes: 5 additions & 1 deletion src/components/App/SideBar/Trending/index.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import { Button, Skeleton } from '@mui/material'
import { useEffect, useState } from 'react'
import { useFormContext } from 'react-hook-form'
import { ClipLoader } from 'react-spinners'
import styled from 'styled-components'
import PlusIcon from '~/components/Icons/PlusIcon'
import SentimentDataIcon from '~/components/Icons/SentimentDataIcon'
Expand All @@ -12,6 +11,7 @@ import { useModal } from '~/stores/useModalStore'
import { Trending as TrendingType } from '~/types'
import { colors } from '~/utils/colors'
import { BriefDescription } from './BriefDescriptionModal'
import { ClipLoader } from 'react-spinners'

const TRENDING_TOPICS = ['Drivechain', 'Ordinals', 'L402', 'Nostr', 'AI']

Expand Down Expand Up @@ -157,6 +157,10 @@ const Wrapper = styled(Flex)`
font-size: 24px;
}
}
.Trendingwrapper {
margin-left: 23px;
margin-top: 20px;
}
.Trendingwrapper {
margin-left: 23px;
Expand Down
13 changes: 13 additions & 0 deletions src/components/Icons/PersonAdd.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
/* eslint-disable */
import React from 'react'

const PersonAdd: React.FC<React.SVGProps<SVGSVGElement>> = (props) => (
<svg width="2em" height="2em" viewBox="0 0 22 16" fill="currentColor" xmlns="http://www.w3.org/2000/svg">
<path
d="M17 7H15C14.7167 7 14.4792 6.90417 14.2875 6.7125C14.0958 6.52083 14 6.28333 14 6C14 5.71667 14.0958 5.47917 14.2875 5.2875C14.4792 5.09583 14.7167 5 15 5H17V3C17 2.71667 17.0958 2.47917 17.2875 2.2875C17.4792 2.09583 17.7167 2 18 2C18.2833 2 18.5208 2.09583 18.7125 2.2875C18.9042 2.47917 19 2.71667 19 3V5H21C21.2833 5 21.5208 5.09583 21.7125 5.2875C21.9042 5.47917 22 5.71667 22 6C22 6.28333 21.9042 6.52083 21.7125 6.7125C21.5208 6.90417 21.2833 7 21 7H19V9C19 9.28333 18.9042 9.52083 18.7125 9.7125C18.5208 9.90417 18.2833 10 18 10C17.7167 10 17.4792 9.90417 17.2875 9.7125C17.0958 9.52083 17 9.28333 17 9V7ZM8 8C6.9 8 5.95833 7.60833 5.175 6.825C4.39167 6.04167 4 5.1 4 4C4 2.9 4.39167 1.95833 5.175 1.175C5.95833 0.391667 6.9 0 8 0C9.1 0 10.0417 0.391667 10.825 1.175C11.6083 1.95833 12 2.9 12 4C12 5.1 11.6083 6.04167 10.825 6.825C10.0417 7.60833 9.1 8 8 8ZM0 14V13.2C0 12.6333 0.145833 12.1125 0.4375 11.6375C0.729167 11.1625 1.11667 10.8 1.6 10.55C2.63333 10.0333 3.68333 9.64583 4.75 9.3875C5.81667 9.12917 6.9 9 8 9C9.1 9 10.1833 9.12917 11.25 9.3875C12.3167 9.64583 13.3667 10.0333 14.4 10.55C14.8833 10.8 15.2708 11.1625 15.5625 11.6375C15.8542 12.1125 16 12.6333 16 13.2V14C16 14.55 15.8042 15.0208 15.4125 15.4125C15.0208 15.8042 14.55 16 14 16H2C1.45 16 0.979167 15.8042 0.5875 15.4125C0.195833 15.0208 0 14.55 0 14Z"
fill="currentColor"
/>
</svg>
)

export default PersonAdd
69 changes: 24 additions & 45 deletions src/components/SettingsModal/SettingsView/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,29 +4,30 @@ import Tabs from '@mui/material/Tabs'
import * as React from 'react'
import { useEffect, useState } from 'react'
import styled from 'styled-components'
import { Button } from '~/components/Button'
import { Flex } from '~/components/common/Flex'
import { Text } from '~/components/common/Text'
import { TAboutParams, getAboutData } from '~/network/fetchSourcesData'
import { useUserStore } from '~/stores/useUserStore'
import { colors } from '~/utils/colors'
import { executeIfProd } from '~/utils/tests'
import { Appearance } from './Appearance'
import { UserPermissions } from '../UserPermissions'
import { General } from './General'
import { Appearance } from './Appearance'

interface TabPanelProps {
children?: React.ReactNode
index: number
value: number
}

const admins = [
'02c431e64078b10925584d64824c9d1d12eca05e2c56660ffa5ac84aa6946adfe5',
'03a9a8d953fe747d0dd94dd3c567ddc58451101e987e2d2bf7a4d1e10a2c89ff38',
'024efa31d1e4f98bccc415b222c9d971866013ad6f95f7d1ed9e8be8e3355a36ff',
'03bfe6723c06fb2b7546df1e8ca1a17ae5c504615da32c945425ccbe8d3ca6260d',
'024efa31d1e4f98bccc415b222c9d971866013ad6f95f7d1ed9e8be8e3355a36ff',
]
// const admins = [
// '02c431e64078b10925584d64824c9d1d12eca05e2c56660ffa5ac84aa6946adfe5',
// '03a9a8d953fe747d0dd94dd3c567ddc58451101e987e2d2bf7a4d1e10a2c89ff38',
// '024efa31d1e4f98bccc415b222c9d971866013ad6f95f7d1ed9e8be8e3355a36ff',
// '03bfe6723c06fb2b7546df1e8ca1a17ae5c504615da32c945425ccbe8d3ca6260d',
// '024efa31d1e4f98bccc415b222c9d971866013ad6f95f7d1ed9e8be8e3355a36ff',
// ]



const defaultData = {
description: '',
Expand Down Expand Up @@ -64,7 +65,7 @@ type Props = {

export const SettingsView: React.FC<Props> = ({ onClose }) => {
const [value, setValue] = useState(0)
const [setIsAdmin, isAdmin, setPubKey, pubKey] = useUserStore((s) => [s.setIsAdmin, s.isAdmin, s.setPubKey, s.pubKey])
const [isAdmin, pubKey] = useUserStore((s) => [s.isAdmin, s.setPubKey, s.pubKey])
const [loading, setLoading] = useState(false)
const [initialValues, setInitialValues] = useState<TAboutParams>(defaultData)

Expand Down Expand Up @@ -98,40 +99,16 @@ export const SettingsView: React.FC<Props> = ({ onClose }) => {
</StyledHeader>
)

const authorize = async () => {
// skipping this for end to end test because it requires a sphinx-relay to be connected
await executeIfProd(async () => {
try {
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
const enable = await sphinx.enable()
const pubKeyRes = enable?.pubkey

setPubKey(pubKeyRes)

if (pubKeyRes) {
setIsAdmin(pubKeyRes && admins.includes(pubKeyRes))
}
} catch (error) {
console.warn(error)
}
})
}

const resolveAdminActions = () => {
if (!pubKey) {
return (
<EditButton kind="small" onClick={authorize}>
Admin
</EditButton>
)
return null
}

if (pubKey && isAdmin) {
if (isAdmin) {
return null
}

return <Text>You are not admin</Text>
return <></>
}

const handleChange = (event: React.SyntheticEvent, newValue: number) => {
Expand All @@ -144,12 +121,18 @@ export const SettingsView: React.FC<Props> = ({ onClose }) => {
<StyledTabs aria-label="basic tabs example" onChange={handleChange} value={value}>
{isAdmin && <StyledTab disableRipple label="General" {...a11yProps(0)} />}
<StyledTab color={colors.white} disableRipple label="Appearance" {...a11yProps(1)} />
{isAdmin && <StyledTab disableRipple label="User Permissions" {...a11yProps(2)} />}
</StyledTabs>
</SettingsHeader>
{isAdmin && (
<TabPanel index={0} value={value}>
{!loading ? <General initialValues={initialValues} /> : <></>}
</TabPanel>
<>
<TabPanel index={0} value={value}>
{!loading ? <General initialValues={initialValues} /> : <></>}
</TabPanel>
<TabPanel index={2} value={value}>
{!loading ? <UserPermissions initialValues={initialValues} /> : <></>}
</TabPanel>
</>
)}
<TabPanel index={isAdmin ? 1 : 0} value={value}>
<Appearance onClose={onClose} />
Expand Down Expand Up @@ -208,7 +191,3 @@ const StyledText = styled(Text)`
font-family: Barlow;
padding: 0 0 0 36px;
`

const EditButton = styled(Button)`
margin-left: auto;
`
7 changes: 7 additions & 0 deletions src/components/SettingsModal/UserPermissions/IconLabel.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import styled from 'styled-components'
import { Flex } from '~/components/common/Flex'

export const IconLabel = styled(Flex)`
display: flex;
margin-top: 2px;
`
160 changes: 160 additions & 0 deletions src/components/SettingsModal/UserPermissions/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
import { Button, InputLabel } from '@mui/material'
import { FC, useState } from 'react'
import { FormProvider, useForm } from 'react-hook-form'
import { ClipLoader } from 'react-spinners'
import styled from 'styled-components'
import InfoIcon from '~/components/Icons/InfoIcon'
import PersonAdd from '~/components/Icons/PersonAdd'
import SimpleTable from '~/components/SourcesTableModal/SourcesView/Sources/Table/SimpleTable'
import { Flex } from '~/components/common/Flex'
import { TextInput } from '~/components/common/TextInput'
import { TAboutParams } from '~/network/fetchSourcesData'
import { colors } from '~/utils'

type Props = {
initialValues: TAboutParams
}

const StyledForm = styled.form`
padding: 2px;
`

const InputSyled = styled(Flex)`
display: flex;
width: 320px;
`

const StyledLabel = styled.p`
color: white;
font-size: 13px;
`

const IconLabel = styled(Flex)`
display: flex;
margin-top: 2px;
`

const InputArea = styled(Flex)`
display: flex;
flex-direction: row;
align-items: end;
gap: 16px;
justify-content: center;
margin-top: 30px;
`

const UserArea = styled(Flex)`
display: flex;
align-items: center;
justify-content: center;
height: 400px;
color: ${colors.GRAY6};
background-color: #1c1e26;
margin-top: 32px;
`

const StyledText = styled.p`
font-family: Barlow;
font-size: 16px;
font-style: normal;
font-weight: 600;
`

const PersonAddBox = styled.div`
display: flex;
align-items: center;
justify-content: center;
flex-direction: column;
gap: 16px;
margin-bottom: 80px;
`

const StyledLoader = styled.div`
display: flex;
align-items: center;
justify-content: center;
flex-direction: row;
color: white;
gap: 8px;
margin-bottom: 80px;
`

export const UserPermissions: FC<Props> = ({ initialValues }) => {
const form = useForm<TAboutParams>({ defaultValues: initialValues, mode: 'onSubmit' })
const [isLoading, setIsLoading] = useState(false)
const [isDataLoaded, setIsDataLoaded] = useState(false)

const TableData = [
{ name: 'Name Surname', identifier: 'aXA60jczLJl1uew...' },
{ name: 'Name Surname', identifier: 'aXA60jczLJl1uew...' },
{ name: 'Name Surname', identifier: 'aXA60jczLJl1uew...' },
{ name: 'Name Surname', identifier: 'aXA60jczLJl1uew...' },
{ name: 'Name Surname', identifier: 'aXA60jczLJl1uew...' },
]

const mockFetchData = (): Promise<void> =>
new Promise((resolve) => {
setTimeout(() => {
resolve()
}, 2000)
})

const onSubmit = form.handleSubmit(async () => {
try {
setIsLoading(true)
await mockFetchData()
setIsDataLoaded(true)
setIsLoading(false)
} catch (error) {
console.warn(error)
setIsLoading(false)
}
})

const handleRemove = (identifier: string) => {
// eslint-disable-next-line no-console
console.log(`Remove item at index: ${identifier}`)
}

let content

if (isLoading) {
content = (
<StyledLoader>
<ClipLoader color={colors.white} />
Adding...
</StyledLoader>
)
} else if (isDataLoaded) {
content = <SimpleTable data={TableData} onRemove={handleRemove} />
} else {
content = (
<PersonAddBox>
<PersonAdd />
<StyledText>Add User</StyledText>
</PersonAddBox>
)
}

return (
<FormProvider {...form}>
<StyledForm onSubmit={onSubmit}>
<InputArea>
<InputSyled pt={20}>
<InputLabel sx={{ display: 'flex', alignItems: 'center', gap: '4px' }}>
<StyledLabel>Enter pubkey</StyledLabel>
<IconLabel>
<InfoIcon />
</IconLabel>
</InputLabel>
<TextInput id="cy-about-pubkey-id" maxLength={50} name="pubkey" placeholder="Paste pubkey here..." />
</InputSyled>
<Button color="secondary" onClick={onSubmit} size="medium" sx={{ minHeight: '38px' }} variant="contained">
Paste
</Button>
</InputArea>
<UserArea>{content}</UserArea>
</StyledForm>
</FormProvider>
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import React from 'react'
import { Table, TableBody, TableCell, TableContainer, TableRow, Paper, Button } from '@mui/material'
import CopyIcon from '~/components/Icons/CopyIcon'

interface RowData {
name: string
identifier: string
}

interface SimpleTableProps {
data: RowData[]
onRemove: (identifier: string) => void
}

const SimpleTable: React.FC<SimpleTableProps> = ({ data, onRemove }) => (
<TableContainer component={Paper}>
<Table aria-label="simple table">
<TableBody>
{data.map((row) => (
<TableRow key={row.identifier}>
<TableCell component="th" scope="row">
{row.name}
</TableCell>
<TableCell>
{row.identifier} <CopyIcon />
</TableCell>
<TableCell>
<Button onClick={() => onRemove(row.identifier)} variant="contained">
Remove
</Button>
</TableCell>
</TableRow>
))}
</TableBody>
</Table>
</TableContainer>
)

export default SimpleTable

0 comments on commit 897b4fa

Please sign in to comment.