Files
AstralRinth/packages/moderation/README.md
IMB11 359fbd4738 feat: moderation improvements (#3881)
* feat: rough draft of tool

* fix: example doc

* feat: multiselect chips

* feat: conditional actions+messaages + utils for handling conditions

* feat: migrate checklist v1 to new format.

* fix: lint issues

* fix: severity util

* feat: README.md

* feat: start implementing new moderation checklist

* feat: message assembly + fix imports

* fix: lint issues

* feat: add input suggestions

* feat: utility cleanup

* fix: icon

* chore: remove debug logging

* chore: remove debug button

* feat: modpack permissions flow into it's own component

* feat: icons + use id in stage selection button

* Support md/plain text in stages.

* fix: checklist not persisting/showing on subpages

* feat: message gen + appr/with/deny buttons

* feat: better notification placement + queue navigation

* fix: default props for futureProjects

* fix: modpack perms message

* fix: issue with future projects props

* fix: tab index + z index fixes

* feat: keybinds

* fix: file approval types

* fix: generate message for non-modpack projects

* feat: add generate message to stages dropdown

* fix: variables not expanding

* feat: requests

* fix: empty message approval

* fix: issues from sync

* chore: add comment for old moderation checklist impl

* fix: git artifacts

* fix: update visibility logic for stages and actions

* fix: cleanup logic for should show

* fix: markdown editor accidental edit
2025-07-11 16:09:04 +00:00

150 lines
4.5 KiB
Markdown

# @modrinth/moderation
This package contains the moderation checklist system used for reviewing projects on Modrinth. It provides a structured and transparent way to define moderation stages, actions, and messages that are displayed to moderators during the review process.
## Structure
The package is organized as follows:
```
/packages/moderation/
├── data/
│ ├── checklist.ts # Main checklist definition - imports and exports all stages
│ ├── messages/ # Markdown files containing message templates
│ │ ├── title/ # Messages for the title stage
│ │ ├── description/ # Messages for the description stage
│ │ └── ... # One directory per stage
│ └── stages/ # Stage definition files
│ ├── title.ts # Title stage definition
│ ├── description.ts # Description stage definition
│ └── ... # One file per stage
└── types/ # Type definitions
├── actions.ts # Action-related types
├── messages.ts # Message-related types
└── stage.ts # Stage-related types
```
## Stages
A stage represents a discrete step in the moderation process, like checking a project's title, description, or links. Each stage has:
- A title displayed to moderators
- A link to guidance documentation
- An optional navigation path to direct moderators to the relevant part of the project page
- A list of actions that moderators can take
Stages are defined in individual files in the `data/stages` directory and are assembled into the complete checklist in `data/checklist.ts`.
## Actions
Actions represent decisions moderators can make for each stage. They can be buttons, dropdowns, toggles, etc. Actions can have:
- Labels displayed to the moderator
- Messages that are included in the final moderation decision
- Suggested moderation status and severity
- Optional text inputs for additional information
- Conditional behavior based on other selected actions
Each action requires a unique `id` field that is used for conditional logic and action relationships. The `suggestedStatus` and `severity` fields help determine the overall moderation outcome.
## Messages
Messages are the actual text that will be included in communications to project authors. To promote maintainability and reuse, messages are stored as Markdown files in the `data/messages` directory, organized by stage.
### Variable replacement
You can use variables in your messages that will be replaced with user input:
1. Define a variable in the `relevantExtraInput` array of an action:
```typescript
relevantExtraInput: [
{
label: 'Explanation for the user',
variable: 'MESSAGE',
required: true,
},
],
```
2. Use the variable in your message with `%VARIABLE%` syntax:
```markdown
# Your Message Title
Here is some explanation about the issue.
%MESSAGE%
More text after the variable.
```
The `%MESSAGE%` placeholder will be replaced with the text entered by the moderator.
## Conditional logic
The moderation system supports conditional behavior that changes based on the selection of other actions.
### Conditional messages
You can define different messages for an action based on other selected actions:
```typescript
{
id: 'my_action',
type: 'button',
label: 'My Action',
weight: 100,
message: async () => (await import('../messages/default-message.md?raw')).default,
conditionalMessages: [
{
conditions: {
requiredActions: ['other_action_id'],
excludedActions: ['another_action_id']
},
message: async () => (await import('../messages/conditional-message.md?raw')).default,
}
]
}
```
### Enabling and disabling actions
Actions can enable or disable other actions when selected:
```typescript
{
id: 'parent_action',
type: 'button',
label: 'Parent Action',
// This will show these actions when parent_action is selected
enablesActions: [
{
id: 'child_action',
type: 'button',
label: 'Child Action',
// ...other properties
}
],
// This will hide actions with these IDs when parent_action is selected
disablesActions: ['incompatible_action_id']
}
```
### Conditional text inputs
Text inputs can be conditionally shown based on selected actions:
```typescript
relevantExtraInput: [
{
label: 'Additional Information',
variable: 'INFO',
showWhen: {
requiredActions: ['specific_action_id'],
excludedActions: ['incompatible_action_id'],
},
},
]
```