aboutsummaryrefslogtreecommitdiffstats
path: root/apps/web
diff options
context:
space:
mode:
authorMohamed Bassem <me@mbassem.com>2025-12-30 13:29:03 +0200
committerGitHub <noreply@github.com>2025-12-30 11:29:03 +0000
commitb20ba9cfccd22159bf8263165cca76aab3147d9c (patch)
tree166f5c477d1c368a5017aae9f726b692d655fc0e /apps/web
parenta0b4a26ad398137e13c35f3fe0dad99154537d91 (diff)
downloadkarakeep-b20ba9cfccd22159bf8263165cca76aab3147d9c.tar.zst
feat: add "URL Does Not Contain" condition to rule engine (#2280)
* feat: add "URL Does Not Contain" condition to rule engine Add a new condition type `urlDoesNotContain` that allows users to create rules based on URLs that do NOT contain specific strings. This enables more flexible rule configurations, such as: - Automatically adding bookmarks to a "Read Later" list if the URL does not contain "reddit.com" or "youtube.com" Changes: - Added `urlDoesNotContain` condition type to Zod schema - Implemented evaluation logic in RuleEngine - Added UI support in ConditionBuilder component - Added translation key for new condition type - Added test coverage for the new condition Fixes #2259 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Mohamed Bassem <MohamedBassem@users.noreply.github.com> * fix type link --------- Co-authored-by: claude[bot] <41898282+claude[bot]@users.noreply.github.com> Co-authored-by: Mohamed Bassem <MohamedBassem@users.noreply.github.com>
Diffstat (limited to 'apps/web')
-rw-r--r--apps/web/components/dashboard/rules/RuleEngineConditionBuilder.tsx19
-rw-r--r--apps/web/lib/i18n/locales/en/translation.json1
2 files changed, 20 insertions, 0 deletions
diff --git a/apps/web/components/dashboard/rules/RuleEngineConditionBuilder.tsx b/apps/web/components/dashboard/rules/RuleEngineConditionBuilder.tsx
index 8faca013..a859a4cc 100644
--- a/apps/web/components/dashboard/rules/RuleEngineConditionBuilder.tsx
+++ b/apps/web/components/dashboard/rules/RuleEngineConditionBuilder.tsx
@@ -54,6 +54,9 @@ export function ConditionBuilder({
case "urlContains":
onChange({ type: "urlContains", str: "" });
break;
+ case "urlDoesNotContain":
+ onChange({ type: "urlDoesNotContain", str: "" });
+ break;
case "importedFromFeed":
onChange({ type: "importedFromFeed", feedId: "" });
break;
@@ -88,6 +91,7 @@ export function ConditionBuilder({
const renderConditionIcon = (type: RuleEngineCondition["type"]) => {
switch (type) {
case "urlContains":
+ case "urlDoesNotContain":
return <Link className="h-4 w-4" />;
case "importedFromFeed":
return <Rss className="h-4 w-4" />;
@@ -118,6 +122,18 @@ export function ConditionBuilder({
</div>
);
+ case "urlDoesNotContain":
+ return (
+ <div className="mt-2">
+ <Input
+ value={value.str}
+ onChange={(e) => onChange({ ...value, str: e.target.value })}
+ placeholder="URL does not contain..."
+ className="w-full"
+ />
+ </div>
+ );
+
case "importedFromFeed":
return (
<div className="mt-2">
@@ -235,6 +251,9 @@ export function ConditionBuilder({
<SelectItem value="urlContains">
{t("settings.rules.conditions_types.url_contains")}
</SelectItem>
+ <SelectItem value="urlDoesNotContain">
+ {t("settings.rules.conditions_types.url_does_not_contain")}
+ </SelectItem>
<SelectItem value="importedFromFeed">
{t("settings.rules.conditions_types.imported_from_feed")}
</SelectItem>
diff --git a/apps/web/lib/i18n/locales/en/translation.json b/apps/web/lib/i18n/locales/en/translation.json
index 58e1af09..87851324 100644
--- a/apps/web/lib/i18n/locales/en/translation.json
+++ b/apps/web/lib/i18n/locales/en/translation.json
@@ -348,6 +348,7 @@
"conditions_types": {
"always": "Always",
"url_contains": "URL Contains",
+ "url_does_not_contain": "URL Does Not Contain",
"imported_from_feed": "Imported From Feed",
"bookmark_type_is": "Bookmark Type Is",
"has_tag": "Has Tag",