Skip to content

Commit

Permalink
feat: add edge count, date, nodes to topics table (#521)
Browse files Browse the repository at this point in the history
Co-authored-by: Расул <[email protected]>
  • Loading branch information
Rassl and Расул authored Oct 23, 2023
1 parent 81c353b commit 15ffa1e
Show file tree
Hide file tree
Showing 6 changed files with 233 additions and 32 deletions.
143 changes: 143 additions & 0 deletions src/components/SourcesTableModal/SourcesView/Topics/Filter/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
import FormControl from '@mui/material/FormControl'
import Popover from '@mui/material/Popover'
import clsx from 'clsx'
import { FC, useState } from 'react'
import styled from 'styled-components'
import CheckIcon from '~/components/Icons/CheckIcon'
import ChevronDownIcon from '~/components/Icons/ChevronDownIcon'
import ChevronUpIcon from '~/components/Icons/ChevronUpIcon'
import { Flex } from '~/components/common/Flex'
import { DATE, DEFAULT, EDGES } from '~/constants'
import { colors } from '~/utils/colors'

type Option = Record<string, string>

const options: Option = {
[DEFAULT]: 'Default',
[DATE]: 'Date',
[EDGES]: 'Edges Count',
}

type Props = {
onChangeFilter: (val: string) => void
currentFilter: string
}

export const Filter: FC<Props> = ({ onChangeFilter, currentFilter }) => {
const [anchorEl, setAnchorEl] = useState<HTMLElement | null>(null)

const handleOpenPopover = (event: React.MouseEvent<HTMLDivElement>) => {
setAnchorEl(event.currentTarget as HTMLElement)
}

const handleClosePopover = () => {
setAnchorEl(null)
}

const handleSelectChange = (option: string) => {
onChangeFilter(option)
handleClosePopover()
}

return (
<div>
<Action onClick={handleOpenPopover}>
<div className="text">Sort By</div>
<div className="value">{options[currentFilter]}</div>
<div className="icon">{!anchorEl ? <ChevronDownIcon /> : <ChevronUpIcon />}</div>
</Action>
<StyledPopover
anchorEl={anchorEl}
anchorOrigin={{
vertical: 'bottom',
horizontal: 'left',
}}
anchorPosition={{
top: 62,
left: 0,
}}
onClose={handleClosePopover}
open={Boolean(anchorEl)}
transformOrigin={{
vertical: 'top',
horizontal: 'left',
}}
>
<FormControl>
{Object.keys(options).map((option) => (
<MenuItem
key={option}
className={clsx({ active: option === currentFilter })}
onClick={() => handleSelectChange(option)}
>
<span className="icon">{option === currentFilter ? <CheckIcon /> : null}</span>
<span>{options[option]}</span>
</MenuItem>
))}
</FormControl>
</StyledPopover>
</div>
)
}

const Action = styled(Flex).attrs({
direction: 'row',
align: 'center',
})`
cursor: pointer;
flex-grow: 1;
color: ${colors.GRAY6};
font-family: Barlow;
font-size: 13px;
font-style: normal;
font-weight: 500;
padding: 0 8px;
.value,
.icon {
color: ${colors.white};
}
.value {
margin: 0 8px 0 4px;
}
`

const MenuItem = styled(Flex).attrs({
direction: 'row',
align: 'center',
})`
font-family: Barlow;
font-size: 13px;
font-style: normal;
font-weight: 500;
color: ${colors.GRAY3};
height: 27px;
cursor: pointer;
&.active {
color: ${colors.white};
}
&:hover {
color: ${colors.white};
}
.icon {
margin-right: 8px;
width: 9px;
font-size: 10px;
}
`

const StyledPopover = styled(Popover)`
&& {
z-index: 99999;
}
.MuiPaper-root {
background: ${colors.BUTTON1};
min-width: 149px;
padding: 16px;
color: ${colors.GRAY3};
box-shadow: 0px 1px 6px 0px rgba(0, 0, 0, 0.2);
border-radius: 6px;
}
`
48 changes: 35 additions & 13 deletions src/components/SourcesTableModal/SourcesView/Topics/Table/index.tsx
Original file line number Diff line number Diff line change
@@ -1,26 +1,30 @@
import { Table as MaterialTable, TableRow } from '@mui/material'
import React from 'react'
import { MdCheckCircle, MdCancel } from 'react-icons/md'
import moment from 'moment'
import React, { useState } from 'react'
import { MdCancel, MdCheckCircle } from 'react-icons/md'
import { ClipLoader } from 'react-spinners'
import styled from 'styled-components'
import FilterOffIcon from '~/components/Icons/FilterOffIcon'
import { Flex } from '~/components/common/Flex'
import { Text } from '~/components/common/Text'
import { putNodeData } from '~/network/fetchSourcesData'
// import { useDataStore } from '~/stores/useDataStore'
import { useDataStore } from '~/stores/useDataStore'
import { Topic } from '~/types'
import { colors } from '~/utils/colors'
import { StyledTableCell, StyledTableHead, StyledTableRow } from '../../common'
import { TopicTableProps } from '../../types'

const Table: React.FC<TopicTableProps> = ({ data, showMuted }) => {
// const setSources = useDataStore((s) => s.setQueuedSources)
const [setTopics] = useDataStore((s) => [s.setTopics])
const [loadingId, setLoadingId] = useState('')

const handleMute = async (refId: string, shouldMute: boolean) => {
if (data?.length) {
setLoadingId(refId)

try {
await putNodeData({ ref_id: refId, node_name: 'muted_topic', node_value: shouldMute })

// setSources(data.filter((i) => i.ref_id !== id))
setTopics(data.filter((i) => i.ref_id !== refId))
} catch (error) {
console.warn(error)
}
Expand All @@ -38,6 +42,9 @@ const Table: React.FC<TopicTableProps> = ({ data, showMuted }) => {
<TableRow component="tr">
<StyledTableCell className="empty" />
<StyledTableCell>Type</StyledTableCell>
<StyledTableCell>Edge Count</StyledTableCell>
<StyledTableCell>Edge list</StyledTableCell>
<StyledTableCell>Date</StyledTableCell>
<StyledTableCell>{showMuted ? 'Unmute' : 'Mute'}</StyledTableCell>
</TableRow>
</StyledTableHead>
Expand All @@ -47,18 +54,33 @@ const Table: React.FC<TopicTableProps> = ({ data, showMuted }) => {
<StyledTableRow key={i.topic}>
<StyledTableCell className="empty" />
<StyledTableCell>{i.topic}</StyledTableCell>
<StyledTableCell>{i.edgeCount}</StyledTableCell>
<StyledTableCell>
{i.edgeList.map((topic) => (
<span key={topic}>{topic}</span>
))}
</StyledTableCell>
<StyledTableCell>
{i.date_added_to_graph ? <span>{moment(i.date_added_to_graph).format('MM.DD.YYYY')}</span> : null}
</StyledTableCell>

<StyledTableCell className="cell-center">
<Flex direction="row" justify="space-between">
<div className="approve-wrapper">
{i.muted_topic ? (
<IconWrapper className="centered" onClick={() => handleMute(i.ref_id, false)}>
<MdCheckCircle color={colors.primaryGreen} fontSize={24} />
</IconWrapper>
{loadingId === i.ref_id ? (
<ClipLoader color={colors.white} size={16} />
) : (
<IconWrapper className="centered" onClick={() => handleMute(i.ref_id, true)}>
<MdCancel color={colors.primaryRed} fontSize={24} />
</IconWrapper>
<>
{i.muted_topic ? (
<IconWrapper className="centered" onClick={() => handleMute(i.ref_id, false)}>
<MdCheckCircle color={colors.primaryGreen} fontSize={24} />
</IconWrapper>
) : (
<IconWrapper className="centered" onClick={() => handleMute(i.ref_id, true)}>
<MdCancel color={colors.primaryRed} fontSize={24} />
</IconWrapper>
)}
</>
)}
</div>
</Flex>
Expand Down
65 changes: 47 additions & 18 deletions src/components/SourcesTableModal/SourcesView/Topics/index.tsx
Original file line number Diff line number Diff line change
@@ -1,20 +1,23 @@
import { useEffect, useState } from 'react'
import { Button } from '@mui/material'
import { useEffect, useMemo, useState } from 'react'
import { ClipLoader } from 'react-spinners'
import styled from 'styled-components'
import { Flex } from '~/components/common/Flex'
import { Text } from '~/components/common/Text'
import { Pill } from '~/components/common/Pill'
import { DATE, DEFAULT, EDGES } from '~/constants'
import { getTopicsData } from '~/network/fetchSourcesData'
import { useDataStore } from '~/stores/useDataStore'
import { FetchTopicResponse } from '~/types'
import { colors } from '~/utils/colors'
import { Heading } from '../common'
import { Filter } from './Filter'
import Table from './Table'

export const TopicSources = () => {
const [loading, setLoading] = useState(true)
const [showMuted, setShowMuted] = useState(false)
const [topics, setTopics] = useDataStore((s) => [s.topics, s.setTopics])
const [currentFilter, setCurrentFilter] = useState(DEFAULT)

useEffect(() => {
const init = async () => {
Expand All @@ -35,27 +38,45 @@ export const TopicSources = () => {
init()
}, [setTopics, showMuted])

const sortedNodes = useMemo(() => {
if (!topics) {
return []
}

if (currentFilter === DEFAULT) {
return topics
}

if (currentFilter === DATE) {
return [...topics].sort((a, b) =>
a.date_added_to_graph && b.date_added_to_graph ? a.date_added_to_graph - b.date_added_to_graph : 1,
)
}

if (currentFilter === EDGES) {
return [...topics].sort((a, b) => a.edgeCount - b.edgeCount)
}

return null
}, [currentFilter, topics])

return (
<Wrapper align="stretch" direction="column" justify="flex-end">
<Wrapper direction="column" justify="flex-end">
<Heading align="flex-start" justify="space-between">
<Text className="title">Topics</Text>
</Heading>
<Pill
className="booster__pill"
onClick={() => setShowMuted(!showMuted)}
style={{ marginLeft: '30px', marginBottom: '10px', padding: '5px 10px 5px 10px', width: 'fit-content' }}
>
{loading ? (
<ClipLoader color={colors.white} />
) : (
<Flex align="center" direction="row" justify="center">
<div style={{ fontSize: 10 }}>Show {showMuted ? 'Unmuted' : 'Muted'}</div>
</Flex>
)}
</Pill>

<ActionsWrapper>
<Button onClick={() => setShowMuted(!showMuted)} size="medium">
{showMuted ? 'Show Unmuted' : 'Show Muted'}
{loading && <ClipLoader color={colors.BLUE_PRESS_STATE} size={10} />}
</Button>

<Filter currentFilter={currentFilter} onChangeFilter={setCurrentFilter} />
</ActionsWrapper>

<TableWrapper align="center" justify={loading ? 'center' : 'flex-start'}>
{loading ? <ClipLoader color={colors.white} /> : <Table data={topics} showMuted={showMuted} />}
{loading ? <ClipLoader color={colors.white} /> : <Table data={sortedNodes || []} showMuted={showMuted} />}
</TableWrapper>
</Wrapper>
)
Expand All @@ -65,7 +86,6 @@ const Wrapper = styled(Flex)`
flex: 1;
.title {
margin-bottom: 32px;
font-size: 20px;
color: ${colors.white};
font-family: Barlow;
Expand Down Expand Up @@ -95,3 +115,12 @@ const TableWrapper = styled(Flex)`
flex: 1;
width: 100%;
`

const ActionsWrapper = styled(Flex).attrs({
direction: 'row',
align: 'center',
justify: 'space-between',
})`
padding: 0 36px;
margin-bottom: 32px;
`
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ export const StyledPill = styled(Button)`
`

export const Heading = styled(Flex)`
margin-bottom: 26px;
margin-bottom: 16px;
padding: 0 36px;
${Text} {
margin-bottom: 0;
Expand Down
4 changes: 4 additions & 0 deletions src/constants/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,10 @@ export const BOOST_ERROR_BUDGET = 'Boost failed, insufficient budget'
export const NODE_ADD_SUCCESS = 'Submitted!'
export const NODE_ADD_ERROR = 'Submission failed, please try again.'

export const DEFAULT = 'default'
export const DATE = 'date'
export const EDGES = 'edges'

type NodeRelativeHighlightColors = {
nodeColor: string
segmentColor: number
Expand Down
3 changes: 3 additions & 0 deletions src/types/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,9 @@ export type Topic = {
topic: string
ref_id: string
muted_topic: string
edgeList: Array<string>
edgeCount: number
date_added_to_graph: null
}

export type SubmitErrRes = {
Expand Down

0 comments on commit 15ffa1e

Please sign in to comment.