fix(tags): Filter system tags from the tags list (#26701)
This commit is contained in:
parent
f084572dc7
commit
4f56f5ee84
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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")
|
||||
|
|
|
|||
Loading…
Reference in New Issue