Skip to content

Commit

Permalink
chore: Migrate /superset/user_slices and /superset/fave_slices to API…
Browse files Browse the repository at this point in the history
… v1 (apache#22964)

Co-authored-by: hughhhh <[email protected]>
  • Loading branch information
diegomedina248 and hughhhh authored Apr 3, 2023
1 parent 13ffb4b commit cdc7af1
Show file tree
Hide file tree
Showing 14 changed files with 208 additions and 43 deletions.
30 changes: 30 additions & 0 deletions docs/static/resources/openapi.json
Original file line number Diff line number Diff line change
Expand Up @@ -1783,12 +1783,21 @@
"changed_on_delta_humanized": {
"readOnly": true
},
"changed_on_dttm": {
"readOnly": true
},
"changed_on_utc": {
"readOnly": true
},
"created_by": {
"$ref": "#/components/schemas/ChartDataRestApi.get_list.User2"
},
"created_by_name": {
"readOnly": true
},
"created_by_url": {
"readOnly": true
},
"created_on_delta_humanized": {
"readOnly": true
},
Expand Down Expand Up @@ -1821,6 +1830,9 @@
"edit_url": {
"readOnly": true
},
"form_data": {
"readOnly": true
},
"id": {
"format": "int32",
"type": "integer"
Expand Down Expand Up @@ -1848,6 +1860,9 @@
"nullable": true,
"type": "string"
},
"slice_url": {
"readOnly": true
},
"table": {
"$ref": "#/components/schemas/ChartDataRestApi.get_list.SqlaTable"
},
Expand Down Expand Up @@ -2576,12 +2591,21 @@
"changed_on_delta_humanized": {
"readOnly": true
},
"changed_on_dttm": {
"readOnly": true
},
"changed_on_utc": {
"readOnly": true
},
"created_by": {
"$ref": "#/components/schemas/ChartRestApi.get_list.User2"
},
"created_by_name": {
"readOnly": true
},
"created_by_url": {
"readOnly": true
},
"created_on_delta_humanized": {
"readOnly": true
},
Expand Down Expand Up @@ -2614,6 +2638,9 @@
"edit_url": {
"readOnly": true
},
"form_data": {
"readOnly": true
},
"id": {
"format": "int32",
"type": "integer"
Expand Down Expand Up @@ -2641,6 +2668,9 @@
"nullable": true,
"type": "string"
},
"slice_url": {
"readOnly": true
},
"table": {
"$ref": "#/components/schemas/ChartRestApi.get_list.SqlaTable"
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
* under the License.
*/
import React from 'react';
import rison from 'rison';
import PropTypes from 'prop-types';
import { CompactPicker } from 'react-color';
import Button from 'src/components/Button';
Expand Down Expand Up @@ -315,34 +316,45 @@ class AnnotationLayer extends React.PureComponent {
});
});
} else if (requiresQuery(sourceType)) {
SupersetClient.get({ endpoint: '/superset/user_slices' }).then(
({ json }) => {
const registry = getChartMetadataRegistry();
this.setState({
isLoadingOptions: false,
valueOptions: json
.filter(x => {
const metadata = registry.get(x.viz_type);
return (
metadata && metadata.canBeAnnotationType(annotationType)
);
})
.map(x => ({
value: x.id,
label: x.title,
slice: {
...x,
data: {
...x.data,
groupby: x.data.groupby?.map(column =>
getColumnLabel(column),
),
},
const queryParams = rison.encode({
filters: [
{
col: 'id',
opr: 'chart_owned_created_favored_by_me',
value: true,
},
],
order_column: 'slice_name',
order_direction: 'asc',
page: 0,
page_size: 25,
});
SupersetClient.get({
endpoint: `/api/v1/chart/?q=${queryParams}`,
}).then(({ json }) => {
const registry = getChartMetadataRegistry();
this.setState({
isLoadingOptions: false,
valueOptions: json.result
.filter(x => {
const metadata = registry.get(x.viz_type);
return metadata && metadata.canBeAnnotationType(annotationType);
})
.map(x => ({
value: x.id,
label: x.slice_name,
slice: {
...x,
data: {
...x.form_data,
groupby: x.form_data.groupby?.map(column =>
getColumnLabel(column),
),
},
})),
});
},
);
},
})),
});
});
} else {
this.setState({
isLoadingOptions: false,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,9 +40,11 @@ beforeAll(() => {
result: [{ label: 'Chart A', value: 'a' }],
});

fetchMock.get('glob:*/superset/user_slices*', [
{ id: 'a', title: 'Chart A', viz_type: 'table', data: {} },
]);
fetchMock.get('glob:*/api/v1/chart/*', {
result: [
{ id: 'a', slice_name: 'Chart A', viz_type: 'table', form_data: {} },
],
});

setupColors();

Expand Down
31 changes: 23 additions & 8 deletions superset-frontend/src/profile/components/Favorites.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,24 +22,39 @@ import moment from 'moment';
import { t } from '@superset-ui/core';
import { DashboardResponse, BootstrapUser } from 'src/types/bootstrapTypes';
import TableLoader from '../../components/TableLoader';
import { Slice } from '../types';
import { Chart } from '../types';

interface FavoritesProps {
user: BootstrapUser;
}

export default class Favorites extends React.PureComponent<FavoritesProps> {
renderSliceTable() {
const mutator = (data: Slice[]) =>
data.map(slice => ({
slice: <a href={slice.url}>{slice.title}</a>,
creator: <a href={slice.creator_url}>{slice.creator}</a>,
favorited: moment.utc(slice.dttm).fromNow(),
_favorited: slice.dttm,
const mutator = (payload: { result: Chart[] }) =>
payload.result.map(slice => ({
slice: <a href={slice.slice_url}>{slice.slice_name}</a>,
creator: <a href={slice.created_by_url}>{slice.created_by_name}</a>,
favorited: moment.utc(slice.changed_on_dttm).fromNow(),
_favorited: slice.changed_on_dttm,
}));

const query = rison.encode({
filters: [
{
col: 'id',
opr: 'chart_is_favorite',
value: true,
},
],
order_column: 'slice_name',
order_direction: 'asc',
page: 0,
page_size: 25,
});

return (
<TableLoader
dataEndpoint={`/superset/fave_slices/${this.props.user?.userId}/`}
dataEndpoint={`/api/v1/chart/?q=${query}`}
className="table-condensed"
columns={['slice', 'creator', 'favorited']}
mutator={mutator}
Expand Down
9 changes: 9 additions & 0 deletions superset-frontend/src/profile/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,15 @@ export type Slice = {
viz_type: string;
};

export type Chart = {
id: number;
slice_name: string;
slice_url: string;
created_by_name?: string;
created_by_url?: string;
changed_on_dttm: number;
};

export type Activity = {
action: string;
item_title: string;
Expand Down
12 changes: 11 additions & 1 deletion superset/charts/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@
ChartFavoriteFilter,
ChartFilter,
ChartHasCreatedByFilter,
ChartOwnedCreatedFavoredByMeFilter,
ChartTagFilter,
)
from superset.charts.schemas import (
Expand Down Expand Up @@ -158,10 +159,13 @@ def ensure_thumbnails_enabled(self) -> Optional[Response]:
"changed_by_name",
"changed_by_url",
"changed_on_delta_humanized",
"changed_on_dttm",
"changed_on_utc",
"created_by.first_name",
"created_by.id",
"created_by.last_name",
"created_by_name",
"created_by_url",
"created_on_delta_humanized",
"datasource_id",
"datasource_name_text",
Expand All @@ -170,6 +174,7 @@ def ensure_thumbnails_enabled(self) -> Optional[Response]:
"description",
"description_markeddown",
"edit_url",
"form_data",
"id",
"last_saved_at",
"last_saved_by.id",
Expand All @@ -183,6 +188,7 @@ def ensure_thumbnails_enabled(self) -> Optional[Response]:
"dashboards.dashboard_title",
"params",
"slice_name",
"slice_url",
"table.default_endpoint",
"table.table_name",
"thumbnail_url",
Expand Down Expand Up @@ -224,7 +230,11 @@ def ensure_thumbnails_enabled(self) -> Optional[Response]:
base_order = ("changed_on", "desc")
base_filters = [["id", ChartFilter, lambda: []]]
search_filters = {
"id": [ChartFavoriteFilter, ChartCertifiedFilter],
"id": [
ChartFavoriteFilter,
ChartCertifiedFilter,
ChartOwnedCreatedFavoredByMeFilter,
],
"slice_name": [ChartAllTextFilter],
"created_by": [ChartHasCreatedByFilter, ChartCreatedByMeFilter],
}
Expand Down
43 changes: 42 additions & 1 deletion superset/charts/filters.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,10 @@
from sqlalchemy.orm import aliased
from sqlalchemy.orm.query import Query

from superset import security_manager
from superset import db, security_manager
from superset.connectors.sqla import models
from superset.connectors.sqla.models import SqlaTable
from superset.models.core import FavStar
from superset.models.slice import Slice
from superset.utils.core import get_user_id
from superset.utils.filters import get_dataset_access_filters
Expand Down Expand Up @@ -127,3 +128,43 @@ def apply(self, query: Query, value: Any) -> Query:
== get_user_id(),
)
)


class ChartOwnedCreatedFavoredByMeFilter(
BaseFilter
): # pylint: disable=too-few-public-methods
"""
Custom filter for the GET chart that filters all charts the user
owns, created, changed or favored.
"""

name = _("Owned Created or Favored")
arg_name = "chart_owned_created_favored_by_me"

def apply(self, query: Query, value: Any) -> Query:
# If anonymous user filter nothing
if security_manager.current_user is None:
return query

owner_ids_query = (
db.session.query(Slice.id)
.join(Slice.owners)
.filter(security_manager.user_model.id == get_user_id())
)

return query.join(
FavStar,
and_(
FavStar.user_id == get_user_id(),
FavStar.class_name == "slice",
Slice.id == FavStar.obj_id,
),
isouter=True,
).filter( # pylint: disable=comparison-with-callable
or_(
Slice.id.in_(owner_ids_query),
Slice.created_by_fk == get_user_id(),
Slice.changed_by_fk == get_user_id(),
FavStar.user_id == get_user_id(),
)
)
1 change: 1 addition & 0 deletions superset/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,7 @@ class RouteMethod: # pylint: disable=too-few-public-methods
"delete_ssh_tunnel": "write",
"get_updated_since": "read",
"stop_query": "read",
"get_user_slices": "read",
"schemas_access_for_file_upload": "read",
"get_objects": "read",
"get_all_objects": "read",
Expand Down
11 changes: 11 additions & 0 deletions superset/models/helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@
)
from superset.utils import core as utils
from superset.utils.core import get_user_id
from superset.utils.dates import datetime_to_epoch

if TYPE_CHECKING:
from superset.connectors.sqla.models import SqlMetric, TableColumn
Expand Down Expand Up @@ -492,6 +493,12 @@ def changed_by_fk(self) -> sa.Column:
nullable=True,
)

@property
def created_by_name(self) -> str:
if self.created_by:
return escape("{}".format(self.created_by))
return ""

@property
def changed_by_name(self) -> str:
if self.changed_by:
Expand All @@ -514,6 +521,10 @@ def changed_on_(self) -> Markup:
def changed_on_delta_humanized(self) -> str:
return self.changed_on_humanized

@renders("changed_on")
def changed_on_dttm(self) -> float:
return datetime_to_epoch(self.changed_on)

@renders("created_on")
def created_on_delta_humanized(self) -> str:
return self.created_on_humanized
Expand Down
Loading

0 comments on commit cdc7af1

Please sign in to comment.