APIv2: Fix autocomplete in Stats API playground (#5286)

Filters autocomplete only showed `"is", "segment"` under autocomplete
instead of all options. This is due to limitations in the vscode
autocomplete package which I don't fully understand but have to do with
partially overlapping `oneOf` definitions. As such the fix was to make
each `oneOf` element as independent of each other as possible.

Basecamp ref: http://localhost:8001/docs/stats-api-playground
This commit is contained in:
Karl-Aksel Puulmann 2025-04-08 18:17:59 +03:00 committed by GitHub
parent 1e17d54b5b
commit f8ddecf080
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 69 additions and 42 deletions

View File

@ -71,7 +71,7 @@ export type CustomPropertyFilterDimensions = string;
export type GoalDimension = "event:goal";
export type TimeDimensions = ("time" | "time:month" | "time:week" | "time:day" | "time:hour") | "time:minute";
export type FilterTree = FilterEntry | FilterAndOr | FilterNot | FilterHasDone;
export type FilterEntry = FilterWithoutGoals | FilterWithGoals | FilterWithPattern | FilterForSegment;
export type FilterEntry = FilterWithoutGoals | FilterWithIs | FilterWithContains | FilterWithPattern;
/**
* @minItems 3
* @maxItems 4
@ -95,20 +95,30 @@ export type Clauses = (string | number)[];
* @minItems 3
* @maxItems 4
*/
export type FilterWithGoals =
| [FilterOperationContains, GoalDimension | SimpleFilterDimensions | CustomPropertyFilterDimensions, Clauses]
export type FilterWithIs =
| ["is", GoalDimension | SimpleFilterDimensions | CustomPropertyFilterDimensions | "segment", Clauses]
| [
FilterOperationContains,
GoalDimension | SimpleFilterDimensions | CustomPropertyFilterDimensions,
"is",
GoalDimension | SimpleFilterDimensions | CustomPropertyFilterDimensions | "segment",
Clauses,
{
case_sensitive?: boolean;
}
];
/**
* filter operation
* @minItems 3
* @maxItems 4
*/
export type FilterOperationContains = "is" | "contains";
export type FilterWithContains =
| ["contains", GoalDimension | SimpleFilterDimensions | CustomPropertyFilterDimensions, Clauses]
| [
"contains",
GoalDimension | SimpleFilterDimensions | CustomPropertyFilterDimensions,
Clauses,
{
case_sensitive?: boolean;
}
];
/**
* @minItems 3
* @maxItems 3
@ -122,11 +132,6 @@ export type FilterWithPattern = [
* filter operation
*/
export type FilterOperationRegex = "matches" | "matches_not";
/**
* @minItems 3
* @maxItems 3
*/
export type FilterForSegment = ["is", "segment", number[]];
/**
* @minItems 2
* @maxItems 2

View File

@ -367,11 +367,6 @@
"enum": ["is_not", "contains_not"],
"description": "filter operation"
},
"filter_operation_contains": {
"type": "string",
"enum": ["is", "contains"],
"description": "filter operation"
},
"filter_with_pattern": {
"type": "array",
"additionalItems": false,
@ -422,14 +417,48 @@
}
]
},
"filter_with_goals": {
"filter_with_is": {
"type": "array",
"additionalItems": false,
"minItems": 3,
"maxItems": 4,
"items": [
{
"$ref": "#/definitions/filter_operation_contains"
"const": "is",
"description": "filter operation"
},
{
"oneOf": [
{ "$ref": "#/definitions/goal_dimension" },
{ "$ref": "#/definitions/simple_filter_dimensions" },
{ "$ref": "#/definitions/custom_property_filter_dimensions" },
{ "const": "segment" }
]
},
{
"$ref": "#/definitions/clauses"
},
{
"type": "object",
"additionalProperties": false,
"properties": {
"case_sensitive": {
"type": "boolean",
"default": true
}
}
}
]
},
"filter_with_contains": {
"type": "array",
"additionalItems": false,
"minItems": 3,
"maxItems": 4,
"items": [
{
"const": "contains",
"description": "filter operation"
},
{
"oneOf": [
@ -453,32 +482,12 @@
}
]
},
"filter_for_segment": {
"type": "array",
"additionalItems": false,
"minItems": 3,
"maxItems": 3,
"items": [
{
"const": "is"
},
{
"const": "segment"
},
{
"type": "array",
"items": {
"type": ["integer"]
}
}
]
},
"filter_entry": {
"oneOf": [
{ "$ref": "#/definitions/filter_without_goals" },
{ "$ref": "#/definitions/filter_with_goals" },
{ "$ref": "#/definitions/filter_with_pattern" },
{ "$ref": "#/definitions/filter_for_segment" }
{ "$ref": "#/definitions/filter_with_is" },
{ "$ref": "#/definitions/filter_with_contains" },
{ "$ref": "#/definitions/filter_with_pattern" }
]
},
"filter_tree": {

View File

@ -2589,5 +2589,18 @@ defmodule Plausible.Stats.Filters.QueryParserTest do
}
)
end
test "validation fails with string segment ids", %{site: site} do
%{
"site_id" => site.domain,
"metrics" => ["visitors"],
"date_range" => "all",
"filters" => [["is", "segment", ["123"]]]
}
|> check_error(
site,
"Invalid filter '[\"is\", \"segment\", [\"123\"]]'."
)
end
end
end