You've already forked AstralRinth
forked from didirus/AstralRinth
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
This commit is contained in:
149
packages/moderation/README.md
Normal file
149
packages/moderation/README.md
Normal file
@@ -0,0 +1,149 @@
|
||||
# @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'],
|
||||
},
|
||||
},
|
||||
]
|
||||
```
|
||||
Reference in New Issue
Block a user