示例#1
0
文件: home.py 项目: MaryamZi/oppia
    def get(self):
        """Handles GET requests."""
        if self.user_id is None:
            raise self.PageNotFoundException

        subscribed_summaries = (
            exp_services.get_exploration_summaries_matching_ids(
                subscription_services.get_exploration_ids_subscribed_to(
                    self.user_id)))

        def _get_intro_card_color(category):
            return (
                feconf.CATEGORIES_TO_COLORS[category] if
                category in feconf.CATEGORIES_TO_COLORS else
                feconf.DEFAULT_COLOR)

        explorations_list = []

        for exp_summary in subscribed_summaries:
            if exp_summary is None:
                continue

            feedback_thread_analytics = feedback_services.get_thread_analytics(
                exp_summary.id)
            explorations_list.append({
                'id': exp_summary.id,
                'title': exp_summary.title,
                'category': exp_summary.category,
                'objective': exp_summary.objective,
                'language_code': exp_summary.language_code,
                'last_updated': utils.get_time_in_millisecs(
                    exp_summary.exploration_model_last_updated),
                'created_on': utils.get_time_in_millisecs(
                    exp_summary.exploration_model_created_on),
                'status': exp_summary.status,
                'community_owned': exp_summary.community_owned,
                'is_editable': True,
                'thumbnail_icon_url': (
                    utils.get_thumbnail_icon_url_for_category(
                        exp_summary.category)),
                'thumbnail_bg_color': utils.get_hex_color_for_category(
                    exp_summary.category),
                'ratings': exp_summary.ratings,
                'num_open_threads': (
                    feedback_thread_analytics.num_open_threads),
                'num_total_threads': (
                    feedback_thread_analytics.num_total_threads),
            })

        explorations_list = sorted(
            explorations_list,
            key=lambda x: (x['num_open_threads'], x['last_updated']),
            reverse=True)

        self.values.update({
            'explorations_list': explorations_list,
        })
        self.render_json(self.values)
示例#2
0
def _get_displayable_exp_summary_dicts(
        exploration_summaries, include_contributors=True):
    """Given a list of exploration summary domain objects, returns a list,
    with the same number of elements, of the corresponding human-readable
    exploration summary dicts. If include_contributors is False, the resulting
    dicts will not have a 'human_readable_contributors_summary' attribute.

    This assumes that all the exploration summary domain objects passed in are
    valid (i.e., none of them are None).
    """
    exploration_ids = [
        exploration_summary.id
        for exploration_summary in exploration_summaries]

    view_counts = (
        stats_jobs_continuous.StatisticsAggregator.get_views_multi(
            exploration_ids))
    displayable_exp_summaries = []

    for ind, exploration_summary in enumerate(exploration_summaries):
        if not exploration_summary:
            continue

        summary_dict = {
            'id': exploration_summary.id,
            'title': exploration_summary.title,
            'activity_type': rights_manager.ACTIVITY_TYPE_EXPLORATION,
            'category': exploration_summary.category,
            'objective': exploration_summary.objective,
            'language_code': exploration_summary.language_code,
            'last_updated_msec': utils.get_time_in_millisecs(
                exploration_summary.exploration_model_last_updated
            ),
            'status': exploration_summary.status,
            'ratings': exploration_summary.ratings,
            'community_owned': exploration_summary.community_owned,
            'tags': exploration_summary.tags,
            'thumbnail_icon_url': utils.get_thumbnail_icon_url_for_category(
                exploration_summary.category),
            'thumbnail_bg_color': utils.get_hex_color_for_category(
                exploration_summary.category),
            'num_views': view_counts[ind],
        }

        if include_contributors:
            summary_dict['human_readable_contributors_summary'] = (
                get_human_readable_contributors_summary(
                    exploration_summary.contributors_summary))

        displayable_exp_summaries.append(summary_dict)

    return displayable_exp_summaries
示例#3
0
def _get_displayable_collection_summary_dicts(collection_summaries):
    """Gets a summary of collections in human readable form.

    Args:
        collection_summaries: list(CollectionSummary). List of collection
        summary domain object.

    Return:
        list(dict). A list of exploration summary dicts in human readable form.
        Example:

        [ {
            'category': u'A category',
            'community_owned': False,
            'id': 'eid2',
            'language_code': 'en',
            'num_views': 0,
            'objective': u'An objective',
            'status': 'public',
            'tags': [],
            'thumbnail_bg_color': '#a33f40',
            'thumbnail_icon_url': self.get_static_asset_url(
                '/images/subjects/Lightbulb.svg'),
            'title': u'Exploration 2 Albert title',
        }, ]
    """
    displayable_collection_summaries = []
    for collection_summary in collection_summaries:
        if collection_summary and collection_summary.status != (
                rights_manager.ACTIVITY_STATUS_PRIVATE):
            displayable_collection_summaries.append({
                'id': collection_summary.id,
                'title': collection_summary.title,
                'category': collection_summary.category,
                'activity_type': feconf.ACTIVITY_TYPE_COLLECTION,
                'objective': collection_summary.objective,
                'language_code': collection_summary.language_code,
                'tags': collection_summary.tags,
                'node_count': collection_summary.node_count,
                'last_updated_msec': utils.get_time_in_millisecs(
                    collection_summary.collection_model_last_updated),
                'thumbnail_icon_url': (
                    utils.get_thumbnail_icon_url_for_category(
                        collection_summary.category)),
                'thumbnail_bg_color': utils.get_hex_color_for_category(
                    collection_summary.category)})
    return displayable_collection_summaries
示例#4
0
    def get(self):
        """Handles GET requests."""
        # TODO(sll): Figure out what to do about explorations in categories
        # other than those explicitly listed.

        query_string = self.request.get('q')
        search_cursor = self.request.get('cursor', None)
        exp_summaries_list, search_cursor = (
            exp_services.get_exploration_summaries_matching_query(
                query_string, cursor=search_cursor))

        explorations_list = [{
            'id': exp_summary.id,
            'title': exp_summary.title,
            'category': exp_summary.category,
            'objective': exp_summary.objective,
            'language_code': exp_summary.language_code,
            'last_updated_msec': utils.get_time_in_millisecs(
                exp_summary.exploration_model_last_updated),
            'status': exp_summary.status,
            'ratings': exp_summary.ratings,
            'community_owned': exp_summary.community_owned,
            # TODO(sll): Replace these with per-category thumbnails.
            'thumbnail_icon_url': utils.get_thumbnail_icon_url_for_category(
                exp_summary.category),
            'thumbnail_bg_color': utils.get_hex_color_for_category(
                exp_summary.category),
        } for exp_summary in exp_summaries_list]

        if len(explorations_list) == feconf.DEFAULT_QUERY_LIMIT:
            logging.error(
                '%s explorations were fetched to load the gallery page. '
                'You may be running up against the default query limits.'
                % feconf.DEFAULT_QUERY_LIMIT)

        preferred_language_codes = [feconf.DEFAULT_LANGUAGE_CODE]
        if self.user_id:
            user_settings = user_services.get_user_settings(self.user_id)
            preferred_language_codes = user_settings.preferred_language_codes

        self.values.update({
            'explorations_list': explorations_list,
            'preferred_language_codes': preferred_language_codes,
            'search_cursor': search_cursor,
        })
        self.render_json(self.values)
示例#5
0
def get_displayable_exp_summary_dicts_matching_ids(exploration_ids):
    """Given a list of exploration ids, filters the list for
    explorations that are currently non-private and not deleted,
    and returns a list of dicts of the corresponding exploration summaries.
    Please use this function when needing summary information to display on
    exploration summary tiles in the frontend.
    """
    displayable_exp_summaries = []
    exploration_summaries = (
        exp_services.get_exploration_summaries_matching_ids(exploration_ids))
    view_counts = (
        stats_jobs_continuous.StatisticsAggregator.get_views_multi(
            exploration_ids))

    for ind, exploration_summary in enumerate(exploration_summaries):
        if exploration_summary and exploration_summary.status != (
                rights_manager.ACTIVITY_STATUS_PRIVATE):
            displayable_exp_summaries.append({
                'id': exploration_summary.id,
                'title': exploration_summary.title,
                'category': exploration_summary.category,
                'objective': exploration_summary.objective,
                'language_code': exploration_summary.language_code,
                'last_updated_msec': utils.get_time_in_millisecs(
                    exploration_summary.exploration_model_last_updated
                ),
                'status': exploration_summary.status,
                'ratings': exploration_summary.ratings,
                'community_owned': exploration_summary.community_owned,
                'human_readable_contributors_summary':
                    get_human_readable_contributors_summary(
                        exploration_summary.contributors_summary),
                'tags': exploration_summary.tags,
                'thumbnail_icon_url': utils.get_thumbnail_icon_url_for_category(
                    exploration_summary.category),
                'thumbnail_bg_color': utils.get_hex_color_for_category(
                    exploration_summary.category),
                'num_views': view_counts[ind],
            })

    return displayable_exp_summaries
示例#6
0
def _get_displayable_collection_summary_dicts(collection_summaries):
    displayable_collection_summaries = []
    for collection_summary in collection_summaries:
        if collection_summary and collection_summary.status != (
                rights_manager.ACTIVITY_STATUS_PRIVATE):
            displayable_collection_summaries.append({
                'id': collection_summary.id,
                'title': collection_summary.title,
                'category': collection_summary.category,
                'activity_type': rights_manager.ACTIVITY_TYPE_COLLECTION,
                'objective': collection_summary.objective,
                'language_code': collection_summary.language_code,
                'tags': collection_summary.tags,
                'node_count': collection_summary.node_count,
                'last_updated_msec': utils.get_time_in_millisecs(
                    collection_summary.collection_model_last_updated),
                'thumbnail_icon_url': utils.get_thumbnail_icon_url_for_category(
                    collection_summary.category),
                'thumbnail_bg_color': utils.get_hex_color_for_category(
                    collection_summary.category)})
    return displayable_collection_summaries
示例#7
0
    def get(self):
        """Handles GET requests."""
        try:
            exp_ids = json.loads(self.request.get('stringified_exp_ids'))
        except Exception:
            raise self.PageNotFoundException

        if (not isinstance(exp_ids, list) or not all([
                isinstance(exp_id, basestring) for exp_id in exp_ids])):
            raise self.PageNotFoundException

        exp_summaries = exp_services.get_exploration_summaries_matching_ids(
            exp_ids)

        self.values.update({
            'summaries': [(None if exp_summary is None else {
                'id': exp_summary.id,
                'title': exp_summary.title,
                'category': exp_summary.category,
                'objective': exp_summary.objective,
                'language_code': exp_summary.language_code,
                'last_updated': utils.get_time_in_millisecs(
                    exp_summary.exploration_model_last_updated),
                'status': exp_summary.status,
                'ratings': exp_summary.ratings,
                'community_owned': exp_summary.community_owned,
                'contributor_names': user_services.get_human_readable_user_ids(
                    exp_summary.contributor_ids),
                'tags': exp_summary.tags,
                'thumbnail_icon_url': (
                    utils.get_thumbnail_icon_url_for_category(
                        exp_summary.category)),
                'thumbnail_bg_color': utils.get_hex_color_for_category(
                    exp_summary.category),
            }) for exp_summary in exp_summaries]
        })
        self.render_json(self.values)
示例#8
0
    def get(self):
        """Handles GET requests."""
        if self.user_id is None:
            raise self.PageNotFoundException

        def _get_intro_card_color(category):
            return (
                feconf.CATEGORIES_TO_COLORS[category] if
                category in feconf.CATEGORIES_TO_COLORS else
                feconf.DEFAULT_COLOR)

        def _round_average_ratings(rating):
            return round(rating, feconf.AVERAGE_RATINGS_DASHBOARD_PRECISION)

        # We need to do the filtering because some activities that were
        # originally subscribed to may have been deleted since.
        subscribed_exploration_summaries = [
            summary for summary in
            exp_services.get_exploration_summaries_matching_ids(
                subscription_services.get_exploration_ids_subscribed_to(
                    self.user_id))
            if summary is not None]
        subscribed_collection_summaries = [
            summary for summary in
            collection_services.get_collection_summaries_matching_ids(
                subscription_services.get_collection_ids_subscribed_to(
                    self.user_id))
            if summary is not None]

        exploration_ids_subscribed_to = [
            summary.id for summary in subscribed_exploration_summaries]

        exp_summary_dicts = summary_services.get_displayable_exp_summary_dicts(
            subscribed_exploration_summaries)
        collection_summary_dicts = []

        feedback_thread_analytics = (
            feedback_services.get_thread_analytics_multi(
                exploration_ids_subscribed_to))

        # TODO(bhenning): Update this to use unresolved answers from
        # stats_services once the training interface is enabled and it's cheaper
        # to retrieve top answers from stats_services.
        for ind, exploration in enumerate(exp_summary_dicts):
            exploration.update(feedback_thread_analytics[ind].to_dict())

        exp_summary_dicts = sorted(
            exp_summary_dicts,
            key=lambda x: (x['num_open_threads'], x['last_updated_msec']),
            reverse=True)

        if (self.username in
                config_domain.WHITELISTED_COLLECTION_EDITOR_USERNAMES.value):
            for collection_summary in subscribed_collection_summaries:
                # TODO(sll): Reuse _get_displayable_collection_summary_dicts()
                # in summary_services, instead of replicating it like this.
                collection_summary_dicts.append({
                    'id': collection_summary.id,
                    'title': collection_summary.title,
                    'category': collection_summary.category,
                    'objective': collection_summary.objective,
                    'language_code': collection_summary.language_code,
                    'last_updated': utils.get_time_in_millisecs(
                        collection_summary.collection_model_last_updated),
                    'created_on': utils.get_time_in_millisecs(
                        collection_summary.collection_model_created_on),
                    'status': collection_summary.status,
                    'node_count': collection_summary.node_count,
                    'community_owned': collection_summary.community_owned,
                    'thumbnail_icon_url': (
                        utils.get_thumbnail_icon_url_for_category(
                            collection_summary.category)),
                    'thumbnail_bg_color': utils.get_hex_color_for_category(
                        collection_summary.category),
                })

        dashboard_stats = (
            user_jobs_continuous.UserStatsAggregator.get_dashboard_stats(
                self.user_id))
        dashboard_stats.update({
            'total_open_feedback': feedback_services.get_total_open_threads(
                feedback_thread_analytics)
        })
        if dashboard_stats and dashboard_stats.get('average_ratings'):
            dashboard_stats['average_ratings'] = (
                _round_average_ratings(dashboard_stats['average_ratings']))

        last_week_stats = (
            user_services.get_last_week_dashboard_stats(self.user_id))
        if last_week_stats and last_week_stats.get('average_ratings'):
            last_week_stats['average_ratings'] = (
                _round_average_ratings(last_week_stats['average_ratings']))

        subscriber_ids = subscription_services.get_all_subscribers_of_creator(
            self.user_id)
        subscribers_settings = user_services.get_users_settings(subscriber_ids)
        subscribers_list = []
        for index, subscriber_settings in enumerate(subscribers_settings):
            subscriber_summary = {
                'subscriber_picture_data_url': (
                    subscriber_settings.profile_picture_data_url),
                'subscriber_username': subscriber_settings.username,
                'subscriber_impact': (
                    user_services.get_user_impact_score(subscriber_ids[index]))
            }

            subscribers_list.append(subscriber_summary)

        self.values.update({
            'explorations_list': exp_summary_dicts,
            'collections_list': collection_summary_dicts,
            'dashboard_stats': dashboard_stats,
            'last_week_stats': last_week_stats,
            'subscribers_list': subscribers_list
        })
        self.render_json(self.values)
示例#9
0
    def get(self, collection_id):
        """Populates the data on the individual collection page."""
        try:
            collection = collection_services.get_collection_by_id(
                collection_id)
        except Exception as e:
            raise self.PageNotFoundException(e)

        exp_ids = collection.exploration_ids
        exp_summaries = (
            exp_services.get_exploration_summaries_matching_ids(exp_ids))
        exp_summaries_dict = {
            exp_id: exp_summaries[ind] for (ind, exp_id) in enumerate(exp_ids)
        }

        # TODO(bhenning): Users should not be recommended explorations they
        # have completed outside the context of a collection.
        next_exploration_ids = None
        completed_exploration_ids = None
        if self.user_id:
            completed_exploration_ids = (
                collection_services.get_completed_exploration_ids(
                    self.user_id, collection_id))
            next_exploration_ids = collection.get_next_exploration_ids(
                completed_exploration_ids)
        else:
            # If the user is not logged in or they have not completed any of
            # the explorations yet within the context of this collection,
            # recommend the initial explorations.
            next_exploration_ids = collection.init_exploration_ids
            completed_exploration_ids = []

        collection_dict = collection.to_dict()
        collection_dict['next_exploration_ids'] = next_exploration_ids
        collection_dict['completed_exploration_ids'] = (
            completed_exploration_ids)

        # Insert an 'exploration' dict into each collection node, where the
        # dict includes meta information about the exploration (ID and title).
        for collection_node in collection_dict['nodes']:
            summary = exp_summaries_dict.get(collection_node['exploration_id'])
            collection_node['exploration'] = {
                'id': collection_node['exploration_id'],
                'title': summary.title if summary else None,
                'category': summary.category if summary else None,
                'objective': summary.objective if summary else None,
                'ratings': summary.ratings if summary else None,
                'last_updated_msec': utils.get_time_in_millisecs(
                    summary.exploration_model_last_updated
                ) if summary else None,
                'thumbnail_icon_url': utils.get_thumbnail_icon_url_for_category(
                    summary.category),
                'thumbnail_bg_color': utils.get_hex_color_for_category(
                    summary.category),
            }

        self.values.update({
            'can_edit': (
                self.user_id and rights_manager.Actor(self.user_id).can_edit(
                    rights_manager.ACTIVITY_TYPE_COLLECTION, collection_id)),
            'collection': collection_dict,
            'info_card_image_url': utils.get_info_card_url_for_category(
                collection.category),
            'is_logged_in': bool(self.user_id),
            'session_id': utils.generate_new_session_id(),
        })

        self.render_json(self.values)
示例#10
0
    def get(self):
        """Handles GET requests."""
        if self.user_id is None:
            raise self.PageNotFoundException

        def _get_intro_card_color(category):
            return (
                feconf.CATEGORIES_TO_COLORS[category] if
                category in feconf.CATEGORIES_TO_COLORS else
                feconf.DEFAULT_COLOR)

        def _round_average_ratings(rating):
            return round(rating, feconf.AVERAGE_RATINGS_DASHBOARD_PRECISION)

        exploration_ids_subscribed_to = (
            subscription_services.get_exploration_ids_subscribed_to(
                self.user_id))

        subscribed_exploration_summaries = filter(None, (
            exp_services.get_exploration_summaries_matching_ids(
                exploration_ids_subscribed_to)))
        subscribed_collection_summaries = filter(None, (
            collection_services.get_collection_summaries_matching_ids(
                subscription_services.get_collection_ids_subscribed_to(
                    self.user_id))))

        exp_summary_list = summary_services.get_displayable_exp_summary_dicts(
            subscribed_exploration_summaries)
        collection_summary_list = []

        feedback_thread_analytics = (
            feedback_services.get_thread_analytics_multi(
                exploration_ids_subscribed_to))

        unresolved_answers_dict = (
            stats_services.get_exps_unresolved_answers_count_for_default_rule(
                exploration_ids_subscribed_to))

        for ind, exploration in enumerate(exp_summary_list):
            exploration.update(feedback_thread_analytics[ind].to_dict())
            exploration.update({
                'num_unresolved_answers': (
                    unresolved_answers_dict[exploration['id']]
                    if exploration['id'] in unresolved_answers_dict else 0
                )
            })

        exp_summary_list = sorted(
            exp_summary_list,
            key=lambda x: (x['num_open_threads'], x['last_updated_msec']),
            reverse=True)

        if (self.username in
                config_domain.WHITELISTED_COLLECTION_EDITOR_USERNAMES.value):
            for collection_summary in subscribed_collection_summaries:
                # TODO(sll): Reuse _get_displayable_collection_summary_dicts()
                # in summary_services, instead of replicating it like this.
                collection_summary_list.append({
                    'id': collection_summary.id,
                    'title': collection_summary.title,
                    'category': collection_summary.category,
                    'objective': collection_summary.objective,
                    'language_code': collection_summary.language_code,
                    'last_updated': utils.get_time_in_millisecs(
                        collection_summary.collection_model_last_updated),
                    'created_on': utils.get_time_in_millisecs(
                        collection_summary.collection_model_created_on),
                    'status': collection_summary.status,
                    'community_owned': collection_summary.community_owned,
                    'thumbnail_icon_url': (
                        utils.get_thumbnail_icon_url_for_category(
                            collection_summary.category)),
                    'thumbnail_bg_color': utils.get_hex_color_for_category(
                        collection_summary.category),
                })

        dashboard_stats = (
            user_jobs_continuous.UserStatsAggregator.get_dashboard_stats(
                self.user_id))
        dashboard_stats.update({
            'total_open_feedback': feedback_services.get_total_open_threads(
                feedback_thread_analytics)
        })
        if dashboard_stats and dashboard_stats.get('average_ratings'):
            dashboard_stats['average_ratings'] = (
                _round_average_ratings(dashboard_stats['average_ratings']))

        last_week_stats = (
            user_services.get_last_week_dashboard_stats(self.user_id))
        if last_week_stats and last_week_stats.get('average_ratings'):
            last_week_stats['average_ratings'] = (
                _round_average_ratings(last_week_stats['average_ratings']))

        self.values.update({
            'explorations_list': exp_summary_list,
            'collections_list': collection_summary_list,
            'dashboard_stats': dashboard_stats,
            'last_week_stats': last_week_stats
        })
        self.render_json(self.values)
示例#11
0
    def get(self):
        """Handles GET requests."""
        if self.user_id is None:
            raise self.PageNotFoundException

        def _get_intro_card_color(category):
            return (
                feconf.CATEGORIES_TO_COLORS[category] if
                category in feconf.CATEGORIES_TO_COLORS else
                feconf.DEFAULT_COLOR)

        exploration_ids_subscribed_to = (
            subscription_services.get_exploration_ids_subscribed_to(
                self.user_id))

        subscribed_exploration_summaries = filter(None, (
            exp_services.get_exploration_summaries_matching_ids(
                exploration_ids_subscribed_to)))
        subscribed_collection_summaries = filter(None, (
            collection_services.get_collection_summaries_matching_ids(
                subscription_services.get_collection_ids_subscribed_to(
                    self.user_id))))

        explorations_list = summary_services.get_displayable_exp_summary_dicts(
            subscribed_exploration_summaries)
        collections_list = []

        feedback_thread_analytics = (
            feedback_services.get_thread_analytics_multi(
                exploration_ids_subscribed_to))

        for ind, exploration in enumerate(explorations_list):
            exploration.update(feedback_thread_analytics[ind].to_dict())

        explorations_list = sorted(
            explorations_list,
            key=lambda x: (x['num_open_threads'], x['last_updated_msec']),
            reverse=True)

        if (self.username in
                config_domain.WHITELISTED_COLLECTION_EDITOR_USERNAMES.value):
            for collection_summary in subscribed_collection_summaries:
                # TODO(sll): Reuse _get_displayable_collection_summary_dicts()
                # in summary_services, instead of replicating it like this.
                collections_list.append({
                    'id': collection_summary.id,
                    'title': collection_summary.title,
                    'category': collection_summary.category,
                    'objective': collection_summary.objective,
                    'language_code': collection_summary.language_code,
                    'last_updated': utils.get_time_in_millisecs(
                        collection_summary.collection_model_last_updated),
                    'created_on': utils.get_time_in_millisecs(
                        collection_summary.collection_model_created_on),
                    'status': collection_summary.status,
                    'community_owned': collection_summary.community_owned,
                    'thumbnail_icon_url': (
                        utils.get_thumbnail_icon_url_for_category(
                            collection_summary.category)),
                    'thumbnail_bg_color': utils.get_hex_color_for_category(
                        collection_summary.category),
                })

        self.values.update({
            'explorations_list': explorations_list,
            'collections_list': collections_list,
            'dashboard_stats': user_services.get_user_dashboard_stats(
                self.user_id)
        })
        self.render_json(self.values)
示例#12
0
    def get(self):
        """Handles GET requests."""
        def _round_average_ratings(rating):
            """Returns the rounded average rating to display on the creator
            dashboard.

            Args:
                rating: float. The rating of the lesson.

            Returns:
                float. The rounded average value of rating.
            """
            return python_utils.ROUND(
                rating, feconf.AVERAGE_RATINGS_DASHBOARD_PRECISION)

        subscribed_exploration_summaries = (
            exp_fetchers.get_exploration_summaries_subscribed_to(self.user_id))
        subscribed_collection_summaries = (
            collection_services.get_collection_summaries_subscribed_to(
                self.user_id))

        exploration_ids_subscribed_to = [
            summary.id for summary in subscribed_exploration_summaries
        ]

        exp_summary_dicts = summary_services.get_displayable_exp_summary_dicts(
            subscribed_exploration_summaries)
        collection_summary_dicts = []

        feedback_thread_analytics = (
            feedback_services.get_thread_analytics_multi(
                exploration_ids_subscribed_to))

        # TODO(bhenning): Update this to use unresolved answers from
        # stats_services once the training interface is enabled and it's cheaper
        # to retrieve top answers from stats_services.
        for ind, exploration in enumerate(exp_summary_dicts):
            exploration.update(feedback_thread_analytics[ind].to_dict())

        exp_summary_dicts = sorted(
            exp_summary_dicts,
            key=lambda x: (x['num_open_threads'], x['last_updated_msec']),
            reverse=True)

        topic_summaries = topic_fetchers.get_all_topic_summaries()
        topic_summary_dicts = [
            summary.to_dict() for summary in topic_summaries
        ]

        if role_services.ACTION_CREATE_COLLECTION in self.user.actions:
            for collection_summary in subscribed_collection_summaries:
                # TODO(sll): Reuse _get_displayable_collection_summary_dicts()
                # in summary_services, instead of replicating it like this.
                collection_summary_dicts.append({
                    'id':
                    collection_summary.id,
                    'title':
                    collection_summary.title,
                    'category':
                    collection_summary.category,
                    'objective':
                    collection_summary.objective,
                    'language_code':
                    collection_summary.language_code,
                    'last_updated_msec':
                    utils.get_time_in_millisecs(
                        collection_summary.collection_model_last_updated),
                    'created_on':
                    utils.get_time_in_millisecs(
                        collection_summary.collection_model_created_on),
                    'status':
                    collection_summary.status,
                    'node_count':
                    collection_summary.node_count,
                    'community_owned':
                    collection_summary.community_owned,
                    'thumbnail_icon_url':
                    (utils.get_thumbnail_icon_url_for_category(
                        collection_summary.category)),
                    'thumbnail_bg_color':
                    utils.get_hex_color_for_category(
                        collection_summary.category),
                })

        dashboard_stats = user_services.get_dashboard_stats(self.user_id)
        dashboard_stats.update({
            'total_open_feedback':
            feedback_services.get_total_open_threads(feedback_thread_analytics)
        })
        if dashboard_stats and dashboard_stats.get('average_ratings'):
            dashboard_stats['average_ratings'] = (_round_average_ratings(
                dashboard_stats['average_ratings']))

        last_week_stats = (user_services.get_last_week_dashboard_stats(
            self.user_id))

        if last_week_stats and len(list(last_week_stats.keys())) != 1:
            logging.exception(
                '\'last_week_stats\' should contain only one key-value pair'
                ' denoting last week dashboard stats of the user keyed by a'
                ' datetime string.')
            last_week_stats = None

        if last_week_stats:
            # 'last_week_stats' is a dict with only one key-value pair denoting
            # last week dashboard stats of the user keyed by a datetime string.
            datetime_of_stats = list(last_week_stats.keys())[0]
            last_week_stats_average_ratings = (list(
                last_week_stats.values())[0].get('average_ratings'))
            if last_week_stats_average_ratings:
                last_week_stats[datetime_of_stats]['average_ratings'] = (
                    _round_average_ratings(last_week_stats_average_ratings))

        subscriber_ids = subscription_services.get_all_subscribers_of_creator(
            self.user_id)
        subscribers_settings = user_services.get_users_settings(subscriber_ids)
        subscribers_list = []
        for index, subscriber_settings in enumerate(subscribers_settings):
            subscriber_summary = {
                'subscriber_picture_data_url':
                (subscriber_settings.profile_picture_data_url),
                'subscriber_username':
                subscriber_settings.username,
                'subscriber_impact':
                (user_services.get_user_impact_score(subscriber_ids[index]))
            }

            subscribers_list.append(subscriber_summary)

        user_settings = user_services.get_user_settings(self.user_id,
                                                        strict=False)
        creator_dashboard_display_pref = (
            user_settings.creator_dashboard_display_pref)

        suggestions_created_by_user = suggestion_services.query_suggestions([
            ('author_id', self.user_id),
            ('suggestion_type', feconf.SUGGESTION_TYPE_EDIT_STATE_CONTENT)
        ])
        suggestions_which_can_be_reviewed = (
            suggestion_services.
            get_all_suggestions_that_can_be_reviewed_by_user(self.user_id))

        for s in suggestions_created_by_user:
            s.populate_old_value_of_change()

        for s in suggestions_which_can_be_reviewed:
            s.populate_old_value_of_change()

        suggestion_dicts_created_by_user = ([
            s.to_dict() for s in suggestions_created_by_user
        ])
        suggestion_dicts_which_can_be_reviewed = ([
            s.to_dict() for s in suggestions_which_can_be_reviewed
        ])

        ids_of_suggestions_created_by_user = ([
            s['suggestion_id'] for s in suggestion_dicts_created_by_user
        ])
        ids_of_suggestions_which_can_be_reviewed = ([
            s['suggestion_id'] for s in suggestion_dicts_which_can_be_reviewed
        ])

        threads_linked_to_suggestions_by_user = ([
            t.to_dict() for t in feedback_services.get_multiple_threads(
                ids_of_suggestions_created_by_user)
        ])
        threads_linked_to_suggestions_which_can_be_reviewed = ([
            t.to_dict() for t in feedback_services.get_multiple_threads(
                ids_of_suggestions_which_can_be_reviewed)
        ])

        self.values.update({
            'explorations_list':
            exp_summary_dicts,
            'collections_list':
            collection_summary_dicts,
            'dashboard_stats':
            dashboard_stats,
            'last_week_stats':
            last_week_stats,
            'subscribers_list':
            subscribers_list,
            'display_preference':
            creator_dashboard_display_pref,
            'threads_for_created_suggestions_list':
            (threads_linked_to_suggestions_by_user),
            'threads_for_suggestions_to_review_list':
            (threads_linked_to_suggestions_which_can_be_reviewed),
            'created_suggestions_list':
            suggestion_dicts_created_by_user,
            'suggestions_to_review_list':
            (suggestion_dicts_which_can_be_reviewed),
            'topic_summary_dicts':
            topic_summary_dicts
        })

        self.render_json(self.values)
示例#13
0
    def get(self):
        """Handles GET requests."""
        def _get_intro_card_color(category):
            return (constants.CATEGORIES_TO_COLORS[category]
                    if category in constants.CATEGORIES_TO_COLORS else
                    constants.DEFAULT_COLOR)

        def _round_average_ratings(rating):
            return round(rating, feconf.AVERAGE_RATINGS_DASHBOARD_PRECISION)

        # We need to do the filtering because some activities that were
        # originally subscribed to may have been deleted since.
        subscribed_exploration_summaries = [
            summary
            for summary in exp_services.get_exploration_summaries_matching_ids(
                subscription_services.get_exploration_ids_subscribed_to(
                    self.user_id)) if summary is not None
        ]
        subscribed_collection_summaries = [
            summary for summary in
            collection_services.get_collection_summaries_matching_ids(
                subscription_services.get_collection_ids_subscribed_to(
                    self.user_id)) if summary is not None
        ]

        exploration_ids_subscribed_to = [
            summary.id for summary in subscribed_exploration_summaries
        ]

        exp_summary_dicts = summary_services.get_displayable_exp_summary_dicts(
            subscribed_exploration_summaries)
        collection_summary_dicts = []

        feedback_thread_analytics = (
            feedback_services.get_thread_analytics_multi(
                exploration_ids_subscribed_to))

        # TODO(bhenning): Update this to use unresolved answers from
        # stats_services once the training interface is enabled and it's cheaper
        # to retrieve top answers from stats_services.
        for ind, exploration in enumerate(exp_summary_dicts):
            exploration.update(feedback_thread_analytics[ind].to_dict())

        exp_summary_dicts = sorted(
            exp_summary_dicts,
            key=lambda x: (x['num_open_threads'], x['last_updated_msec']),
            reverse=True)

        if feconf.ENABLE_NEW_STRUCTURES:
            topic_summaries = topic_services.get_all_topic_summaries()
            topic_summary_dicts = [
                summary.to_dict() for summary in topic_summaries
            ]

        if role_services.ACTION_CREATE_COLLECTION in self.user.actions:
            for collection_summary in subscribed_collection_summaries:
                # TODO(sll): Reuse _get_displayable_collection_summary_dicts()
                # in summary_services, instead of replicating it like this.
                collection_summary_dicts.append({
                    'id':
                    collection_summary.id,
                    'title':
                    collection_summary.title,
                    'category':
                    collection_summary.category,
                    'objective':
                    collection_summary.objective,
                    'language_code':
                    collection_summary.language_code,
                    'last_updated':
                    utils.get_time_in_millisecs(
                        collection_summary.collection_model_last_updated),
                    'created_on':
                    utils.get_time_in_millisecs(
                        collection_summary.collection_model_created_on),
                    'status':
                    collection_summary.status,
                    'node_count':
                    collection_summary.node_count,
                    'community_owned':
                    collection_summary.community_owned,
                    'thumbnail_icon_url':
                    (utils.get_thumbnail_icon_url_for_category(
                        collection_summary.category)),
                    'thumbnail_bg_color':
                    utils.get_hex_color_for_category(
                        collection_summary.category),
                })

        dashboard_stats = (
            user_jobs_continuous.UserStatsAggregator.get_dashboard_stats(
                self.user_id))
        dashboard_stats.update({
            'total_open_feedback':
            feedback_services.get_total_open_threads(feedback_thread_analytics)
        })
        if dashboard_stats and dashboard_stats.get('average_ratings'):
            dashboard_stats['average_ratings'] = (_round_average_ratings(
                dashboard_stats['average_ratings']))

        last_week_stats = (user_services.get_last_week_dashboard_stats(
            self.user_id))
        if last_week_stats and last_week_stats.get('average_ratings'):
            last_week_stats['average_ratings'] = (_round_average_ratings(
                last_week_stats['average_ratings']))

        subscriber_ids = subscription_services.get_all_subscribers_of_creator(
            self.user_id)
        subscribers_settings = user_services.get_users_settings(subscriber_ids)
        subscribers_list = []
        for index, subscriber_settings in enumerate(subscribers_settings):
            subscriber_summary = {
                'subscriber_picture_data_url':
                (subscriber_settings.profile_picture_data_url),
                'subscriber_username':
                subscriber_settings.username,
                'subscriber_impact':
                (user_services.get_user_impact_score(subscriber_ids[index]))
            }

            subscribers_list.append(subscriber_summary)

        user_settings = user_services.get_user_settings(self.user_id,
                                                        strict=False)
        creator_dashboard_display_pref = (
            user_settings.creator_dashboard_display_pref)

        suggestions_created_by_user = suggestion_services.query_suggestions([
            ('author_id', self.user_id),
            ('suggestion_type',
             suggestion_models.SUGGESTION_TYPE_EDIT_STATE_CONTENT)
        ])
        suggestions_which_can_be_reviewed = (
            suggestion_services.
            get_all_suggestions_that_can_be_reviewed_by_user(self.user_id))

        for s in suggestions_created_by_user:
            s.populate_old_value_of_change()

        for s in suggestions_which_can_be_reviewed:
            s.populate_old_value_of_change()

        suggestion_dicts_created_by_user = ([
            s.to_dict() for s in suggestions_created_by_user
        ])
        suggestion_dicts_which_can_be_reviewed = ([
            s.to_dict() for s in suggestions_which_can_be_reviewed
        ])

        ids_of_suggestions_created_by_user = ([
            s['suggestion_id'] for s in suggestion_dicts_created_by_user
        ])
        ids_of_suggestions_which_can_be_reviewed = ([
            s['suggestion_id'] for s in suggestion_dicts_which_can_be_reviewed
        ])

        threads_linked_to_suggestions_by_user = ([
            t.to_dict() for t in feedback_services.get_multiple_threads(
                ids_of_suggestions_created_by_user)
        ])
        threads_linked_to_suggestions_which_can_be_reviewed = ([
            t.to_dict() for t in feedback_services.get_multiple_threads(
                ids_of_suggestions_which_can_be_reviewed)
        ])

        self.values.update({
            'explorations_list':
            exp_summary_dicts,
            'collections_list':
            collection_summary_dicts,
            'dashboard_stats':
            dashboard_stats,
            'last_week_stats':
            last_week_stats,
            'subscribers_list':
            subscribers_list,
            'display_preference':
            creator_dashboard_display_pref,
            'threads_for_created_suggestions_list':
            (threads_linked_to_suggestions_by_user),
            'threads_for_suggestions_to_review_list':
            (threads_linked_to_suggestions_which_can_be_reviewed),
            'created_suggestions_list':
            suggestion_dicts_created_by_user,
            'suggestions_to_review_list':
            suggestion_dicts_which_can_be_reviewed
        })
        if feconf.ENABLE_NEW_STRUCTURES:
            self.values.update({'topic_summary_dicts': topic_summary_dicts})
        self.render_json(self.values)
示例#14
0
def get_displayable_exp_summary_dicts(exploration_summaries):
    """Gets a summary of explorations in human readable form.

    Given a list of exploration summary domain objects, returns a list,
    with the same number of elements, of the corresponding human-readable
    exploration summary dicts.
    This assumes that all the exploration summary domain objects passed in are
    valid (i.e., none of them are None).

    Args:
        exploration_summaries: list(ExplorationSummary). List of exploration
            summary objects.

    Returns:
        list(dict). A list of exploration summary dicts in human readable form.
        Example:

        [ {
            'category': u'A category',
            'community_owned': False,
            'id': 'eid2',
            'language_code': 'en',
            'num_views': 0,
            'objective': u'An objective',
            'status': 'public',
            'tags': [],
            'thumbnail_bg_color': '#a33f40',
            'thumbnail_icon_url': self.get_static_asset_url(
                '/images/subjects/Lightbulb.svg'),
            'title': u'Exploration 2 Albert title',
        }, ]
    """
    exp_version_references = [
        exp_domain.ExpVersionReference(exp_summary.id, exp_summary.version)
        for exp_summary in exploration_summaries
    ]
    exp_stats_list = stats_services.get_exploration_stats_multi(
        exp_version_references)
    view_counts = [exp_stats.num_starts for exp_stats in exp_stats_list]

    displayable_exp_summaries = []

    for ind, exploration_summary in enumerate(exploration_summaries):
        if exploration_summary:
            summary_dict = {
                'id':
                exploration_summary.id,
                'title':
                exploration_summary.title,
                'activity_type':
                constants.ACTIVITY_TYPE_EXPLORATION,
                'category':
                exploration_summary.category,
                'created_on_msec':
                utils.get_time_in_millisecs(
                    exploration_summary.exploration_model_created_on),
                'objective':
                exploration_summary.objective,
                'language_code':
                exploration_summary.language_code,
                'last_updated_msec':
                utils.get_time_in_millisecs(
                    exploration_summary.exploration_model_last_updated),
                'human_readable_contributors_summary':
                (get_human_readable_contributors_summary(
                    exploration_summary.contributors_summary)),
                'status':
                exploration_summary.status,
                'ratings':
                exploration_summary.ratings,
                'community_owned':
                exploration_summary.community_owned,
                'tags':
                exploration_summary.tags,
                'thumbnail_icon_url':
                utils.get_thumbnail_icon_url_for_category(
                    exploration_summary.category),
                'thumbnail_bg_color':
                utils.get_hex_color_for_category(exploration_summary.category),
                'num_views':
                view_counts[ind],
            }

            displayable_exp_summaries.append(summary_dict)

    return displayable_exp_summaries
示例#15
0
    def get(self):
        """Handles GET requests."""
        if self.user_id is None:
            raise self.PageNotFoundException

        def _get_intro_card_color(category):
            return (feconf.CATEGORIES_TO_COLORS[category] if category
                    in feconf.CATEGORIES_TO_COLORS else feconf.DEFAULT_COLOR)

        def _round_average_ratings(rating):
            return round(rating, feconf.AVERAGE_RATINGS_DASHBOARD_PRECISION)

        # We need to do the filtering because some activities that were
        # originally subscribed to may have been deleted since.
        subscribed_exploration_summaries = [
            summary
            for summary in exp_services.get_exploration_summaries_matching_ids(
                subscription_services.get_exploration_ids_subscribed_to(
                    self.user_id)) if summary is not None
        ]
        subscribed_collection_summaries = [
            summary for summary in
            collection_services.get_collection_summaries_matching_ids(
                subscription_services.get_collection_ids_subscribed_to(
                    self.user_id)) if summary is not None
        ]

        exploration_ids_subscribed_to = [
            summary.id for summary in subscribed_exploration_summaries
        ]

        exp_summary_dicts = summary_services.get_displayable_exp_summary_dicts(
            subscribed_exploration_summaries)
        collection_summary_dicts = []

        feedback_thread_analytics = (
            feedback_services.get_thread_analytics_multi(
                exploration_ids_subscribed_to))

        # TODO(bhenning): Update this to use unresolved answers from
        # stats_services once the training interface is enabled and it's cheaper
        # to retrieve top answers from stats_services.
        for ind, exploration in enumerate(exp_summary_dicts):
            exploration.update(feedback_thread_analytics[ind].to_dict())

        exp_summary_dicts = sorted(
            exp_summary_dicts,
            key=lambda x: (x['num_open_threads'], x['last_updated_msec']),
            reverse=True)

        if (self.username in
                config_domain.WHITELISTED_COLLECTION_EDITOR_USERNAMES.value):
            for collection_summary in subscribed_collection_summaries:
                # TODO(sll): Reuse _get_displayable_collection_summary_dicts()
                # in summary_services, instead of replicating it like this.
                collection_summary_dicts.append({
                    'id':
                    collection_summary.id,
                    'title':
                    collection_summary.title,
                    'category':
                    collection_summary.category,
                    'objective':
                    collection_summary.objective,
                    'language_code':
                    collection_summary.language_code,
                    'last_updated':
                    utils.get_time_in_millisecs(
                        collection_summary.collection_model_last_updated),
                    'created_on':
                    utils.get_time_in_millisecs(
                        collection_summary.collection_model_created_on),
                    'status':
                    collection_summary.status,
                    'node_count':
                    collection_summary.node_count,
                    'community_owned':
                    collection_summary.community_owned,
                    'thumbnail_icon_url':
                    (utils.get_thumbnail_icon_url_for_category(
                        collection_summary.category)),
                    'thumbnail_bg_color':
                    utils.get_hex_color_for_category(
                        collection_summary.category),
                })

        dashboard_stats = (
            user_jobs_continuous.UserStatsAggregator.get_dashboard_stats(
                self.user_id))
        dashboard_stats.update({
            'total_open_feedback':
            feedback_services.get_total_open_threads(feedback_thread_analytics)
        })
        if dashboard_stats and dashboard_stats.get('average_ratings'):
            dashboard_stats['average_ratings'] = (_round_average_ratings(
                dashboard_stats['average_ratings']))

        last_week_stats = (user_services.get_last_week_dashboard_stats(
            self.user_id))
        if last_week_stats and last_week_stats.get('average_ratings'):
            last_week_stats['average_ratings'] = (_round_average_ratings(
                last_week_stats['average_ratings']))

        subscriber_ids = subscription_services.get_all_subscribers_of_creator(
            self.user_id)
        subscribers_settings = user_services.get_users_settings(subscriber_ids)
        subscribers_list = []
        for index, subscriber_settings in enumerate(subscribers_settings):
            subscriber_summary = {
                'subscriber_picture_data_url':
                (subscriber_settings.profile_picture_data_url),
                'subscriber_username':
                subscriber_settings.username,
                'subscriber_impact':
                (user_services.get_user_impact_score(subscriber_ids[index]))
            }

            subscribers_list.append(subscriber_summary)

        self.values.update({
            'explorations_list': exp_summary_dicts,
            'collections_list': collection_summary_dicts,
            'dashboard_stats': dashboard_stats,
            'last_week_stats': last_week_stats,
            'subscribers_list': subscribers_list
        })
        self.render_json(self.values)
示例#16
0
def get_displayable_exp_summary_dicts(exploration_summaries):
    """Gets a summary of explorations in human readable form.

    Given a list of exploration summary domain objects, returns a list,
    with the same number of elements, of the corresponding human-readable
    exploration summary dicts.
    This assumes that all the exploration summary domain objects passed in are
    valid (i.e., none of them are None).

    Args:
        exploration_summaries: list(ExplorationSummary). List of exploration
        summary objects.

    Return:
        list(dict). A list of exploration summary dicts in human readable form.
        Example:

        [ {
            'category': u'A category',
            'community_owned': False,
            'id': 'eid2',
            'language_code': 'en',
            'num_views': 0,
            'objective': u'An objective',
            'status': 'public',
            'tags': [],
            'thumbnail_bg_color': '#a33f40',
            'thumbnail_icon_url': self.get_static_asset_url(
                '/images/subjects/Lightbulb.svg'),
            'title': u'Exploration 2 Albert title',
        }, ]
    """
    exploration_ids = [
        exploration_summary.id
        for exploration_summary in exploration_summaries]

    view_counts = (
        stats_jobs_continuous.StatisticsAggregator.get_views_multi(
            exploration_ids))
    displayable_exp_summaries = []

    for ind, exploration_summary in enumerate(exploration_summaries):
        if not exploration_summary:
            continue

        summary_dict = {
            'id': exploration_summary.id,
            'title': exploration_summary.title,
            'activity_type': feconf.ACTIVITY_TYPE_EXPLORATION,
            'category': exploration_summary.category,
            'created_on_msec': utils.get_time_in_millisecs(
                exploration_summary.exploration_model_created_on),
            'objective': exploration_summary.objective,
            'language_code': exploration_summary.language_code,
            'last_updated_msec': utils.get_time_in_millisecs(
                exploration_summary.exploration_model_last_updated
            ),
            'human_readable_contributors_summary': (
                get_human_readable_contributors_summary(
                    exploration_summary.contributors_summary)
            ),
            'status': exploration_summary.status,
            'ratings': exploration_summary.ratings,
            'community_owned': exploration_summary.community_owned,
            'tags': exploration_summary.tags,
            'thumbnail_icon_url': utils.get_thumbnail_icon_url_for_category(
                exploration_summary.category),
            'thumbnail_bg_color': utils.get_hex_color_for_category(
                exploration_summary.category),
            'num_views': view_counts[ind],
        }

        displayable_exp_summaries.append(summary_dict)

    return displayable_exp_summaries
示例#17
0
    def get(self):
        """Handles GET requests."""
        if self.user_id is None:
            raise self.PageNotFoundException

        def _get_intro_card_color(category):
            return (feconf.CATEGORIES_TO_COLORS[category] if category
                    in feconf.CATEGORIES_TO_COLORS else feconf.DEFAULT_COLOR)

        def _round_average_ratings(rating):
            return round(rating, feconf.AVERAGE_RATINGS_DASHBOARD_PRECISION)

        exploration_ids_subscribed_to = (
            subscription_services.get_exploration_ids_subscribed_to(
                self.user_id))

        subscribed_exploration_summaries = filter(
            None, (exp_services.get_exploration_summaries_matching_ids(
                exploration_ids_subscribed_to)))
        subscribed_collection_summaries = filter(
            None, (collection_services.get_collection_summaries_matching_ids(
                subscription_services.get_collection_ids_subscribed_to(
                    self.user_id))))

        exp_summary_list = summary_services.get_displayable_exp_summary_dicts(
            subscribed_exploration_summaries)
        collection_summary_list = []

        feedback_thread_analytics = (
            feedback_services.get_thread_analytics_multi(
                exploration_ids_subscribed_to))

        unresolved_answers_dict = (
            stats_services.get_exps_unresolved_answers_count_for_default_rule(
                exploration_ids_subscribed_to))

        for ind, exploration in enumerate(exp_summary_list):
            exploration.update(feedback_thread_analytics[ind].to_dict())
            exploration.update({
                'num_unresolved_answers':
                (unresolved_answers_dict[exploration['id']]
                 if exploration['id'] in unresolved_answers_dict else 0)
            })

        exp_summary_list = sorted(
            exp_summary_list,
            key=lambda x: (x['num_open_threads'], x['last_updated_msec']),
            reverse=True)

        if (self.username in
                config_domain.WHITELISTED_COLLECTION_EDITOR_USERNAMES.value):
            for collection_summary in subscribed_collection_summaries:
                # TODO(sll): Reuse _get_displayable_collection_summary_dicts()
                # in summary_services, instead of replicating it like this.
                collection_summary_list.append({
                    'id':
                    collection_summary.id,
                    'title':
                    collection_summary.title,
                    'category':
                    collection_summary.category,
                    'objective':
                    collection_summary.objective,
                    'language_code':
                    collection_summary.language_code,
                    'last_updated':
                    utils.get_time_in_millisecs(
                        collection_summary.collection_model_last_updated),
                    'created_on':
                    utils.get_time_in_millisecs(
                        collection_summary.collection_model_created_on),
                    'status':
                    collection_summary.status,
                    'community_owned':
                    collection_summary.community_owned,
                    'thumbnail_icon_url':
                    (utils.get_thumbnail_icon_url_for_category(
                        collection_summary.category)),
                    'thumbnail_bg_color':
                    utils.get_hex_color_for_category(
                        collection_summary.category),
                })

        dashboard_stats = (
            user_jobs_continuous.UserStatsAggregator.get_dashboard_stats(
                self.user_id))
        dashboard_stats.update({
            'total_open_feedback':
            feedback_services.get_total_open_threads(feedback_thread_analytics)
        })
        if dashboard_stats and dashboard_stats.get('average_ratings'):
            dashboard_stats['average_ratings'] = (_round_average_ratings(
                dashboard_stats['average_ratings']))

        last_week_stats = (user_services.get_last_week_dashboard_stats(
            self.user_id))
        if last_week_stats and last_week_stats.get('average_ratings'):
            last_week_stats['average_ratings'] = (_round_average_ratings(
                last_week_stats['average_ratings']))

        self.values.update({
            'explorations_list': exp_summary_list,
            'collections_list': collection_summary_list,
            'dashboard_stats': dashboard_stats,
            'last_week_stats': last_week_stats
        })
        self.render_json(self.values)