Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
8acce8e
admin mod, prio stub
colinmegill Jun 20, 2025
d50edc5
hclust route checkpoitn
colinmegill Jun 20, 2025
9102048
labels working
colinmegill Jun 20, 2025
5fc1ee4
remove logging, get towards hclust
colinmegill Jun 20, 2025
d8b9f29
hclust explration 22
colinmegill Jun 22, 2025
dd7445f
contour plot
colinmegill Jun 22, 2025
e213ef8
contours
colinmegill Jun 22, 2025
b52a93d
prio take 1
colinmegill Jun 23, 2025
e468ae9
distances
colinmegill Jun 23, 2025
4111e6b
remove dead 600 file
colinmegill Jun 23, 2025
8087fc1
add more defense for small models
colinmegill Jun 23, 2025
8dc48dd
topic prioritize mock
colinmegill Jun 24, 2025
8c7fce8
webpack build size
colinmegill Jun 24, 2025
c1d6627
topic sections
colinmegill Jun 24, 2025
8656208
merge fix
colinmegill Jun 24, 2025
46dea73
add simple route
colinmegill Jun 24, 2025
abbd766
Restructure priority calculation to use group-based extremity
whilo Jun 23, 2025
6d86fa3
Refactor priority calculation: separate formulas from service logic
whilo Jun 24, 2025
98d9227
Revert "Refactor priority calculation: separate formulas from service…
colinmegill Jun 24, 2025
fdfa009
topic agenda collapse prototype tetris-y
colinmegill Jun 25, 2025
4ddb689
topic agenda setting demo
colinmegill Jun 25, 2025
79c946b
begin basic bulk upload capability
tevko Jun 25, 2025
c3e6dab
save state
tevko Jun 25, 2025
6987ce1
split by distance doesn't owrk
colinmegill Jun 25, 2025
7ca6b5c
sentence transformer model
colinmegill Jun 28, 2025
d2cfed2
componetize
colinmegill Jun 28, 2025
b84971e
drive detail
colinmegill Jun 28, 2025
92d4e6e
more specifics
colinmegill Jun 28, 2025
d678cc2
log archetypal comments
colinmegill Jun 28, 2025
486f3ac
dynamo table and node services
colinmegill Jun 28, 2025
5ef5e15
Don't crash when we have not votes.
whilo Jun 27, 2025
923cb12
suppress logging
colinmegill Jul 1, 2025
e5ec4ef
differnet approach for prepended labesl
colinmegill Jul 1, 2025
e993f44
Te arch updates topicmod (#2086)
tevko Jul 4, 2025
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
15 changes: 15 additions & 0 deletions client-admin/src/components/conversation-admin/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import ConversationConfig from './conversation-config'
import ConversationStats from './stats'

import ModerateComments from './comment-moderation/'
import TopicModeration from './topic-moderation/'

// import DataExport from "./data-export";
import ShareAndEmbed from './share-and-embed'
Expand Down Expand Up @@ -82,6 +83,16 @@ class ConversationAdminContainer extends React.Component {
Moderate
</Link>
</Box>
<Box sx={{ mb: [3] }}>
<Link
sx={{
variant: url === 'topics' ? 'links.activeNav' : 'links.nav'
}}
data-test-id="moderate-topics"
to={`${match.url}/topics`}>
Topic Mod
</Link>
</Box>
<Box sx={{ mb: [3] }}>
<Link
sx={{
Expand Down Expand Up @@ -118,6 +129,10 @@ class ConversationAdminContainer extends React.Component {
path={`${match.path}/comments`}
component={ModerateComments}
/>
<Route
path={`${match.path}/topics`}
render={(props) => <TopicModeration {...props} conversation_id={match.params.conversation_id} />}
/>
<Route
exact
path={`${match.path}/stats`}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
# Topic Moderation Components

This directory contains the React components for the Topic-Based Moderation system in pol.is.

## Components

### `index.js` - TopicModeration
Main container component with tabbed navigation between different views:
- Topics Tree view
- Proximity Map visualization
- Statistics dashboard

### `topic-tree.js` - TopicTree
Hierarchical display of topics organized by layers:
- Layer selection (0, 1, 2, or all)
- Topic cards with moderation controls
- Bulk topic-level actions (Accept/Reject/Meta)
- Navigation to detailed comment view

### `topic-detail.js` - TopicDetail
Detailed view of comments within a specific topic:
- Individual comment display with selection
- Bulk comment selection and actions
- UMAP coordinate display
- Moderation status tracking

### `proximity-visualization.js` - ProximityVisualization
SVG-based UMAP visualization:
- Interactive scatter plot of comment positions
- Cluster grouping visualization
- Color coding by moderation status
- Layer selection for different granularities

### `topic-stats.js` - TopicStats
Statistics and progress tracking:
- Moderation completion rates
- Status distribution (pending/accepted/rejected/meta)
- Progress bars and visual indicators
- Overview dashboard

## Usage

The components are integrated into the conversation admin interface at:
`/m/:conversation_id/topics`

## Dependencies

- React with hooks
- theme-ui for styling
- React Router for navigation
- SVG manipulation for visualizations

## Data Flow

1. Components fetch data from `/api/v3/topicMod/*` endpoints
2. Real-time polling for updates (60-second intervals)
3. Optimistic UI updates for moderation actions
4. Error handling with retry mechanisms

## Styling

Uses theme-ui variants and custom CSS in `topic-moderation.css` for:
- Hover effects and transitions
- Status-based color coding
- Responsive design
- Loading states and animations
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
// Copyright (C) 2012-present, The Authors. This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License, version 3, as published by the Free Software Foundation. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with this program. If not, see <http://www.gnu.org/licenses/>.
/** @jsx jsx */

import ComponentHelpers from '../../../util/component-helpers'
import NoPermission from '../no-permission'
import React from 'react'
import { connect } from 'react-redux'
import { Heading, Flex, Box, jsx } from 'theme-ui'
import { Switch, Route, Link } from 'react-router-dom'

import TopicTree from './topic-tree'
import TopicDetail from './topic-detail'

Check failure on line 12 in client-admin/src/components/conversation-admin/topic-moderation/index.js

View workflow job for this annotation

GitHub Actions / eslint

'TopicDetail' is defined but never used
import TopicStats from './topic-stats'
import ProximityVisualization from './proximity-visualization'

Check failure on line 14 in client-admin/src/components/conversation-admin/topic-moderation/index.js

View workflow job for this annotation

GitHub Actions / eslint

'ProximityVisualization' is defined but never used

const mapStateToProps = (state, ownProps) => {
return {
topics: state.topic_mod_topics,
stats: state.topic_mod_stats,
zid_metadata: state.zid_metadata
}
}

const pollFrequency = 60000

Check failure on line 24 in client-admin/src/components/conversation-admin/topic-moderation/index.js

View workflow job for this annotation

GitHub Actions / eslint

'pollFrequency' is assigned a value but never used

@connect((state) => state.zid_metadata)
@connect(mapStateToProps)
class TopicModeration extends React.Component {
loadTopics() {
// Dispatch actions to load topics data
// TODO: Implement actions for loading topic moderation data
console.log('Loading topics for conversation:', this.props.conversation_id)
}

componentDidMount() {
this.loadTopics()
// Temporarily disable polling to debug crash
// this.getTopicsRepeatedly = setInterval(() => {
// this.loadTopics()
// }, pollFrequency)
}

componentWillUnmount() {
clearInterval(this.getTopicsRepeatedly)
}

render() {
// Check if zid_metadata is still loading
if (!this.props.zid_metadata || this.props.zid_metadata.loading) {
return (
<Box sx={{ textAlign: 'center', py: 4 }}>
<div>Loading...</div>
</Box>
)
}

if (ComponentHelpers.shouldShowPermissionsError(this.props)) {
return <NoPermission />
}

const { match, location } = this.props
const url = location.pathname.split('/')[4]

return (
<Box>
<Heading
as="h3"
sx={{
fontSize: [3, null, 4],
lineHeight: 'body',
mb: [3, null, 4]
}}>
Topic Moderation
</Heading>
<Flex sx={{ mb: [4] }}>
<Link
sx={{
mr: [4],
variant: url ? 'links.nav' : 'links.activeNav'
}}
to={`${match.url}`}>
Topics Tree
</Link>
<Link
sx={{
mr: [4],
variant: url === 'proximity' ? 'links.activeNav' : 'links.nav'
}}
to={`${match.url}/proximity`}>
Proximity Map
</Link>
<Link
sx={{
mr: [4],
variant: url === 'stats' ? 'links.activeNav' : 'links.nav'
}}
to={`${match.url}/stats`}>
Statistics
</Link>
</Flex>
<Box>
<Switch>
<Route
exact
path={`${match.url}`}
render={(props) => <TopicTree {...props} conversation_id={this.props.conversation_id} />}
/>
<Route
exact
path={`${match.url}/proximity`}
render={() => <div>Proximity Visualization Coming Soon</div>}
/>
<Route
exact
path={`${match.url}/stats`}
render={(props) => <TopicStats {...props} conversation_id={this.props.conversation_id} />}
/>
<Route
exact
path={`${match.url}/topic/:topicKey`}
render={() => <div>Topic Detail Coming Soon</div>}
/>
</Switch>
</Box>
</Box>
)
}
}

export default TopicModeration
Loading
Loading