Ejemplo n.º 1
0
    def test_get_exploration_ids_subscribed_to(self):
        self.assertEqual(subscription_services.get_exploration_ids_subscribed_to(USER_ID), [])

        subscription_services.subscribe_to_exploration(USER_ID, EXP_ID)
        self.assertEqual(subscription_services.get_exploration_ids_subscribed_to(USER_ID), [EXP_ID])

        subscription_services.subscribe_to_exploration(USER_ID, EXP_ID_2)
        self.assertEqual(subscription_services.get_exploration_ids_subscribed_to(USER_ID), [EXP_ID, EXP_ID_2])
Ejemplo n.º 2
0
    def test_get_exploration_ids_subscribed_to(self):
        USER_ID = "user_id"
        self.assertEqual(subscription_services.get_exploration_ids_subscribed_to(USER_ID), [])

        EXP_ID = "exp_id"
        subscription_services.subscribe_to_exploration(USER_ID, EXP_ID)
        self.assertEqual(subscription_services.get_exploration_ids_subscribed_to(USER_ID), [EXP_ID])

        EXP_2_ID = "exp_id_2"
        subscription_services.subscribe_to_exploration(USER_ID, EXP_2_ID)
        self.assertEqual(subscription_services.get_exploration_ids_subscribed_to(USER_ID), [EXP_ID, EXP_2_ID])
Ejemplo n.º 3
0
    def test_get_exploration_ids_subscribed_to(self):
        self.assertEqual(
            subscription_services.get_exploration_ids_subscribed_to(
                USER_ID), [])

        subscription_services.subscribe_to_exploration(USER_ID, EXP_ID)
        self.assertEqual(
            subscription_services.get_exploration_ids_subscribed_to(USER_ID),
            [EXP_ID])

        subscription_services.subscribe_to_exploration(USER_ID, EXP_ID_2)
        self.assertEqual(
            subscription_services.get_exploration_ids_subscribed_to(USER_ID),
            [EXP_ID, EXP_ID_2])
Ejemplo n.º 4
0
def mark_exploration_as_completed(user_id, exp_id):
    """Adds the exploration id to the completed list of the user unless the
    exploration has already been completed or has been created/edited by the
    user. It is also removed from the incomplete list and the learner playlist
    (if present).

    Args:
        user_id: str. The id of the user who has completed the exploration.
        exp_id: str. The id of the completed exploration.
    """
    completed_activities_model = (user_models.CompletedActivitiesModel.get(
        user_id, strict=False))
    if not completed_activities_model:
        completed_activities_model = (user_models.CompletedActivitiesModel(
            id=user_id))

    # We don't want anything that appears in the user's creator dashboard to
    # appear in the learner dashboard. Since the subscribed explorations
    # (edited/created) appear in the creator dashboard they will not appear in
    # the learner dashboard.
    subscribed_exploration_ids = (
        subscription_services.get_exploration_ids_subscribed_to(user_id))

    activities_completed = _get_completed_activities_from_model(
        completed_activities_model)

    if (exp_id not in subscribed_exploration_ids
            and exp_id not in activities_completed.exploration_ids):
        # Remove the exploration from the in progress and learner playlist
        # (if present) as it is now completed.
        remove_exp_from_incomplete_list(user_id, exp_id)
        learner_playlist_services.remove_exploration_from_learner_playlist(
            user_id, exp_id)
        activities_completed.add_exploration_id(exp_id)
        _save_completed_activities(activities_completed)
Ejemplo n.º 5
0
    def test_get_exploration_ids_subscribed_to(self):
        USER_ID = 'user_id'
        self.assertEqual(
            subscription_services.get_exploration_ids_subscribed_to(USER_ID),
            [])

        EXP_ID = 'exp_id'
        subscription_services.subscribe_to_exploration(USER_ID, EXP_ID)
        self.assertEqual(
            subscription_services.get_exploration_ids_subscribed_to(USER_ID),
            [EXP_ID])

        EXP_2_ID = 'exp_id_2'
        subscription_services.subscribe_to_exploration(USER_ID, EXP_2_ID)
        self.assertEqual(
            subscription_services.get_exploration_ids_subscribed_to(USER_ID),
            [EXP_ID, EXP_2_ID])
Ejemplo n.º 6
0
    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)
Ejemplo n.º 7
0
def mark_exploration_as_incomplete(
        user_id, exploration_id, state_name, exploration_version):
    """Adds the exploration id to the incomplete list of the user unless the
    exploration has been already completed or has been created/edited by the
    user. If the exploration is already present in the incomplete list, just the
    details associated with it are updated. If the exploration is present in the
    learner playlist, it is removed.

    Args:
        user_id: str. The id of the user who partially completed the
            exploration.
        exploration_id: str. The id of the partially completed exploration.
        state_name: str. The name of the state at which the user left the
            exploration.
        exploration_version: str. The version of the exploration played by the
            learner.
    """
    incomplete_activities_model = (
        user_models.IncompleteActivitiesModel.get(
            user_id, strict=False))
    if not incomplete_activities_model:
        incomplete_activities_model = (
            user_models.IncompleteActivitiesModel(id=user_id))

    exploration_ids = get_all_completed_exp_ids(user_id)

    subscribed_exploration_ids = (
        subscription_services.get_exploration_ids_subscribed_to(user_id))

    incomplete_activities = _get_incomplete_activities_from_model(
        incomplete_activities_model)

    if (exploration_id not in exploration_ids and
            exploration_id not in subscribed_exploration_ids):

        if exploration_id not in incomplete_activities.exploration_ids:
            # Remove the exploration from the learner playlist (if present) as
            # it is currently now being completed.
            learner_playlist_services.remove_exploration_from_learner_playlist(
                user_id, exploration_id)
            incomplete_activities.add_exploration_id(exploration_id)

        last_playthrough_information_model = (
            user_models.ExpUserLastPlaythroughModel.get(
                user_id, exploration_id))
        if not last_playthrough_information_model:
            last_playthrough_information_model = (
                user_models.ExpUserLastPlaythroughModel.create(
                    user_id, exploration_id))

        last_playthrough_information = _get_last_playthrough_information(
            last_playthrough_information_model)
        last_playthrough_information.update_last_played_information(
            exploration_version, state_name)

        _save_last_playthrough_information(last_playthrough_information)
        _save_incomplete_activities(incomplete_activities)
Ejemplo n.º 8
0
def get_exploration_summaries_subscribed_to(user_id):
    """Returns a list of ExplorationSummary domain objects that the user
    subscribes to.

    Args:
        user_id: str. The id of the user.

    Returns:
        list(ExplorationSummary). List of ExplorationSummary domain objects that
        the user subscribes to.
    """
    return [
        summary for summary in get_exploration_summaries_matching_ids(
            subscription_services.get_exploration_ids_subscribed_to(user_id))
        if summary is not None
    ]
Ejemplo n.º 9
0
def mark_exploration_to_be_played_later(user_id,
                                        exploration_id,
                                        position_to_be_inserted=None):
    """Adds the exploration id to the learner playlist of the user at the given
    position. If the position is not specified, the exploration gets added at
    the end. If the exploration is created or has been edited by the user it is
    not added as these appear on the creator dashboard of the creator. The
    maximum limit of the learner playlist is
    feconf.MAX_LEARNER_PLAYLIST_ACTIVITY_COUNT. If the count exceeds
    feconf.MAX_LEARNER_PLAYLIST_ACTIVITY_COUNT, the exploration is not added.

    Args:
        user_id: str. The id of the user.
        exploration_id: str. The id of the exploration to be added to the
            learner playlist.
        position_to_be_inserted: int|None. If this is specified the exploration
            gets inserted at the given position. Otherwise it gets added at the
            end.

    Returns:
        (bool, bool). The first boolean indicates whether the playlist limit
        of the user has been exceeded, and the second boolean indicates
        whether the exploration is among one of the created or edited
        explorations of the user.
    """
    learner_playlist_model = user_models.LearnerPlaylistModel.get(user_id,
                                                                  strict=False)
    if not learner_playlist_model:
        learner_playlist_model = (user_models.LearnerPlaylistModel(id=user_id))

    subscribed_exploration_ids = (
        subscription_services.get_exploration_ids_subscribed_to(user_id))

    learner_playlist = get_learner_playlist_from_model(learner_playlist_model)

    playlist_limit_exceeded = False
    exp_belongs_to_subscribed_explorations = False
    if exploration_id not in subscribed_exploration_ids:
        exploration_ids_count = len(learner_playlist.exploration_ids)
        if position_to_be_inserted is None:
            if exploration_id not in learner_playlist.exploration_ids:
                if exploration_ids_count < MAX_LEARNER_PLAYLIST_ACTIVITY_COUNT:
                    learner_playlist.add_exploration_id_to_list(exploration_id)
                else:
                    playlist_limit_exceeded = True
        else:
            if exploration_id not in learner_playlist.exploration_ids:
                if exploration_ids_count < MAX_LEARNER_PLAYLIST_ACTIVITY_COUNT:
                    learner_playlist.insert_exploration_id_at_given_position(
                        exploration_id, position_to_be_inserted)
                else:
                    playlist_limit_exceeded = True
            else:
                learner_playlist.remove_exploration_id(exploration_id)
                learner_playlist.insert_exploration_id_at_given_position(
                    exploration_id, position_to_be_inserted)
        save_learner_playlist(learner_playlist)
    else:
        exp_belongs_to_subscribed_explorations = True

    return playlist_limit_exceeded, exp_belongs_to_subscribed_explorations
Ejemplo n.º 10
0
    def get(self):
        """Handles GET requests."""
        def _get_intro_card_color(category):
            """Returns the intro card color according to the category.

            Args:
                category: str. The category of the lesson.

            Returns:
                str. The intro card color according to the category.
            """
            return (constants.CATEGORIES_TO_COLORS[category]
                    if category in constants.CATEGORIES_TO_COLORS else
                    constants.DEFAULT_COLOR)

        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 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 constants.ENABLE_NEW_STRUCTURE_PLAYERS:
            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 constants.ENABLE_NEW_STRUCTURE_PLAYERS:
            self.values.update({'topic_summary_dicts': topic_summary_dicts})
        self.render_json(self.values)
Ejemplo n.º 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)

        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)
Ejemplo n.º 12
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 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)

        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,
        })
        self.render_json(self.values)
Ejemplo n.º 13
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)
Ejemplo n.º 14
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_for_default_rule(
                exploration_ids_subscribed_to))

        total_unresolved_answers = 0

        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']]['count']
                 if exploration['id'] in unresolved_answers_dict else 0),
                'top_unresolved_answers':
                (unresolved_answers_dict[
                    exploration['id']]['unresolved_answers']
                 [:feconf.TOP_UNRESOLVED_ANSWERS_COUNT_DASHBOARD])
            })
            total_unresolved_answers += exploration['num_unresolved_answers']

        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,
                    '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),
            'total_unresolved_answers':
            total_unresolved_answers
        })
        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)
Ejemplo n.º 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)

        subscribed_exploration_summaries = (
            exp_services.get_exploration_summaries_matching_ids(
                subscription_services.get_exploration_ids_subscribed_to(
                    self.user_id)))
        subscribed_collection_summaries = (
            collection_services.get_collection_summaries_matching_ids(
                subscription_services.get_collection_ids_subscribed_to(
                    self.user_id)))

        explorations_list = []
        collections_list = []

        for exp_summary in subscribed_exploration_summaries:
            if exp_summary is None:
                continue

            feedback_thread_analytics = feedback_services.get_thread_analytics(
                exp_summary.id)
            # TODO(sll): Reuse _get_displayable_exp_summary_dicts() in
            # summary_services, instead of replicating it like this.
            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,
                '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)

        if (self.username in
                config_domain.WHITELISTED_COLLECTION_EDITOR_USERNAMES.value):
            for collection_summary in subscribed_collection_summaries:
                if collection_summary is None:
                    continue

                # 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,
        })
        self.render_json(self.values)
Ejemplo n.º 16
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)