nytai commented on a change in pull request #11502: URL: https://github.com/apache/incubator-superset/pull/11502#discussion_r516410236
########## File path: superset-frontend/src/views/CRUD/hooks.ts ########## @@ -299,64 +299,66 @@ export function useSingleViewResource<D extends object = any>( }; } -// the hooks api has some known limitations around stale state in closures. -// See https://github.com/reactjs/rfcs/blob/master/text/0068-react-hooks.md#drawbacks -// the useRef hook is a way of getting around these limitations by having a consistent ref -// that points to the most recent value. export function useFavoriteStatus( - initialState: FavoriteStatus, - baseURL: string, + type: 'chart' | 'dashboard', + ids: Array<string | number>, handleErrorMsg: (message: string) => void, ) { - const [favoriteStatus, setFavoriteStatus] = useState<FavoriteStatus>( - initialState, - ); - const favoriteStatusRef = useRef<FavoriteStatus>(favoriteStatus); - useEffect(() => { - favoriteStatusRef.current = favoriteStatus; - }); + const [favoriteStatus, setFavoriteStatus] = useState<FavoriteStatus>({}); const updateFavoriteStatus = (update: FavoriteStatus) => setFavoriteStatus(currentState => ({ ...currentState, ...update })); - const fetchFaveStar = (id: number) => { + useEffect(() => { + if (!ids.length) { + return; + } SupersetClient.get({ - endpoint: `${baseURL}/${id}/count/`, + endpoint: `/api/v1/${type}/favorite_status/?q=${rison.encode(ids)}`, }).then( ({ json }) => { - updateFavoriteStatus({ [id]: json.count > 0 }); + const update = (json?.result as { + id: string; + value: boolean; + }[])?.reduce((acc, element) => { + acc[element.id] = element.value; + return acc; + }, {}); + updateFavoriteStatus(update); }, createErrorHandler(errMsg => handleErrorMsg( t('There was an error fetching the favorite status: %s', errMsg), ), ), ); - }; - - const saveFaveStar = (id: number, isStarred: boolean) => { - const urlSuffix = isStarred ? 'unselect' : 'select'; - - SupersetClient.get({ - endpoint: `${baseURL}/${id}/${urlSuffix}/`, - }).then( - () => { - updateFavoriteStatus({ [id]: !isStarred }); - }, - createErrorHandler(errMsg => - handleErrorMsg( - t('There was an error saving the favorite status: %s', errMsg), + }, [ids]); + + const saveFaveStar = useCallback( + (id: number, isStarred: boolean) => { + const urlSuffix = isStarred ? 'unselect' : 'select'; + console.log('fetching', id, isStarred); + SupersetClient.get({ + endpoint: `/superset/favstar/${ + type === 'chart' ? 'slice' : 'Dashboard' + }/${id}/${urlSuffix}/`, + }).then( + ({ json }) => { + updateFavoriteStatus({ + [id]: (json as { count: number })?.count > 0, + }); + }, + createErrorHandler(errMsg => + handleErrorMsg( + t('There was an error saving the favorite status: %s', errMsg), + ), Review comment: I really like the `makeApi` util! ########## File path: superset/dashboards/api.py ########## @@ -589,3 +596,48 @@ def thumbnail( return Response( FileWrapper(screenshot), mimetype="image/png", direct_passthrough=True ) + + @expose("/favorite_status/", methods=["GET"]) + @protect() + @safe + @statsd_metrics + @rison(get_fav_star_ids_schema) + def favorite_status(self, **kwargs: Any) -> Response: + """Favorite Stars for Dashboards + --- + get: + description: >- + Check favorited dashboards for current user + parameters: + - in: query + name: q + content: + application/json: + schema: + $ref: '#/components/schemas/get_fav_star_ids_schema' + responses: + 200: + description: + content: + application/json: + schema: + $ref: "#/components/schemas/GetFavStarIdsSchema" + 400: + $ref: '#/components/responses/400' + 401: + $ref: '#/components/responses/401' + 404: + $ref: '#/components/responses/404' + 500: + $ref: '#/components/responses/500' + """ + requested_ids = kwargs["rison"] + dashboards = DashboardDAO.find_by_ids(requested_ids) Review comment: Unfortunately we need to run this additional query. The find_by_ids method has business logic to ensure the user has access to the requested dashboard by applying the dashboard filter (https://github.com/preset-io/incubator-superset/blob/cb866b30c0a7029ff558297b1f15c7328f64c500/superset/dashboards/filters.py#L59). We could try to fetch the favorite_ids with the dashboard filter in a subquery, but the performance gains wouldn't be significant. We're also doing something similar for bulk delete already (https://github.com/preset-io/incubator-superset/blob/cb866b30c0a7029ff558297b1f15c7328f64c500/superset/dashboards/commands/bulk_delete.py#L54). ########## File path: superset-frontend/src/views/CRUD/hooks.ts ########## @@ -299,64 +301,85 @@ export function useSingleViewResource<D extends object = any>( }; } -// the hooks api has some known limitations around stale state in closures. -// See https://github.com/reactjs/rfcs/blob/master/text/0068-react-hooks.md#drawbacks -// the useRef hook is a way of getting around these limitations by having a consistent ref -// that points to the most recent value. +enum FavStarClassName { + CHART = 'slice', + DASHBOARD = 'Dashboard', +} + +type FavoriteStatusResponse = { + result: Array<{ + id: string; + value: boolean; + }>; +}; + +const favoriteApis = { + chart: makeApi<string, FavoriteStatusResponse>({ Review comment: Yup, just a simple `encodeRison` flag would be enough to pass a properly typed object yet still have it issue a rison request. ---------------------------------------------------------------- This is an automated message from the Apache Git Service. To respond to the message, please log on to GitHub and use the URL above to go to the specific comment. For queries about this service, please contact Infrastructure at: [email protected] --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
