diff --git a/apps/web/app/(app)/(survey-editor)/environments/[environmentId]/surveys/[surveyId]/edit/components/LogicEditorConditions.tsx b/apps/web/app/(app)/(survey-editor)/environments/[environmentId]/surveys/[surveyId]/edit/components/LogicEditorConditions.tsx
index 5c74564688..17e0afb755 100644
--- a/apps/web/app/(app)/(survey-editor)/environments/[environmentId]/surveys/[surveyId]/edit/components/LogicEditorConditions.tsx
+++ b/apps/web/app/(app)/(survey-editor)/environments/[environmentId]/surveys/[surveyId]/edit/components/LogicEditorConditions.tsx
@@ -244,7 +244,13 @@ export function LogicEditorConditions({
const conditionOperatorOptions = getConditionOperatorOptions(condition, localSurvey);
const { show, options, showInput = false, inputType } = getMatchValueProps(condition, localSurvey, t);
- const allowMultiSelect = ["equalsOneOf", "includesAllOf", "includesOneOf"].includes(condition.operator);
+ const allowMultiSelect = [
+ "equalsOneOf",
+ "includesAllOf",
+ "includesOneOf",
+ "doesNotIncludeOneOf",
+ "doesNotIncludeAllOf",
+ ].includes(condition.operator);
return (
diff --git a/apps/web/app/(app)/(survey-editor)/environments/[environmentId]/surveys/[surveyId]/edit/lib/logicRuleEngine.ts b/apps/web/app/(app)/(survey-editor)/environments/[environmentId]/surveys/[surveyId]/edit/lib/logicRuleEngine.ts
index 048be52abf..a5af1f4825 100644
--- a/apps/web/app/(app)/(survey-editor)/environments/[environmentId]/surveys/[surveyId]/edit/lib/logicRuleEngine.ts
+++ b/apps/web/app/(app)/(survey-editor)/environments/[environmentId]/surveys/[surveyId]/edit/lib/logicRuleEngine.ts
@@ -116,6 +116,14 @@ export const logicRules = {
label: "environments.surveys.edit.does_not_equal",
value: ZSurveyLogicConditionsOperator.Enum.doesNotEqual,
},
+ {
+ label: "environments.surveys.edit.does_not_include_one_of",
+ value: ZSurveyLogicConditionsOperator.Enum.doesNotIncludeOneOf,
+ },
+ {
+ label: "environments.surveys.edit.does_not_include_all_of",
+ value: ZSurveyLogicConditionsOperator.Enum.doesNotIncludeAllOf,
+ },
{
label: "environments.surveys.edit.includes_all_of",
value: ZSurveyLogicConditionsOperator.Enum.includesAllOf,
@@ -144,6 +152,14 @@ export const logicRules = {
label: "environments.surveys.edit.does_not_equal",
value: ZSurveyLogicConditionsOperator.Enum.doesNotEqual,
},
+ {
+ label: "environments.surveys.edit.does_not_include_one_of",
+ value: ZSurveyLogicConditionsOperator.Enum.doesNotIncludeOneOf,
+ },
+ {
+ label: "environments.surveys.edit.does_not_include_all_of",
+ value: ZSurveyLogicConditionsOperator.Enum.doesNotIncludeAllOf,
+ },
{
label: "environments.surveys.edit.includes_all_of",
value: ZSurveyLogicConditionsOperator.Enum.includesAllOf,
diff --git a/packages/lib/messages/de-DE.json b/packages/lib/messages/de-DE.json
index ad209d52be..018222d6f3 100644
--- a/packages/lib/messages/de-DE.json
+++ b/packages/lib/messages/de-DE.json
@@ -1351,6 +1351,8 @@
"does_not_contain": "Enthält nicht",
"does_not_end_with": "Endet nicht mit",
"does_not_equal": "Ungleich",
+ "does_not_include_all_of": "Enthält nicht alle von",
+ "does_not_include_one_of": "Enthält nicht eines von",
"does_not_start_with": "Fängt nicht an mit",
"edit_recall": "Erinnerung bearbeiten",
"edit_segment": "Segment bearbeiten",
diff --git a/packages/lib/messages/en-US.json b/packages/lib/messages/en-US.json
index 8f279f1408..a1e657aac6 100644
--- a/packages/lib/messages/en-US.json
+++ b/packages/lib/messages/en-US.json
@@ -1351,6 +1351,8 @@
"does_not_contain": "Does not contain",
"does_not_end_with": "Does not end with",
"does_not_equal": "Does not equal",
+ "does_not_include_all_of": "Does not include all of",
+ "does_not_include_one_of": "Does not include one of",
"does_not_start_with": "Does not start with",
"edit_recall": "Edit Recall",
"edit_segment": "Edit Segment",
diff --git a/packages/lib/messages/pt-BR.json b/packages/lib/messages/pt-BR.json
index ab7073257a..0239f700d5 100644
--- a/packages/lib/messages/pt-BR.json
+++ b/packages/lib/messages/pt-BR.json
@@ -1351,6 +1351,8 @@
"does_not_contain": "não contém",
"does_not_end_with": "Não termina com",
"does_not_equal": "não é igual",
+ "does_not_include_all_of": "Não inclui todos de",
+ "does_not_include_one_of": "Não inclui um de",
"does_not_start_with": "Não começa com",
"edit_recall": "Editar Lembrete",
"edit_segment": "Editar Segmento",
diff --git a/packages/lib/surveyLogic/utils.ts b/packages/lib/surveyLogic/utils.ts
index f142f34d45..5a8ab44571 100644
--- a/packages/lib/surveyLogic/utils.ts
+++ b/packages/lib/surveyLogic/utils.ts
@@ -425,6 +425,18 @@ const evaluateSingleCondition = (
Array.isArray(rightValue) &&
rightValue.some((v) => leftValue.includes(v))
);
+ case "doesNotIncludeAllOf":
+ return (
+ Array.isArray(leftValue) &&
+ Array.isArray(rightValue) &&
+ rightValue.every((v) => !leftValue.includes(v))
+ );
+ case "doesNotIncludeOneOf":
+ return (
+ Array.isArray(leftValue) &&
+ Array.isArray(rightValue) &&
+ rightValue.some((v) => !leftValue.includes(v))
+ );
case "isAccepted":
return leftValue === "accepted";
case "isClicked":
diff --git a/packages/types/surveys/types.ts b/packages/types/surveys/types.ts
index e558730fd3..8bf40c7159 100644
--- a/packages/types/surveys/types.ts
+++ b/packages/types/surveys/types.ts
@@ -249,6 +249,8 @@ export const ZSurveyLogicConditionsOperator = z.enum([
"equalsOneOf",
"includesAllOf",
"includesOneOf",
+ "doesNotIncludeOneOf",
+ "doesNotIncludeAllOf",
"isClicked",
"isAccepted",
"isBefore",
@@ -1212,9 +1214,16 @@ const isInvalidOperatorsForQuestionType = (
case TSurveyQuestionTypeEnum.MultipleChoiceMulti:
case TSurveyQuestionTypeEnum.PictureSelection:
if (
- !["equals", "doesNotEqual", "includesAllOf", "includesOneOf", "isSubmitted", "isSkipped"].includes(
- operator
- )
+ ![
+ "equals",
+ "doesNotEqual",
+ "includesAllOf",
+ "includesOneOf",
+ "doesNotIncludeAllOf",
+ "doesNotIncludeOneOf",
+ "isSubmitted",
+ "isSkipped",
+ ].includes(operator)
) {
isInvalidOperator = true;
}
@@ -1553,7 +1562,11 @@ const validateConditions = (
});
}
}
- } else if (condition.operator === "includesAllOf" || condition.operator === "includesOneOf") {
+ } else if (
+ ["includesAllOf", "includesOneOf", "doesNotIncludeAllOf", "doesNotIncludeOneOf"].includes(
+ condition.operator
+ )
+ ) {
if (!Array.isArray(rightOperand.value)) {
issues.push({
code: z.ZodIssueCode.custom,