feat: route-centric rules, approve popup, emoji picker, 5-column sync table

- Schema: SyncRouteRuleMap junction table, ruleIntent on TenantRule,
  ForwardFormat/Frequency/ApprovalMode columns on SyncRoute, INTEREST
  match type
- Worker: remove global AUTO_APPROVE forwarding; per-route rule evaluation
  in ingest processor — POSITIVE rules auto-forward that route, NEGATIVE
  rules block it, fallback to approvalMode
- API: PATCH /routes/:id, rule assign/unassign endpoints, approve now
  accepts targetGroupIds, new GET /messages/:id/routes for popup data
- Web: 5-column route table with settings + rules dialogs, ForwardTarget
  popup with rule-based pre-selection, ruleIntent toggle + emoji dropdown
  (👍/👎 only) + INTEREST type in rules manager

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-06-25 13:58:02 +05:30
parent e598073dc7
commit 73956fd1e3
24 changed files with 1277 additions and 225 deletions
+23 -1
View File
@@ -1,13 +1,22 @@
export type RuleMatchType = 'HASHTAG' | 'PREFIX' | 'REACTION_EMOJI';
export type RuleMatchType = 'HASHTAG' | 'PREFIX' | 'REACTION_EMOJI' | 'INTEREST';
export type RuleAction = 'FLAG' | 'AUTO_APPROVE' | 'SKIP' | 'REJECT';
export type RuleIntent = 'POSITIVE' | 'NEGATIVE';
export type ForwardFormat = 'THREADED' | 'DIGEST' | 'SUMMARY';
export type ForwardFrequency = 'INSTANT' | 'FIVE_MIN' | 'FIFTEEN_MIN' | 'ONE_HOUR' | 'ONE_DAY' | 'SEVEN_DAYS';
export type ApprovalMode = 'MANUAL' | 'AUTO';
export interface TenantRuleData {
id: string;
tenantId: string;
matchType: RuleMatchType;
matchValue: string;
action: RuleAction;
ruleIntent: RuleIntent;
priority: number;
isActive: boolean;
createdAt: string;
@@ -18,6 +27,7 @@ export interface CreateRuleRequest {
matchType: RuleMatchType;
matchValue: string;
action: RuleAction;
ruleIntent?: RuleIntent;
priority?: number;
isActive?: boolean;
}
@@ -26,6 +36,18 @@ export interface UpdateRuleRequest {
matchType?: RuleMatchType;
matchValue?: string;
action?: RuleAction;
ruleIntent?: RuleIntent;
priority?: number;
isActive?: boolean;
}
export interface RouteForMessage {
routeId: string;
targetGroupId: string;
targetGroupName: string;
approvalMode: ApprovalMode;
forwardFormat: ForwardFormat;
withAttachment: boolean;
frequency: ForwardFrequency;
ruleDecision: 'FORWARD' | 'BLOCK' | 'NONE';
}