From acc7d0c892f963071333e81b1f93ff02221ec4a3 Mon Sep 17 00:00:00 2001 From: kevkevin Date: Tue, 17 Oct 2023 21:02:31 -0500 Subject: [PATCH] feat: added Topics in popup to mute unrelated topics (#502) --- package.json | 2 +- .../SourcesView/QueuedSources/Table/index.tsx | 2 +- .../SourcesView/Sources/Table/index.tsx | 2 +- .../SourcesView/Sources/index.tsx | 4 +- .../SourcesView/Topics/Table/index.tsx | 91 +++++++++++++++++ .../SourcesView/Topics/index.tsx | 97 +++++++++++++++++++ .../SourcesTableModal/SourcesView/index.tsx | 5 + .../SourcesTableModal/SourcesView/types.ts | 7 +- src/network/fetchSourcesData/index.ts | 23 ++++- src/stores/useDataStore/index.ts | 7 +- src/types/index.ts | 16 +++ 11 files changed, 247 insertions(+), 9 deletions(-) create mode 100644 src/components/SourcesTableModal/SourcesView/Topics/Table/index.tsx create mode 100644 src/components/SourcesTableModal/SourcesView/Topics/index.tsx diff --git a/package.json b/package.json index 2621e37fe..12c91ce70 100644 --- a/package.json +++ b/package.json @@ -83,7 +83,7 @@ "prettier": "npx prettier --config prettier.config.js --check ./src", "postinstall": "husky install", "typecheck": "tsc --noEmit", - "lint": "eslint src --max-warnings 22" + "lint": "eslint src --max-warnings 24" }, "eslintConfig": { "extends": [ diff --git a/src/components/SourcesTableModal/SourcesView/QueuedSources/Table/index.tsx b/src/components/SourcesTableModal/SourcesView/QueuedSources/Table/index.tsx index a2e06cf71..921577216 100644 --- a/src/components/SourcesTableModal/SourcesView/QueuedSources/Table/index.tsx +++ b/src/components/SourcesTableModal/SourcesView/QueuedSources/Table/index.tsx @@ -30,7 +30,7 @@ const Table: React.FC = ({ data }) => { await approveRadarData(id, enable.pubkey) - setSources(data.filter((i) => i.ref_id !== id)) + setSources(data.filter((i: Sources) => i.ref_id !== id)) } catch (error) { console.warn(error) } diff --git a/src/components/SourcesTableModal/SourcesView/Sources/Table/index.tsx b/src/components/SourcesTableModal/SourcesView/Sources/Table/index.tsx index 3d93524a1..0887bcdc3 100644 --- a/src/components/SourcesTableModal/SourcesView/Sources/Table/index.tsx +++ b/src/components/SourcesTableModal/SourcesView/Sources/Table/index.tsx @@ -52,7 +52,7 @@ const Table: React.FC = ({ data, canEdit = false }) => { try { await deleteRadarData(id) - setSources(data?.filter((i) => i.ref_id !== id)) + setSources(data?.filter((i: Sources) => i.ref_id !== id)) } catch (error) { console.warn(error) } finally { diff --git a/src/components/SourcesTableModal/SourcesView/Sources/index.tsx b/src/components/SourcesTableModal/SourcesView/Sources/index.tsx index a14294858..b9561617f 100644 --- a/src/components/SourcesTableModal/SourcesView/Sources/index.tsx +++ b/src/components/SourcesTableModal/SourcesView/Sources/index.tsx @@ -13,7 +13,7 @@ import { ToastMessage } from '~/components/common/Toast/toastMessage' import { getRadarData, triggerRadarJob } from '~/network/fetchSourcesData' import { useDataStore } from '~/stores/useDataStore' import { useUserStore } from '~/stores/useUserStore' -import { FetchRadarResponse, SubmitErrRes } from '~/types' +import { FetchRadarResponse, SubmitErrRes, Sources as TSources } from '~/types' import { colors } from '~/utils/colors' import { executeIfProd } from '~/utils/tests' import { Heading, StyledPill } from '../common' @@ -134,7 +134,7 @@ export const Sources = () => { return You are not admin } - const tableValues = sources?.filter((val) => !typeFilter || val.source_type === typeFilter) + const tableValues = sources?.filter((val: TSources) => !typeFilter || val.source_type === typeFilter) return ( diff --git a/src/components/SourcesTableModal/SourcesView/Topics/Table/index.tsx b/src/components/SourcesTableModal/SourcesView/Topics/Table/index.tsx new file mode 100644 index 000000000..dd49bb5e5 --- /dev/null +++ b/src/components/SourcesTableModal/SourcesView/Topics/Table/index.tsx @@ -0,0 +1,91 @@ +import { Table as MaterialTable, TableRow } from '@mui/material' +import React from 'react' +import { MdCheckCircle, MdCancel } from 'react-icons/md' +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 { Topic } from '~/types' +import { colors } from '~/utils/colors' +import { StyledTableCell, StyledTableHead, StyledTableRow } from '../../common' +import { TopicTableProps } from '../../types' + +const Table: React.FC = ({ data, showMuted }) => { + // const setSources = useDataStore((s) => s.setQueuedSources) + + const handleMute = async (refId: string, shouldMute: boolean) => { + if (data?.length) { + try { + await putNodeData({ ref_id: refId, node_name: 'muted_topic', node_value: shouldMute }) + + // setSources(data.filter((i) => i.ref_id !== id)) + } catch (error) { + console.warn(error) + } + } + } + + return !data?.length ? ( + + There is not any results for selected filters + + + ) : ( + + + + + Type + {showMuted ? 'Unmute' : 'Mute'} + + + {data?.length && ( + + {data?.map((i: Topic) => ( + + + {i.topic} + + + +
+ {i.muted_topic ? ( + handleMute(i.ref_id, false)}> + + + ) : ( + handleMute(i.ref_id, true)}> + + + )} +
+
+
+ +
+ ))} + + )} +
+ ) +} + +export default Table + +const IconWrapper = styled(Flex)` + width: 20px; + height: 20px; + border-radius: 50%; + cursor: pointer; + background: transparent; + color: ${colors.lightBlue500}; + &.centered { + margin: 0 auto; + } + + & + & { + margin-left: 4px; + } +` diff --git a/src/components/SourcesTableModal/SourcesView/Topics/index.tsx b/src/components/SourcesTableModal/SourcesView/Topics/index.tsx new file mode 100644 index 000000000..32f4962ae --- /dev/null +++ b/src/components/SourcesTableModal/SourcesView/Topics/index.tsx @@ -0,0 +1,97 @@ +import { useEffect, 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 { getTopicsData } from '~/network/fetchSourcesData' +import { useDataStore } from '~/stores/useDataStore' +import { FetchTopicResponse } from '~/types' +import { colors } from '~/utils/colors' +import { Heading } from '../common' +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]) + + useEffect(() => { + const init = async () => { + setLoading(true) + + try { + const mutedParam = showMuted ? 'True' : 'False' + const data: FetchTopicResponse = await getTopicsData({ muted: mutedParam }) + + setTopics(data.data) + } catch (error) { + console.warn(error) + } finally { + setLoading(false) + } + } + + init() + }, [setTopics, showMuted]) + + return ( + + + Topics + + setShowMuted(!showMuted)} + style={{ marginLeft: '30px', marginBottom: '10px', padding: '5px 10px 5px 10px', width: 'fit-content' }} + > + {loading ? ( + + ) : ( + +
Show {showMuted ? 'Unmuted' : 'Muted'}
+
+ )} +
+ + + {loading ? : } + + + ) +} + +const Wrapper = styled(Flex)` + flex: 1; + + .title { + margin-bottom: 32px; + font-size: 20px; + color: ${colors.white}; + font-family: Barlow; + font-size: 22px; + font-style: normal; + font-weight: 600; + line-height: normal; + } + + .subtitle { + color: ${colors.GRAY3}; + font-family: Barlow; + font-size: 13px; + font-style: normal; + font-weight: 400; + line-height: normal; + } + + & .filters { + overflow-x: auto; + } +` + +const TableWrapper = styled(Flex)` + min-height: 0; + overflow: auto; + flex: 1; + width: 100%; +` diff --git a/src/components/SourcesTableModal/SourcesView/index.tsx b/src/components/SourcesTableModal/SourcesView/index.tsx index 0a3b322bc..514dcb88c 100644 --- a/src/components/SourcesTableModal/SourcesView/index.tsx +++ b/src/components/SourcesTableModal/SourcesView/index.tsx @@ -6,6 +6,7 @@ import { Flex } from '~/components/common/Flex' import { colors } from '~/utils/colors' import { QueuedSources } from './QueuedSources' import { Sources } from './Sources' +import { TopicSources } from './Topics' interface TabPanelProps { children?: React.ReactNode @@ -48,6 +49,7 @@ export const SourcesView = () => { + @@ -55,6 +57,9 @@ export const SourcesView = () => { + + + ) } diff --git a/src/components/SourcesTableModal/SourcesView/types.ts b/src/components/SourcesTableModal/SourcesView/types.ts index 7e4df893b..df423df0a 100644 --- a/src/components/SourcesTableModal/SourcesView/types.ts +++ b/src/components/SourcesTableModal/SourcesView/types.ts @@ -1,9 +1,14 @@ -import { Sources } from '~/types' +import { Sources, Topic } from '~/types' export type Props = { data: Sources[] | undefined } +export type TopicTableProps = { + data: Topic[] | null + showMuted?: boolean +} + export type TdProps = { width?: string } diff --git a/src/network/fetchSourcesData/index.ts b/src/network/fetchSourcesData/index.ts index f19dbd350..8f433f90a 100644 --- a/src/network/fetchSourcesData/index.ts +++ b/src/network/fetchSourcesData/index.ts @@ -1,4 +1,4 @@ -import { FetchRadarResponse, RadarRequest, SubmitErrRes } from '~/types' +import { FetchRadarResponse, FetchTopicResponse, RadarRequest, SubmitErrRes, NodeRequest } from '~/types' import { api } from '../api' type TradarParams = { @@ -15,10 +15,15 @@ export type TAboutParams = { search_term?: string } +type TtopicsParams = { + muted?: string + skip?: string + limit?: string +} + const defaultParams = { skip: '0', limit: '500', - approved: 'True', } export const getRadarData = async (queryParams: TradarParams = defaultParams) => { @@ -29,6 +34,14 @@ export const getRadarData = async (queryParams: TradarParams = defaultParams) => return response } +export const getTopicsData = async (queryParams: TtopicsParams = defaultParams) => { + const response = await api.get( + `/topics?${new URLSearchParams({ ...defaultParams, ...queryParams }).toString()}`, + ) + + return response +} + export const getAboutData = async () => { const response = await api.get('/about') @@ -49,6 +62,12 @@ export const putRadarData = async (id: string, data: RadarRequest) => { return response } +export const putNodeData = async (data: NodeRequest) => { + const response = await api.put(`/node`, JSON.stringify(data)) + + return response +} + export const approveRadarData = async (id: string, pubkey: string) => { const response = await api.put(`/radar/${id}/approve`, JSON.stringify({ approve: 'True', pubkey })) diff --git a/src/stores/useDataStore/index.ts b/src/stores/useDataStore/index.ts index 52cdf8d8f..3846c5b6f 100644 --- a/src/stores/useDataStore/index.ts +++ b/src/stores/useDataStore/index.ts @@ -2,7 +2,7 @@ import create from 'zustand' import { nodesAreRelatives } from '~/components/Universe/constants' import { isChileGraph } from '~/constants' import { fetchGraphData } from '~/network/fetchGraphData' -import { GraphData, NodeExtended, NodeType, Sources } from '~/types' +import { GraphData, NodeExtended, NodeType, Sources, Topic } from '~/types' import { saveSearchTerm } from '~/utils/relayHelper/index' export type GraphStyle = 'split' | 'force' | 'sphere' | 'earth' @@ -24,6 +24,7 @@ type DataStore = { selectedTimestamp: NodeExtended | null sources: Sources[] | null queuedSources: Sources[] | null + topics: Topic[] | null sphinxModalIsOpen: boolean cameraFocusTrigger: boolean selectedNodeRelativeIds: string[] @@ -44,6 +45,7 @@ type DataStore = { setSelectedTimestamp: (selectedTimestamp: NodeExtended | null) => void setSources: (sources: Sources[] | null) => void setQueuedSources: (sources: Sources[] | null) => void + setTopics: (topics: Topic[] | null) => void setSphinxModalOpen: (_: boolean) => void setCameraFocusTrigger: (_: boolean) => void setIsFetching: (_: boolean) => void @@ -70,6 +72,7 @@ const defaultData: Omit< | 'setCameraFocusTrigger' | 'setSources' | 'setQueuedSources' + | 'setTopics' | 'setGraphRadius' | 'setGraphStyle' | 'setNearbyNodeIds' @@ -88,6 +91,7 @@ const defaultData: Omit< isFetching: false, isTimestampLoaded: false, queuedSources: null, + topics: null, hoveredNode: null, selectedNode: null, selectedTimestamp: null, @@ -136,6 +140,7 @@ export const useDataStore = create((set, get) => ({ setGraphRadius: (graphRadius) => set({ graphRadius }), setGraphStyle: (graphStyle) => set({ graphStyle }), setQueuedSources: (queuedSources) => set({ queuedSources }), + setTopics: (topics) => set({ topics }), setHoveredNode: (hoveredNode) => set({ hoveredNode }), setSelectedNode: (selectedNode) => { const stateSelectedNode = get().selectedNode diff --git a/src/types/index.ts b/src/types/index.ts index 848dfa494..6348d7286 100644 --- a/src/types/index.ts +++ b/src/types/index.ts @@ -17,11 +17,21 @@ export type FetchRadarResponse = { data: Sources[] } +export type FetchTopicResponse = { + data: Topic[] +} + export type RadarRequest = { source: string source_type: string } +export type NodeRequest = { + ref_id: string + node_name: string + node_value: boolean +} + export type Node = { boost?: number | null children?: string[] @@ -142,6 +152,12 @@ export type Sources = { ref_id: string } +export type Topic = { + topic: string + ref_id: string + muted_topic: string +} + export type SubmitErrRes = { error?: { message?: string } }