fix(tags): Filter system tags from the tags list (#26701)

This commit is contained in:
Vitor Avila 2024-01-26 17:00:27 -03:00 committed by GitHub
parent f084572dc7
commit 4f56f5ee84
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 108 additions and 3 deletions

View File

@ -59,6 +59,17 @@ function TagList(props: TagListProps) {
const { addDangerToast, addSuccessToast, user } = props;
const { userId } = user;
const initialFilters = useMemo(
() => [
{
id: 'type',
operator: 'custom_tag',
value: true,
},
],
[],
);
const {
state: {
loading,
@ -70,7 +81,14 @@ function TagList(props: TagListProps) {
fetchData,
toggleBulkSelect,
refreshData,
} = useListViewResource<Tag>('tag', t('tag'), addDangerToast);
} = useListViewResource<Tag>(
'tag',
t('tag'),
addDangerToast,
undefined,
undefined,
initialFilters,
);
const [showTagModal, setShowTagModal] = useState<boolean>(false);
const [tagToEdit, setTagToEdit] = useState<Tag | null>(null);

View File

@ -80,7 +80,7 @@ def import_chart(
def import_dashboard(
# pylint: disable=too-many-branches,too-many-locals,too-many-statements
# pylint: disable=too-many-locals,too-many-statements
dashboard_to_import: Dashboard,
dataset_id_mapping: Optional[dict[int, int]] = None,
import_time: Optional[int] = None,

View File

@ -40,6 +40,7 @@ from superset.constants import MODEL_API_RW_METHOD_PERMISSION_MAP, RouteMethod
from superset.daos.tag import TagDAO
from superset.exceptions import MissingUserContextException
from superset.extensions import event_logger
from superset.tags.filters import UserCreatedTagTypeFilter
from superset.tags.models import ObjectType, Tag
from superset.tags.schemas import (
delete_tags_schema,
@ -119,6 +120,8 @@ class TagRestApi(BaseSupersetModelRestApi):
}
allowed_rel_fields = {"created_by", "changed_by"}
search_filters = {"type": [UserCreatedTagTypeFilter]}
add_model_schema = TagPostSchema()
edit_model_schema = TagPutSchema()
tag_get_response_schema = TagGetResponseSchema()

39
superset/tags/filters.py Normal file
View File

@ -0,0 +1,39 @@
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
from flask_babel import lazy_gettext as _
from sqlalchemy.orm import Query
from superset.tags.models import Tag, TagType
from superset.views.base import BaseFilter
class UserCreatedTagTypeFilter(BaseFilter): # pylint: disable=too-few-public-methods
"""
Filter for tag type.
When set to True, only user-created tags are returned.
When set to False, only system tags are returned.
"""
name = _("Is custom tag")
arg_name = "custom_tag"
def apply(self, query: Query, value: bool) -> Query:
if value:
return query.filter(Tag.type == TagType.custom)
if value is False:
return query.filter(Tag.type != TagType.custom)
return query

View File

@ -15,7 +15,6 @@
# specific language governing permissions and limitations
# under the License.
# pylint: disable=invalid-name
# pylint: disable=too-many-lines
from __future__ import annotations
import contextlib

View File

@ -17,6 +17,7 @@
# isort:skip_file
"""Unit tests for Superset"""
import json
import prison
from datetime import datetime
from flask import g
@ -30,6 +31,7 @@ from superset.models.slice import Slice
from superset.models.sql_lab import SavedQuery
from superset.tags.models import user_favorite_tag_table
from unittest.mock import patch
from urllib import parse
import tests.integration_tests.test_app
@ -175,6 +177,50 @@ class TestTagApi(SupersetTestCase):
# check expected columns
assert data["list_columns"] == TAGS_LIST_COLUMNS
def test_get_list_tag_filtered(self):
"""
Query API: Test get list query applying filters for
type == "custom" and type != "custom"
"""
tags = [
{"name": "Test custom Tag", "type": "custom"},
{"name": "type:dashboard", "type": "type"},
{"name": "owner:1", "type": "owner"},
{"name": "Another Tag", "type": "custom"},
{"name": "favorited_by:1", "type": "favorited_by"},
]
for tag in tags:
self.insert_tag(
name=tag["name"],
tag_type=tag["type"],
)
self.login(username="admin")
# Only user-created tags
query = {
"filters": [
{
"col": "type",
"opr": "custom_tag",
"value": True,
}
],
}
uri = f"api/v1/tag/?{parse.urlencode({'q': prison.dumps(query)})}"
rv = self.client.get(uri)
self.assertEqual(rv.status_code, 200)
data = json.loads(rv.data.decode("utf-8"))
assert data["count"] == 2
# Only system tags
query["filters"][0]["value"] = False
uri = f"api/v1/tag/?{parse.urlencode({'q': prison.dumps(query)})}"
rv = self.client.get(uri)
self.assertEqual(rv.status_code, 200)
data = json.loads(rv.data.decode("utf-8"))
assert data["count"] == 3
# test add tagged objects
@pytest.mark.usefixtures("load_world_bank_dashboard_with_slices")
@pytest.mark.usefixtures("load_birth_names_dashboard_with_slices")