mirror of
https://github.com/apache/superset.git
synced 2026-04-19 08:04:53 +00:00
feat: add created by chart CRUD view (#11067)
This commit is contained in:
@@ -18,7 +18,7 @@
|
|||||||
*/
|
*/
|
||||||
import { CHART_LIST } from './chart_list.helper';
|
import { CHART_LIST } from './chart_list.helper';
|
||||||
|
|
||||||
describe('chart filters', () => {
|
describe('chart card view filters', () => {
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
cy.login();
|
cy.login();
|
||||||
cy.server();
|
cy.server();
|
||||||
@@ -36,26 +36,88 @@ describe('chart filters', () => {
|
|||||||
cy.get('.ant-card').should('not.exist');
|
cy.get('.ant-card').should('not.exist');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should filter by created by correctly', () => {
|
||||||
|
// filter by created by
|
||||||
|
cy.get('.Select__control').eq(1).click();
|
||||||
|
cy.get('.Select__menu').contains('alpha user').click();
|
||||||
|
cy.get('.ant-card').should('not.exist');
|
||||||
|
cy.get('.Select__control').eq(1).click();
|
||||||
|
cy.get('.Select__menu').contains('gamma user').click();
|
||||||
|
cy.get('.ant-card').should('not.exist');
|
||||||
|
});
|
||||||
|
|
||||||
it('should filter by viz type correctly', () => {
|
it('should filter by viz type correctly', () => {
|
||||||
// filter by viz type
|
// filter by viz type
|
||||||
cy.get('.Select__control').eq(1).click();
|
cy.get('.Select__control').eq(2).click();
|
||||||
cy.get('.Select__menu').contains('area').click({ timeout: 5000 });
|
cy.get('.Select__menu').contains('area').click({ timeout: 5000 });
|
||||||
cy.get('.ant-card').its('length').should('be.gt', 0);
|
cy.get('.ant-card').its('length').should('be.gt', 0);
|
||||||
cy.get('.ant-card').contains("World's Pop Growth").should('exist');
|
cy.get('.ant-card').contains("World's Pop Growth").should('exist');
|
||||||
cy.get('.Select__control').eq(1).click();
|
cy.get('.Select__control').eq(2).click();
|
||||||
cy.get('.Select__control').eq(1).type('world_map{enter}');
|
cy.get('.Select__control').eq(2).type('world_map{enter}');
|
||||||
cy.get('.ant-card').should('have.length', 1);
|
cy.get('.ant-card').should('have.length', 1);
|
||||||
cy.get('.ant-card').contains('% Rural').should('exist');
|
cy.get('.ant-card').contains('% Rural').should('exist');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should filter by datasource correctly', () => {
|
it('should filter by datasource correctly', () => {
|
||||||
// filter by datasource
|
// filter by datasource
|
||||||
cy.get('.Select__control').eq(2).click();
|
cy.get('.Select__control').eq(3).click();
|
||||||
cy.get('.Select__menu').contains('unicode_test').click();
|
cy.get('.Select__menu').contains('unicode_test').click();
|
||||||
cy.get('.ant-card').should('have.length', 1);
|
cy.get('.ant-card').should('have.length', 1);
|
||||||
cy.get('.ant-card').contains('Unicode Cloud').should('exist');
|
cy.get('.ant-card').contains('Unicode Cloud').should('exist');
|
||||||
cy.get('.Select__control').eq(2).click();
|
cy.get('.Select__control').eq(3).click();
|
||||||
cy.get('.Select__control').eq(2).type('energy_usage{enter}{enter}');
|
cy.get('.Select__control').eq(3).type('energy_usage{enter}{enter}');
|
||||||
cy.get('.ant-card').its('length').should('be.gt', 0);
|
cy.get('.ant-card').its('length').should('be.gt', 0);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('chart list view filters', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
cy.login();
|
||||||
|
cy.server();
|
||||||
|
cy.visit(CHART_LIST);
|
||||||
|
cy.get('[data-test="list-view"]').click();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should filter by owners correctly', () => {
|
||||||
|
// filter by owners
|
||||||
|
cy.get('.Select__control').first().click();
|
||||||
|
cy.get('.Select__menu').contains('alpha user').click();
|
||||||
|
cy.get('.table-row').should('not.exist');
|
||||||
|
cy.get('.Select__control').first().click();
|
||||||
|
cy.get('.Select__menu').contains('gamma user').click();
|
||||||
|
cy.get('.table-row').should('not.exist');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should filter by created by correctly', () => {
|
||||||
|
// filter by created by
|
||||||
|
cy.get('.Select__control').eq(1).click();
|
||||||
|
cy.get('.Select__menu').contains('alpha user').click();
|
||||||
|
cy.get('.table-row').should('not.exist');
|
||||||
|
cy.get('.Select__control').eq(1).click();
|
||||||
|
cy.get('.Select__menu').contains('gamma user').click();
|
||||||
|
cy.get('.table-row').should('not.exist');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should filter by viz type correctly', () => {
|
||||||
|
// filter by viz type
|
||||||
|
cy.get('.Select__control').eq(2).click();
|
||||||
|
cy.get('.Select__menu').contains('area').click({ timeout: 5000 });
|
||||||
|
cy.get('.table-row').its('length').should('be.gt', 0);
|
||||||
|
cy.get('.table-row').contains("World's Pop Growth").should('exist');
|
||||||
|
cy.get('.Select__control').eq(2).click();
|
||||||
|
cy.get('.Select__control').eq(2).type('world_map{enter}');
|
||||||
|
cy.get('.table-row').should('have.length', 1);
|
||||||
|
cy.get('.table-row').contains('% Rural').should('exist');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should filter by datasource correctly', () => {
|
||||||
|
// filter by datasource
|
||||||
|
cy.get('.Select__control').eq(3).click();
|
||||||
|
cy.get('.Select__menu').contains('unicode_test').click();
|
||||||
|
cy.get('.table-row').should('have.length', 1);
|
||||||
|
cy.get('.table-row').contains('Unicode Cloud').should('exist');
|
||||||
|
cy.get('.Select__control').eq(3).click();
|
||||||
|
cy.get('.Select__control').eq(3).type('energy_usage{enter}{enter}');
|
||||||
|
cy.get('.table-row').its('length').should('be.gt', 0);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ describe('chart list view', () => {
|
|||||||
cy.get('[data-test="list-view"]').click();
|
cy.get('[data-test="list-view"]').click();
|
||||||
});
|
});
|
||||||
|
|
||||||
it.skip('should load rows', () => {
|
it('should load rows', () => {
|
||||||
cy.get('.chart-list-view');
|
cy.get('.chart-list-view');
|
||||||
cy.get('table[role="table"]').should('be.visible');
|
cy.get('table[role="table"]').should('be.visible');
|
||||||
|
|
||||||
@@ -38,7 +38,8 @@ describe('chart list view', () => {
|
|||||||
cy.get('th[role="columnheader"]:nth-child(4)').contains('Dataset');
|
cy.get('th[role="columnheader"]:nth-child(4)').contains('Dataset');
|
||||||
cy.get('th[role="columnheader"]:nth-child(5)').contains('Modified By');
|
cy.get('th[role="columnheader"]:nth-child(5)').contains('Modified By');
|
||||||
cy.get('th[role="columnheader"]:nth-child(6)').contains('Last Modified');
|
cy.get('th[role="columnheader"]:nth-child(6)').contains('Last Modified');
|
||||||
cy.get('th[role="columnheader"]:nth-child(7)').contains('Actions');
|
cy.get('th[role="columnheader"]:nth-child(7)').contains('Created By');
|
||||||
|
cy.get('th[role="columnheader"]:nth-child(8)').contains('Actions');
|
||||||
cy.get('.table-row').should('have.length', 25);
|
cy.get('.table-row').should('have.length', 25);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -63,6 +63,7 @@ describe('dashboard filters list view', () => {
|
|||||||
cy.login();
|
cy.login();
|
||||||
cy.server();
|
cy.server();
|
||||||
cy.visit(DASHBOARD_LIST);
|
cy.visit(DASHBOARD_LIST);
|
||||||
|
cy.get('[data-test="list-view"]').click();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should filter by owners correctly', () => {
|
it('should filter by owners correctly', () => {
|
||||||
|
|||||||
@@ -257,6 +257,17 @@ function ChartList(props: ChartListProps) {
|
|||||||
hidden: true,
|
hidden: true,
|
||||||
disableSortBy: true,
|
disableSortBy: true,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
Cell: ({
|
||||||
|
row: {
|
||||||
|
original: { created_by: createdBy },
|
||||||
|
},
|
||||||
|
}: any) =>
|
||||||
|
createdBy ? `${createdBy.first_name} ${createdBy.last_name}` : '',
|
||||||
|
Header: t('Created By'),
|
||||||
|
accessor: 'created_by',
|
||||||
|
disableSortBy: true,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
Cell: ({ row: { original } }: any) => {
|
Cell: ({ row: { original } }: any) => {
|
||||||
const handleDelete = () => handleChartDelete(original);
|
const handleDelete = () => handleChartDelete(original);
|
||||||
@@ -324,7 +335,27 @@ function ChartList(props: ChartListProps) {
|
|||||||
createErrorHandler(errMsg =>
|
createErrorHandler(errMsg =>
|
||||||
props.addDangerToast(
|
props.addDangerToast(
|
||||||
t(
|
t(
|
||||||
'An error occurred while fetching chart dataset values: %s',
|
'An error occurred while fetching chart owners values: %s',
|
||||||
|
errMsg,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
paginate: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Header: t('Created By'),
|
||||||
|
id: 'created_by',
|
||||||
|
input: 'select',
|
||||||
|
operator: 'rel_o_m',
|
||||||
|
unfilteredLabel: 'All',
|
||||||
|
fetchSelects: createFetchRelated(
|
||||||
|
'chart',
|
||||||
|
'created_by',
|
||||||
|
createErrorHandler(errMsg =>
|
||||||
|
props.addDangerToast(
|
||||||
|
t(
|
||||||
|
'An error occurred while fetching chart created by values: %s',
|
||||||
errMsg,
|
errMsg,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -107,22 +107,25 @@ class ChartRestApi(BaseSupersetModelRestApi):
|
|||||||
"changed_by_url",
|
"changed_by_url",
|
||||||
"changed_on_delta_humanized",
|
"changed_on_delta_humanized",
|
||||||
"changed_on_utc",
|
"changed_on_utc",
|
||||||
|
"created_by.first_name",
|
||||||
|
"created_by.id",
|
||||||
|
"created_by.last_name",
|
||||||
"datasource_id",
|
"datasource_id",
|
||||||
"datasource_name_text",
|
"datasource_name_text",
|
||||||
"datasource_type",
|
"datasource_type",
|
||||||
"datasource_url",
|
"datasource_url",
|
||||||
"description",
|
"description",
|
||||||
"id",
|
"id",
|
||||||
|
"owners.first_name",
|
||||||
|
"owners.id",
|
||||||
|
"owners.last_name",
|
||||||
|
"owners.username",
|
||||||
"params",
|
"params",
|
||||||
"slice_name",
|
"slice_name",
|
||||||
"table.default_endpoint",
|
"table.default_endpoint",
|
||||||
"table.table_name",
|
"table.table_name",
|
||||||
"thumbnail_url",
|
"thumbnail_url",
|
||||||
"url",
|
"url",
|
||||||
"owners.id",
|
|
||||||
"owners.username",
|
|
||||||
"owners.first_name",
|
|
||||||
"owners.last_name",
|
|
||||||
"viz_type",
|
"viz_type",
|
||||||
]
|
]
|
||||||
list_select_columns = list_columns + ["changed_by_fk", "changed_on"]
|
list_select_columns = list_columns + ["changed_by_fk", "changed_on"]
|
||||||
@@ -135,6 +138,7 @@ class ChartRestApi(BaseSupersetModelRestApi):
|
|||||||
"viz_type",
|
"viz_type",
|
||||||
]
|
]
|
||||||
search_columns = [
|
search_columns = [
|
||||||
|
"created_by",
|
||||||
"datasource_id",
|
"datasource_id",
|
||||||
"datasource_name",
|
"datasource_name",
|
||||||
"datasource_type",
|
"datasource_type",
|
||||||
@@ -172,10 +176,11 @@ class ChartRestApi(BaseSupersetModelRestApi):
|
|||||||
}
|
}
|
||||||
|
|
||||||
related_field_filters = {
|
related_field_filters = {
|
||||||
"owners": RelatedFieldFilter("first_name", FilterRelatedOwners)
|
"owners": RelatedFieldFilter("first_name", FilterRelatedOwners),
|
||||||
|
"created_by": RelatedFieldFilter("first_name", FilterRelatedOwners),
|
||||||
}
|
}
|
||||||
|
|
||||||
allowed_rel_fields = {"owners"}
|
allowed_rel_fields = {"owners", "created_by"}
|
||||||
|
|
||||||
def __init__(self) -> None:
|
def __init__(self) -> None:
|
||||||
if is_feature_enabled("THUMBNAILS"):
|
if is_feature_enabled("THUMBNAILS"):
|
||||||
|
|||||||
@@ -48,6 +48,7 @@ class TestChartApi(SupersetTestCase, ApiOwnersTestCaseMixin):
|
|||||||
slice_name: str,
|
slice_name: str,
|
||||||
owners: List[int],
|
owners: List[int],
|
||||||
datasource_id: int,
|
datasource_id: int,
|
||||||
|
created_by=None,
|
||||||
datasource_type: str = "table",
|
datasource_type: str = "table",
|
||||||
description: Optional[str] = None,
|
description: Optional[str] = None,
|
||||||
viz_type: Optional[str] = None,
|
viz_type: Optional[str] = None,
|
||||||
@@ -62,15 +63,16 @@ class TestChartApi(SupersetTestCase, ApiOwnersTestCaseMixin):
|
|||||||
datasource_type, datasource_id, db.session
|
datasource_type, datasource_id, db.session
|
||||||
)
|
)
|
||||||
slice = Slice(
|
slice = Slice(
|
||||||
slice_name=slice_name,
|
cache_timeout=cache_timeout,
|
||||||
|
created_by=created_by,
|
||||||
datasource_id=datasource.id,
|
datasource_id=datasource.id,
|
||||||
datasource_name=datasource.name,
|
datasource_name=datasource.name,
|
||||||
datasource_type=datasource.type,
|
datasource_type=datasource.type,
|
||||||
owners=obj_owners,
|
|
||||||
description=description,
|
description=description,
|
||||||
viz_type=viz_type,
|
owners=obj_owners,
|
||||||
params=params,
|
params=params,
|
||||||
cache_timeout=cache_timeout,
|
slice_name=slice_name,
|
||||||
|
viz_type=viz_type,
|
||||||
)
|
)
|
||||||
db.session.add(slice)
|
db.session.add(slice)
|
||||||
db.session.commit()
|
db.session.commit()
|
||||||
@@ -93,12 +95,12 @@ class TestChartApi(SupersetTestCase, ApiOwnersTestCaseMixin):
|
|||||||
"""
|
"""
|
||||||
Chart API: Test delete bulk
|
Chart API: Test delete bulk
|
||||||
"""
|
"""
|
||||||
admin_id = self.get_user("admin").id
|
admin = self.get_user("admin")
|
||||||
chart_count = 4
|
chart_count = 4
|
||||||
chart_ids = list()
|
chart_ids = list()
|
||||||
for chart_name_index in range(chart_count):
|
for chart_name_index in range(chart_count):
|
||||||
chart_ids.append(
|
chart_ids.append(
|
||||||
self.insert_chart(f"title{chart_name_index}", [admin_id], 1).id
|
self.insert_chart(f"title{chart_name_index}", [admin.id], 1, admin).id
|
||||||
)
|
)
|
||||||
self.login(username="admin")
|
self.login(username="admin")
|
||||||
argument = chart_ids
|
argument = chart_ids
|
||||||
@@ -365,7 +367,7 @@ class TestChartApi(SupersetTestCase, ApiOwnersTestCaseMixin):
|
|||||||
admin = self.get_user("admin")
|
admin = self.get_user("admin")
|
||||||
gamma = self.get_user("gamma")
|
gamma = self.get_user("gamma")
|
||||||
|
|
||||||
chart_id = self.insert_chart("title", [admin.id], 1).id
|
chart_id = self.insert_chart("title", [admin.id], 1, admin).id
|
||||||
birth_names_table_id = SupersetTestCase.get_table_by_name("birth_names").id
|
birth_names_table_id = SupersetTestCase.get_table_by_name("birth_names").id
|
||||||
chart_data = {
|
chart_data = {
|
||||||
"slice_name": "title1_changed",
|
"slice_name": "title1_changed",
|
||||||
@@ -384,6 +386,7 @@ class TestChartApi(SupersetTestCase, ApiOwnersTestCaseMixin):
|
|||||||
self.assertEqual(rv.status_code, 200)
|
self.assertEqual(rv.status_code, 200)
|
||||||
model = db.session.query(Slice).get(chart_id)
|
model = db.session.query(Slice).get(chart_id)
|
||||||
related_dashboard = db.session.query(Dashboard).get(1)
|
related_dashboard = db.session.query(Dashboard).get(1)
|
||||||
|
self.assertEqual(model.created_by, admin)
|
||||||
self.assertEqual(model.slice_name, "title1_changed")
|
self.assertEqual(model.slice_name, "title1_changed")
|
||||||
self.assertEqual(model.description, "description1")
|
self.assertEqual(model.description, "description1")
|
||||||
self.assertIn(admin, model.owners)
|
self.assertIn(admin, model.owners)
|
||||||
@@ -902,7 +905,9 @@ class TestChartApi(SupersetTestCase, ApiOwnersTestCaseMixin):
|
|||||||
self.assertEqual(rv.status_code, 400)
|
self.assertEqual(rv.status_code, 400)
|
||||||
|
|
||||||
def test_chart_data_with_invalid_datasource(self):
|
def test_chart_data_with_invalid_datasource(self):
|
||||||
"""Chart data API: Test chart data query with invalid schema"""
|
"""
|
||||||
|
Chart data API: Test chart data query with invalid schema
|
||||||
|
"""
|
||||||
self.login(username="admin")
|
self.login(username="admin")
|
||||||
table = self.get_table_by_name("birth_names")
|
table = self.get_table_by_name("birth_names")
|
||||||
payload = get_query_context(table.name, table.id, table.type)
|
payload = get_query_context(table.name, table.id, table.type)
|
||||||
@@ -911,7 +916,9 @@ class TestChartApi(SupersetTestCase, ApiOwnersTestCaseMixin):
|
|||||||
self.assertEqual(rv.status_code, 400)
|
self.assertEqual(rv.status_code, 400)
|
||||||
|
|
||||||
def test_chart_data_with_invalid_enum_value(self):
|
def test_chart_data_with_invalid_enum_value(self):
|
||||||
"""Chart data API: Test chart data query with invalid enum value"""
|
"""
|
||||||
|
Chart data API: Test chart data query with invalid enum value
|
||||||
|
"""
|
||||||
self.login(username="admin")
|
self.login(username="admin")
|
||||||
table = self.get_table_by_name("birth_names")
|
table = self.get_table_by_name("birth_names")
|
||||||
payload = get_query_context(table.name, table.id, table.type)
|
payload = get_query_context(table.name, table.id, table.type)
|
||||||
|
|||||||
Reference in New Issue
Block a user