Skip to content

Commit

Permalink
feat: and or condition for action (#1616)
Browse files Browse the repository at this point in the history
  • Loading branch information
hyoban authored Nov 18, 2024
1 parent f6cbace commit 4193a6b
Show file tree
Hide file tree
Showing 6 changed files with 226 additions and 89 deletions.
185 changes: 119 additions & 66 deletions apps/renderer/src/modules/settings/action-card.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ import type {
} from "@follow/models/types"
import { stopPropagation } from "@follow/utils/dom"
import { cn } from "@follow/utils/utils"
import { useMemo, useState } from "react"
import { Fragment, useMemo, useState } from "react"
import { useTranslation } from "react-i18next"

import { Collapse, CollapseControlled } from "~/components/ui/collapse"
Expand Down Expand Up @@ -60,23 +60,49 @@ const FieldTableHeader = () => {
return (
<TableHeader>
<TableRow>
<TableHead size="sm" />
<TableHead size="sm">{t("actions.action_card.field")}</TableHead>
<TableHead size="sm">{t("actions.action_card.operator")}</TableHead>
<TableHead size="sm">{t("actions.action_card.value")}</TableHead>
<TableHead size="sm" />
</TableRow>
</TableHeader>
)
}

const DeleteTableCell = ({ disabled, onClick }: { disabled?: boolean; onClick?: () => void }) => (
<TableCell size="sm" className="flex h-10 items-center pr-1">
<Button variant="ghost" className="w-full px-0" disabled={disabled} onClick={onClick}>
<TableCell size="sm" className="flex h-10 items-center">
<Button variant="ghost" className="w-full" disabled={disabled} onClick={onClick}>
<i className="i-mgc-delete-2-cute-re text-zinc-600" />
</Button>
</TableCell>
)

const AndTableCell = ({ disabled, onClick }: { disabled?: boolean; onClick?: () => void }) => {
const { t } = useTranslation("settings")
return (
<TableCell size="sm">
<Button variant="outline" className="w-full" disabled={disabled} onClick={onClick}>
{t("actions.action_card.and")}
</Button>
</TableCell>
)
}

const OrTableRow = ({ onClick, disabled }: { onClick?: () => void; disabled?: boolean }) => {
const { t } = useTranslation("settings")
return (
<Button
variant="outline"
className="mt-1 w-full gap-1"
buttonClassName="py-1"
onClick={onClick}
disabled={disabled}
>
{t("actions.action_card.or")}
</Button>
)
}

const AddTableRow = ({ onClick, disabled }: { onClick?: () => void; disabled?: boolean }) => {
const { t } = useTranslation("settings")
return (
Expand Down Expand Up @@ -310,7 +336,7 @@ export function ActionCard({
if (value === "all") {
data.condition = []
} else {
data.condition = [{}]
data.condition = [[{}]]
}
onChange(data)
}}
Expand All @@ -329,77 +355,104 @@ export function ActionCard({
<Table>
<FieldTableHeader />
<TableBody>
{data.condition.map((condition, conditionIdx) => {
const change = (key: string, value: string | number) => {
if (!data.condition[conditionIdx]) {
data.condition[conditionIdx] = {}
{data.condition.flatMap((orConditions, orConditionIdx) => {
return orConditions.map((condition, conditionIdx) => {
const change = (key: string, value: string | number) => {
if (!data.condition[orConditionIdx]) {
data.condition[orConditionIdx] = [{}]
}
data.condition[orConditionIdx][conditionIdx][key] = value
onChange(data)
}
data.condition[conditionIdx][key] = value
onChange(data)
}
const type =
FeedOptions.find((option) => option.value === condition.field)?.type ||
"text"
return (
<TableRow key={conditionIdx}>
<DeleteTableCell
disabled={disabled}
onClick={() => {
data.condition.splice(conditionIdx, 1)
onChange(data)
}}
/>
<TableCell size="sm">
<Select
disabled={disabled}
value={condition.field}
onValueChange={(value: ActionFeedField) => change("field", value)}
>
<CommonSelectTrigger />
<SelectContent>
{FeedOptions.map((option) => (
<SelectItem key={option.value} value={option.value}>
{option.name}
</SelectItem>
))}
</SelectContent>
</Select>
</TableCell>
<OperationTableCell
type={type}
disabled={disabled}
value={condition.operator}
onValueChange={(value) => change("operator", value)}
/>
<TableCell size="sm">
{type === "view" ? (
<Select
const type =
FeedOptions.find((option) => option.value === condition.field)?.type ||
"text"
return (
<Fragment key={orConditionIdx}>
{conditionIdx === 0 && orConditionIdx !== 0 && (
<TableRow className="flex h-16 items-center">
<Button disabled variant="outline">
Or
</Button>
</TableRow>
)}
<TableRow>
<TableCell size="sm">
<Select
disabled={disabled}
value={condition.field}
onValueChange={(value: ActionFeedField) =>
change("field", value)
}
>
<CommonSelectTrigger />
<SelectContent>
{FeedOptions.map((option) => (
<SelectItem key={option.value} value={option.value}>
{option.name}
</SelectItem>
))}
</SelectContent>
</Select>
</TableCell>
<OperationTableCell
type={type}
disabled={disabled}
onValueChange={(value) => change("value", value)}
value={condition.value}
>
<CommonSelectTrigger />
<ViewSelectContent />
</Select>
) : (
<Input
value={condition.operator}
onValueChange={(value) => change("operator", value)}
/>
<TableCell size="sm">
{type === "view" ? (
<Select
disabled={disabled}
onValueChange={(value) => change("value", value)}
value={condition.value}
>
<CommonSelectTrigger />
<ViewSelectContent />
</Select>
) : (
<Input
disabled={disabled}
type={type}
value={condition.value}
className="h-8"
onChange={(e) => change("value", e.target.value)}
/>
)}
</TableCell>
<AndTableCell
disabled={disabled}
type={type}
value={condition.value}
className="h-8"
onChange={(e) => change("value", e.target.value)}
onClick={() => {
data.condition[orConditionIdx].push({})
onChange(data)
}}
/>
<DeleteTableCell
disabled={disabled}
onClick={() => {
data.condition.splice(orConditionIdx, 1)
onChange(data)
}}
/>
</TableRow>
{conditionIdx !== orConditions.length - 1 && (
<TableRow className="relative flex items-center">
<Button disabled variant="outline">
And
</Button>
</TableRow>
)}
</TableCell>
</TableRow>
)
</Fragment>
)
})
})}
</TableBody>
</Table>
<AddTableRow
<OrTableRow
disabled={disabled}
onClick={() => {
data.condition.push({})
data.condition.push([{}])
onChange(data)
}}
/>
Expand Down
20 changes: 18 additions & 2 deletions apps/renderer/src/modules/settings/tabs/actions/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,30 @@ export const ActionSetting = () => {

useEffect(() => {
if (actions.data?.rules) {
setActionsData(actions.data.rules)
setActionsData(
actions.data.rules.map((rule) => {
const { condition } = rule
// fix old data
const finalCondition =
condition.length > 0 && Array.isArray(condition[0]) ? condition : [condition]

return {
...rule,
condition: finalCondition as any,
}
}),
)
}
}, [actions.data?.rules])

const mutation = useMutation({
mutationFn: async () => {
actionsData.forEach((action) => {
action.condition = action.condition.filter((c) => c.field && c.operator && c.value)
action.condition = action.condition
.map((condition) => {
return condition.filter((c) => c.field && c.operator && c.value)
})
.filter((c) => c.length > 0)
action.result.rewriteRules = action.result.rewriteRules?.filter((r) => r.from && r.to)
action.result.blockRules = action.result.blockRules?.filter(
(r) => r.field && r.operator && r.value,
Expand Down
2 changes: 2 additions & 0 deletions changelog/next.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

## New Features

- And Or conditions for actions

## Improvements

## Bug Fixes
2 changes: 2 additions & 0 deletions locales/settings/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
"actions.actionName": "Action {{number}}",
"actions.action_card.add": "Add",
"actions.action_card.all": "All",
"actions.action_card.and": "And",
"actions.action_card.block": "Block",
"actions.action_card.block_rules": "Block Rules",
"actions.action_card.custom_filters": "Custom filters",
Expand Down Expand Up @@ -36,6 +37,7 @@
"actions.action_card.operation_options.is_not_equal_to": "is not equal to",
"actions.action_card.operation_options.matches_regex": "matches regex",
"actions.action_card.operator": "Operator",
"actions.action_card.or": "Or",
"actions.action_card.rewrite_rules": "Rewrite Rules",
"actions.action_card.silence": "Silence",
"actions.action_card.source_content": "View source content",
Expand Down
2 changes: 1 addition & 1 deletion packages/models/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ export type ActionsInput = {
field?: ActionFeedField
operator?: ActionOperation
value?: string
}[]
}[][]
result: {
disabled?: boolean
translation?: string
Expand Down
Loading

0 comments on commit 4193a6b

Please sign in to comment.