From f7af52252f7ed44634236878748d2013e2f692d0 Mon Sep 17 00:00:00 2001 From: Arunabh98 Date: Wed, 26 Jul 2017 14:42:42 +0530 Subject: [PATCH 01/65] Init work. --- core/controllers/learner_playlist.py | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 core/controllers/learner_playlist.py diff --git a/core/controllers/learner_playlist.py b/core/controllers/learner_playlist.py new file mode 100644 index 000000000000..72b8386a5f1a --- /dev/null +++ b/core/controllers/learner_playlist.py @@ -0,0 +1,20 @@ +# Copyright 2014 The Oppia Authors. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS-IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""Controllers for the learner playlist.""" + +from core.controllers import base + +class AddExplorationToLearnerPlaylistHandler(base.BaseHandler): + """Adds the exploration id received as payload to From 2e6a78db50e640d1c5c53b4eb52d0d382729b2d3 Mon Sep 17 00:00:00 2001 From: Arunabh98 Date: Wed, 26 Jul 2017 18:13:29 +0530 Subject: [PATCH 02/65] Learner dashboard milestone 3.1 --- core/controllers/learner_playlist.py | 55 ++++- core/controllers/learner_playlist_test.py | 267 ++++++++++++++++++++++ feconf.py | 1 + main.py | 19 ++ 4 files changed, 341 insertions(+), 1 deletion(-) create mode 100644 core/controllers/learner_playlist_test.py diff --git a/core/controllers/learner_playlist.py b/core/controllers/learner_playlist.py index 72b8386a5f1a..372d77f565a6 100644 --- a/core/controllers/learner_playlist.py +++ b/core/controllers/learner_playlist.py @@ -15,6 +15,59 @@ """Controllers for the learner playlist.""" from core.controllers import base +from core.domain import learner_progress_services +from core.domain import learner_playlist_services + class AddExplorationToLearnerPlaylistHandler(base.BaseHandler): - """Adds the exploration id received as payload to + """Handler for adding the id of the exploration received as payload to the + playlist of the user. + """ + + @base.require_user + def post(self): + exploration_id = self.payload.get('exploration_id') + position_to_be_inserted_in = self.payload.get('index') + learner_progress_services.add_exp_to_learner_playlist( + self.user_id, exploration_id, position_to_be_inserted_in) + self.render_json(self.values) + + +class AddCollectionToLearnerPlaylistHandler(base.BaseHandler): + """Handler for adding the id of the collection received as payload to the + playlist of the user. + """ + + @base.require_user + def post(self): + collection_id = self.payload.get('collection_id') + position_to_be_inserted_in = self.payload.get('index') + learner_progress_services.add_collection_to_learner_playlist( + self.user_id, collection_id, position_to_be_inserted_in) + self.render_json(self.values) + + +class RemoveExplorationFromPlaylistHandler(base.BaseHandler): + """Handler for removing the id of the exploration received as payload to + the playlist of the user. + """ + + @base.require_user + def post(self): + exploration_id = self.payload.get('exploration_id') + learner_playlist_services.remove_exploration_from_learner_playlist( + self.user_id, exploration_id) + self.render_json(self.values) + + +class RemoveCollectionFromPlaylistHandler(base.BaseHandler): + """Handler for removing the id of the collection received as payload to + the playlist of the user. + """ + + @base.require_user + def post(self): + collection_id = self.payload.get('collection_id') + learner_playlist_services.remove_collection_from_learner_playlist( + self.user_id, collection_id) + self.render_json(self.values) diff --git a/core/controllers/learner_playlist_test.py b/core/controllers/learner_playlist_test.py new file mode 100644 index 000000000000..e6d94667de6b --- /dev/null +++ b/core/controllers/learner_playlist_test.py @@ -0,0 +1,267 @@ +# Copyright 2014 The Oppia Authors. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS-IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""Tests for the learner playlist.""" + +from core.domain import learner_playlist_services +from core.domain import learner_progress_services +from core.platform import models +from core.tests import test_utils +import feconf + + +class LearnerPlaylistHandlerTests(test_utils.GenericTestBase): + OWNER_EMAIL = 'owner@example.com' + OWNER_USERNAME = 'owner' + + EXP_ID_1 = 'exp_id_1' + EXP_TITLE_1 = 'exp title 1' + EXP_ID_2 = 'exp_id_2' + EXP_TITLE_2 = 'exp title 2' + EXP_ID_3 = 'exp_id_3' + EXP_TITLE_3 = 'exp title 3' + + COL_ID_1 = 'col_id_1' + COL_TITLE_1 = 'col title 1' + COL_ID_2 = 'col_id_2' + COL_TITLE_2 = 'col title 2' + COL_ID_3 = 'col_id_3' + COL_TITLE_3 = 'col title 3' + + def setUp(self): + super(LearnerPlaylistHandlerTests, self).setUp() + self.signup(self.OWNER_EMAIL, self.OWNER_USERNAME) + self.signup(self.VIEWER_EMAIL, self.VIEWER_USERNAME) + + self.viewer_id = self.get_user_id_from_email(self.VIEWER_EMAIL) + self.owner_id = self.get_user_id_from_email(self.OWNER_EMAIL) + + # Save the explorations. + self.save_new_default_exploration( + self.EXP_ID_1, self.owner_id, title=self.EXP_TITLE_1) + self.save_new_default_exploration( + self.EXP_ID_2, self.owner_id, title=self.EXP_TITLE_2) + self.save_new_default_exploration( + self.EXP_ID_3, self.owner_id, title=self.EXP_TITLE_3) + # Save the collections. + self.save_new_default_collection( + self.COL_ID_1, self.owner_id, title=self.COL_TITLE_1) + self.save_new_default_collection( + self.COL_ID_2, self.owner_id, title=self.COL_TITLE_2) + self.save_new_default_collection( + self.COL_ID_3, self.owner_id, title=self.COL_TITLE_3) + + def test_add_exploration_to_learner_playlist(self): + self.login(self.VIEWER_EMAIL) + response = self.testapp.get(feconf.LEARNER_DASHBOARD_URL) + csrf_token = self.get_csrf_token_from_response(response) + + # Add one exploration to the playlist. + payload = { + 'exploration_id': self.EXP_ID_1 + } + self.post_json( + '%s/add_exploration_to_learner_playlist' % + feconf.LEARNER_PLAYLIST_DATA_URL, payload, csrf_token) + self.assertEqual( + learner_playlist_services.get_all_exp_ids_in_learner_playlist( + self.viewer_id), [self.EXP_ID_1]) + + # Add another exploration. + payload = { + 'exploration_id': self.EXP_ID_2 + } + self.post_json( + '%s/add_exploration_to_learner_playlist' % + feconf.LEARNER_PLAYLIST_DATA_URL, payload, csrf_token) + self.assertEqual( + learner_playlist_services.get_all_exp_ids_in_learner_playlist( + self.viewer_id), [self.EXP_ID_1, self.EXP_ID_2]) + + # User rearranges the explorations. 'exp title 2' is shifted to the + # first position. + payload = { + 'exploration_id': self.EXP_ID_2, + 'index': 0 + } + self.post_json( + '%s/add_exploration_to_learner_playlist' % + feconf.LEARNER_PLAYLIST_DATA_URL, payload, csrf_token) + self.assertEqual( + learner_playlist_services.get_all_exp_ids_in_learner_playlist( + self.viewer_id), [self.EXP_ID_2, self.EXP_ID_1]) + + # If an exploration belongs to the incomplete list or completed list, it + # should not be added. Here we test for the completed case. + learner_progress_services.mark_exploration_as_completed( + self.viewer_id, self.EXP_ID_3) + payload = { + 'exploration_id': self.EXP_ID_3, + } + self.post_json( + '%s/add_exploration_to_learner_playlist' % + feconf.LEARNER_PLAYLIST_DATA_URL, payload, csrf_token) + self.assertEqual( + learner_playlist_services.get_all_exp_ids_in_learner_playlist( + self.viewer_id), [self.EXP_ID_2, self.EXP_ID_1]) + + self.logout() + + def test_add_collection_to_learner_playlist(self): + self.login(self.VIEWER_EMAIL) + response = self.testapp.get(feconf.LEARNER_DASHBOARD_URL) + csrf_token = self.get_csrf_token_from_response(response) + + # Add one exploration to the playlist. + payload = { + 'collection_id': self.COL_ID_1 + } + self.post_json( + '%s/add_collection_to_learner_playlist' % + feconf.LEARNER_PLAYLIST_DATA_URL, payload, csrf_token) + self.assertEqual( + learner_playlist_services.get_all_collection_ids_in_learner_playlist( # pylint: disable=line-too-long + self.viewer_id), [self.COL_ID_1]) + + # Add another exploration. + payload = { + 'collection_id': self.COL_ID_2 + } + self.post_json( + '%s/add_collection_to_learner_playlist' % + feconf.LEARNER_PLAYLIST_DATA_URL, payload, csrf_token) + self.assertEqual( + learner_playlist_services.get_all_collection_ids_in_learner_playlist( # pylint: disable=line-too-long + self.viewer_id), [self.COL_ID_1, self.COL_ID_2]) + + # User rearranges the explorations. 'exp title 2' is shifted to the + # first position. + payload = { + 'collection_id': self.COL_ID_2, + 'index': 0 + } + self.post_json( + '%s/add_collection_to_learner_playlist' % + feconf.LEARNER_PLAYLIST_DATA_URL, payload, csrf_token) + self.assertEqual( + learner_playlist_services.get_all_collection_ids_in_learner_playlist( + self.viewer_id), [self.COL_ID_2, self.COL_ID_1]) + + # If an exploration belongs to the incomplete list or completed list, it + # should not be added. Here we test for the completed case. + learner_progress_services.mark_collection_as_completed( + self.viewer_id, self.COL_ID_3) + payload = { + 'collection_id': self.COL_ID_3 + } + self.post_json( + '%s/add_collection_to_learner_playlist' % + feconf.LEARNER_PLAYLIST_DATA_URL, payload, csrf_token) + self.assertEqual( + learner_playlist_services.get_all_collection_ids_in_learner_playlist( + self.viewer_id), [self.COL_ID_2, self.COL_ID_1]) + + self.logout() + + def test_remove_exploration_from_learner_playlist(self): + self.login(self.VIEWER_EMAIL) + response = self.testapp.get(feconf.LEARNER_DASHBOARD_URL) + csrf_token = self.get_csrf_token_from_response(response) + + # Add explorations to the learner playlist. + learner_progress_services.add_exp_to_learner_playlist( + self.viewer_id, self.EXP_ID_1) + learner_progress_services.add_exp_to_learner_playlist( + self.viewer_id, self.EXP_ID_2) + self.assertEqual( + learner_playlist_services.get_all_exp_ids_in_learner_playlist( + self.viewer_id), [self.EXP_ID_1, self.EXP_ID_2]) + + # Remove an exploration. + payload = { + 'exploration_id': self.EXP_ID_1 + } + self.post_json( + '%s/remove_exploration_from_learner_playlist' % + feconf.LEARNER_PLAYLIST_DATA_URL, payload, csrf_token) + self.assertEqual( + learner_playlist_services.get_all_exp_ids_in_learner_playlist( + self.viewer_id), [self.EXP_ID_2]) + + # Removing the same exploration again has no effect. + self.post_json( + '%s/remove_exploration_from_learner_playlist' % + feconf.LEARNER_PLAYLIST_DATA_URL, payload, csrf_token) + self.assertEqual( + learner_playlist_services.get_all_exp_ids_in_learner_playlist( + self.viewer_id), [self.EXP_ID_2]) + + # Remove the second exploration. + payload = { + 'exploration_id': self.EXP_ID_2 + } + self.post_json( + '%s/remove_exploration_from_learner_playlist' % + feconf.LEARNER_PLAYLIST_DATA_URL, payload, csrf_token) + self.assertEqual( + learner_playlist_services.get_all_exp_ids_in_learner_playlist( + self.viewer_id), []) + + self.logout() + + def test_remove_collection_from_learner_playlist(self): + self.login(self.VIEWER_EMAIL) + response = self.testapp.get(feconf.LEARNER_DASHBOARD_URL) + csrf_token = self.get_csrf_token_from_response(response) + + # Add collections to the learner playlist. + learner_progress_services.add_collection_to_learner_playlist( + self.viewer_id, self.COL_ID_1) + learner_progress_services.add_collection_to_learner_playlist( + self.viewer_id, self.COL_ID_2) + self.assertEqual( + learner_playlist_services.get_all_collection_ids_in_learner_playlist( # pylint: disable=line-too-long + self.viewer_id), [self.COL_ID_1, self.COL_ID_2]) + + # Remove a collection. + payload = { + 'collection_id': self.COL_ID_1 + } + self.post_json( + '%s/remove_collection_from_learner_playlist' % + feconf.LEARNER_PLAYLIST_DATA_URL, payload, csrf_token) + self.assertEqual( + learner_playlist_services.get_all_collection_ids_in_learner_playlist( # pylint: disable=line-too-long + self.viewer_id), [self.COL_ID_2]) + + # Removing the same collection again has no effect. + self.post_json( + '%s/remove_collection_from_learner_playlist' % + feconf.LEARNER_PLAYLIST_DATA_URL, payload, csrf_token) + self.assertEqual( + learner_playlist_services.get_all_collection_ids_in_learner_playlist( # pylint: disable=line-too-long + self.viewer_id), [self.COL_ID_2]) + + # Remove the second collection. + payload = { + 'collection_id': self.COL_ID_2 + } + self.post_json( + '%s/remove_collection_from_learner_playlist' % + feconf.LEARNER_PLAYLIST_DATA_URL, payload, csrf_token) + self.assertEqual( + learner_playlist_services.get_all_collection_ids_in_learner_playlist( # pylint: disable=line-too-long + self.viewer_id), []) + + self.logout() diff --git a/feconf.py b/feconf.py index a6988a81a63c..950afca9d98a 100644 --- a/feconf.py +++ b/feconf.py @@ -578,6 +578,7 @@ def get_empty_ratings(): LEARNER_DASHBOARD_URL = '/learner_dashboard' LEARNER_DASHBOARD_DATA_URL = '/learnerdashboardhandler/data' LEARNER_DASHBOARD_FEEDBACK_THREAD_DATA_URL = '/learnerdashboardthreadhandler' +LEARNER_PLAYLIST_DATA_URL = '/learnerplaylisthandler' LIBRARY_GROUP_DATA_URL = '/librarygrouphandler' LIBRARY_INDEX_URL = '/library' LIBRARY_INDEX_DATA_URL = '/libraryindexhandler' diff --git a/main.py b/main.py index 669c520d55e6..df89e9b9e8f7 100644 --- a/main.py +++ b/main.py @@ -29,6 +29,7 @@ from core.controllers import editor from core.controllers import feedback from core.controllers import learner_dashboard +from core.controllers import learner_playlist from core.controllers import library from core.controllers import moderator from core.controllers import pages @@ -219,6 +220,24 @@ def ui_access_wrapper(self, *args, **kwargs): get_redirect_route( r'%s/remove_in_progress_collection' % feconf.LEARNER_DASHBOARD_URL, reader.RemoveCollectionFromIncompleteListHandler), + + get_redirect_route( + r'%s/add_exploration_to_learner_playlist' % + feconf.LEARNER_PLAYLIST_DATA_URL, + learner_playlist.AddExplorationToLearnerPlaylistHandler), + get_redirect_route( + r'%s/add_collection_to_learner_playlist' % + feconf.LEARNER_PLAYLIST_DATA_URL, + learner_playlist.AddCollectionToLearnerPlaylistHandler), + get_redirect_route( + r'%s/remove_exploration_from_learner_playlist' % + feconf.LEARNER_PLAYLIST_DATA_URL, + learner_playlist.RemoveExplorationFromPlaylistHandler), + get_redirect_route( + r'%s/remove_collection_from_learner_playlist' % + feconf.LEARNER_PLAYLIST_DATA_URL, + learner_playlist.RemoveCollectionFromPlaylistHandler), + get_redirect_route( r'/imagehandler//', resources.ImageHandler), From 58bf6b3fda69dc3575db66b5a102dd4b54825732 Mon Sep 17 00:00:00 2001 From: Arunabh98 Date: Wed, 26 Jul 2017 18:23:47 +0530 Subject: [PATCH 03/65] Fix lint errors. --- core/controllers/learner_playlist_test.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/core/controllers/learner_playlist_test.py b/core/controllers/learner_playlist_test.py index e6d94667de6b..d75fdec43350 100644 --- a/core/controllers/learner_playlist_test.py +++ b/core/controllers/learner_playlist_test.py @@ -16,7 +16,6 @@ from core.domain import learner_playlist_services from core.domain import learner_progress_services -from core.platform import models from core.tests import test_utils import feconf @@ -155,7 +154,7 @@ def test_add_collection_to_learner_playlist(self): '%s/add_collection_to_learner_playlist' % feconf.LEARNER_PLAYLIST_DATA_URL, payload, csrf_token) self.assertEqual( - learner_playlist_services.get_all_collection_ids_in_learner_playlist( + learner_playlist_services.get_all_collection_ids_in_learner_playlist( # pylint: disable=line-too-long self.viewer_id), [self.COL_ID_2, self.COL_ID_1]) # If an exploration belongs to the incomplete list or completed list, it @@ -169,7 +168,7 @@ def test_add_collection_to_learner_playlist(self): '%s/add_collection_to_learner_playlist' % feconf.LEARNER_PLAYLIST_DATA_URL, payload, csrf_token) self.assertEqual( - learner_playlist_services.get_all_collection_ids_in_learner_playlist( + learner_playlist_services.get_all_collection_ids_in_learner_playlist( # pylint: disable=line-too-long self.viewer_id), [self.COL_ID_2, self.COL_ID_1]) self.logout() From ab3adf953d76635ef68d8057634ed3119cc868cf Mon Sep 17 00:00:00 2001 From: Arunabh98 Date: Thu, 27 Jul 2017 01:30:45 +0530 Subject: [PATCH 04/65] Add tests. --- core/controllers/learner_dashboard.py | 9 ++ core/controllers/learner_dashboard_test.py | 34 +++++ core/domain/learner_progress_domain.py | 9 +- core/domain/learner_progress_services.py | 132 +++++++++++++++++- core/domain/learner_progress_services_test.py | 18 +++ 5 files changed, 196 insertions(+), 6 deletions(-) diff --git a/core/controllers/learner_dashboard.py b/core/controllers/learner_dashboard.py index b70e4991e6bf..5e1d30be16d7 100644 --- a/core/controllers/learner_dashboard.py +++ b/core/controllers/learner_dashboard.py @@ -73,6 +73,13 @@ def get(self): learner_progress_services.get_collection_summary_dicts( learner_progress.incomplete_collection_summaries)) + exploration_playlist_summary_dicts = ( + summary_services.get_displayable_exp_summary_dicts( + learner_progress.exploration_playlist_summaries)) + collection_playlist_summary_dicts = ( + learner_progress_services.get_collection_summary_dicts( + learner_progress.collection_playlist_summaries)) + creators_subscribed_to = ( subscription_services.get_all_creators_subscribed_to(self.user_id)) creators_settings = user_services.get_users_settings( @@ -96,6 +103,8 @@ def get(self): 'completed_collections_list': completed_collection_summary_dicts, 'incomplete_explorations_list': incomplete_exp_summary_dicts, 'incomplete_collections_list': incomplete_collection_summary_dicts, + 'exploration_playlist': exploration_playlist_summary_dicts, + 'collection_playlist': collection_playlist_summary_dicts, 'number_of_deleted_activities': number_of_deleted_activities, 'completed_to_incomplete_collections': ( completed_to_incomplete_collections), diff --git a/core/controllers/learner_dashboard_test.py b/core/controllers/learner_dashboard_test.py index 8ba5e83fa8f9..c28dbf1e5eee 100644 --- a/core/controllers/learner_dashboard_test.py +++ b/core/controllers/learner_dashboard_test.py @@ -110,6 +110,40 @@ def test_can_see_incomplete_collections(self): response['incomplete_collections_list'][0]['id'], self.COL_ID) self.logout() + def test_can_see_exploration_playlist(self): + self.login(self.VIEWER_EMAIL) + + response = self.get_json(feconf.LEARNER_DASHBOARD_DATA_URL) + self.assertEqual(len(response['exploration_playlist']), 0) + + self.save_new_default_exploration( + self.EXP_ID, self.owner_id, title=self.EXP_TITLE) + + learner_progress_services.add_exp_to_learner_playlist( + self.viewer_id, self.EXP_ID) + response = self.get_json(feconf.LEARNER_DASHBOARD_DATA_URL) + self.assertEqual(len(response['exploration_playlist']), 1) + self.assertEqual( + response['exploration_playlist'][0]['id'], self.EXP_ID) + self.logout() + + def test_can_see_collection_playlist(self): + self.login(self.VIEWER_EMAIL) + + response = self.get_json(feconf.LEARNER_DASHBOARD_DATA_URL) + self.assertEqual(len(response['collection_playlist']), 0) + + self.save_new_default_collection( + self.COL_ID, self.owner_id, title=self.COL_TITLE) + + learner_progress_services.add_collection_to_learner_playlist( + self.viewer_id, self.COL_ID) + response = self.get_json(feconf.LEARNER_DASHBOARD_DATA_URL) + self.assertEqual(len(response['collection_playlist']), 1) + self.assertEqual( + response['collection_playlist'][0]['id'], self.COL_ID) + self.logout() + def test_can_see_subscription(self): self.login(self.VIEWER_EMAIL) diff --git a/core/domain/learner_progress_domain.py b/core/domain/learner_progress_domain.py index 10b5868439b8..1c0addb35db9 100644 --- a/core/domain/learner_progress_domain.py +++ b/core/domain/learner_progress_domain.py @@ -21,7 +21,8 @@ class LearnerProgress(object): def __init__(self, incomplete_exp_summaries, incomplete_collection_summaries, completed_exp_summaries, - completed_collection_summaries): + completed_collection_summaries, exploration_playlist, + collection_playlist): """Constructs a LearnerProgress domain object. Args: @@ -34,8 +35,14 @@ def __init__(self, incomplete_exp_summaries, the explorations partially completed by the learner. completed_collection_summaries: list(CollectionSummary). The summaries of the collections partially completed by the learner. + exploration_playlist: list(ExplorationSummary). The summaries of the + explorations in the learner playlist. + collection_playlist: list(CollectionSummary). The summaries of the + collections in the learner playlist. """ self.incomplete_exp_summaries = incomplete_exp_summaries self.incomplete_collection_summaries = incomplete_collection_summaries self.completed_exp_summaries = completed_exp_summaries self.completed_collection_summaries = completed_collection_summaries + self.exploration_playlist_summaries = exploration_playlist + self.collection_playlist_summaries = collection_playlist diff --git a/core/domain/learner_progress_services.py b/core/domain/learner_progress_services.py index dddb8ca29ca6..0d15aa9267c9 100644 --- a/core/domain/learner_progress_services.py +++ b/core/domain/learner_progress_services.py @@ -357,6 +357,32 @@ def add_collection_to_learner_playlist( user_id, collection_id, position_to_be_inserted) +def remove_entity_ids_from_playlist(user_id, exploration_ids, + collection_ids): + """Removes the explorations and collections from the playlist of the user. + + Args: + user_id: str. The id of the user. + exploration_ids: list(str). The ids of the explorations to be removed. + collection_ids: list(str). The ids of the collections to be removed. + """ + learner_playlist_model = user_models.LearnerPlaylistModel.get( + user_id, strict=False) + + if learner_playlist_model: + learner_playlist = ( + learner_playlist_services.get_learner_playlist_from_model( + learner_playlist_model)) + + for exploration_id in exploration_ids: + learner_playlist.remove_exploration_id(exploration_id) + + for collection_id in collection_ids: + learner_playlist.remove_collection_id(collection_id) + + learner_playlist_services.save_learner_playlist(learner_playlist) + + def remove_exp_from_completed_list(user_id, exploration_id): """Removes the exploration from the completed list of the user (if present). @@ -399,7 +425,8 @@ def remove_collection_from_completed_list(user_id, collection_id): def remove_entity_ids_from_completed_list(user_id, exploration_ids, collection_ids): - """Removes the collections from the completed list of the user. + """Removes the explorations and collections from the completed list of the + learner. Args: user_id: str. The id of the user. @@ -729,6 +756,63 @@ def get_filtered_incomplete_collection_summaries(collection_summaries, nonexistent_incomplete_collection_ids) +def get_filtered_exp_playlist_summaries(exploration_summaries, + exploration_ids): + """Returns a list of summaries of the explorations in the learner playlist + and the ids of explorations that are no longer present. + + Args: + exploration_summaries: list(ExplorationSummary). The list of exploration + summary domain objects to be filtered. + exploration_ids: list(str). The ids of the explorations corresponding to + the exploration summary domain objects. + + Returns: + tuple. A 2-tuple whose elements are as follows: + - list(ExplorationSummary). Filtered list of ExplorationSummary domain + objects of the explorations in the learner playlist. + - list(str). The ids of the explorations that are no longer present. + """ + nonexistent_playlist_exp_ids = [] + filtered_exp_playlist_summaries = [] + for index, exploration_summary in enumerate(exploration_summaries): + if exploration_summary is None: + nonexistent_playlist_exp_ids.append(exploration_ids[index]) + else: + filtered_exp_playlist_summaries.append(exploration_summary) + + return filtered_exp_playlist_summaries, nonexistent_playlist_exp_ids + + +def get_filtered_collection_playlist_summaries(collection_summaries, + collection_ids): + """Returns a list of summaries of the collections in the learner playlist + and the ids of collections that are no longer present. + + Args: + collection_summaries: list(CollectionSummary). The list of collection + summary domain objects to be filtered. + collection_ids: list(str). The ids of the collections corresponding to + the collection summary domain objects. + + Returns: + tuple. A 2-tuple whose elements are as follows: + - list(CollectionSummary). Filtered list of CollectionSummary domain + objects of the collections in the learner playlist. + - list(str). The ids of the collections that are no longer present. + """ + nonexistent_playlist_collection_ids = [] + filtered_collection_playlist_summaries = [] + for index, collection_summary in enumerate(collection_summaries): + if collection_summary is None: + nonexistent_playlist_collection_ids.append(collection_ids[index]) + else: + filtered_collection_playlist_summaries.append(collection_summary) + + return (filtered_collection_playlist_summaries, + nonexistent_playlist_collection_ids) + + def get_collection_summary_dicts(collection_summaries): """Returns a displayable summary dict of the the collection summaries given to it. @@ -794,7 +878,8 @@ def get_activity_progress(user_id): datastore_services.fetch_multiple_entities_by_ids_and_models( [ ('CompletedActivitiesModel', [user_id]), - ('IncompleteActivitiesModel', [user_id]) + ('IncompleteActivitiesModel', [user_id]), + ('LearnerPlaylistModel', [user_id]) ])) # If completed model is present. @@ -817,19 +902,34 @@ def get_activity_progress(user_id): incomplete_exploration_ids = [] incomplete_collection_ids = [] + # If learner playlist model is present. + if learner_progress_models[2][0]: + learner_playlist = ( + learner_playlist_services.get_learner_playlist_from_model( + learner_progress_models[2][0])) + exploration_playlist_ids = learner_playlist.exploration_ids + collection_playlist_ids = learner_playlist.collection_ids + else: + exploration_playlist_ids = [] + collection_playlist_ids = [] + activity_models = ( datastore_services.fetch_multiple_entities_by_ids_and_models( [ ('ExpSummaryModel', incomplete_exploration_ids), ('CollectionSummaryModel', incomplete_collection_ids), ('ExpSummaryModel', completed_exploration_ids), - ('CollectionSummaryModel', completed_collection_ids) + ('CollectionSummaryModel', completed_collection_ids), + ('ExpSummaryModel', exploration_playlist_ids), + ('CollectionSummaryModel', collection_playlist_ids) ])) incomplete_exploration_models = activity_models[0] incomplete_collection_models = activity_models[1] completed_exploration_models = activity_models[2] completed_collection_models = activity_models[3] + exploration_playlist_models = activity_models[4] + collection_playlist_models = activity_models[5] incomplete_exp_summaries = ( [exp_services.get_exploration_summary_from_model(model) @@ -843,6 +943,12 @@ def get_activity_progress(user_id): completed_collection_summaries = ( [collection_services.get_collection_summary_from_model(model) if model else None for model in completed_collection_models]) + exploration_playlist_summaries = ( + [exp_services.get_exploration_summary_from_model(model) + if model else None for model in exploration_playlist_models]) + collection_playlist_summaries = ( + [collection_services.get_collection_summary_from_model(model) + if model else None for model in collection_playlist_models]) filtered_incomplete_exp_summaries, nonexistent_incomplete_exp_ids = ( get_filtered_incomplete_exp_summaries( @@ -870,11 +976,22 @@ def get_activity_progress(user_id): get_filtered_incomplete_collection_summaries( incomplete_collection_summaries, incomplete_collection_ids)) + filtered_exp_playlist_summaries, nonexistent_playlist_exp_ids = ( + get_filtered_exp_playlist_summaries( + exploration_playlist_summaries, exploration_playlist_ids)) + + (filtered_collection_playlist_summaries, + nonexistent_playlist_collection_ids) = ( + get_filtered_collection_playlist_summaries( + collection_playlist_summaries, collection_playlist_ids)) + number_of_deleted_activities = { 'incomplete_explorations': len(nonexistent_incomplete_exp_ids), 'incomplete_collections': len(nonexistent_incomplete_collection_ids), 'completed_explorations': len(nonexistent_completed_exp_ids), - 'completed_collections': len(nonexistent_completed_collection_ids) + 'completed_collections': len(nonexistent_completed_collection_ids), + 'exploration_playlist': len(nonexistent_playlist_exp_ids), + 'collection_playlist': len(nonexistent_playlist_collection_ids) } remove_entity_ids_from_incomplete_list( @@ -883,12 +1000,17 @@ def get_activity_progress(user_id): remove_entity_ids_from_completed_list( user_id, nonexistent_completed_exp_ids, nonexistent_completed_collection_ids) + remove_entity_ids_from_playlist( + user_id, nonexistent_playlist_exp_ids, + nonexistent_playlist_collection_ids) learner_progress = learner_progress_domain.LearnerProgress( filtered_incomplete_exp_summaries, filtered_incomplete_collection_summaries, filtered_completed_exp_summaries, - filtered_completed_collection_summaries) + filtered_completed_collection_summaries, + filtered_exp_playlist_summaries, + filtered_collection_playlist_summaries) return (learner_progress, number_of_deleted_activities, completed_to_incomplete_collection_titles) diff --git a/core/domain/learner_progress_services_test.py b/core/domain/learner_progress_services_test.py index dcd1f3054783..fd036e0181df 100644 --- a/core/domain/learner_progress_services_test.py +++ b/core/domain/learner_progress_services_test.py @@ -516,11 +516,13 @@ def test_get_all_incomplete_collection_ids(self): def test_get_activity_progress(self): # Add an entity to each of the sections. + # Add activities to the completed section. learner_progress_services.mark_exploration_as_completed( self.user_id, self.EXP_ID_0) learner_progress_services.mark_collection_as_completed( self.user_id, self.COL_ID_0) + # Add activities to the incomplete section. state_name = 'state name' version = 1 learner_progress_services.mark_exploration_as_incomplete( @@ -528,6 +530,12 @@ def test_get_activity_progress(self): learner_progress_services.mark_collection_as_incomplete( self.user_id, self.COL_ID_1) + # Add activities to the playlist section. + learner_progress_services.add_exp_to_learner_playlist( + self.user_id, self.EXP_ID_3) + learner_progress_services.add_collection_to_learner_playlist( + self.user_id, self.COL_ID_3) + # Get the progress of the user. activity_progress = learner_progress_services.get_activity_progress( self.user_id) @@ -540,11 +548,17 @@ def test_get_activity_progress(self): activity_progress[0].completed_exp_summaries) completed_collection_summaries = ( activity_progress[0].completed_collection_summaries) + exploration_playlist_summaries = ( + activity_progress[0].exploration_playlist_summaries) + collection_playlist_summaries = ( + activity_progress[0].collection_playlist_summaries) self.assertEqual(len(incomplete_exp_summaries), 1) self.assertEqual(len(incomplete_collection_summaries), 1) self.assertEqual(len(completed_exp_summaries), 1) self.assertEqual(len(completed_collection_summaries), 1) + self.assertEqual(len(exploration_playlist_summaries), 1) + self.assertEqual(len(collection_playlist_summaries), 1) self.assertEqual( incomplete_exp_summaries[0].title, 'Sillat Suomi') @@ -554,6 +568,10 @@ def test_get_activity_progress(self): completed_exp_summaries[0].title, 'Bridges in England') self.assertEqual( completed_collection_summaries[0].title, 'Bridges') + self.assertEqual( + exploration_playlist_summaries[0].title, 'Welcome Oppia') + self.assertEqual( + collection_playlist_summaries[0].title, 'Welcome Oppia Collection') # Delete an exploration. exp_services.delete_exploration(self.owner_id, self.EXP_ID_1) From bb5692c83383aef949100e7d5037ae51114cd27f Mon Sep 17 00:00:00 2001 From: Arunabh98 Date: Sun, 30 Jul 2017 18:12:51 +0530 Subject: [PATCH 05/65] Combine handlers. --- assets/constants.js | 4 +- core/controllers/learner_playlist.py | 78 ++------------- core/controllers/learner_playlist_test.py | 116 +++++++++------------- core/controllers/reader.py | 17 ++++ core/controllers/reader_test.py | 53 ++++------ feconf.py | 1 + main.py | 19 +--- 7 files changed, 103 insertions(+), 185 deletions(-) diff --git a/assets/constants.js b/assets/constants.js index cb2679af9333..4fecc155d2fb 100644 --- a/assets/constants.js +++ b/assets/constants.js @@ -19,8 +19,8 @@ var constants = { "Mathematics", "Medicine", "Music", "Philosophy", "Physics", "Poetry", "Probability", "Programming", "Puzzles", "Reading", "Spanish", "Sport", "Statistics", "Trigonometry", "Welcome"], - "ACTIVITY_TYPE_EXPLORATIONS": "explorations", - "ACTIVITY_TYPE_COLLECTIONS": "collections", + "ACTIVITY_TYPE_EXPLORATION": "exploration", + "ACTIVITY_TYPE_COLLECTION": "collection", "DISABLED_EXPLORATION_IDS": ["5"], "TESTING_CONSTANT": "test", "LIBRARY_TILE_WIDTH_PX": 208, diff --git a/core/controllers/learner_playlist.py b/core/controllers/learner_playlist.py index f10d6151d222..d3f1a2aaa219 100644 --- a/core/controllers/learner_playlist.py +++ b/core/controllers/learner_playlist.py @@ -25,82 +25,24 @@ class LearnerPlaylistHandler(base.BaseHandler): """Handles operations related to the learner playlist.""" @acl_decorators.can_access_learner_dashboard - def post(self): + def post(self, activity_type, activity_id): position_to_be_inserted_in = self.payload.get('index') - activity_type = self.payload.get('activity_type') - if activity_type == constants.ACTIVITY_TYPE_EXPLORATIONS: - exploration_id = self.payload.get('exploration_id') + if activity_type == constants.ACTIVITY_TYPE_EXPLORATION: learner_progress_services.add_exp_to_learner_playlist( - self.user_id, exploration_id, position_to_be_inserted_in) - elif activity_type == constants.ACTIVITY_TYPE_COLLECTIONS: - collection_id = self.payload.get('collection_id') + self.user_id, activity_id, position_to_be_inserted_in) + elif activity_type == constants.ACTIVITY_TYPE_COLLECTION: learner_progress_services.add_collection_to_learner_playlist( - self.user_id, collection_id, position_to_be_inserted_in) + self.user_id, activity_id, position_to_be_inserted_in) self.render_json(self.values) @acl_decorators.can_access_learner_dashboard - def delete(self): - activity_type = self.payload.get('activity_type') - if activity_type == constants.ACTIVITY_TYPE_EXPLORATIONS: - exploration_id = self.payload.get('exploration_id') + def delete(self, activity_type, activity_id): + if activity_type == constants.ACTIVITY_TYPE_EXPLORATION: learner_playlist_services.remove_exploration_from_learner_playlist( - self.user_id, exploration_id) - elif activity_type == constants.ACTIVITY_TYPE_COLLECTIONS: - collection_id = self.payload.get('collection_id') + self.user_id, activity_id) + elif activity_type == constants.ACTIVITY_TYPE_COLLECTION: learner_playlist_services.remove_collection_from_learner_playlist( - self.user_id, collection_id) + self.user_id, activity_id) - -class AddExplorationToLearnerPlaylistHandler(base.BaseHandler): - """Handler for adding the id of the exploration received as payload to the - playlist of the user. - """ - - @acl_decorators.can_access_learner_dashboard - def post(self): - exploration_id = self.payload.get('exploration_id') - position_to_be_inserted_in = self.payload.get('index') - learner_progress_services.add_exp_to_learner_playlist( - self.user_id, exploration_id, position_to_be_inserted_in) - self.render_json(self.values) - - -class AddCollectionToLearnerPlaylistHandler(base.BaseHandler): - """Handler for adding the id of the collection received as payload to the - playlist of the user. - """ - - @acl_decorators.can_access_learner_dashboard - def post(self): - collection_id = self.payload.get('collection_id') - position_to_be_inserted_in = self.payload.get('index') - learner_progress_services.add_collection_to_learner_playlist( - self.user_id, collection_id, position_to_be_inserted_in) - self.render_json(self.values) - - -class RemoveExplorationFromPlaylistHandler(base.BaseHandler): - """Handler for removing the id of the exploration received as payload to - the playlist of the user. - """ - - @acl_decorators.can_access_learner_dashboard - def post(self): - exploration_id = self.payload.get('exploration_id') - learner_playlist_services.remove_exploration_from_learner_playlist( - self.user_id, exploration_id) - self.render_json(self.values) - - -class RemoveCollectionFromPlaylistHandler(base.BaseHandler): - """Handler for removing the id of the collection received as payload to - the playlist of the user. - """ - - @acl_decorators.can_access_learner_dashboard - def post(self): - collection_id = self.payload.get('collection_id') - learner_playlist_services.remove_collection_from_learner_playlist( - self.user_id, collection_id) self.render_json(self.values) diff --git a/core/controllers/learner_playlist_test.py b/core/controllers/learner_playlist_test.py index dde82e99a63a..a6f74963a475 100644 --- a/core/controllers/learner_playlist_test.py +++ b/core/controllers/learner_playlist_test.py @@ -20,6 +20,9 @@ from core.tests import test_utils import feconf +EXPLORATION_TYPE = constants.ACTIVITY_TYPE_EXPLORATION +COLLECTION_TYPE = constants.ACTIVITY_TYPE_COLLECTION + class LearnerPlaylistHandlerTests(test_utils.GenericTestBase): OWNER_EMAIL = 'owner@example.com' @@ -31,7 +34,6 @@ class LearnerPlaylistHandlerTests(test_utils.GenericTestBase): EXP_TITLE_2 = 'exp title 2' EXP_ID_3 = 'exp_id_3' EXP_TITLE_3 = 'exp title 3' - COL_ID_1 = 'col_id_1' COL_TITLE_1 = 'col title 1' COL_ID_2 = 'col_id_2' @@ -68,21 +70,19 @@ def test_add_exploration_to_learner_playlist(self): csrf_token = self.get_csrf_token_from_response(response) # Add one exploration to the playlist. - payload = { - 'exploration_id': self.EXP_ID_1, - 'activity_type': constants.ACTIVITY_TYPE_EXPLORATIONS - } - self.post_json(feconf.LEARNER_PLAYLIST_DATA_URL, payload, csrf_token) + self.post_json( + '%s/%s/%s' % ( + feconf.LEARNER_PLAYLIST_DATA_URL, EXPLORATION_TYPE, + self.EXP_ID_1), {}, csrf_token) self.assertEqual( learner_playlist_services.get_all_exp_ids_in_learner_playlist( self.viewer_id), [self.EXP_ID_1]) # Add another exploration. - payload = { - 'exploration_id': self.EXP_ID_2, - 'activity_type': constants.ACTIVITY_TYPE_EXPLORATIONS - } - self.post_json(feconf.LEARNER_PLAYLIST_DATA_URL, payload, csrf_token) + self.post_json( + '%s/%s/%s' % ( + feconf.LEARNER_PLAYLIST_DATA_URL, EXPLORATION_TYPE, + self.EXP_ID_2), {}, csrf_token) self.assertEqual( learner_playlist_services.get_all_exp_ids_in_learner_playlist( self.viewer_id), [self.EXP_ID_1, self.EXP_ID_2]) @@ -90,11 +90,12 @@ def test_add_exploration_to_learner_playlist(self): # User rearranges the explorations. 'exp title 2' is shifted to the # first position. payload = { - 'exploration_id': self.EXP_ID_2, - 'activity_type': constants.ACTIVITY_TYPE_EXPLORATIONS, 'index': 0 } - self.post_json(feconf.LEARNER_PLAYLIST_DATA_URL, payload, csrf_token) + self.post_json( + '%s/%s/%s' % ( + feconf.LEARNER_PLAYLIST_DATA_URL, EXPLORATION_TYPE, + self.EXP_ID_2), payload, csrf_token) self.assertEqual( learner_playlist_services.get_all_exp_ids_in_learner_playlist( self.viewer_id), [self.EXP_ID_2, self.EXP_ID_1]) @@ -103,11 +104,10 @@ def test_add_exploration_to_learner_playlist(self): # should not be added. Here we test for the completed case. learner_progress_services.mark_exploration_as_completed( self.viewer_id, self.EXP_ID_3) - payload = { - 'exploration_id': self.EXP_ID_3, - 'activity_type': constants.ACTIVITY_TYPE_EXPLORATIONS - } - self.post_json(feconf.LEARNER_PLAYLIST_DATA_URL, payload, csrf_token) + self.post_json( + '%s/%s/%s' % ( + feconf.LEARNER_PLAYLIST_DATA_URL, EXPLORATION_TYPE, + self.EXP_ID_3), {}, csrf_token) self.assertEqual( learner_playlist_services.get_all_exp_ids_in_learner_playlist( self.viewer_id), [self.EXP_ID_2, self.EXP_ID_1]) @@ -120,21 +120,18 @@ def test_add_collection_to_learner_playlist(self): csrf_token = self.get_csrf_token_from_response(response) # Add one collection to the playlist. - payload = { - 'collection_id': self.COL_ID_1, - 'activity_type': constants.ACTIVITY_TYPE_COLLECTIONS - } - self.post_json(feconf.LEARNER_PLAYLIST_DATA_URL, payload, csrf_token) + self.post_json( + '%s/%s/%s' % ( + feconf.LEARNER_PLAYLIST_DATA_URL, COLLECTION_TYPE, + self.COL_ID_1), {}, csrf_token) self.assertEqual( learner_playlist_services.get_all_collection_ids_in_learner_playlist( # pylint: disable=line-too-long self.viewer_id), [self.COL_ID_1]) # Add another exploration. - payload = { - 'collection_id': self.COL_ID_2, - 'activity_type': constants.ACTIVITY_TYPE_COLLECTIONS - } - self.post_json(feconf.LEARNER_PLAYLIST_DATA_URL, payload, csrf_token) + self.post_json('%s/%s/%s' % ( + feconf.LEARNER_PLAYLIST_DATA_URL, COLLECTION_TYPE, + self.COL_ID_2), {}, csrf_token) self.assertEqual( learner_playlist_services.get_all_collection_ids_in_learner_playlist( # pylint: disable=line-too-long self.viewer_id), [self.COL_ID_1, self.COL_ID_2]) @@ -142,11 +139,12 @@ def test_add_collection_to_learner_playlist(self): # User rearranges the explorations. 'exp title 2' is shifted to the # first position. payload = { - 'collection_id': self.COL_ID_2, - 'activity_type': constants.ACTIVITY_TYPE_COLLECTIONS, 'index': 0 } - self.post_json(feconf.LEARNER_PLAYLIST_DATA_URL, payload, csrf_token) + self.post_json( + '%s/%s/%s' % ( + feconf.LEARNER_PLAYLIST_DATA_URL, COLLECTION_TYPE, + self.COL_ID_2), payload, csrf_token) self.assertEqual( learner_playlist_services.get_all_collection_ids_in_learner_playlist( # pylint: disable=line-too-long self.viewer_id), [self.COL_ID_2, self.COL_ID_1]) @@ -155,11 +153,9 @@ def test_add_collection_to_learner_playlist(self): # should not be added. Here we test for the completed case. learner_progress_services.mark_collection_as_completed( self.viewer_id, self.COL_ID_3) - payload = { - 'collection_id': self.COL_ID_3, - 'activity_type': constants.ACTIVITY_TYPE_COLLECTIONS - } - self.post_json(feconf.LEARNER_PLAYLIST_DATA_URL, payload, csrf_token) + self.post_json('%s/%s/%s' % ( + feconf.LEARNER_PLAYLIST_DATA_URL, COLLECTION_TYPE, + self.COL_ID_3), {}, csrf_token) self.assertEqual( learner_playlist_services.get_all_collection_ids_in_learner_playlist( # pylint: disable=line-too-long self.viewer_id), [self.COL_ID_2, self.COL_ID_1]) @@ -168,8 +164,6 @@ def test_add_collection_to_learner_playlist(self): def test_remove_exploration_from_learner_playlist(self): self.login(self.VIEWER_EMAIL) - response = self.testapp.get(feconf.LEARNER_DASHBOARD_URL) - csrf_token = self.get_csrf_token_from_response(response) # Add explorations to the learner playlist. learner_progress_services.add_exp_to_learner_playlist( @@ -181,27 +175,26 @@ def test_remove_exploration_from_learner_playlist(self): self.viewer_id), [self.EXP_ID_1, self.EXP_ID_2]) # Remove an exploration. - payload = { - 'exploration_id': self.EXP_ID_1, - 'activity_type': constants.ACTIVITY_TYPE_EXPLORATIONS - } - self.delete_json(feconf.LEARNER_PLAYLIST_DATA_URL, payload, csrf_token) + self.testapp.delete(str( + '%s/%s/%s' % ( + feconf.LEARNER_PLAYLIST_DATA_URL, EXPLORATION_TYPE, + self.EXP_ID_1))) self.assertEqual( learner_playlist_services.get_all_exp_ids_in_learner_playlist( self.viewer_id), [self.EXP_ID_2]) # Removing the same exploration again has no effect. - self.delete_json(feconf.LEARNER_PLAYLIST_DATA_URL, payload, csrf_token) + self.testapp.delete(str('%s/%s/%s' % ( + feconf.LEARNER_PLAYLIST_DATA_URL, EXPLORATION_TYPE, + self.EXP_ID_1))) self.assertEqual( learner_playlist_services.get_all_exp_ids_in_learner_playlist( self.viewer_id), [self.EXP_ID_2]) # Remove the second exploration. - payload = { - 'exploration_id': self.EXP_ID_2, - 'activity_type': constants.ACTIVITY_TYPE_EXPLORATIONS - } - self.delete_json(feconf.LEARNER_PLAYLIST_DATA_URL, payload, csrf_token) + self.testapp.delete(str('%s/%s/%s' % ( + feconf.LEARNER_PLAYLIST_DATA_URL, EXPLORATION_TYPE, + self.EXP_ID_2))) self.assertEqual( learner_playlist_services.get_all_exp_ids_in_learner_playlist( self.viewer_id), []) @@ -210,8 +203,6 @@ def test_remove_exploration_from_learner_playlist(self): def test_remove_collection_from_learner_playlist(self): self.login(self.VIEWER_EMAIL) - response = self.testapp.get(feconf.LEARNER_DASHBOARD_URL) - csrf_token = self.get_csrf_token_from_response(response) # Add collections to the learner playlist. learner_progress_services.add_collection_to_learner_playlist( @@ -223,31 +214,22 @@ def test_remove_collection_from_learner_playlist(self): self.viewer_id), [self.COL_ID_1, self.COL_ID_2]) # Remove a collection. - payload = { - 'collection_id': self.COL_ID_1 - } - self.post_json( - '%s/remove_collection_from_learner_playlist' % - feconf.LEARNER_PLAYLIST_DATA_URL, payload, csrf_token) + self.testapp.delete(str('%s/%s/%s' % ( + feconf.LEARNER_PLAYLIST_DATA_URL, COLLECTION_TYPE, self.COL_ID_1))) self.assertEqual( learner_playlist_services.get_all_collection_ids_in_learner_playlist( # pylint: disable=line-too-long self.viewer_id), [self.COL_ID_2]) # Removing the same collection again has no effect. - self.post_json( - '%s/remove_collection_from_learner_playlist' % - feconf.LEARNER_PLAYLIST_DATA_URL, payload, csrf_token) + self.testapp.delete(str('%s/%s/%s' % ( + feconf.LEARNER_PLAYLIST_DATA_URL, COLLECTION_TYPE, self.COL_ID_1))) self.assertEqual( learner_playlist_services.get_all_collection_ids_in_learner_playlist( # pylint: disable=line-too-long self.viewer_id), [self.COL_ID_2]) # Remove the second collection. - payload = { - 'collection_id': self.COL_ID_2 - } - self.post_json( - '%s/remove_collection_from_learner_playlist' % - feconf.LEARNER_PLAYLIST_DATA_URL, payload, csrf_token) + self.testapp.delete(str('%s/%s/%s' % ( + feconf.LEARNER_PLAYLIST_DATA_URL, COLLECTION_TYPE, self.COL_ID_2))) self.assertEqual( learner_playlist_services.get_all_collection_ids_in_learner_playlist( # pylint: disable=line-too-long self.viewer_id), []) diff --git a/core/controllers/reader.py b/core/controllers/reader.py index 94f9d12d5ef4..9ec1156c770b 100644 --- a/core/controllers/reader.py +++ b/core/controllers/reader.py @@ -20,6 +20,7 @@ import jinja2 +from constants import constants from core.controllers import base from core.domain import acl_decorators from core.domain import classifier_services @@ -442,6 +443,22 @@ def post(self, exploration_id): self.render_json(self.values) +class LearnerIncompleteActivityHandler(base.BaseHandler): + """Handles operations related to the activities in the incomplete list of + the user. + """ + @acl_decorators.can_access_learner_dashboard + def delete(self, activity_type, activity_id): + if activity_type == constants.ACTIVITY_TYPE_EXPLORATION: + learner_progress_services.remove_exp_from_incomplete_list( + self.user_id, activity_id) + elif activity_type == constants.ACTIVITY_TYPE_COLLECTION: + learner_progress_services.remove_collection_from_incomplete_list( + self.user_id, activity_id) + + self.render_json(self.values) + + class RemoveExpFromIncompleteListHandler(base.BaseHandler): """Handles operations related to removing an exploration from the partially completed list of a user. diff --git a/core/controllers/reader_test.py b/core/controllers/reader_test.py index 600ba4addf27..46216acf7da6 100644 --- a/core/controllers/reader_test.py +++ b/core/controllers/reader_test.py @@ -16,6 +16,7 @@ import os +from constants import constants from core.domain import collection_domain from core.domain import collection_services from core.domain import exp_domain @@ -26,6 +27,9 @@ from core.tests import test_utils import feconf +EXPLORATION_TYPE = constants.ACTIVITY_TYPE_EXPLORATION +COLLECTION_TYPE = constants.ACTIVITY_TYPE_COLLECTION + class ReaderPermissionsTest(test_utils.GenericTestBase): """Test permissions for readers to view explorations.""" @@ -667,10 +671,7 @@ def test_remove_exp_from_incomplete_list_handler(self): """Test handler for removing explorations from the partially completed list. """ - self.login(self.USER_EMAIL) - response = self.testapp.get(feconf.LIBRARY_INDEX_URL) - csrf_token = self.get_csrf_token_from_response(response) state_name = 'state_name' version = 1 @@ -684,26 +685,20 @@ def test_remove_exp_from_incomplete_list_handler(self): learner_progress_services.get_all_incomplete_exp_ids( self.user_id), [self.EXP_ID_0, self.EXP_ID_1]) - payload = { - 'exploration_id': self.EXP_ID_0 - } - # Remove one exploration. - self.post_json( - '%s/remove_in_progress_exploration' % feconf.LEARNER_DASHBOARD_URL, - payload, csrf_token) + self.testapp.delete(str( + '%s/%s/%s' % + (feconf.LEARNER_INCOMPLETE_ACTIVITY_DATA_URL, EXPLORATION_TYPE, + self.EXP_ID_0))) self.assertEqual( learner_progress_services.get_all_incomplete_exp_ids( self.user_id), [self.EXP_ID_1]) - payload = { - 'exploration_id': self.EXP_ID_1 - } - # Remove another exploration. - self.post_json( - '%s/remove_in_progress_exploration' % feconf.LEARNER_DASHBOARD_URL, - payload, csrf_token) + self.testapp.delete(str( + '%s/%s/%s' % + (feconf.LEARNER_INCOMPLETE_ACTIVITY_DATA_URL, EXPLORATION_TYPE, + self.EXP_ID_1))) self.assertEqual( learner_progress_services.get_all_incomplete_exp_ids( self.user_id), []) @@ -712,8 +707,6 @@ def test_remove_collection_from_incomplete_list_handler(self): """Test handler for removing collections from incomplete list.""" self.login(self.USER_EMAIL) - response = self.testapp.get(feconf.LIBRARY_INDEX_URL) - csrf_token = self.get_csrf_token_from_response(response) # Add two collections to incomplete list. learner_progress_services.mark_collection_as_incomplete( @@ -724,26 +717,20 @@ def test_remove_collection_from_incomplete_list_handler(self): learner_progress_services.get_all_incomplete_collection_ids( self.user_id), [self.COL_ID_0, self.COL_ID_1]) - payload = { - 'collection_id': self.COL_ID_0 - } - # Remove one collection. - self.post_json( - '%s/remove_in_progress_collection' % feconf.LEARNER_DASHBOARD_URL, - payload, csrf_token) + self.testapp.delete(str( + '%s/%s/%s' % + (feconf.LEARNER_INCOMPLETE_ACTIVITY_DATA_URL, COLLECTION_TYPE, + self.COL_ID_0))) self.assertEqual( learner_progress_services.get_all_incomplete_collection_ids( self.user_id), [self.COL_ID_1]) - payload = { - 'collection_id': self.COL_ID_1 - } - # Remove another collection. - self.post_json( - '%s/remove_in_progress_collection' % feconf.LEARNER_DASHBOARD_URL, - payload, csrf_token) + self.testapp.delete(str( + '%s/%s/%s' % + (feconf.LEARNER_INCOMPLETE_ACTIVITY_DATA_URL, COLLECTION_TYPE, + self.COL_ID_1))) self.assertEqual( learner_progress_services.get_all_incomplete_collection_ids( self.user_id), []) diff --git a/feconf.py b/feconf.py index 014416b7e79a..57dd6ecf5d3d 100644 --- a/feconf.py +++ b/feconf.py @@ -579,6 +579,7 @@ def get_empty_ratings(): LEARNER_DASHBOARD_DATA_URL = '/learnerdashboardhandler/data' LEARNER_DASHBOARD_FEEDBACK_THREAD_DATA_URL = '/learnerdashboardthreadhandler' LEARNER_PLAYLIST_DATA_URL = '/learnerplaylistactivityhandler' +LEARNER_INCOMPLETE_ACTIVITY_DATA_URL = '/incompleteactivityhandler' LIBRARY_GROUP_DATA_URL = '/librarygrouphandler' LIBRARY_INDEX_URL = '/library' LIBRARY_INDEX_DATA_URL = '/libraryindexhandler' diff --git a/main.py b/main.py index 4c05ae1ad253..5f59547ec34e 100644 --- a/main.py +++ b/main.py @@ -218,25 +218,14 @@ def ui_access_wrapper(self, *args, **kwargs): learner_dashboard.LearnerDashboardFeedbackThreadHandler), get_redirect_route( - r'%s/remove_in_progress_exploration' % feconf.LEARNER_DASHBOARD_URL, - reader.RemoveExpFromIncompleteListHandler), - get_redirect_route( - r'%s/remove_in_progress_collection' % feconf.LEARNER_DASHBOARD_URL, - reader.RemoveCollectionFromIncompleteListHandler), + r'%s//' % + feconf.LEARNER_INCOMPLETE_ACTIVITY_DATA_URL, + reader.LearnerIncompleteActivityHandler), get_redirect_route( - r'%s' % feconf.LEARNER_PLAYLIST_DATA_URL, + r'%s//' % feconf.LEARNER_PLAYLIST_DATA_URL, learner_playlist.LearnerPlaylistHandler), - get_redirect_route( - r'%s/remove_exploration_from_learner_playlist' % - feconf.LEARNER_PLAYLIST_DATA_URL, - learner_playlist.RemoveExplorationFromPlaylistHandler), - get_redirect_route( - r'%s/remove_collection_from_learner_playlist' % - feconf.LEARNER_PLAYLIST_DATA_URL, - learner_playlist.RemoveCollectionFromPlaylistHandler), - get_redirect_route( r'/imagehandler//', resources.ImageHandler), From d0526be07ff532524b4cb6b00a00521e11546921 Mon Sep 17 00:00:00 2001 From: Arunabh98 Date: Sun, 30 Jul 2017 18:38:00 +0530 Subject: [PATCH 06/65] Add tests. --- core/domain/learner_progress_services_test.py | 41 ++++++++++++++++++- 1 file changed, 39 insertions(+), 2 deletions(-) diff --git a/core/domain/learner_progress_services_test.py b/core/domain/learner_progress_services_test.py index c8625b26ceb7..56c764d0509f 100644 --- a/core/domain/learner_progress_services_test.py +++ b/core/domain/learner_progress_services_test.py @@ -573,8 +573,12 @@ def test_get_activity_progress(self): self.assertEqual( collection_playlist_summaries[0].title, 'Welcome Oppia Collection') - # Delete an exploration. + # Delete an exploration in the completed section. + exp_services.delete_exploration(self.owner_id, self.EXP_ID_0) + # Delete an exploration in the incomplete section. exp_services.delete_exploration(self.owner_id, self.EXP_ID_1) + # Delete an exploration in the playlist section. + exp_services.delete_exploration(self.owner_id, self.EXP_ID_3) # Add an exploration to a collection that has already been completed. collection_services.update_collection( self.owner_id, self.COL_ID_0, [{ @@ -590,8 +594,15 @@ def test_get_activity_progress(self): # section. self.assertEqual( len(activity_progress[0].incomplete_exp_summaries), 0) - # Check that the dashboard records the exploration deleted. + # Check that the dashboard records the exploration deleted in the + # completed section. + self.assertEqual(activity_progress[1]['completed_explorations'], 1) + # Check that the dashboard records the exploration deleted in the + # incomplete section. self.assertEqual(activity_progress[1]['incomplete_explorations'], 1) + # Check that the dashboard records the exploration deleted in the + # playlist section. + self.assertEqual(activity_progress[1]['exploration_playlist'], 1) incomplete_collection_summaries = ( activity_progress[0].incomplete_collection_summaries) @@ -602,3 +613,29 @@ def test_get_activity_progress(self): self.assertEqual(incomplete_collection_summaries[1].title, 'Bridges') # Check that the dashboard has recorded the change in the collection. self.assertEqual(activity_progress[2], ['Bridges']) + + # Now suppose the user has completed the collection. It should be added + # back to the completed section. + learner_progress_services.mark_collection_as_completed( + self.user_id, self.COL_ID_0) + + # Delete a collection in the completed section. + collection_services.delete_collection(self.owner_id, self.COL_ID_0) + # Delete a collection in the incomplete section. + collection_services.delete_collection(self.owner_id, self.COL_ID_1) + # Delete a collection in the playlist section. + collection_services.delete_collection(self.owner_id, self.COL_ID_3) + + # Get the progress of the user. + activity_progress = learner_progress_services.get_activity_progress( + self.user_id) + + # Check that the dashboard records the collection deleted in the + # completed section. + self.assertEqual(activity_progress[1]['completed_collections'], 1) + # Check that the dashboard records the collection deleted in the + # incomplete section. + self.assertEqual(activity_progress[1]['incomplete_collections'], 1) + # Check that the dashboard records the collection deleted in the + # playlist section. + self.assertEqual(activity_progress[1]['collection_playlist'], 1) From 747d7eca6b4258d28d071d5c99d760909d1ffb3b Mon Sep 17 00:00:00 2001 From: Arunabh98 Date: Sun, 30 Jul 2017 18:43:54 +0530 Subject: [PATCH 07/65] Remove the old handlers. --- core/controllers/reader.py | 28 ---------------------------- 1 file changed, 28 deletions(-) diff --git a/core/controllers/reader.py b/core/controllers/reader.py index 9ec1156c770b..f5706e051f72 100644 --- a/core/controllers/reader.py +++ b/core/controllers/reader.py @@ -459,34 +459,6 @@ def delete(self, activity_type, activity_id): self.render_json(self.values) -class RemoveExpFromIncompleteListHandler(base.BaseHandler): - """Handles operations related to removing an exploration from the partially - completed list of a user. - """ - - @acl_decorators.can_access_learner_dashboard - def post(self): - """Handles POST requests.""" - exploration_id = self.payload.get('exploration_id') - learner_progress_services.remove_exp_from_incomplete_list( - self.user_id, exploration_id) - self.render_json(self.values) - - -class RemoveCollectionFromIncompleteListHandler(base.BaseHandler): - """Handles operations related to removing a collection from the partially - completed list of a user. - """ - - @acl_decorators.can_access_learner_dashboard - def post(self): - """Handles POST requests.""" - collection_id = self.payload.get('collection_id') - learner_progress_services.remove_collection_from_incomplete_list( - self.user_id, collection_id) - self.render_json(self.values) - - class RatingHandler(base.BaseHandler): """Records the rating of an exploration submitted by a user. From 24b58a6d041f0c8212333fb95619d51c4e739327 Mon Sep 17 00:00:00 2001 From: Arunabh98 Date: Sun, 30 Jul 2017 18:48:38 +0530 Subject: [PATCH 08/65] Fix function name. --- core/domain/learner_progress_services.py | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/core/domain/learner_progress_services.py b/core/domain/learner_progress_services.py index 254d1de49b16..861251e366b6 100644 --- a/core/domain/learner_progress_services.py +++ b/core/domain/learner_progress_services.py @@ -544,7 +544,7 @@ def get_all_completed_exp_ids(user_id): return [] -def get_filtered_completed_exp_summaries(exploration_summaries, +def _get_filtered_completed_exp_summaries(exploration_summaries, exploration_ids): """Returns a list of summaries of the completed exploration ids and the ids of explorations that are no longer present. @@ -596,7 +596,7 @@ def get_all_completed_collection_ids(user_id): return [] -def get_filtered_completed_collection_summaries(user_id, collection_summaries, +def _get_filtered_completed_collection_summaries(user_id, collection_summaries, collection_ids): """Returns a list of summaries of the completed collection ids, the ids of collections that are no longer present and the summaries of the @@ -676,7 +676,7 @@ def get_all_incomplete_exp_ids(user_id): return [] -def get_filtered_incomplete_exp_summaries(exploration_summaries, +def _get_filtered_incomplete_exp_summaries(exploration_summaries, exploration_ids): """Returns a list of summaries of the incomplete exploration ids and the ids of explorations that are no longer present. @@ -727,7 +727,7 @@ def get_all_incomplete_collection_ids(user_id): return [] -def get_filtered_incomplete_collection_summaries(collection_summaries, +def _get_filtered_incomplete_collection_summaries(collection_summaries, collection_ids): """Returns a list of summaries of the incomplete collection ids and the ids of collections that are no longer present. @@ -756,7 +756,7 @@ def get_filtered_incomplete_collection_summaries(collection_summaries, nonexistent_incomplete_collection_ids) -def get_filtered_exp_playlist_summaries(exploration_summaries, +def _get_filtered_exp_playlist_summaries(exploration_summaries, exploration_ids): """Returns a list of summaries of the explorations in the learner playlist and the ids of explorations that are no longer present. @@ -784,7 +784,7 @@ def get_filtered_exp_playlist_summaries(exploration_summaries, return filtered_exp_playlist_summaries, nonexistent_playlist_exp_ids -def get_filtered_collection_playlist_summaries(collection_summaries, +def _get_filtered_collection_playlist_summaries(collection_summaries, collection_ids): """Returns a list of summaries of the collections in the learner playlist and the ids of collections that are no longer present. @@ -951,17 +951,17 @@ def get_activity_progress(user_id): if model else None for model in collection_playlist_models]) filtered_incomplete_exp_summaries, nonexistent_incomplete_exp_ids = ( - get_filtered_incomplete_exp_summaries( + _get_filtered_incomplete_exp_summaries( incomplete_exp_summaries, incomplete_exploration_ids)) filtered_completed_exp_summaries, nonexistent_completed_exp_ids = ( - get_filtered_completed_exp_summaries( + _get_filtered_completed_exp_summaries( completed_exp_summaries, completed_exploration_ids)) (filtered_completed_collection_summaries, nonexistent_completed_collection_ids, completed_to_incomplete_collection_summaries) = ( - get_filtered_completed_collection_summaries( + _get_filtered_completed_collection_summaries( user_id, completed_collection_summaries, completed_collection_ids)) completed_to_incomplete_collection_titles = [] @@ -973,16 +973,16 @@ def get_activity_progress(user_id): (filtered_incomplete_collection_summaries, nonexistent_incomplete_collection_ids) = ( - get_filtered_incomplete_collection_summaries( + _get_filtered_incomplete_collection_summaries( incomplete_collection_summaries, incomplete_collection_ids)) filtered_exp_playlist_summaries, nonexistent_playlist_exp_ids = ( - get_filtered_exp_playlist_summaries( + _get_filtered_exp_playlist_summaries( exploration_playlist_summaries, exploration_playlist_ids)) (filtered_collection_playlist_summaries, nonexistent_playlist_collection_ids) = ( - get_filtered_collection_playlist_summaries( + _get_filtered_collection_playlist_summaries( collection_playlist_summaries, collection_playlist_ids)) number_of_deleted_activities = { From 20534ab978d7a29ee5182b56a6b5f85cff09c5b7 Mon Sep 17 00:00:00 2001 From: Arunabh98 Date: Wed, 2 Aug 2017 15:29:54 +0530 Subject: [PATCH 09/65] Address review comments 2. --- core/controllers/collection_editor.py | 5 +- core/controllers/collection_viewer.py | 5 +- core/controllers/editor.py | 16 +- core/controllers/learner_dashboard.py | 2 +- core/controllers/learner_dashboard_test.py | 2 +- core/controllers/learner_playlist.py | 2 +- core/controllers/learner_playlist_test.py | 2 +- core/controllers/reader.py | 6 +- core/domain/acl_decorators.py | 19 +- core/domain/activity_domain.py | 5 +- core/domain/activity_services.py | 6 +- core/domain/activity_services_test.py | 6 +- core/domain/collection_services.py | 3 +- core/domain/exp_jobs_one_off.py | 3 +- core/domain/exp_services.py | 3 +- core/domain/learner_playlist_services.py | 2 +- core/domain/learner_playlist_services_test.py | 2 +- core/domain/learner_progress_domain.py | 2 +- core/domain/learner_progress_services.py | 24 +- core/domain/learner_progress_services_test.py | 3 +- core/domain/rights_manager.py | 155 ++++----- core/domain/rights_manager_test.py | 325 +++++++++--------- core/domain/summary_services.py | 18 +- core/domain/summary_services_test.py | 18 +- core/storage/activity/gae_models_test.py | 6 +- .../LearnerDashboardBackendApiService.js | 2 +- .../learner_dashboard/LearnerDashboard.js | 3 +- core/tests/protractor/learnerDashboard.js | 2 +- feconf.py | 2 +- 29 files changed, 328 insertions(+), 321 deletions(-) diff --git a/core/controllers/collection_editor.py b/core/controllers/collection_editor.py index dcaad8bc877f..d64e0766be77 100644 --- a/core/controllers/collection_editor.py +++ b/core/controllers/collection_editor.py @@ -16,6 +16,7 @@ """Controllers for the collections editor.""" +from constants import constants from core.controllers import base from core.domain import acl_decorators from core.domain import collection_services @@ -145,7 +146,7 @@ def get(self, collection_id): 'can_edit': True, 'can_unpublish': rights_manager.Actor( self.user_id).can_unpublish( - feconf.ACTIVITY_TYPE_COLLECTION, collection_id), + constants.ACTIVITY_TYPE_COLLECTION, collection_id), 'collection_id': collection.id, 'is_private': rights_manager.is_collection_private(collection_id), 'owner_names': rights_manager.get_collection_owner_names( @@ -186,7 +187,7 @@ def put(self, collection_id): 'can_edit': True, 'can_unpublish': rights_manager.Actor( self.user_id).can_unpublish( - feconf.ACTIVITY_TYPE_COLLECTION, collection_id), + constants.ACTIVITY_TYPE_COLLECTION, collection_id), 'collection_id': collection.id, 'is_private': rights_manager.is_collection_private(collection_id), 'owner_names': rights_manager.get_collection_owner_names( diff --git a/core/controllers/collection_viewer.py b/core/controllers/collection_viewer.py index 413d5ee12e24..52558575fcbe 100644 --- a/core/controllers/collection_viewer.py +++ b/core/controllers/collection_viewer.py @@ -14,6 +14,7 @@ """Controllers for the Oppia collection learner view.""" +from constants import constants from core.controllers import base from core.domain import acl_decorators from core.domain import collection_services @@ -47,7 +48,7 @@ def get(self, collection_id): self.username in whitelisted_usernames and self.username not in config_domain.BANNED_USERNAMES.value and rights_manager.Actor(self.user_id).can_edit( - feconf.ACTIVITY_TYPE_COLLECTION, collection_id) + constants.ACTIVITY_TYPE_COLLECTION, collection_id) ), 'is_logged_in': bool(self.user_id), 'collection_id': collection_id, @@ -80,7 +81,7 @@ def get(self, collection_id): self.values.update({ 'can_edit': ( self.user_id and rights_manager.Actor(self.user_id).can_edit( - feconf.ACTIVITY_TYPE_COLLECTION, collection_id)), + constants.ACTIVITY_TYPE_COLLECTION, collection_id)), 'collection': collection_dict, 'is_logged_in': bool(self.user_id), 'session_id': utils.generate_new_session_id(), diff --git a/core/controllers/editor.py b/core/controllers/editor.py index 3aed4da65e9b..899479375c7d 100644 --- a/core/controllers/editor.py +++ b/core/controllers/editor.py @@ -126,7 +126,7 @@ def get(self, exploration_id): bool(self.user_id) and self.username not in config_domain.BANNED_USERNAMES.value and rights_manager.Actor(self.user_id).can_edit( - feconf.ACTIVITY_TYPE_EXPLORATION, exploration_id)) + constants.ACTIVITY_TYPE_EXPLORATION, exploration_id)) visualizations_html = visualization_registry.Registry.get_full_html() @@ -159,26 +159,26 @@ def get(self, exploration_id): 'additional_angular_modules': additional_angular_modules, 'can_delete': rights_manager.Actor( self.user_id).can_delete( - feconf.ACTIVITY_TYPE_EXPLORATION, exploration_id), + constants.ACTIVITY_TYPE_EXPLORATION, exploration_id), 'can_edit': can_edit, 'can_modify_roles': rights_manager.Actor( self.user_id).can_modify_roles( - feconf.ACTIVITY_TYPE_EXPLORATION, exploration_id), + constants.ACTIVITY_TYPE_EXPLORATION, exploration_id), 'can_publicize': rights_manager.Actor( self.user_id).can_publicize( - feconf.ACTIVITY_TYPE_EXPLORATION, exploration_id), + constants.ACTIVITY_TYPE_EXPLORATION, exploration_id), 'can_publish': rights_manager.Actor( self.user_id).can_publish( - feconf.ACTIVITY_TYPE_EXPLORATION, exploration_id), + constants.ACTIVITY_TYPE_EXPLORATION, exploration_id), 'can_release_ownership': rights_manager.Actor( self.user_id).can_release_ownership( - feconf.ACTIVITY_TYPE_EXPLORATION, exploration_id), + constants.ACTIVITY_TYPE_EXPLORATION, exploration_id), 'can_unpublicize': rights_manager.Actor( self.user_id).can_unpublicize( - feconf.ACTIVITY_TYPE_EXPLORATION, exploration_id), + constants.ACTIVITY_TYPE_EXPLORATION, exploration_id), 'can_unpublish': rights_manager.Actor( self.user_id).can_unpublish( - feconf.ACTIVITY_TYPE_EXPLORATION, exploration_id), + constants.ACTIVITY_TYPE_EXPLORATION, exploration_id), 'dependencies_html': jinja2.utils.Markup(dependencies_html), 'gadget_templates': jinja2.utils.Markup(gadget_templates), 'interaction_templates': jinja2.utils.Markup( diff --git a/core/controllers/learner_dashboard.py b/core/controllers/learner_dashboard.py index 09810020a4a6..b4f97b631faa 100644 --- a/core/controllers/learner_dashboard.py +++ b/core/controllers/learner_dashboard.py @@ -1,4 +1,4 @@ -# Copyright 2014 The Oppia Authors. All Rights Reserved. +# Copyright 2017 The Oppia Authors. All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/core/controllers/learner_dashboard_test.py b/core/controllers/learner_dashboard_test.py index c28dbf1e5eee..825abc5e2fda 100644 --- a/core/controllers/learner_dashboard_test.py +++ b/core/controllers/learner_dashboard_test.py @@ -1,4 +1,4 @@ -# Copyright 2014 The Oppia Authors. All Rights Reserved. +# Copyright 2017 The Oppia Authors. All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/core/controllers/learner_playlist.py b/core/controllers/learner_playlist.py index d3f1a2aaa219..69e84b3a55d6 100644 --- a/core/controllers/learner_playlist.py +++ b/core/controllers/learner_playlist.py @@ -1,4 +1,4 @@ -# Copyright 2014 The Oppia Authors. All Rights Reserved. +# Copyright 2017 The Oppia Authors. All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/core/controllers/learner_playlist_test.py b/core/controllers/learner_playlist_test.py index a6f74963a475..a19b879c5e47 100644 --- a/core/controllers/learner_playlist_test.py +++ b/core/controllers/learner_playlist_test.py @@ -1,4 +1,4 @@ -# Copyright 2014 The Oppia Authors. All Rights Reserved. +# Copyright 2017 The Oppia Authors. All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/core/controllers/reader.py b/core/controllers/reader.py index f5706e051f72..424211cbb435 100644 --- a/core/controllers/reader.py +++ b/core/controllers/reader.py @@ -133,7 +133,7 @@ def get(self, exploration_id): bool(self.username) and self.username not in config_domain.BANNED_USERNAMES.value and rights_manager.Actor(self.user_id).can_edit( - feconf.ACTIVITY_TYPE_EXPLORATION, exploration_id)) + constants.ACTIVITY_TYPE_EXPLORATION, exploration_id)) # This check is needed in order to show the correct page when a 404 # error is raised. The self.request.get('iframed') part of the check is @@ -179,7 +179,7 @@ def get(self, exploration_id): bool(self.username) and self.username not in config_domain.BANNED_USERNAMES.value and rights_manager.Actor(self.user_id).can_edit( - feconf.ACTIVITY_TYPE_EXPLORATION, exploration_id)) + constants.ACTIVITY_TYPE_EXPLORATION, exploration_id)) try: # If the exploration does not exist, a 404 error is raised. @@ -215,7 +215,7 @@ def get(self, exploration_id): 'can_edit': ( self.user_id and rights_manager.Actor(self.user_id).can_edit( - feconf.ACTIVITY_TYPE_EXPLORATION, exploration_id)), + constants.ACTIVITY_TYPE_EXPLORATION, exploration_id)), 'exploration': exploration.to_player_dict(), 'exploration_id': exploration_id, 'is_logged_in': bool(self.user_id), diff --git a/core/domain/acl_decorators.py b/core/domain/acl_decorators.py index 03fb2c2f787a..43a34e917329 100644 --- a/core/domain/acl_decorators.py +++ b/core/domain/acl_decorators.py @@ -16,6 +16,7 @@ """Decorators to provide authorization across the site.""" +from constants import constants from core.controllers import base from core.domain import rights_manager from core.domain import role_services @@ -40,23 +41,23 @@ def check_activity_accessible( Returns: bool. Whether the given activity can be accessed. """ - if activity_type == feconf.ACTIVITY_TYPE_EXPLORATION: + if activity_type == constants.ACTIVITY_TYPE_EXPLORATION: if activity_id in feconf.DISABLED_EXPLORATION_IDS: return False activity_rights = ( rights_manager.get_exploration_rights(activity_id, strict=False) - if activity_type == feconf.ACTIVITY_TYPE_EXPLORATION + if activity_type == constants.ACTIVITY_TYPE_EXPLORATION else rights_manager.get_collection_rights(activity_id, strict=False)) action_play_public = ( role_services.ACTION_PLAY_ANY_PUBLIC_EXPLORATION - if activity_type == feconf.ACTIVITY_TYPE_EXPLORATION + if activity_type == constants.ACTIVITY_TYPE_EXPLORATION else role_services.ACTION_PLAY_ANY_PUBLIC_COLLECTION) action_play_private = ( role_services.ACTION_PLAY_ANY_PRIVATE_EXPLORATION - if activity_type == feconf.ACTIVITY_TYPE_EXPLORATION + if activity_type == constants.ACTIVITY_TYPE_EXPLORATION else role_services.ACTION_PLAY_ANY_PRIVATE_COLLECTION) if activity_rights is None: @@ -124,7 +125,7 @@ def can_play_exploration(handler): def test_can_play(self, exploration_id, **kwargs): if check_activity_accessible( - self.user_id, self.actions, feconf.ACTIVITY_TYPE_EXPLORATION, + self.user_id, self.actions, constants.ACTIVITY_TYPE_EXPLORATION, exploration_id): return handler(self, exploration_id, **kwargs) else: @@ -139,7 +140,7 @@ def can_play_collection(handler): def test_can_play(self, collection_id, **kwargs): if check_activity_accessible( - self.user_id, self.actions, feconf.ACTIVITY_TYPE_COLLECTION, + self.user_id, self.actions, constants.ACTIVITY_TYPE_COLLECTION, collection_id): return handler(self, collection_id, **kwargs) else: @@ -156,7 +157,7 @@ def can_download_exploration(handler): def test_can_download(self, exploration_id, **kwargs): if check_activity_accessible( - self.user_id, self.actions, feconf.ACTIVITY_TYPE_EXPLORATION, + self.user_id, self.actions, constants.ACTIVITY_TYPE_EXPLORATION, exploration_id): return handler(self, exploration_id, **kwargs) else: @@ -173,7 +174,7 @@ def can_view_exploration_stats(handler): def test_can_view_stats(self, exploration_id, **kwargs): if check_activity_accessible( - self.user_id, self.actions, feconf.ACTIVITY_TYPE_EXPLORATION, + self.user_id, self.actions, constants.ACTIVITY_TYPE_EXPLORATION, exploration_id): return handler(self, exploration_id, **kwargs) else: @@ -383,7 +384,7 @@ def test_can_access(self, exploration_id, **kwargs): if check_activity_accessible( self.user_id, self.actions, - feconf.ACTIVITY_TYPE_EXPLORATION, exploration_id): + constants.ACTIVITY_TYPE_EXPLORATION, exploration_id): return handler(self, exploration_id, **kwargs) else: raise self.UnauthorizedUserException( diff --git a/core/domain/activity_domain.py b/core/domain/activity_domain.py index d05689eb0916..eab09d4937ca 100644 --- a/core/domain/activity_domain.py +++ b/core/domain/activity_domain.py @@ -16,7 +16,7 @@ """Domain object for a reference to an activity.""" -import feconf +from constants import constants class ActivityReference(object): @@ -52,7 +52,8 @@ def validate(self): Raises: Exception: The activity type is invalid. """ - if self.type not in feconf.ALL_ACTIVITY_TYPES: + if (self.type != constants.ACTIVITY_TYPE_EXPLORATION and + self.type != constants.ACTIVITY_TYPE_COLLECTION): raise Exception('Invalid activity type: %s' % self.type) def to_dict(self): diff --git a/core/domain/activity_services.py b/core/domain/activity_services.py index 385c3a3c5a47..9932de81f53a 100644 --- a/core/domain/activity_services.py +++ b/core/domain/activity_services.py @@ -18,9 +18,9 @@ import logging +from constants import constants from core.domain import activity_domain from core.platform import models -import feconf (activity_models,) = models.Registry.import_models([models.NAMES.activity]) @@ -114,9 +114,9 @@ def split_by_type(activity_references): """ exploration_ids, collection_ids = [], [] for activity_reference in activity_references: - if activity_reference.type == feconf.ACTIVITY_TYPE_EXPLORATION: + if activity_reference.type == constants.ACTIVITY_TYPE_EXPLORATION: exploration_ids.append(activity_reference.id) - elif activity_reference.type == feconf.ACTIVITY_TYPE_COLLECTION: + elif activity_reference.type == constants.ACTIVITY_TYPE_COLLECTION: collection_ids.append(activity_reference.id) else: raise Exception( diff --git a/core/domain/activity_services_test.py b/core/domain/activity_services_test.py index e3576c16b3f7..73b8d08af3d0 100644 --- a/core/domain/activity_services_test.py +++ b/core/domain/activity_services_test.py @@ -14,13 +14,13 @@ # See the License for the specific language governing permissions and # limitations under the License. +from constants import constants from core.domain import activity_domain from core.domain import activity_services from core.domain import collection_services from core.domain import exp_services from core.domain import rights_manager from core.tests import test_utils -import feconf class ActivityServicesTests(test_utils.GenericTestBase): @@ -32,11 +32,11 @@ class ActivityServicesTests(test_utils.GenericTestBase): def _create_exploration_reference(self, exploration_id): return activity_domain.ActivityReference( - feconf.ACTIVITY_TYPE_EXPLORATION, exploration_id) + constants.ACTIVITY_TYPE_EXPLORATION, exploration_id) def _create_collection_reference(self, collection_id): return activity_domain.ActivityReference( - feconf.ACTIVITY_TYPE_COLLECTION, collection_id) + constants.ACTIVITY_TYPE_COLLECTION, collection_id) def _compare_lists(self, reference_list_1, reference_list_2): hashes_1 = [reference.get_hash() for reference in reference_list_1] diff --git a/core/domain/collection_services.py b/core/domain/collection_services.py index 452e287041a5..f4541885501e 100644 --- a/core/domain/collection_services.py +++ b/core/domain/collection_services.py @@ -28,6 +28,7 @@ import logging import os +from constants import constants from core.domain import activity_services from core.domain import collection_domain from core.domain import exp_services @@ -849,7 +850,7 @@ def delete_collection(committer_id, collection_id, force_deletion=False): # Remove the collection from the featured activity list, if necessary. activity_services.remove_featured_activity( - feconf.ACTIVITY_TYPE_COLLECTION, collection_id) + constants.ACTIVITY_TYPE_COLLECTION, collection_id) def get_collection_snapshots_metadata(collection_id): diff --git a/core/domain/exp_jobs_one_off.py b/core/domain/exp_jobs_one_off.py index f28ff3971a91..f05212567b4e 100644 --- a/core/domain/exp_jobs_one_off.py +++ b/core/domain/exp_jobs_one_off.py @@ -19,6 +19,7 @@ import ast import logging +from constants import constants from core import jobs from core.domain import exp_domain from core.domain import exp_services @@ -139,7 +140,7 @@ def reduce(exp_id, stringified_commit_times_msecs): commit_time_string in stringified_commit_times_msecs] first_published_msec = min(commit_times_msecs) rights_manager.update_activity_first_published_msec( - feconf.ACTIVITY_TYPE_EXPLORATION, exp_id, + constants.ACTIVITY_TYPE_EXPLORATION, exp_id, first_published_msec) diff --git a/core/domain/exp_services.py b/core/domain/exp_services.py index f810b857da17..3b233fc52d77 100644 --- a/core/domain/exp_services.py +++ b/core/domain/exp_services.py @@ -31,6 +31,7 @@ import StringIO import zipfile +from constants import constants from core.domain import activity_services from core.domain import email_subscription_services from core.domain import exp_domain @@ -927,7 +928,7 @@ def delete_exploration(committer_id, exploration_id, force_deletion=False): # Remove the exploration from the featured activity references, if # necessary. activity_services.remove_featured_activity( - feconf.ACTIVITY_TYPE_EXPLORATION, exploration_id) + constants.ACTIVITY_TYPE_EXPLORATION, exploration_id) # Operations on exploration snapshots. diff --git a/core/domain/learner_playlist_services.py b/core/domain/learner_playlist_services.py index 453f01173441..ceb3077f4939 100644 --- a/core/domain/learner_playlist_services.py +++ b/core/domain/learner_playlist_services.py @@ -1,6 +1,6 @@ # coding: utf-8 # -# Copyright 2014 The Oppia Authors. All Rights Reserved. +# Copyright 2017 The Oppia Authors. All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/core/domain/learner_playlist_services_test.py b/core/domain/learner_playlist_services_test.py index 9844cb827f16..d3ee7a392354 100644 --- a/core/domain/learner_playlist_services_test.py +++ b/core/domain/learner_playlist_services_test.py @@ -1,6 +1,6 @@ # coding: utf-8 # -# Copyright 2014 The Oppia Authors. All Rights Reserved. +# Copyright 2017 The Oppia Authors. All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/core/domain/learner_progress_domain.py b/core/domain/learner_progress_domain.py index 1c0addb35db9..bf9bb42e23b8 100644 --- a/core/domain/learner_progress_domain.py +++ b/core/domain/learner_progress_domain.py @@ -1,6 +1,6 @@ # coding: utf-8 # -# Copyright 2014 The Oppia Authors. All Rights Reserved. +# Copyright 2017 The Oppia Authors. All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/core/domain/learner_progress_services.py b/core/domain/learner_progress_services.py index 861251e366b6..f572adfc5e48 100644 --- a/core/domain/learner_progress_services.py +++ b/core/domain/learner_progress_services.py @@ -1,6 +1,6 @@ # coding: utf-8 # -# Copyright 2014 The Oppia Authors. All Rights Reserved. +# Copyright 2017 The Oppia Authors. All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -87,12 +87,12 @@ def _get_last_playthrough_information(last_playthrough_model): def _save_completed_activities(activities_completed): - """Save an activities completed domain object as an - CompletedActivities model in the datastore. + """Save an activities completed domain object as a + CompletedActivitiesModel instance in the datastore. Args: activities_completed: CompletedActivities. The activities - completed object to be saved in the datastore. + completed domain object to be saved in the datastore. """ completed_activities_model = user_models.CompletedActivitiesModel( id=activities_completed.id, @@ -105,7 +105,7 @@ def _save_completed_activities(activities_completed): def _save_incomplete_activities(incomplete_activities): """Save an incomplete activities domain object as an - IncompleteActivities model in the datastore. + IncompleteActivitiesModel instance in the datastore. Args: incomplete_activities: IncompleteActivities. The incomplete @@ -123,7 +123,7 @@ def _save_incomplete_activities(incomplete_activities): def _save_last_playthrough_information(last_playthrough_information): """Save an ExpUserLastPlaythrough domain object as an - ExpUserLastPlaythrough model in the datastore. + ExpUserLastPlaythroughModel instance in the datastore. Args: last_playthrough_information: ExpUserLastPlaythrough. The last @@ -545,7 +545,7 @@ def get_all_completed_exp_ids(user_id): def _get_filtered_completed_exp_summaries(exploration_summaries, - exploration_ids): + exploration_ids): """Returns a list of summaries of the completed exploration ids and the ids of explorations that are no longer present. @@ -597,7 +597,7 @@ def get_all_completed_collection_ids(user_id): def _get_filtered_completed_collection_summaries(user_id, collection_summaries, - collection_ids): + collection_ids): """Returns a list of summaries of the completed collection ids, the ids of collections that are no longer present and the summaries of the collections being shifted to the incomplete section on account of new @@ -677,7 +677,7 @@ def get_all_incomplete_exp_ids(user_id): def _get_filtered_incomplete_exp_summaries(exploration_summaries, - exploration_ids): + exploration_ids): """Returns a list of summaries of the incomplete exploration ids and the ids of explorations that are no longer present. @@ -728,7 +728,7 @@ def get_all_incomplete_collection_ids(user_id): def _get_filtered_incomplete_collection_summaries(collection_summaries, - collection_ids): + collection_ids): """Returns a list of summaries of the incomplete collection ids and the ids of collections that are no longer present. @@ -757,7 +757,7 @@ def _get_filtered_incomplete_collection_summaries(collection_summaries, def _get_filtered_exp_playlist_summaries(exploration_summaries, - exploration_ids): + exploration_ids): """Returns a list of summaries of the explorations in the learner playlist and the ids of explorations that are no longer present. @@ -785,7 +785,7 @@ def _get_filtered_exp_playlist_summaries(exploration_summaries, def _get_filtered_collection_playlist_summaries(collection_summaries, - collection_ids): + collection_ids): """Returns a list of summaries of the collections in the learner playlist and the ids of collections that are no longer present. diff --git a/core/domain/learner_progress_services_test.py b/core/domain/learner_progress_services_test.py index 56c764d0509f..7d2920d6227a 100644 --- a/core/domain/learner_progress_services_test.py +++ b/core/domain/learner_progress_services_test.py @@ -1,6 +1,6 @@ # coding: utf-8 # -# Copyright 2014 The Oppia Authors. All Rights Reserved. +# Copyright 2017 The Oppia Authors. All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -515,7 +515,6 @@ def test_get_all_incomplete_collection_ids(self): self.user_id), [self.COL_ID_0, self.COL_ID_1]) def test_get_activity_progress(self): - # Add an activity to each of the sections. # Add activities to the completed section. learner_progress_services.mark_exploration_as_completed( self.user_id, self.EXP_ID_0) diff --git a/core/domain/rights_manager.py b/core/domain/rights_manager.py index 781727602233..ec75778bdd34 100644 --- a/core/domain/rights_manager.py +++ b/core/domain/rights_manager.py @@ -18,6 +18,7 @@ import logging +from constants import constants from core.domain import activity_services from core.domain import config_domain from core.domain import subscription_services @@ -200,8 +201,8 @@ def _get_activity_rights_from_model(activity_rights_model, activity_type): activity_rights_model: ActivityRightsModel. Activity rights from the datastore. activity_type: str. The type of activity. Possible values: - feconf.ACTIVITY_TYPE_EXPLORATION - feconf.ACTIVITY_TYPE_COLLECTION + constants.ACTIVITY_TYPE_EXPLORATION + constants.ACTIVITY_TYPE_COLLECTION Returns: ActivityRights. The rights object created from the model. @@ -214,7 +215,7 @@ def _get_activity_rights_from_model(activity_rights_model, activity_type): community_owned=activity_rights_model.community_owned, cloned_from=( activity_rights_model.cloned_from - if activity_type == feconf.ACTIVITY_TYPE_EXPLORATION else None), + if activity_type == constants.ACTIVITY_TYPE_EXPLORATION else None), status=activity_rights_model.status, viewable_if_private=activity_rights_model.viewable_if_private, first_published_msec=activity_rights_model.first_published_msec @@ -232,17 +233,17 @@ def _save_activity_rights( activity_rights: ActivityRights. The rights object for the given activity. activity_type: str. The type of activity. Possible values: - feconf.ACTIVITY_TYPE_EXPLORATION - feconf.ACTIVITY_TYPE_COLLECTION + constants.ACTIVITY_TYPE_EXPLORATION + constants.ACTIVITY_TYPE_COLLECTION commit_message: str. Descriptive message for the commit. commit_cmds: list(dict). A list of commands describing what kind of commit was done. """ activity_rights.validate() - if activity_type == feconf.ACTIVITY_TYPE_EXPLORATION: + if activity_type == constants.ACTIVITY_TYPE_EXPLORATION: model_cls = exp_models.ExplorationRightsModel - elif activity_type == feconf.ACTIVITY_TYPE_COLLECTION: + elif activity_type == constants.ACTIVITY_TYPE_COLLECTION: model_cls = collection_models.CollectionRightsModel model = model_cls.get(activity_rights.id, strict=False) @@ -296,14 +297,14 @@ def _update_activity_summary(activity_type, activity_rights): Args: activity_type: str. The type of activity. Possible values: - feconf.ACTIVITY_TYPE_EXPLORATION - feconf.ACTIVITY_TYPE_COLLECTION + constants.ACTIVITY_TYPE_EXPLORATION + constants.ACTIVITY_TYPE_COLLECTION activity_rights: ActivityRights. The rights object for the given activity. """ - if activity_type == feconf.ACTIVITY_TYPE_EXPLORATION: + if activity_type == constants.ACTIVITY_TYPE_EXPLORATION: _update_exploration_summary(activity_rights) - elif activity_type == feconf.ACTIVITY_TYPE_COLLECTION: + elif activity_type == constants.ACTIVITY_TYPE_COLLECTION: _update_collection_summary(activity_rights) @@ -316,8 +317,8 @@ def update_activity_first_published_msec( Args: activity_type: str. The type of activity. Possible values: - feconf.ACTIVITY_TYPE_EXPLORATION - feconf.ACTIVITY_TYPE_COLLECTION + constants.ACTIVITY_TYPE_EXPLORATION + constants.ACTIVITY_TYPE_COLLECTION activity_id: str. ID of the activity. first_published_msec: float. First publication time in milliseconds since the Epoch. @@ -381,7 +382,7 @@ def get_exploration_rights(exploration_id, strict=True): if model is None: return None return _get_activity_rights_from_model( - model, feconf.ACTIVITY_TYPE_EXPLORATION) + model, constants.ACTIVITY_TYPE_EXPLORATION) def is_exploration_private(exploration_id): @@ -467,7 +468,7 @@ def get_collection_rights(collection_id, strict=True): if model is None: return None return _get_activity_rights_from_model( - model, feconf.ACTIVITY_TYPE_COLLECTION) + model, constants.ACTIVITY_TYPE_COLLECTION) def get_collection_owner_names(collection_id): @@ -517,8 +518,8 @@ def _get_activity_rights(activity_type, activity_id): Args: activity_type: str. The type of activity. Possible values: - feconf.ACTIVITY_TYPE_EXPLORATION - feconf.ACTIVITY_TYPE_COLLECTION + constants.ACTIVITY_TYPE_EXPLORATION + constants.ACTIVITY_TYPE_COLLECTION activity_id: str. ID of the activity. Returns: @@ -527,9 +528,9 @@ def _get_activity_rights(activity_type, activity_id): Raises: Exception. activity_type provided is unknown. """ - if activity_type == feconf.ACTIVITY_TYPE_EXPLORATION: + if activity_type == constants.ACTIVITY_TYPE_EXPLORATION: return get_exploration_rights(activity_id, strict=False) - elif activity_type == feconf.ACTIVITY_TYPE_COLLECTION: + elif activity_type == constants.ACTIVITY_TYPE_COLLECTION: return get_collection_rights(activity_id, strict=False) else: raise Exception( @@ -621,8 +622,8 @@ def is_owner(self, activity_type, activity_id): Args: activity_type: str. The type of activity. Possible values: - feconf.ACTIVITY_TYPE_EXPLORATION - feconf.ACTIVITY_TYPE_COLLECTION + constants.ACTIVITY_TYPE_EXPLORATION + constants.ACTIVITY_TYPE_COLLECTION activity_id: str. ID of the activity. Returns: @@ -638,8 +639,8 @@ def has_editing_rights(self, activity_type, activity_id): Args: activity_type: str. The type of activity. Possible values: - feconf.ACTIVITY_TYPE_EXPLORATION - feconf.ACTIVITY_TYPE_COLLECTION + constants.ACTIVITY_TYPE_EXPLORATION + constants.ACTIVITY_TYPE_COLLECTION activity_id: str. ID of the activity. Returns: @@ -656,8 +657,8 @@ def has_viewing_rights(self, activity_type, activity_id): Args: activity_type: str. The type of activity. Possible values: - feconf.ACTIVITY_TYPE_EXPLORATION - feconf.ACTIVITY_TYPE_COLLECTION + constants.ACTIVITY_TYPE_EXPLORATION + constants.ACTIVITY_TYPE_COLLECTION activity_id: str. ID of the activity. Returns: @@ -673,8 +674,8 @@ def can_play(self, activity_type, activity_id): Args: activity_type: str. The type of activity. Possible values: - feconf.ACTIVITY_TYPE_EXPLORATION - feconf.ACTIVITY_TYPE_COLLECTION + constants.ACTIVITY_TYPE_EXPLORATION + constants.ACTIVITY_TYPE_COLLECTION activity_id: str. ID of the activity. Returns: @@ -690,8 +691,8 @@ def can_view(self, activity_type, activity_id): Args: activity_type: str. The type of activity. Possible values: - feconf.ACTIVITY_TYPE_EXPLORATION - feconf.ACTIVITY_TYPE_COLLECTION + constants.ACTIVITY_TYPE_EXPLORATION + constants.ACTIVITY_TYPE_COLLECTION activity_id: str. ID of the activity. Returns: @@ -706,8 +707,8 @@ def can_edit(self, activity_type, activity_id): Args: activity_type: str. The type of activity. Possible values: - feconf.ACTIVITY_TYPE_EXPLORATION - feconf.ACTIVITY_TYPE_COLLECTION + constants.ACTIVITY_TYPE_EXPLORATION + constants.ACTIVITY_TYPE_COLLECTION activity_id: str. ID of the activity. Returns: @@ -723,8 +724,8 @@ def can_delete(self, activity_type, activity_id): Args: activity_type: str. The type of activity. Possible values: - feconf.ACTIVITY_TYPE_EXPLORATION - feconf.ACTIVITY_TYPE_COLLECTION + constants.ACTIVITY_TYPE_EXPLORATION + constants.ACTIVITY_TYPE_COLLECTION activity_id: str. ID of the activity. Returns: @@ -745,8 +746,8 @@ def can_change_private_viewability( Args: activity_type: str. The type of activity. Possible values: - feconf.ACTIVITY_TYPE_EXPLORATION - feconf.ACTIVITY_TYPE_COLLECTION + constants.ACTIVITY_TYPE_EXPLORATION + constants.ACTIVITY_TYPE_COLLECTION activity_id: str. ID of the activity. Returns: @@ -761,8 +762,8 @@ def can_publish(self, activity_type, activity_id): Args: activity_type: str. The type of activity. Possible values: - feconf.ACTIVITY_TYPE_EXPLORATION - feconf.ACTIVITY_TYPE_COLLECTION + constants.ACTIVITY_TYPE_EXPLORATION + constants.ACTIVITY_TYPE_COLLECTION activity_id: str. ID of the activity. Returns: @@ -785,8 +786,8 @@ def can_unpublish(self, activity_type, activity_id): Args: activity_type: str. The type of activity. Possible values: - feconf.ACTIVITY_TYPE_EXPLORATION - feconf.ACTIVITY_TYPE_COLLECTION + constants.ACTIVITY_TYPE_EXPLORATION + constants.ACTIVITY_TYPE_COLLECTION activity_id: str. ID of the activity. Returns: @@ -810,8 +811,8 @@ def can_modify_roles(self, activity_type, activity_id): Args: activity_type: str. The type of activity. Possible values: - feconf.ACTIVITY_TYPE_EXPLORATION - feconf.ACTIVITY_TYPE_COLLECTION + constants.ACTIVITY_TYPE_EXPLORATION + constants.ACTIVITY_TYPE_COLLECTION activity_id: str. ID of the activity. Returns: @@ -832,8 +833,8 @@ def can_release_ownership(self, activity_type, activity_id): Args: activity_type: str. The type of activity. Possible values: - feconf.ACTIVITY_TYPE_EXPLORATION - feconf.ACTIVITY_TYPE_COLLECTION + constants.ACTIVITY_TYPE_EXPLORATION + constants.ACTIVITY_TYPE_COLLECTION activity_id: str. ID of the activity. Returns: @@ -854,8 +855,8 @@ def can_publicize(self, activity_type, activity_id): Args: activity_type: str. The type of activity. Possible values: - feconf.ACTIVITY_TYPE_EXPLORATION - feconf.ACTIVITY_TYPE_COLLECTION + constants.ACTIVITY_TYPE_EXPLORATION + constants.ACTIVITY_TYPE_COLLECTION activity_id: str. ID of the activity. Returns: @@ -875,8 +876,8 @@ def can_unpublicize(self, activity_type, activity_id): Args: activity_type: str. The type of activity. Possible values: - feconf.ACTIVITY_TYPE_EXPLORATION - feconf.ACTIVITY_TYPE_COLLECTION + constants.ACTIVITY_TYPE_EXPLORATION + constants.ACTIVITY_TYPE_COLLECTION activity_id: str. ID of the activity. Returns: @@ -907,8 +908,8 @@ def _assign_role( ROLE_VIEWER activity_id: str. ID of the activity. activity_type: str. The type of activity. Possible values: - feconf.ACTIVITY_TYPE_EXPLORATION - feconf.ACTIVITY_TYPE_COLLECTION + constants.ACTIVITY_TYPE_EXPLORATION + constants.ACTIVITY_TYPE_COLLECTION Raises: Exception. The committer does not have rights to modify a role. @@ -995,8 +996,8 @@ def _release_ownership_of_activity(committer_id, activity_id, activity_type): committer_id: str. ID of the user who is performing the action. activity_id: str. ID of the activity. activity_type: str. The type of activity. Possible values: - feconf.ACTIVITY_TYPE_EXPLORATION - feconf.ACTIVITY_TYPE_COLLECTION + constants.ACTIVITY_TYPE_EXPLORATION + constants.ACTIVITY_TYPE_COLLECTION Raise: Exception. The committer does not have release rights. @@ -1032,17 +1033,17 @@ def _change_activity_status( committer_id: str. ID of the user who is performing the update action. activity_id: str. ID of the activity. activity_type: str. The type of activity. Possible values: - feconf.ACTIVITY_TYPE_EXPLORATION - feconf.ACTIVITY_TYPE_COLLECTION + constants.ACTIVITY_TYPE_EXPLORATION + constants.ACTIVITY_TYPE_COLLECTION new_status: str. The new status of the activity. commit_message: str. The human-written commit message for this change. """ activity_rights = _get_activity_rights(activity_type, activity_id) old_status = activity_rights.status activity_rights.status = new_status - if activity_type == feconf.ACTIVITY_TYPE_EXPLORATION: + if activity_type == constants.ACTIVITY_TYPE_EXPLORATION: cmd_type = CMD_CHANGE_EXPLORATION_STATUS - elif activity_type == feconf.ACTIVITY_TYPE_COLLECTION: + elif activity_type == constants.ACTIVITY_TYPE_COLLECTION: cmd_type = CMD_CHANGE_COLLECTION_STATUS commit_cmds = [{ 'cmd': cmd_type, @@ -1069,8 +1070,8 @@ def _publish_activity(committer_id, activity_id, activity_type): committer_id: str. ID of the committer. activity_id: str. ID of the activity. activity_type: str. The type of activity. Possible values: - feconf.ACTIVITY_TYPE_EXPLORATION - feconf.ACTIVITY_TYPE_COLLECTION + constants.ACTIVITY_TYPE_EXPLORATION + constants.ACTIVITY_TYPE_COLLECTION Raises: Exception. The committer does not have rights to publish the @@ -1094,8 +1095,8 @@ def _unpublish_activity(committer_id, activity_id, activity_type): committer_id: str. ID of the committer. activity_id: str. ID of the activity. activity_type: str. The type of activity. Possible values: - feconf.ACTIVITY_TYPE_EXPLORATION - feconf.ACTIVITY_TYPE_COLLECTION + constants.ACTIVITY_TYPE_EXPLORATION + constants.ACTIVITY_TYPE_COLLECTION Raises: Exception. The committer does not have rights to unpublish the @@ -1121,8 +1122,8 @@ def _publicize_activity(committer_id, activity_id, activity_type): committer_id: str. ID of the committer. activity_id: str. ID of the activity. activity_type: str. The type of activity. Possible values: - feconf.ACTIVITY_TYPE_EXPLORATION - feconf.ACTIVITY_TYPE_COLLECTION + constants.ACTIVITY_TYPE_EXPLORATION + constants.ACTIVITY_TYPE_COLLECTION Raises: Exception. The committer does not have rights to publicize the activity. @@ -1146,8 +1147,8 @@ def _unpublicize_activity(committer_id, activity_id, activity_type): committer_id: str. ID of the committer. activity_id: str. ID of the activity. activity_type: str. The type of activity. Possible values: - feconf.ACTIVITY_TYPE_EXPLORATION - feconf.ACTIVITY_TYPE_COLLECTION + constants.ACTIVITY_TYPE_EXPLORATION + constants.ACTIVITY_TYPE_COLLECTION Raises: Exception. The committer does not have rights to unpublicize the @@ -1187,7 +1188,7 @@ def assign_role_for_exploration( """ _assign_role( committer_id, assignee_id, new_role, exploration_id, - feconf.ACTIVITY_TYPE_EXPLORATION) + constants.ACTIVITY_TYPE_EXPLORATION) if new_role in [ROLE_OWNER, ROLE_EDITOR]: subscription_services.subscribe_to_exploration( assignee_id, exploration_id) @@ -1205,7 +1206,7 @@ def release_ownership_of_exploration(committer_id, exploration_id): _release_ownership_of_activity. """ _release_ownership_of_activity( - committer_id, exploration_id, feconf.ACTIVITY_TYPE_EXPLORATION) + committer_id, exploration_id, constants.ACTIVITY_TYPE_EXPLORATION) def set_private_viewability_of_exploration( @@ -1228,7 +1229,7 @@ def set_private_viewability_of_exploration( Exception. If the viewable_if_private property is already as desired. """ if not Actor(committer_id).can_change_private_viewability( - feconf.ACTIVITY_TYPE_EXPLORATION, exploration_id): + constants.ACTIVITY_TYPE_EXPLORATION, exploration_id): logging.error( 'User %s tried to change private viewability of exploration %s ' 'but was refused permission.' % (committer_id, exploration_id)) @@ -1254,7 +1255,7 @@ def set_private_viewability_of_exploration( 'Made exploration viewable only to invited playtesters.') _save_activity_rights( - committer_id, exploration_rights, feconf.ACTIVITY_TYPE_EXPLORATION, + committer_id, exploration_rights, constants.ACTIVITY_TYPE_EXPLORATION, commit_message, commit_cmds) _update_exploration_summary(exploration_rights) @@ -1274,7 +1275,7 @@ def publish_exploration(committer_id, exploration_id): _publish_activity. """ _publish_activity( - committer_id, exploration_id, feconf.ACTIVITY_TYPE_EXPLORATION) + committer_id, exploration_id, constants.ACTIVITY_TYPE_EXPLORATION) def unpublish_exploration(committer_id, exploration_id): @@ -1289,7 +1290,7 @@ def unpublish_exploration(committer_id, exploration_id): _unpublish_activity. """ _unpublish_activity( - committer_id, exploration_id, feconf.ACTIVITY_TYPE_EXPLORATION) + committer_id, exploration_id, constants.ACTIVITY_TYPE_EXPLORATION) def publicize_exploration(committer_id, exploration_id): @@ -1307,7 +1308,7 @@ def publicize_exploration(committer_id, exploration_id): _publicize_activity. """ _publicize_activity( - committer_id, exploration_id, feconf.ACTIVITY_TYPE_EXPLORATION) + committer_id, exploration_id, constants.ACTIVITY_TYPE_EXPLORATION) def unpublicize_exploration(committer_id, exploration_id): @@ -1322,7 +1323,7 @@ def unpublicize_exploration(committer_id, exploration_id): _unpublicize_activity. """ _unpublicize_activity( - committer_id, exploration_id, feconf.ACTIVITY_TYPE_EXPLORATION) + committer_id, exploration_id, constants.ACTIVITY_TYPE_EXPLORATION) # Rights functions for collections. @@ -1348,7 +1349,7 @@ def assign_role_for_collection( """ _assign_role( committer_id, assignee_id, new_role, collection_id, - feconf.ACTIVITY_TYPE_COLLECTION) + constants.ACTIVITY_TYPE_COLLECTION) if new_role in [ROLE_OWNER, ROLE_EDITOR]: subscription_services.subscribe_to_collection( assignee_id, collection_id) @@ -1366,7 +1367,7 @@ def release_ownership_of_collection(committer_id, collection_id): _release_ownership_of_activity. """ _release_ownership_of_activity( - committer_id, collection_id, feconf.ACTIVITY_TYPE_COLLECTION) + committer_id, collection_id, constants.ACTIVITY_TYPE_COLLECTION) def publish_collection(committer_id, collection_id): @@ -1384,7 +1385,7 @@ def publish_collection(committer_id, collection_id): _publish_activity. """ _publish_activity( - committer_id, collection_id, feconf.ACTIVITY_TYPE_COLLECTION) + committer_id, collection_id, constants.ACTIVITY_TYPE_COLLECTION) def unpublish_collection(committer_id, collection_id): @@ -1400,7 +1401,7 @@ def unpublish_collection(committer_id, collection_id): """ _unpublish_activity( - committer_id, collection_id, feconf.ACTIVITY_TYPE_COLLECTION) + committer_id, collection_id, constants.ACTIVITY_TYPE_COLLECTION) def publicize_collection(committer_id, collection_id): @@ -1418,7 +1419,7 @@ def publicize_collection(committer_id, collection_id): _publicize_activity. """ _publicize_activity( - committer_id, collection_id, feconf.ACTIVITY_TYPE_COLLECTION) + committer_id, collection_id, constants.ACTIVITY_TYPE_COLLECTION) def unpublicize_collection(committer_id, collection_id): @@ -1433,4 +1434,4 @@ def unpublicize_collection(committer_id, collection_id): _unpublicize_activity. """ _unpublicize_activity( - committer_id, collection_id, feconf.ACTIVITY_TYPE_COLLECTION) + committer_id, collection_id, constants.ACTIVITY_TYPE_COLLECTION) diff --git a/core/domain/rights_manager_test.py b/core/domain/rights_manager_test.py index 3e076df3ed26..d9500bb03675 100644 --- a/core/domain/rights_manager_test.py +++ b/core/domain/rights_manager_test.py @@ -14,6 +14,7 @@ """Tests for classes and methods relating to user rights.""" +from constants import constants from core.domain import collection_services from core.domain import exp_domain from core.domain import exp_services @@ -69,42 +70,42 @@ def test_demo_exploration(self): self.assertTrue( rights_manager.Actor(self.user_id_a).can_play( - feconf.ACTIVITY_TYPE_EXPLORATION, '1')) + constants.ACTIVITY_TYPE_EXPLORATION, '1')) self.assertTrue( rights_manager.Actor(self.user_id_a).can_view( - feconf.ACTIVITY_TYPE_EXPLORATION, '1')) + constants.ACTIVITY_TYPE_EXPLORATION, '1')) self.assertTrue( rights_manager.Actor(self.user_id_a).can_edit( - feconf.ACTIVITY_TYPE_EXPLORATION, '1')) + constants.ACTIVITY_TYPE_EXPLORATION, '1')) self.assertFalse( rights_manager.Actor(self.user_id_a).can_delete( - feconf.ACTIVITY_TYPE_EXPLORATION, '1')) + constants.ACTIVITY_TYPE_EXPLORATION, '1')) self.assertTrue( rights_manager.Actor(self.user_id_admin).can_play( - feconf.ACTIVITY_TYPE_EXPLORATION, '1')) + constants.ACTIVITY_TYPE_EXPLORATION, '1')) self.assertTrue( rights_manager.Actor(self.user_id_admin).can_view( - feconf.ACTIVITY_TYPE_EXPLORATION, '1')) + constants.ACTIVITY_TYPE_EXPLORATION, '1')) self.assertTrue( rights_manager.Actor(self.user_id_admin).can_edit( - feconf.ACTIVITY_TYPE_EXPLORATION, '1')) + constants.ACTIVITY_TYPE_EXPLORATION, '1')) self.assertTrue( rights_manager.Actor(self.user_id_admin).can_delete( - feconf.ACTIVITY_TYPE_EXPLORATION, '1')) + constants.ACTIVITY_TYPE_EXPLORATION, '1')) self.assertTrue( rights_manager.Actor(self.user_id_moderator).can_play( - feconf.ACTIVITY_TYPE_EXPLORATION, '1')) + constants.ACTIVITY_TYPE_EXPLORATION, '1')) self.assertTrue( rights_manager.Actor(self.user_id_moderator).can_view( - feconf.ACTIVITY_TYPE_EXPLORATION, '1')) + constants.ACTIVITY_TYPE_EXPLORATION, '1')) self.assertTrue( rights_manager.Actor(self.user_id_moderator).can_edit( - feconf.ACTIVITY_TYPE_EXPLORATION, '1')) + constants.ACTIVITY_TYPE_EXPLORATION, '1')) self.assertTrue( rights_manager.Actor(self.user_id_moderator).can_delete( - feconf.ACTIVITY_TYPE_EXPLORATION, '1')) + constants.ACTIVITY_TYPE_EXPLORATION, '1')) def test_non_splash_page_demo_exploration(self): # Note: there is no difference between permissions for demo @@ -115,42 +116,42 @@ def test_non_splash_page_demo_exploration(self): self.assertTrue( rights_manager.Actor(self.user_id_a).can_play( - feconf.ACTIVITY_TYPE_EXPLORATION, '3')) + constants.ACTIVITY_TYPE_EXPLORATION, '3')) self.assertTrue( rights_manager.Actor(self.user_id_a).can_view( - feconf.ACTIVITY_TYPE_EXPLORATION, '3')) + constants.ACTIVITY_TYPE_EXPLORATION, '3')) self.assertTrue(rights_manager.Actor( self.user_id_a).can_edit( - feconf.ACTIVITY_TYPE_EXPLORATION, '3')) + constants.ACTIVITY_TYPE_EXPLORATION, '3')) self.assertFalse(rights_manager.Actor( self.user_id_a).can_delete( - feconf.ACTIVITY_TYPE_EXPLORATION, '3')) + constants.ACTIVITY_TYPE_EXPLORATION, '3')) self.assertTrue( rights_manager.Actor(self.user_id_admin).can_play( - feconf.ACTIVITY_TYPE_EXPLORATION, '3')) + constants.ACTIVITY_TYPE_EXPLORATION, '3')) self.assertTrue( rights_manager.Actor(self.user_id_admin).can_view( - feconf.ACTIVITY_TYPE_EXPLORATION, '3')) + constants.ACTIVITY_TYPE_EXPLORATION, '3')) self.assertTrue(rights_manager.Actor( self.user_id_admin).can_edit( - feconf.ACTIVITY_TYPE_EXPLORATION, '3')) + constants.ACTIVITY_TYPE_EXPLORATION, '3')) self.assertTrue( rights_manager.Actor(self.user_id_admin).can_delete( - feconf.ACTIVITY_TYPE_EXPLORATION, '3')) + constants.ACTIVITY_TYPE_EXPLORATION, '3')) self.assertTrue( rights_manager.Actor(self.user_id_moderator).can_play( - feconf.ACTIVITY_TYPE_EXPLORATION, '3')) + constants.ACTIVITY_TYPE_EXPLORATION, '3')) self.assertTrue( rights_manager.Actor(self.user_id_moderator).can_view( - feconf.ACTIVITY_TYPE_EXPLORATION, '3')) + constants.ACTIVITY_TYPE_EXPLORATION, '3')) self.assertTrue( rights_manager.Actor(self.user_id_moderator).can_edit( - feconf.ACTIVITY_TYPE_EXPLORATION, '3')) + constants.ACTIVITY_TYPE_EXPLORATION, '3')) self.assertTrue( rights_manager.Actor(self.user_id_moderator).can_delete( - feconf.ACTIVITY_TYPE_EXPLORATION, '3')) + constants.ACTIVITY_TYPE_EXPLORATION, '3')) def test_ownership_of_exploration(self): exp = exp_domain.Exploration.create_default_exploration(self.EXP_ID) @@ -162,14 +163,14 @@ def test_ownership_of_exploration(self): self.assertTrue( rights_manager.Actor(self.user_id_a).is_owner( - feconf.ACTIVITY_TYPE_EXPLORATION, self.EXP_ID)) + constants.ACTIVITY_TYPE_EXPLORATION, self.EXP_ID)) self.assertFalse( rights_manager.Actor(self.user_id_b).is_owner( - feconf.ACTIVITY_TYPE_EXPLORATION, self.EXP_ID)) + constants.ACTIVITY_TYPE_EXPLORATION, self.EXP_ID)) self.assertFalse( rights_manager.Actor(self.user_id_admin).is_owner( - feconf.ACTIVITY_TYPE_EXPLORATION, self.EXP_ID)) + constants.ACTIVITY_TYPE_EXPLORATION, self.EXP_ID)) def test_newly_created_exploration(self): exp = exp_domain.Exploration.create_default_exploration(self.EXP_ID) @@ -177,55 +178,55 @@ def test_newly_created_exploration(self): self.assertTrue( rights_manager.Actor(self.user_id_a).can_play( - feconf.ACTIVITY_TYPE_EXPLORATION, self.EXP_ID)) + constants.ACTIVITY_TYPE_EXPLORATION, self.EXP_ID)) self.assertTrue( rights_manager.Actor(self.user_id_a).can_view( - feconf.ACTIVITY_TYPE_EXPLORATION, self.EXP_ID)) + constants.ACTIVITY_TYPE_EXPLORATION, self.EXP_ID)) self.assertTrue( rights_manager.Actor(self.user_id_a).can_edit( - feconf.ACTIVITY_TYPE_EXPLORATION, self.EXP_ID)) + constants.ACTIVITY_TYPE_EXPLORATION, self.EXP_ID)) self.assertTrue( rights_manager.Actor(self.user_id_a).can_delete( - feconf.ACTIVITY_TYPE_EXPLORATION, self.EXP_ID)) + constants.ACTIVITY_TYPE_EXPLORATION, self.EXP_ID)) self.assertTrue( rights_manager.Actor(self.user_id_admin).can_play( - feconf.ACTIVITY_TYPE_EXPLORATION, self.EXP_ID)) + constants.ACTIVITY_TYPE_EXPLORATION, self.EXP_ID)) self.assertTrue( rights_manager.Actor(self.user_id_admin).can_view( - feconf.ACTIVITY_TYPE_EXPLORATION, self.EXP_ID)) + constants.ACTIVITY_TYPE_EXPLORATION, self.EXP_ID)) self.assertTrue( rights_manager.Actor(self.user_id_admin).can_edit( - feconf.ACTIVITY_TYPE_EXPLORATION, self.EXP_ID)) + constants.ACTIVITY_TYPE_EXPLORATION, self.EXP_ID)) self.assertFalse( rights_manager.Actor(self.user_id_admin).can_delete( - feconf.ACTIVITY_TYPE_EXPLORATION, self.EXP_ID)) + constants.ACTIVITY_TYPE_EXPLORATION, self.EXP_ID)) self.assertTrue( rights_manager.Actor(self.user_id_moderator).can_play( - feconf.ACTIVITY_TYPE_EXPLORATION, self.EXP_ID)) + constants.ACTIVITY_TYPE_EXPLORATION, self.EXP_ID)) self.assertTrue( rights_manager.Actor(self.user_id_moderator).can_view( - feconf.ACTIVITY_TYPE_EXPLORATION, self.EXP_ID)) + constants.ACTIVITY_TYPE_EXPLORATION, self.EXP_ID)) self.assertFalse( rights_manager.Actor(self.user_id_moderator).can_edit( - feconf.ACTIVITY_TYPE_EXPLORATION, self.EXP_ID)) + constants.ACTIVITY_TYPE_EXPLORATION, self.EXP_ID)) self.assertFalse( rights_manager.Actor(self.user_id_moderator).can_delete( - feconf.ACTIVITY_TYPE_EXPLORATION, self.EXP_ID)) + constants.ACTIVITY_TYPE_EXPLORATION, self.EXP_ID)) self.assertFalse( rights_manager.Actor(self.user_id_b).can_play( - feconf.ACTIVITY_TYPE_EXPLORATION, self.EXP_ID)) + constants.ACTIVITY_TYPE_EXPLORATION, self.EXP_ID)) self.assertFalse( rights_manager.Actor(self.user_id_b).can_view( - feconf.ACTIVITY_TYPE_EXPLORATION, self.EXP_ID)) + constants.ACTIVITY_TYPE_EXPLORATION, self.EXP_ID)) self.assertFalse( rights_manager.Actor(self.user_id_b).can_edit( - feconf.ACTIVITY_TYPE_EXPLORATION, self.EXP_ID)) + constants.ACTIVITY_TYPE_EXPLORATION, self.EXP_ID)) self.assertFalse( rights_manager.Actor(self.user_id_b).can_delete( - feconf.ACTIVITY_TYPE_EXPLORATION, self.EXP_ID)) + constants.ACTIVITY_TYPE_EXPLORATION, self.EXP_ID)) def test_inviting_collaborator_to_exploration(self): exp = exp_domain.Exploration.create_default_exploration(self.EXP_ID) @@ -233,16 +234,16 @@ def test_inviting_collaborator_to_exploration(self): self.assertFalse( rights_manager.Actor(self.user_id_b).can_play( - feconf.ACTIVITY_TYPE_EXPLORATION, self.EXP_ID)) + constants.ACTIVITY_TYPE_EXPLORATION, self.EXP_ID)) self.assertFalse( rights_manager.Actor(self.user_id_b).can_view( - feconf.ACTIVITY_TYPE_EXPLORATION, self.EXP_ID)) + constants.ACTIVITY_TYPE_EXPLORATION, self.EXP_ID)) self.assertFalse( rights_manager.Actor(self.user_id_b).can_edit( - feconf.ACTIVITY_TYPE_EXPLORATION, self.EXP_ID)) + constants.ACTIVITY_TYPE_EXPLORATION, self.EXP_ID)) self.assertFalse( rights_manager.Actor(self.user_id_b).can_delete( - feconf.ACTIVITY_TYPE_EXPLORATION, self.EXP_ID)) + constants.ACTIVITY_TYPE_EXPLORATION, self.EXP_ID)) rights_manager.assign_role_for_exploration( self.user_id_a, self.EXP_ID, self.user_id_b, @@ -250,16 +251,16 @@ def test_inviting_collaborator_to_exploration(self): self.assertTrue( rights_manager.Actor(self.user_id_b).can_play( - feconf.ACTIVITY_TYPE_EXPLORATION, self.EXP_ID)) + constants.ACTIVITY_TYPE_EXPLORATION, self.EXP_ID)) self.assertTrue( rights_manager.Actor(self.user_id_b).can_view( - feconf.ACTIVITY_TYPE_EXPLORATION, self.EXP_ID)) + constants.ACTIVITY_TYPE_EXPLORATION, self.EXP_ID)) self.assertTrue( rights_manager.Actor(self.user_id_b).can_edit( - feconf.ACTIVITY_TYPE_EXPLORATION, self.EXP_ID)) + constants.ACTIVITY_TYPE_EXPLORATION, self.EXP_ID)) self.assertFalse( rights_manager.Actor(self.user_id_b).can_delete( - feconf.ACTIVITY_TYPE_EXPLORATION, self.EXP_ID)) + constants.ACTIVITY_TYPE_EXPLORATION, self.EXP_ID)) def test_inviting_playtester_to_exploration(self): exp = exp_domain.Exploration.create_default_exploration(self.EXP_ID) @@ -267,16 +268,16 @@ def test_inviting_playtester_to_exploration(self): self.assertFalse( rights_manager.Actor(self.user_id_b).can_play( - feconf.ACTIVITY_TYPE_EXPLORATION, self.EXP_ID)) + constants.ACTIVITY_TYPE_EXPLORATION, self.EXP_ID)) self.assertFalse( rights_manager.Actor(self.user_id_b).can_view( - feconf.ACTIVITY_TYPE_EXPLORATION, self.EXP_ID)) + constants.ACTIVITY_TYPE_EXPLORATION, self.EXP_ID)) self.assertFalse( rights_manager.Actor(self.user_id_b).can_edit( - feconf.ACTIVITY_TYPE_EXPLORATION, self.EXP_ID)) + constants.ACTIVITY_TYPE_EXPLORATION, self.EXP_ID)) self.assertFalse( rights_manager.Actor(self.user_id_b).can_delete( - feconf.ACTIVITY_TYPE_EXPLORATION, self.EXP_ID)) + constants.ACTIVITY_TYPE_EXPLORATION, self.EXP_ID)) rights_manager.assign_role_for_exploration( self.user_id_a, self.EXP_ID, self.user_id_b, @@ -284,16 +285,16 @@ def test_inviting_playtester_to_exploration(self): self.assertTrue( rights_manager.Actor(self.user_id_b).can_play( - feconf.ACTIVITY_TYPE_EXPLORATION, self.EXP_ID)) + constants.ACTIVITY_TYPE_EXPLORATION, self.EXP_ID)) self.assertTrue( rights_manager.Actor(self.user_id_b).can_view( - feconf.ACTIVITY_TYPE_EXPLORATION, self.EXP_ID)) + constants.ACTIVITY_TYPE_EXPLORATION, self.EXP_ID)) self.assertFalse( rights_manager.Actor(self.user_id_b).can_edit( - feconf.ACTIVITY_TYPE_EXPLORATION, self.EXP_ID)) + constants.ACTIVITY_TYPE_EXPLORATION, self.EXP_ID)) self.assertFalse( rights_manager.Actor(self.user_id_b).can_delete( - feconf.ACTIVITY_TYPE_EXPLORATION, self.EXP_ID)) + constants.ACTIVITY_TYPE_EXPLORATION, self.EXP_ID)) def test_setting_rights_of_exploration(self): exp = exp_domain.Exploration.create_default_exploration(self.EXP_ID) @@ -338,37 +339,37 @@ def test_publishing_and_unpublishing_exploration(self): self.assertFalse( rights_manager.Actor(self.user_id_b).can_play( - feconf.ACTIVITY_TYPE_EXPLORATION, self.EXP_ID)) + constants.ACTIVITY_TYPE_EXPLORATION, self.EXP_ID)) self.assertFalse( rights_manager.Actor(self.user_id_b).can_view( - feconf.ACTIVITY_TYPE_EXPLORATION, self.EXP_ID)) + constants.ACTIVITY_TYPE_EXPLORATION, self.EXP_ID)) rights_manager.publish_exploration(self.user_id_a, self.EXP_ID) self.assertTrue( rights_manager.Actor(self.user_id_b).can_play( - feconf.ACTIVITY_TYPE_EXPLORATION, self.EXP_ID)) + constants.ACTIVITY_TYPE_EXPLORATION, self.EXP_ID)) self.assertTrue( rights_manager.Actor(self.user_id_b).can_view( - feconf.ACTIVITY_TYPE_EXPLORATION, self.EXP_ID)) + constants.ACTIVITY_TYPE_EXPLORATION, self.EXP_ID)) self.assertFalse( rights_manager.Actor(self.user_id_a).can_unpublish( - feconf.ACTIVITY_TYPE_EXPLORATION, self.EXP_ID)) + constants.ACTIVITY_TYPE_EXPLORATION, self.EXP_ID)) rights_manager.unpublish_exploration(self.user_id_admin, self.EXP_ID) self.assertTrue( rights_manager.Actor(self.user_id_a).can_play( - feconf.ACTIVITY_TYPE_EXPLORATION, self.EXP_ID)) + constants.ACTIVITY_TYPE_EXPLORATION, self.EXP_ID)) self.assertTrue( rights_manager.Actor(self.user_id_a).can_view( - feconf.ACTIVITY_TYPE_EXPLORATION, self.EXP_ID)) + constants.ACTIVITY_TYPE_EXPLORATION, self.EXP_ID)) self.assertFalse( rights_manager.Actor(self.user_id_b).can_play( - feconf.ACTIVITY_TYPE_EXPLORATION, self.EXP_ID)) + constants.ACTIVITY_TYPE_EXPLORATION, self.EXP_ID)) self.assertFalse( rights_manager.Actor(self.user_id_b).can_view( - feconf.ACTIVITY_TYPE_EXPLORATION, self.EXP_ID)) + constants.ACTIVITY_TYPE_EXPLORATION, self.EXP_ID)) def test_can_only_delete_unpublished_explorations(self): exp = exp_domain.Exploration.create_default_exploration( @@ -377,19 +378,19 @@ def test_can_only_delete_unpublished_explorations(self): self.assertTrue( rights_manager.Actor(self.user_id_a).can_delete( - feconf.ACTIVITY_TYPE_EXPLORATION, self.EXP_ID)) + constants.ACTIVITY_TYPE_EXPLORATION, self.EXP_ID)) rights_manager.publish_exploration(self.user_id_a, self.EXP_ID) self.assertFalse( rights_manager.Actor(self.user_id_a).can_delete( - feconf.ACTIVITY_TYPE_EXPLORATION, self.EXP_ID)) + constants.ACTIVITY_TYPE_EXPLORATION, self.EXP_ID)) rights_manager.unpublish_exploration(self.user_id_admin, self.EXP_ID) self.assertTrue( rights_manager.Actor(self.user_id_a).can_delete( - feconf.ACTIVITY_TYPE_EXPLORATION, self.EXP_ID)) + constants.ACTIVITY_TYPE_EXPLORATION, self.EXP_ID)) def test_can_publicize_exploration(self): exp = exp_domain.Exploration.create_default_exploration( @@ -400,10 +401,10 @@ def test_can_publicize_exploration(self): self.assertFalse( rights_manager.Actor(self.user_id_a).can_publicize( - feconf.ACTIVITY_TYPE_EXPLORATION, self.EXP_ID)) + constants.ACTIVITY_TYPE_EXPLORATION, self.EXP_ID)) self.assertTrue( rights_manager.Actor(self.user_id_admin).can_publicize( - feconf.ACTIVITY_TYPE_EXPLORATION, self.EXP_ID)) + constants.ACTIVITY_TYPE_EXPLORATION, self.EXP_ID)) def test_changing_viewability_of_exploration(self): exp = exp_domain.Exploration.create_default_exploration( @@ -412,17 +413,17 @@ def test_changing_viewability_of_exploration(self): self.assertFalse( rights_manager.Actor(self.user_id_b).can_view( - feconf.ACTIVITY_TYPE_EXPLORATION, self.EXP_ID)) + constants.ACTIVITY_TYPE_EXPLORATION, self.EXP_ID)) self.assertTrue(rights_manager.Actor( self.user_id_a).can_change_private_viewability( - feconf.ACTIVITY_TYPE_EXPLORATION, self.EXP_ID)) + constants.ACTIVITY_TYPE_EXPLORATION, self.EXP_ID)) self.assertFalse(rights_manager.Actor( self.user_id_b).can_change_private_viewability( - feconf.ACTIVITY_TYPE_EXPLORATION, self.EXP_ID)) + constants.ACTIVITY_TYPE_EXPLORATION, self.EXP_ID)) self.assertTrue(rights_manager.Actor( self.user_id_admin).can_change_private_viewability( - feconf.ACTIVITY_TYPE_EXPLORATION, self.EXP_ID)) + constants.ACTIVITY_TYPE_EXPLORATION, self.EXP_ID)) with self.assertRaisesRegexp(Exception, 'already the current value'): rights_manager.set_private_viewability_of_exploration( @@ -435,35 +436,35 @@ def test_changing_viewability_of_exploration(self): self.user_id_a, self.EXP_ID, True) self.assertTrue( rights_manager.Actor(self.user_id_a).can_view( - feconf.ACTIVITY_TYPE_EXPLORATION, self.EXP_ID)) + constants.ACTIVITY_TYPE_EXPLORATION, self.EXP_ID)) self.assertTrue( rights_manager.Actor(self.user_id_b).can_view( - feconf.ACTIVITY_TYPE_EXPLORATION, self.EXP_ID)) + constants.ACTIVITY_TYPE_EXPLORATION, self.EXP_ID)) rights_manager.set_private_viewability_of_exploration( self.user_id_a, self.EXP_ID, False) self.assertTrue( rights_manager.Actor(self.user_id_a).can_view( - feconf.ACTIVITY_TYPE_EXPLORATION, self.EXP_ID)) + constants.ACTIVITY_TYPE_EXPLORATION, self.EXP_ID)) self.assertFalse( rights_manager.Actor(self.user_id_b).can_view( - feconf.ACTIVITY_TYPE_EXPLORATION, self.EXP_ID)) + constants.ACTIVITY_TYPE_EXPLORATION, self.EXP_ID)) rights_manager.publish_exploration(self.user_id_a, self.EXP_ID) self.assertFalse(rights_manager.Actor( self.user_id_a).can_change_private_viewability( - feconf.ACTIVITY_TYPE_EXPLORATION, self.EXP_ID)) + constants.ACTIVITY_TYPE_EXPLORATION, self.EXP_ID)) rights_manager.unpublish_exploration(self.user_id_admin, self.EXP_ID) self.assertTrue(rights_manager.Actor( self.user_id_a).can_change_private_viewability( - feconf.ACTIVITY_TYPE_EXPLORATION, self.EXP_ID)) + constants.ACTIVITY_TYPE_EXPLORATION, self.EXP_ID)) self.assertFalse(rights_manager.Actor( self.user_id_b).can_change_private_viewability( - feconf.ACTIVITY_TYPE_EXPLORATION, self.EXP_ID)) + constants.ACTIVITY_TYPE_EXPLORATION, self.EXP_ID)) self.assertTrue(rights_manager.Actor( self.user_id_admin).can_change_private_viewability( - feconf.ACTIVITY_TYPE_EXPLORATION, self.EXP_ID)) + constants.ACTIVITY_TYPE_EXPLORATION, self.EXP_ID)) def test_check_exploration_rights(self): exp = exp_domain.Exploration.create_default_exploration(self.EXP_ID) @@ -535,42 +536,42 @@ def test_demo_collection(self): self.assertTrue( rights_manager.Actor(self.user_id_a).can_play( - feconf.ACTIVITY_TYPE_COLLECTION, '0')) + constants.ACTIVITY_TYPE_COLLECTION, '0')) self.assertTrue( rights_manager.Actor(self.user_id_a).can_view( - feconf.ACTIVITY_TYPE_COLLECTION, '0')) + constants.ACTIVITY_TYPE_COLLECTION, '0')) self.assertTrue( rights_manager.Actor(self.user_id_a).can_edit( - feconf.ACTIVITY_TYPE_COLLECTION, '0')) + constants.ACTIVITY_TYPE_COLLECTION, '0')) self.assertFalse( rights_manager.Actor(self.user_id_a).can_delete( - feconf.ACTIVITY_TYPE_COLLECTION, '0')) + constants.ACTIVITY_TYPE_COLLECTION, '0')) self.assertTrue( rights_manager.Actor(self.user_id_admin).can_play( - feconf.ACTIVITY_TYPE_COLLECTION, '0')) + constants.ACTIVITY_TYPE_COLLECTION, '0')) self.assertTrue( rights_manager.Actor(self.user_id_admin).can_view( - feconf.ACTIVITY_TYPE_COLLECTION, '0')) + constants.ACTIVITY_TYPE_COLLECTION, '0')) self.assertTrue( rights_manager.Actor(self.user_id_admin).can_edit( - feconf.ACTIVITY_TYPE_COLLECTION, '0')) + constants.ACTIVITY_TYPE_COLLECTION, '0')) self.assertTrue( rights_manager.Actor(self.user_id_admin).can_delete( - feconf.ACTIVITY_TYPE_COLLECTION, '0')) + constants.ACTIVITY_TYPE_COLLECTION, '0')) self.assertTrue( rights_manager.Actor(self.user_id_moderator).can_play( - feconf.ACTIVITY_TYPE_COLLECTION, '0')) + constants.ACTIVITY_TYPE_COLLECTION, '0')) self.assertTrue( rights_manager.Actor(self.user_id_moderator).can_view( - feconf.ACTIVITY_TYPE_COLLECTION, '0')) + constants.ACTIVITY_TYPE_COLLECTION, '0')) self.assertTrue( rights_manager.Actor(self.user_id_moderator).can_edit( - feconf.ACTIVITY_TYPE_COLLECTION, '0')) + constants.ACTIVITY_TYPE_COLLECTION, '0')) self.assertTrue( rights_manager.Actor(self.user_id_moderator).can_delete( - feconf.ACTIVITY_TYPE_COLLECTION, '0')) + constants.ACTIVITY_TYPE_COLLECTION, '0')) def test_ownership_of_collection(self): self.save_new_default_collection(self.COLLECTION_ID, self.user_id_a) @@ -585,14 +586,14 @@ def test_ownership_of_collection(self): self.assertTrue( rights_manager.Actor(self.user_id_a).is_owner( - feconf.ACTIVITY_TYPE_COLLECTION, self.COLLECTION_ID)) + constants.ACTIVITY_TYPE_COLLECTION, self.COLLECTION_ID)) self.assertFalse( rights_manager.Actor(self.user_id_b).is_owner( - feconf.ACTIVITY_TYPE_COLLECTION, self.COLLECTION_ID)) + constants.ACTIVITY_TYPE_COLLECTION, self.COLLECTION_ID)) self.assertFalse( rights_manager.Actor(self.user_id_admin).is_owner( - feconf.ACTIVITY_TYPE_COLLECTION, self.COLLECTION_ID)) + constants.ACTIVITY_TYPE_COLLECTION, self.COLLECTION_ID)) def test_newly_created_collection(self): self.save_new_default_collection(self.COLLECTION_ID, self.user_id_a) @@ -603,55 +604,55 @@ def test_newly_created_collection(self): self.assertTrue( rights_manager.Actor(self.user_id_a).can_play( - feconf.ACTIVITY_TYPE_COLLECTION, self.COLLECTION_ID)) + constants.ACTIVITY_TYPE_COLLECTION, self.COLLECTION_ID)) self.assertTrue( rights_manager.Actor(self.user_id_a).can_view( - feconf.ACTIVITY_TYPE_COLLECTION, self.COLLECTION_ID)) + constants.ACTIVITY_TYPE_COLLECTION, self.COLLECTION_ID)) self.assertTrue( rights_manager.Actor(self.user_id_a).can_edit( - feconf.ACTIVITY_TYPE_COLLECTION, self.COLLECTION_ID)) + constants.ACTIVITY_TYPE_COLLECTION, self.COLLECTION_ID)) self.assertTrue( rights_manager.Actor(self.user_id_a).can_delete( - feconf.ACTIVITY_TYPE_COLLECTION, self.COLLECTION_ID)) + constants.ACTIVITY_TYPE_COLLECTION, self.COLLECTION_ID)) self.assertTrue( rights_manager.Actor(self.user_id_admin).can_play( - feconf.ACTIVITY_TYPE_COLLECTION, self.COLLECTION_ID)) + constants.ACTIVITY_TYPE_COLLECTION, self.COLLECTION_ID)) self.assertTrue( rights_manager.Actor(self.user_id_admin).can_view( - feconf.ACTIVITY_TYPE_COLLECTION, self.COLLECTION_ID)) + constants.ACTIVITY_TYPE_COLLECTION, self.COLLECTION_ID)) self.assertTrue( rights_manager.Actor(self.user_id_admin).can_edit( - feconf.ACTIVITY_TYPE_COLLECTION, self.COLLECTION_ID)) + constants.ACTIVITY_TYPE_COLLECTION, self.COLLECTION_ID)) self.assertFalse( rights_manager.Actor(self.user_id_admin).can_delete( - feconf.ACTIVITY_TYPE_COLLECTION, self.COLLECTION_ID)) + constants.ACTIVITY_TYPE_COLLECTION, self.COLLECTION_ID)) self.assertTrue( rights_manager.Actor(self.user_id_moderator).can_play( - feconf.ACTIVITY_TYPE_COLLECTION, self.COLLECTION_ID)) + constants.ACTIVITY_TYPE_COLLECTION, self.COLLECTION_ID)) self.assertTrue( rights_manager.Actor(self.user_id_moderator).can_view( - feconf.ACTIVITY_TYPE_COLLECTION, self.COLLECTION_ID)) + constants.ACTIVITY_TYPE_COLLECTION, self.COLLECTION_ID)) self.assertFalse( rights_manager.Actor(self.user_id_moderator).can_edit( - feconf.ACTIVITY_TYPE_COLLECTION, self.COLLECTION_ID)) + constants.ACTIVITY_TYPE_COLLECTION, self.COLLECTION_ID)) self.assertFalse( rights_manager.Actor(self.user_id_moderator).can_delete( - feconf.ACTIVITY_TYPE_COLLECTION, self.COLLECTION_ID)) + constants.ACTIVITY_TYPE_COLLECTION, self.COLLECTION_ID)) self.assertFalse( rights_manager.Actor(self.user_id_b).can_play( - feconf.ACTIVITY_TYPE_COLLECTION, self.COLLECTION_ID)) + constants.ACTIVITY_TYPE_COLLECTION, self.COLLECTION_ID)) self.assertFalse( rights_manager.Actor(self.user_id_b).can_view( - feconf.ACTIVITY_TYPE_COLLECTION, self.COLLECTION_ID)) + constants.ACTIVITY_TYPE_COLLECTION, self.COLLECTION_ID)) self.assertFalse( rights_manager.Actor(self.user_id_b).can_edit( - feconf.ACTIVITY_TYPE_COLLECTION, self.COLLECTION_ID)) + constants.ACTIVITY_TYPE_COLLECTION, self.COLLECTION_ID)) self.assertFalse( rights_manager.Actor(self.user_id_b).can_delete( - feconf.ACTIVITY_TYPE_COLLECTION, self.COLLECTION_ID)) + constants.ACTIVITY_TYPE_COLLECTION, self.COLLECTION_ID)) def test_inviting_collaborator_to_collection(self): self.save_new_valid_collection( @@ -661,34 +662,34 @@ def test_inviting_collaborator_to_collection(self): # Verify initial editor permissions for the collection. self.assertFalse( rights_manager.Actor(self.user_id_b).can_play( - feconf.ACTIVITY_TYPE_COLLECTION, self.COLLECTION_ID)) + constants.ACTIVITY_TYPE_COLLECTION, self.COLLECTION_ID)) self.assertFalse( rights_manager.Actor(self.user_id_b).can_view( - feconf.ACTIVITY_TYPE_COLLECTION, self.COLLECTION_ID)) + constants.ACTIVITY_TYPE_COLLECTION, self.COLLECTION_ID)) self.assertFalse( rights_manager.Actor(self.user_id_b).can_edit( - feconf.ACTIVITY_TYPE_COLLECTION, self.COLLECTION_ID)) + constants.ACTIVITY_TYPE_COLLECTION, self.COLLECTION_ID)) self.assertFalse( rights_manager.Actor(self.user_id_b).can_delete( - feconf.ACTIVITY_TYPE_COLLECTION, self.COLLECTION_ID)) + constants.ACTIVITY_TYPE_COLLECTION, self.COLLECTION_ID)) # Verify initial editor permissions for the exploration within the # collection. self.assertFalse( rights_manager.Actor(self.user_id_b).can_play( - feconf.ACTIVITY_TYPE_EXPLORATION, + constants.ACTIVITY_TYPE_EXPLORATION, self.EXP_ID_FOR_COLLECTION)) self.assertFalse( rights_manager.Actor(self.user_id_b).can_view( - feconf.ACTIVITY_TYPE_EXPLORATION, + constants.ACTIVITY_TYPE_EXPLORATION, self.EXP_ID_FOR_COLLECTION)) self.assertFalse( rights_manager.Actor(self.user_id_b).can_edit( - feconf.ACTIVITY_TYPE_EXPLORATION, + constants.ACTIVITY_TYPE_EXPLORATION, self.EXP_ID_FOR_COLLECTION)) self.assertFalse( rights_manager.Actor(self.user_id_b).can_delete( - feconf.ACTIVITY_TYPE_EXPLORATION, + constants.ACTIVITY_TYPE_EXPLORATION, self.EXP_ID_FOR_COLLECTION)) # User A adds user B to the collection as an editor. @@ -704,34 +705,34 @@ def test_inviting_collaborator_to_collection(self): # Ensure User B is now an editor of the collection. self.assertTrue( rights_manager.Actor(self.user_id_b).can_play( - feconf.ACTIVITY_TYPE_COLLECTION, self.COLLECTION_ID)) + constants.ACTIVITY_TYPE_COLLECTION, self.COLLECTION_ID)) self.assertTrue( rights_manager.Actor(self.user_id_b).can_view( - feconf.ACTIVITY_TYPE_COLLECTION, self.COLLECTION_ID)) + constants.ACTIVITY_TYPE_COLLECTION, self.COLLECTION_ID)) self.assertTrue( rights_manager.Actor(self.user_id_b).can_edit( - feconf.ACTIVITY_TYPE_COLLECTION, self.COLLECTION_ID)) + constants.ACTIVITY_TYPE_COLLECTION, self.COLLECTION_ID)) self.assertFalse( rights_manager.Actor(self.user_id_b).can_delete( - feconf.ACTIVITY_TYPE_COLLECTION, self.COLLECTION_ID)) + constants.ACTIVITY_TYPE_COLLECTION, self.COLLECTION_ID)) # Ensure User B is not an editor of the exploration within the # collection. self.assertFalse( rights_manager.Actor(self.user_id_b).can_play( - feconf.ACTIVITY_TYPE_EXPLORATION, + constants.ACTIVITY_TYPE_EXPLORATION, self.EXP_ID_FOR_COLLECTION)) self.assertFalse( rights_manager.Actor(self.user_id_b).can_view( - feconf.ACTIVITY_TYPE_EXPLORATION, + constants.ACTIVITY_TYPE_EXPLORATION, self.EXP_ID_FOR_COLLECTION)) self.assertFalse( rights_manager.Actor(self.user_id_b).can_edit( - feconf.ACTIVITY_TYPE_EXPLORATION, + constants.ACTIVITY_TYPE_EXPLORATION, self.EXP_ID_FOR_COLLECTION)) self.assertFalse( rights_manager.Actor(self.user_id_b).can_delete( - feconf.ACTIVITY_TYPE_EXPLORATION, + constants.ACTIVITY_TYPE_EXPLORATION, self.EXP_ID_FOR_COLLECTION)) def test_inviting_playtester_to_collection(self): @@ -742,34 +743,34 @@ def test_inviting_playtester_to_collection(self): # Verify initial viewer permissions for the collection. self.assertFalse( rights_manager.Actor(self.user_id_b).can_play( - feconf.ACTIVITY_TYPE_COLLECTION, self.COLLECTION_ID)) + constants.ACTIVITY_TYPE_COLLECTION, self.COLLECTION_ID)) self.assertFalse( rights_manager.Actor(self.user_id_b).can_view( - feconf.ACTIVITY_TYPE_COLLECTION, self.COLLECTION_ID)) + constants.ACTIVITY_TYPE_COLLECTION, self.COLLECTION_ID)) self.assertFalse( rights_manager.Actor(self.user_id_b).can_edit( - feconf.ACTIVITY_TYPE_COLLECTION, self.COLLECTION_ID)) + constants.ACTIVITY_TYPE_COLLECTION, self.COLLECTION_ID)) self.assertFalse( rights_manager.Actor(self.user_id_b).can_delete( - feconf.ACTIVITY_TYPE_COLLECTION, self.COLLECTION_ID)) + constants.ACTIVITY_TYPE_COLLECTION, self.COLLECTION_ID)) # Verify initial viewer permissions for the exploration within the # collection. self.assertFalse( rights_manager.Actor(self.user_id_b).can_play( - feconf.ACTIVITY_TYPE_EXPLORATION, + constants.ACTIVITY_TYPE_EXPLORATION, self.EXP_ID_FOR_COLLECTION)) self.assertFalse( rights_manager.Actor(self.user_id_b).can_view( - feconf.ACTIVITY_TYPE_EXPLORATION, + constants.ACTIVITY_TYPE_EXPLORATION, self.EXP_ID_FOR_COLLECTION)) self.assertFalse( rights_manager.Actor(self.user_id_b).can_edit( - feconf.ACTIVITY_TYPE_EXPLORATION, + constants.ACTIVITY_TYPE_EXPLORATION, self.EXP_ID_FOR_COLLECTION)) self.assertFalse( rights_manager.Actor(self.user_id_b).can_delete( - feconf.ACTIVITY_TYPE_EXPLORATION, + constants.ACTIVITY_TYPE_EXPLORATION, self.EXP_ID_FOR_COLLECTION)) # User A adds user B to the collection as a viewer. @@ -780,34 +781,34 @@ def test_inviting_playtester_to_collection(self): # Ensure User B is now a viewer of the collection. self.assertTrue( rights_manager.Actor(self.user_id_b).can_play( - feconf.ACTIVITY_TYPE_COLLECTION, self.COLLECTION_ID)) + constants.ACTIVITY_TYPE_COLLECTION, self.COLLECTION_ID)) self.assertTrue( rights_manager.Actor(self.user_id_b).can_view( - feconf.ACTIVITY_TYPE_COLLECTION, self.COLLECTION_ID)) + constants.ACTIVITY_TYPE_COLLECTION, self.COLLECTION_ID)) self.assertFalse( rights_manager.Actor(self.user_id_b).can_edit( - feconf.ACTIVITY_TYPE_COLLECTION, self.COLLECTION_ID)) + constants.ACTIVITY_TYPE_COLLECTION, self.COLLECTION_ID)) self.assertFalse( rights_manager.Actor(self.user_id_b).can_delete( - feconf.ACTIVITY_TYPE_COLLECTION, self.COLLECTION_ID)) + constants.ACTIVITY_TYPE_COLLECTION, self.COLLECTION_ID)) # Ensure User B cannot view the exploration just because he/she has # access to the collection containing it. self.assertFalse( rights_manager.Actor(self.user_id_b).can_play( - feconf.ACTIVITY_TYPE_EXPLORATION, + constants.ACTIVITY_TYPE_EXPLORATION, self.EXP_ID_FOR_COLLECTION)) self.assertFalse( rights_manager.Actor(self.user_id_b).can_view( - feconf.ACTIVITY_TYPE_EXPLORATION, + constants.ACTIVITY_TYPE_EXPLORATION, self.EXP_ID_FOR_COLLECTION)) self.assertFalse( rights_manager.Actor(self.user_id_b).can_edit( - feconf.ACTIVITY_TYPE_EXPLORATION, + constants.ACTIVITY_TYPE_EXPLORATION, self.EXP_ID_FOR_COLLECTION)) self.assertFalse( rights_manager.Actor(self.user_id_b).can_delete( - feconf.ACTIVITY_TYPE_EXPLORATION, + constants.ACTIVITY_TYPE_EXPLORATION, self.EXP_ID_FOR_COLLECTION)) def test_setting_rights_of_collection(self): @@ -850,58 +851,58 @@ def test_publishing_and_unpublishing_collection(self): self.assertFalse( rights_manager.Actor(self.user_id_b).can_play( - feconf.ACTIVITY_TYPE_COLLECTION, self.COLLECTION_ID)) + constants.ACTIVITY_TYPE_COLLECTION, self.COLLECTION_ID)) self.assertFalse( rights_manager.Actor(self.user_id_b).can_view( - feconf.ACTIVITY_TYPE_COLLECTION, self.COLLECTION_ID)) + constants.ACTIVITY_TYPE_COLLECTION, self.COLLECTION_ID)) rights_manager.publish_collection(self.user_id_a, self.COLLECTION_ID) self.assertTrue( rights_manager.Actor(self.user_id_b).can_play( - feconf.ACTIVITY_TYPE_COLLECTION, self.COLLECTION_ID)) + constants.ACTIVITY_TYPE_COLLECTION, self.COLLECTION_ID)) self.assertTrue( rights_manager.Actor(self.user_id_b).can_view( - feconf.ACTIVITY_TYPE_COLLECTION, self.COLLECTION_ID)) + constants.ACTIVITY_TYPE_COLLECTION, self.COLLECTION_ID)) self.assertFalse( rights_manager.Actor(self.user_id_a).can_unpublish( - feconf.ACTIVITY_TYPE_COLLECTION, self.COLLECTION_ID)) + constants.ACTIVITY_TYPE_COLLECTION, self.COLLECTION_ID)) rights_manager.unpublish_collection( self.user_id_admin, self.COLLECTION_ID) self.assertTrue( rights_manager.Actor(self.user_id_a).can_play( - feconf.ACTIVITY_TYPE_COLLECTION, self.COLLECTION_ID)) + constants.ACTIVITY_TYPE_COLLECTION, self.COLLECTION_ID)) self.assertTrue( rights_manager.Actor(self.user_id_a).can_view( - feconf.ACTIVITY_TYPE_COLLECTION, self.COLLECTION_ID)) + constants.ACTIVITY_TYPE_COLLECTION, self.COLLECTION_ID)) self.assertFalse( rights_manager.Actor(self.user_id_b).can_play( - feconf.ACTIVITY_TYPE_COLLECTION, self.COLLECTION_ID)) + constants.ACTIVITY_TYPE_COLLECTION, self.COLLECTION_ID)) self.assertFalse( rights_manager.Actor(self.user_id_b).can_view( - feconf.ACTIVITY_TYPE_COLLECTION, self.COLLECTION_ID)) + constants.ACTIVITY_TYPE_COLLECTION, self.COLLECTION_ID)) def test_can_only_delete_unpublished_collections(self): self.save_new_default_collection(self.COLLECTION_ID, self.user_id_a) self.assertTrue( rights_manager.Actor(self.user_id_a).can_delete( - feconf.ACTIVITY_TYPE_COLLECTION, self.COLLECTION_ID)) + constants.ACTIVITY_TYPE_COLLECTION, self.COLLECTION_ID)) rights_manager.publish_collection(self.user_id_a, self.COLLECTION_ID) self.assertFalse( rights_manager.Actor(self.user_id_a).can_delete( - feconf.ACTIVITY_TYPE_COLLECTION, self.COLLECTION_ID)) + constants.ACTIVITY_TYPE_COLLECTION, self.COLLECTION_ID)) rights_manager.unpublish_collection( self.user_id_admin, self.COLLECTION_ID) self.assertTrue( rights_manager.Actor(self.user_id_a).can_delete( - feconf.ACTIVITY_TYPE_COLLECTION, self.COLLECTION_ID)) + constants.ACTIVITY_TYPE_COLLECTION, self.COLLECTION_ID)) def test_can_publicize_collection(self): self.save_new_default_collection(self.COLLECTION_ID, self.user_id_a) @@ -910,7 +911,7 @@ def test_can_publicize_collection(self): self.assertFalse( rights_manager.Actor(self.user_id_a).can_publicize( - feconf.ACTIVITY_TYPE_COLLECTION, self.COLLECTION_ID)) + constants.ACTIVITY_TYPE_COLLECTION, self.COLLECTION_ID)) self.assertTrue( rights_manager.Actor(self.user_id_admin).can_publicize( - feconf.ACTIVITY_TYPE_COLLECTION, self.COLLECTION_ID)) + constants.ACTIVITY_TYPE_COLLECTION, self.COLLECTION_ID)) diff --git a/core/domain/summary_services.py b/core/domain/summary_services.py index 88394a5206d2..56b714bf52e1 100644 --- a/core/domain/summary_services.py +++ b/core/domain/summary_services.py @@ -16,13 +16,13 @@ """Commands that can be used to operate on activity summaries.""" +from constants import constants from core.domain import activity_services from core.domain import collection_services from core.domain import exp_services from core.domain import rights_manager from core.domain import stats_jobs_continuous from core.domain import user_services -import feconf import utils _LIBRARY_INDEX_GROUPS = [{ @@ -255,7 +255,7 @@ def get_exploration_metadata_dicts(exploration_ids, editor_user_id=None): if editor_user_id is None: continue if not rights_manager.Actor(editor_user_id).can_edit( - feconf.ACTIVITY_TYPE_EXPLORATION, + constants.ACTIVITY_TYPE_EXPLORATION, exploration_summary.id): continue @@ -317,7 +317,7 @@ def get_displayable_exp_summary_dicts_matching_ids( if editor_user_id is None: continue if not rights_manager.Actor(editor_user_id).can_edit( - feconf.ACTIVITY_TYPE_EXPLORATION, + constants.ACTIVITY_TYPE_EXPLORATION, exploration_summary.id): continue @@ -374,7 +374,7 @@ def get_displayable_exp_summary_dicts(exploration_summaries): summary_dict = { 'id': exploration_summary.id, 'title': exploration_summary.title, - 'activity_type': feconf.ACTIVITY_TYPE_EXPLORATION, + 'activity_type': constants.ACTIVITY_TYPE_EXPLORATION, 'category': exploration_summary.category, 'created_on_msec': utils.get_time_in_millisecs( exploration_summary.exploration_model_created_on), @@ -437,7 +437,7 @@ def _get_displayable_collection_summary_dicts(collection_summaries): 'id': collection_summary.id, 'title': collection_summary.title, 'category': collection_summary.category, - 'activity_type': feconf.ACTIVITY_TYPE_COLLECTION, + 'activity_type': constants.ACTIVITY_TYPE_COLLECTION, 'objective': collection_summary.objective, 'language_code': collection_summary.language_code, 'tags': collection_summary.tags, @@ -569,12 +569,12 @@ def require_activities_to_be_public(activity_references): activity_references) activity_summaries_by_type = [{ - 'type': feconf.ACTIVITY_TYPE_EXPLORATION, + 'type': constants.ACTIVITY_TYPE_EXPLORATION, 'ids': exploration_ids, 'summaries': exp_services.get_exploration_summaries_matching_ids( exploration_ids), }, { - 'type': feconf.ACTIVITY_TYPE_COLLECTION, + 'type': constants.ACTIVITY_TYPE_COLLECTION, 'ids': collection_ids, 'summaries': collection_services.get_collection_summaries_matching_ids( collection_ids), @@ -630,11 +630,11 @@ def get_featured_activity_summary_dicts(language_codes): collection_ids) summary_dicts_by_id = { - feconf.ACTIVITY_TYPE_EXPLORATION: { + constants.ACTIVITY_TYPE_EXPLORATION: { summary_dict['id']: summary_dict for summary_dict in exp_summary_dicts }, - feconf.ACTIVITY_TYPE_COLLECTION: { + constants.ACTIVITY_TYPE_COLLECTION: { summary_dict['id']: summary_dict for summary_dict in col_summary_dicts }, diff --git a/core/domain/summary_services_test.py b/core/domain/summary_services_test.py index 7af71a401854..721b8a885086 100644 --- a/core/domain/summary_services_test.py +++ b/core/domain/summary_services_test.py @@ -336,7 +336,7 @@ def test_for_featured_explorations(self): """ activity_services.update_featured_activity_references([ activity_domain.ActivityReference( - feconf.ACTIVITY_TYPE_EXPLORATION, self.EXP_ID_2) + constants.ACTIVITY_TYPE_EXPLORATION, self.EXP_ID_2) ]) featured_activity_summaries = ( @@ -362,9 +362,9 @@ def test_language_code_filter(self): """Note that both EXP_ID_1 is in Spanish and EXP_ID_2 is in English.""" activity_services.update_featured_activity_references([ activity_domain.ActivityReference( - feconf.ACTIVITY_TYPE_EXPLORATION, self.EXP_ID_1), + constants.ACTIVITY_TYPE_EXPLORATION, self.EXP_ID_1), activity_domain.ActivityReference( - feconf.ACTIVITY_TYPE_EXPLORATION, self.EXP_ID_2) + constants.ACTIVITY_TYPE_EXPLORATION, self.EXP_ID_2) ]) featured_activity_summaries = ( @@ -834,11 +834,11 @@ def test_requiring_nonexistent_activities_be_public_raises_exception(self): with self.assertRaisesRegexp(Exception, 'non-existent exploration'): summary_services.require_activities_to_be_public([ activity_domain.ActivityReference( - feconf.ACTIVITY_TYPE_EXPLORATION, 'fake')]) + constants.ACTIVITY_TYPE_EXPLORATION, 'fake')]) with self.assertRaisesRegexp(Exception, 'non-existent collection'): summary_services.require_activities_to_be_public([ activity_domain.ActivityReference( - feconf.ACTIVITY_TYPE_COLLECTION, 'fake')]) + constants.ACTIVITY_TYPE_COLLECTION, 'fake')]) def test_requiring_private_activities_to_be_public_raises_exception(self): self.save_new_valid_exploration(self.EXP_ID_0, self.owner_id) @@ -849,11 +849,11 @@ def test_requiring_private_activities_to_be_public_raises_exception(self): with self.assertRaisesRegexp(Exception, 'private exploration'): summary_services.require_activities_to_be_public([ activity_domain.ActivityReference( - feconf.ACTIVITY_TYPE_EXPLORATION, self.EXP_ID_0)]) + constants.ACTIVITY_TYPE_EXPLORATION, self.EXP_ID_0)]) with self.assertRaisesRegexp(Exception, 'private collection'): summary_services.require_activities_to_be_public([ activity_domain.ActivityReference( - feconf.ACTIVITY_TYPE_COLLECTION, self.COL_ID_2)]) + constants.ACTIVITY_TYPE_COLLECTION, self.COL_ID_2)]) def test_requiring_public_activities_to_be_public_succeeds(self): self.save_new_valid_exploration(self.EXP_ID_0, self.owner_id) @@ -866,9 +866,9 @@ def test_requiring_public_activities_to_be_public_succeeds(self): # There are no validation errors. summary_services.require_activities_to_be_public([ activity_domain.ActivityReference( - feconf.ACTIVITY_TYPE_EXPLORATION, self.EXP_ID_0), + constants.ACTIVITY_TYPE_EXPLORATION, self.EXP_ID_0), activity_domain.ActivityReference( - feconf.ACTIVITY_TYPE_COLLECTION, self.COL_ID_2)]) + constants.ACTIVITY_TYPE_COLLECTION, self.COL_ID_2)]) class CollectionNodeMetadataDictsTest( diff --git a/core/storage/activity/gae_models_test.py b/core/storage/activity/gae_models_test.py index 1b421b298a15..7d2ec9a4be83 100644 --- a/core/storage/activity/gae_models_test.py +++ b/core/storage/activity/gae_models_test.py @@ -14,9 +14,9 @@ # See the License for the specific language governing permissions and # limitations under the License. +from constants import constants from core.platform import models from core.tests import test_utils -import feconf (activity_models,) = models.Registry.import_models([models.NAMES.activity]) @@ -42,7 +42,7 @@ def test_updating_featured_activity_list(self): self.assertEqual(featured_model_instance.activity_references, []) featured_model_instance.activity_references = [{ - 'type': feconf.ACTIVITY_TYPE_EXPLORATION, + 'type': constants.ACTIVITY_TYPE_EXPLORATION, 'id': '0', }] featured_model_instance.put() @@ -51,6 +51,6 @@ def test_updating_featured_activity_list(self): activity_models.ActivityReferencesModel.get_or_create('featured')) self.assertEqual(featured_model_instance.id, 'featured') self.assertEqual(featured_model_instance.activity_references, [{ - 'type': feconf.ACTIVITY_TYPE_EXPLORATION, + 'type': constants.ACTIVITY_TYPE_EXPLORATION, 'id': '0', }]) diff --git a/core/templates/dev/head/domain/learner_dashboard/LearnerDashboardBackendApiService.js b/core/templates/dev/head/domain/learner_dashboard/LearnerDashboardBackendApiService.js index f84aa9809015..f08d97dd5c5b 100644 --- a/core/templates/dev/head/domain/learner_dashboard/LearnerDashboardBackendApiService.js +++ b/core/templates/dev/head/domain/learner_dashboard/LearnerDashboardBackendApiService.js @@ -1,4 +1,4 @@ -// Copyright 2015 The Oppia Authors. All Rights Reserved. +// Copyright 2017 The Oppia Authors. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/core/templates/dev/head/pages/learner_dashboard/LearnerDashboard.js b/core/templates/dev/head/pages/learner_dashboard/LearnerDashboard.js index 84d32e16c061..e402d469a1ba 100644 --- a/core/templates/dev/head/pages/learner_dashboard/LearnerDashboard.js +++ b/core/templates/dev/head/pages/learner_dashboard/LearnerDashboard.js @@ -1,4 +1,4 @@ -// Copyright 2014 The Oppia Authors. All Rights Reserved. +// Copyright 2017 The Oppia Authors. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -370,7 +370,6 @@ oppia.controller('LearnerDashboard', [ $scope.sectionNameI18nId = sectionNameI18nId; $scope.subsectionName = subsectionName; $scope.activityTitle = activity.title; - console.log($scope.sectionNameI18nId); $scope.remove = function() { /* eslint-disable max-len */ if (subsectionName === diff --git a/core/tests/protractor/learnerDashboard.js b/core/tests/protractor/learnerDashboard.js index cc227e754acc..795e74813c74 100644 --- a/core/tests/protractor/learnerDashboard.js +++ b/core/tests/protractor/learnerDashboard.js @@ -1,4 +1,4 @@ -// Copyright 2014 The Oppia Authors. All Rights Reserved. +// Copyright 2017 The Oppia Authors. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/feconf.py b/feconf.py index 57dd6ecf5d3d..2d349d77f7d8 100644 --- a/feconf.py +++ b/feconf.py @@ -579,7 +579,7 @@ def get_empty_ratings(): LEARNER_DASHBOARD_DATA_URL = '/learnerdashboardhandler/data' LEARNER_DASHBOARD_FEEDBACK_THREAD_DATA_URL = '/learnerdashboardthreadhandler' LEARNER_PLAYLIST_DATA_URL = '/learnerplaylistactivityhandler' -LEARNER_INCOMPLETE_ACTIVITY_DATA_URL = '/incompleteactivityhandler' +LEARNER_INCOMPLETE_ACTIVITY_DATA_URL = '/learnerincompleteactivityhandler' LIBRARY_GROUP_DATA_URL = '/librarygrouphandler' LIBRARY_INDEX_URL = '/library' LIBRARY_INDEX_DATA_URL = '/libraryindexhandler' From 98eba4c8c0d6077fff612ab1dff664f98956fb5d Mon Sep 17 00:00:00 2001 From: Arunabh98 Date: Wed, 2 Aug 2017 15:33:52 +0530 Subject: [PATCH 10/65] Remove redundant code. --- feconf.py | 5 ----- 1 file changed, 5 deletions(-) diff --git a/feconf.py b/feconf.py index 2d349d77f7d8..021d869c9a4a 100644 --- a/feconf.py +++ b/feconf.py @@ -682,11 +682,6 @@ def get_empty_ratings(): # is taken to be 12 hours. PROXIMAL_TIMEDELTA_SECS = 12 * 60 * 60 -# Types of activities that can be created with Oppia. -ACTIVITY_TYPE_EXPLORATION = 'exploration' -ACTIVITY_TYPE_COLLECTION = 'collection' -ALL_ACTIVITY_TYPES = [ACTIVITY_TYPE_EXPLORATION, ACTIVITY_TYPE_COLLECTION] - # These categories are shown in the library navbar. SEARCH_DROPDOWN_CATEGORIES = sorted([ 'Mathematics', From 82819c27a10663c7a15cdbde91fb89760218941b Mon Sep 17 00:00:00 2001 From: Arunabh98 Date: Wed, 2 Aug 2017 15:48:36 +0530 Subject: [PATCH 11/65] Address another review comment. --- core/controllers/learner_playlist_test.py | 45 ++++++++++++++--------- core/controllers/reader_test.py | 15 ++++---- 2 files changed, 36 insertions(+), 24 deletions(-) diff --git a/core/controllers/learner_playlist_test.py b/core/controllers/learner_playlist_test.py index a19b879c5e47..af3c656d6e1b 100644 --- a/core/controllers/learner_playlist_test.py +++ b/core/controllers/learner_playlist_test.py @@ -20,9 +20,6 @@ from core.tests import test_utils import feconf -EXPLORATION_TYPE = constants.ACTIVITY_TYPE_EXPLORATION -COLLECTION_TYPE = constants.ACTIVITY_TYPE_COLLECTION - class LearnerPlaylistHandlerTests(test_utils.GenericTestBase): OWNER_EMAIL = 'owner@example.com' @@ -72,7 +69,8 @@ def test_add_exploration_to_learner_playlist(self): # Add one exploration to the playlist. self.post_json( '%s/%s/%s' % ( - feconf.LEARNER_PLAYLIST_DATA_URL, EXPLORATION_TYPE, + feconf.LEARNER_PLAYLIST_DATA_URL, + constants.ACTIVITY_TYPE_EXPLORATION, self.EXP_ID_1), {}, csrf_token) self.assertEqual( learner_playlist_services.get_all_exp_ids_in_learner_playlist( @@ -81,7 +79,8 @@ def test_add_exploration_to_learner_playlist(self): # Add another exploration. self.post_json( '%s/%s/%s' % ( - feconf.LEARNER_PLAYLIST_DATA_URL, EXPLORATION_TYPE, + feconf.LEARNER_PLAYLIST_DATA_URL, + constants.ACTIVITY_TYPE_EXPLORATION, self.EXP_ID_2), {}, csrf_token) self.assertEqual( learner_playlist_services.get_all_exp_ids_in_learner_playlist( @@ -94,7 +93,8 @@ def test_add_exploration_to_learner_playlist(self): } self.post_json( '%s/%s/%s' % ( - feconf.LEARNER_PLAYLIST_DATA_URL, EXPLORATION_TYPE, + feconf.LEARNER_PLAYLIST_DATA_URL, + constants.ACTIVITY_TYPE_EXPLORATION, self.EXP_ID_2), payload, csrf_token) self.assertEqual( learner_playlist_services.get_all_exp_ids_in_learner_playlist( @@ -106,7 +106,8 @@ def test_add_exploration_to_learner_playlist(self): self.viewer_id, self.EXP_ID_3) self.post_json( '%s/%s/%s' % ( - feconf.LEARNER_PLAYLIST_DATA_URL, EXPLORATION_TYPE, + feconf.LEARNER_PLAYLIST_DATA_URL, + constants.ACTIVITY_TYPE_EXPLORATION, self.EXP_ID_3), {}, csrf_token) self.assertEqual( learner_playlist_services.get_all_exp_ids_in_learner_playlist( @@ -122,7 +123,8 @@ def test_add_collection_to_learner_playlist(self): # Add one collection to the playlist. self.post_json( '%s/%s/%s' % ( - feconf.LEARNER_PLAYLIST_DATA_URL, COLLECTION_TYPE, + feconf.LEARNER_PLAYLIST_DATA_URL, + constants.ACTIVITY_TYPE_COLLECTION, self.COL_ID_1), {}, csrf_token) self.assertEqual( learner_playlist_services.get_all_collection_ids_in_learner_playlist( # pylint: disable=line-too-long @@ -130,7 +132,8 @@ def test_add_collection_to_learner_playlist(self): # Add another exploration. self.post_json('%s/%s/%s' % ( - feconf.LEARNER_PLAYLIST_DATA_URL, COLLECTION_TYPE, + feconf.LEARNER_PLAYLIST_DATA_URL, + constants.ACTIVITY_TYPE_COLLECTION, self.COL_ID_2), {}, csrf_token) self.assertEqual( learner_playlist_services.get_all_collection_ids_in_learner_playlist( # pylint: disable=line-too-long @@ -143,7 +146,8 @@ def test_add_collection_to_learner_playlist(self): } self.post_json( '%s/%s/%s' % ( - feconf.LEARNER_PLAYLIST_DATA_URL, COLLECTION_TYPE, + feconf.LEARNER_PLAYLIST_DATA_URL, + constants.ACTIVITY_TYPE_COLLECTION, self.COL_ID_2), payload, csrf_token) self.assertEqual( learner_playlist_services.get_all_collection_ids_in_learner_playlist( # pylint: disable=line-too-long @@ -154,7 +158,8 @@ def test_add_collection_to_learner_playlist(self): learner_progress_services.mark_collection_as_completed( self.viewer_id, self.COL_ID_3) self.post_json('%s/%s/%s' % ( - feconf.LEARNER_PLAYLIST_DATA_URL, COLLECTION_TYPE, + feconf.LEARNER_PLAYLIST_DATA_URL, + constants.ACTIVITY_TYPE_COLLECTION, self.COL_ID_3), {}, csrf_token) self.assertEqual( learner_playlist_services.get_all_collection_ids_in_learner_playlist( # pylint: disable=line-too-long @@ -177,7 +182,8 @@ def test_remove_exploration_from_learner_playlist(self): # Remove an exploration. self.testapp.delete(str( '%s/%s/%s' % ( - feconf.LEARNER_PLAYLIST_DATA_URL, EXPLORATION_TYPE, + feconf.LEARNER_PLAYLIST_DATA_URL, + constants.ACTIVITY_TYPE_EXPLORATION, self.EXP_ID_1))) self.assertEqual( learner_playlist_services.get_all_exp_ids_in_learner_playlist( @@ -185,7 +191,8 @@ def test_remove_exploration_from_learner_playlist(self): # Removing the same exploration again has no effect. self.testapp.delete(str('%s/%s/%s' % ( - feconf.LEARNER_PLAYLIST_DATA_URL, EXPLORATION_TYPE, + feconf.LEARNER_PLAYLIST_DATA_URL, + constants.ACTIVITY_TYPE_EXPLORATION, self.EXP_ID_1))) self.assertEqual( learner_playlist_services.get_all_exp_ids_in_learner_playlist( @@ -193,7 +200,8 @@ def test_remove_exploration_from_learner_playlist(self): # Remove the second exploration. self.testapp.delete(str('%s/%s/%s' % ( - feconf.LEARNER_PLAYLIST_DATA_URL, EXPLORATION_TYPE, + feconf.LEARNER_PLAYLIST_DATA_URL, + constants.ACTIVITY_TYPE_EXPLORATION, self.EXP_ID_2))) self.assertEqual( learner_playlist_services.get_all_exp_ids_in_learner_playlist( @@ -215,21 +223,24 @@ def test_remove_collection_from_learner_playlist(self): # Remove a collection. self.testapp.delete(str('%s/%s/%s' % ( - feconf.LEARNER_PLAYLIST_DATA_URL, COLLECTION_TYPE, self.COL_ID_1))) + feconf.LEARNER_PLAYLIST_DATA_URL, + constants.ACTIVITY_TYPE_COLLECTION, self.COL_ID_1))) self.assertEqual( learner_playlist_services.get_all_collection_ids_in_learner_playlist( # pylint: disable=line-too-long self.viewer_id), [self.COL_ID_2]) # Removing the same collection again has no effect. self.testapp.delete(str('%s/%s/%s' % ( - feconf.LEARNER_PLAYLIST_DATA_URL, COLLECTION_TYPE, self.COL_ID_1))) + feconf.LEARNER_PLAYLIST_DATA_URL, + constants.ACTIVITY_TYPE_COLLECTION, self.COL_ID_1))) self.assertEqual( learner_playlist_services.get_all_collection_ids_in_learner_playlist( # pylint: disable=line-too-long self.viewer_id), [self.COL_ID_2]) # Remove the second collection. self.testapp.delete(str('%s/%s/%s' % ( - feconf.LEARNER_PLAYLIST_DATA_URL, COLLECTION_TYPE, self.COL_ID_2))) + feconf.LEARNER_PLAYLIST_DATA_URL, + constants.ACTIVITY_TYPE_COLLECTION, self.COL_ID_2))) self.assertEqual( learner_playlist_services.get_all_collection_ids_in_learner_playlist( # pylint: disable=line-too-long self.viewer_id), []) diff --git a/core/controllers/reader_test.py b/core/controllers/reader_test.py index 46216acf7da6..4515fa9b6fd7 100644 --- a/core/controllers/reader_test.py +++ b/core/controllers/reader_test.py @@ -27,9 +27,6 @@ from core.tests import test_utils import feconf -EXPLORATION_TYPE = constants.ACTIVITY_TYPE_EXPLORATION -COLLECTION_TYPE = constants.ACTIVITY_TYPE_COLLECTION - class ReaderPermissionsTest(test_utils.GenericTestBase): """Test permissions for readers to view explorations.""" @@ -688,7 +685,8 @@ def test_remove_exp_from_incomplete_list_handler(self): # Remove one exploration. self.testapp.delete(str( '%s/%s/%s' % - (feconf.LEARNER_INCOMPLETE_ACTIVITY_DATA_URL, EXPLORATION_TYPE, + (feconf.LEARNER_INCOMPLETE_ACTIVITY_DATA_URL, + constants.ACTIVITY_TYPE_EXPLORATION, self.EXP_ID_0))) self.assertEqual( learner_progress_services.get_all_incomplete_exp_ids( @@ -697,7 +695,8 @@ def test_remove_exp_from_incomplete_list_handler(self): # Remove another exploration. self.testapp.delete(str( '%s/%s/%s' % - (feconf.LEARNER_INCOMPLETE_ACTIVITY_DATA_URL, EXPLORATION_TYPE, + (feconf.LEARNER_INCOMPLETE_ACTIVITY_DATA_URL, + constants.ACTIVITY_TYPE_EXPLORATION, self.EXP_ID_1))) self.assertEqual( learner_progress_services.get_all_incomplete_exp_ids( @@ -720,7 +719,8 @@ def test_remove_collection_from_incomplete_list_handler(self): # Remove one collection. self.testapp.delete(str( '%s/%s/%s' % - (feconf.LEARNER_INCOMPLETE_ACTIVITY_DATA_URL, COLLECTION_TYPE, + (feconf.LEARNER_INCOMPLETE_ACTIVITY_DATA_URL, + constants.ACTIVITY_TYPE_COLLECTION, self.COL_ID_0))) self.assertEqual( learner_progress_services.get_all_incomplete_collection_ids( @@ -729,7 +729,8 @@ def test_remove_collection_from_incomplete_list_handler(self): # Remove another collection. self.testapp.delete(str( '%s/%s/%s' % - (feconf.LEARNER_INCOMPLETE_ACTIVITY_DATA_URL, COLLECTION_TYPE, + (feconf.LEARNER_INCOMPLETE_ACTIVITY_DATA_URL, + constants.ACTIVITY_TYPE_COLLECTION, self.COL_ID_1))) self.assertEqual( learner_progress_services.get_all_incomplete_collection_ids( From 6a044ea1a5cba56571e1e487523cfec72d39eb88 Mon Sep 17 00:00:00 2001 From: Arunabh98 Date: Thu, 3 Aug 2017 17:50:06 +0530 Subject: [PATCH 12/65] Add play later to option. --- assets/i18n/en.json | 1 + assets/i18n/qqq.json | 1 + assets/images/general/play_later_icon.svg | 5 +++++ .../learner_dashboard/LearnerDashboard.js | 3 ++- .../learner_dashboard/learner_dashboard.html | 18 ++++++++++++++++++ 5 files changed, 27 insertions(+), 1 deletion(-) create mode 100644 assets/images/general/play_later_icon.svg diff --git a/assets/i18n/en.json b/assets/i18n/en.json index e36e9ce8f16a..bfc3c528f824 100644 --- a/assets/i18n/en.json +++ b/assets/i18n/en.json @@ -224,6 +224,7 @@ "I18N_LEARNER_DASHBOARD_INCOMPLETE_SECTION": "In Progress", "I18N_LEARNER_DASHBOARD_INTRO_MESSAGE_PART_ONE": "It looks like you haven't tried any of our explorations yet.", "I18N_LEARNER_DASHBOARD_INTRO_MESSAGE_PART_TWO": "Let's get started on this exciting journey!", + "I18N_LEARNER_DASHBOARD_PLAYLIST_SECTION": "Play Later", "I18N_LEARNER_DASHBOARD_REMOVE_ACTIVITY_MODAL_BODY": "Are you sure you want to remove '<[entityTitle]>' from your '<[sectionNameI18nId | translate]>' list?", "I18N_LEARNER_DASHBOARD_REMOVE_ACTIVITY_MODAL_HEADER": "Remove from '<[sectionNameI18nId | translate]>' list?", "I18N_LEARNER_DASHBOARD_REMOVE_BUTTON": "Remove", diff --git a/assets/i18n/qqq.json b/assets/i18n/qqq.json index 42f8ca835003..a38385eee81d 100644 --- a/assets/i18n/qqq.json +++ b/assets/i18n/qqq.json @@ -224,6 +224,7 @@ "I18N_LEARNER_DASHBOARD_INCOMPLETE_SECTION": "Text for the incomplete section in the learner dashboard.", "I18N_LEARNER_DASHBOARD_INTRO_MESSAGE_PART_ONE": "First part of the introductory message that appears on the learner dashboard when there is no activity.", "I18N_LEARNER_DASHBOARD_INTRO_MESSAGE_PART_TWO": "Second part of the introductory message that appears on the learner dashboard when there is no activity.", + "I18N_LEARNER_DASHBOARD_PLAYLIST_SECTION": "Text for the playlist section in the learner dashboard. Will contain all the explorations and collections which the user wants to play later but doesn't have the time at the moment.", "I18N_LEARNER_DASHBOARD_REMOVE_ACTIVITY_MODAL_BODY": "Text that appears in the body of the remove modal in the learner dashboard. It asks the user if he/she is sure to remove the activity from the learner dashboard. The 'sectionNameI18nId' describes which section of the learner dashboard the user is in. The 'entityTitle' is the name of the lesson the user wants to remove from the learner dashboard.", "I18N_LEARNER_DASHBOARD_REMOVE_ACTIVITY_MODAL_HEADER": "Text that appears as the header of the remove modal in the learner dashboard. The 'sectionNameI18nId' describes which section of the learner dashboard the user is in.", "I18N_LEARNER_DASHBOARD_REMOVE_BUTTON": "Text that appears in a button in a modal in the learner dashboard. Clicking on it, the user confirms his/her action of removing a activity from the learner dashboard.\n{{Identical|Remove}}", diff --git a/assets/images/general/play_later_icon.svg b/assets/images/general/play_later_icon.svg new file mode 100644 index 000000000000..432b7764f530 --- /dev/null +++ b/assets/images/general/play_later_icon.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/core/templates/dev/head/pages/learner_dashboard/LearnerDashboard.js b/core/templates/dev/head/pages/learner_dashboard/LearnerDashboard.js index d2cc5c89235d..3fcc8dcc3728 100644 --- a/core/templates/dev/head/pages/learner_dashboard/LearnerDashboard.js +++ b/core/templates/dev/head/pages/learner_dashboard/LearnerDashboard.js @@ -20,7 +20,8 @@ oppia.constant('LEARNER_DASHBOARD_SECTION_I18N_IDS', { INCOMPLETE: 'I18N_LEARNER_DASHBOARD_INCOMPLETE_SECTION', COMPLETED: 'I18N_LEARNER_DASHBOARD_COMPLETED_SECTION', SUBSCRIPTIONS: 'I18N_LEARNER_DASHBOARD_SUBSCRIPTIONS_SECTION', - FEEDBACK: 'I18N_LEARNER_DASHBOARD_FEEDBACK_SECTION' + FEEDBACK: 'I18N_LEARNER_DASHBOARD_FEEDBACK_SECTION', + PLAYLIST: 'I18N_LEARNER_DASHBOARD_PLAYLIST_SECTION' }); oppia.constant('LEARNER_DASHBOARD_SUBSECTION_I18N_IDS', { diff --git a/core/templates/dev/head/pages/learner_dashboard/learner_dashboard.html b/core/templates/dev/head/pages/learner_dashboard/learner_dashboard.html index d1ddec57fa77..c88feec61fbd 100644 --- a/core/templates/dev/head/pages/learner_dashboard/learner_dashboard.html +++ b/core/templates/dev/head/pages/learner_dashboard/learner_dashboard.html @@ -132,6 +132,24 @@

<[subscriptionsList.length]>

(<[numberOfUnreadThreads]>) +

+ + +

+ From 1861d4cc8900366997ba751b81b1cea67640bc97 Mon Sep 17 00:00:00 2001 From: Arunabh98 Date: Thu, 3 Aug 2017 19:10:57 +0530 Subject: [PATCH 13/65] Add play later icon. --- assets/i18n/en.json | 1 + assets/i18n/qqq.json | 1 + assets/images/general/play_later_icon.svg | 5 ----- core/templates/dev/head/css/oppia.css | 11 +++++++++++ core/templates/dev/head/pages/library/Library.js | 4 ++++ core/templates/dev/head/pages/library/library.html | 13 +++++++++++-- 6 files changed, 28 insertions(+), 7 deletions(-) delete mode 100644 assets/images/general/play_later_icon.svg diff --git a/assets/i18n/en.json b/assets/i18n/en.json index bfc3c528f824..f977fb988345 100644 --- a/assets/i18n/en.json +++ b/assets/i18n/en.json @@ -288,6 +288,7 @@ "I18N_LIBRARY_GROUPS_SCIENCE" : "Science", "I18N_LIBRARY_GROUPS_SOCIAL_SCIENCE": "Social Science", "I18N_LIBRARY_GROUPS_TOP_RATED_EXPLORATIONS": "Top-Rated Explorations", + "I18N_LIBRARY_ADD_TO_LEARNER_PLAYLIST": "Add to Play Later", "I18N_LIBRARY_LAST_UPDATED": "Last updated", "I18N_LIBRARY_LOADING": "Loading", "I18N_LIBRARY_MAIN_HEADER": "Imagine what you could learn today...", diff --git a/assets/i18n/qqq.json b/assets/i18n/qqq.json index a38385eee81d..9d1c4b1cfea1 100644 --- a/assets/i18n/qqq.json +++ b/assets/i18n/qqq.json @@ -288,6 +288,7 @@ "I18N_LIBRARY_GROUPS_SCIENCE": "Title of a group of explorations - This text is shown on top of a group of explorations regarding the same topic.\n{{Identical|Science}}", "I18N_LIBRARY_GROUPS_SOCIAL_SCIENCE": "Title of a group of explorations - This text is shown on top of a group of explorations regarding the same topic.", "I18N_LIBRARY_GROUPS_TOP_RATED_EXPLORATIONS": "Title of a group of explorations - This text is shown on top of a group of explorations. It makes reference to explorations with higher score given by the users.", + "I18N_LIBRARY_ADD_TO_LEARNER_PLAYLIST": "Text that appears when the user hovers over a clock icon that appears on top of the activities in the library section. The clock icon indicates to the user that he/she can add the activity to his/her learner playlist which he/she can then play later.", "I18N_LIBRARY_LAST_UPDATED": "Text displayed when hovered over the clock icon inside an exploration tile in card view of creator dashboard.\n{{Identical|Last updated}}", "I18N_LIBRARY_LOADING": "Text displayed in the middle of the page while the content is being loaded.\n{{Identical|Loading}}", "I18N_LIBRARY_MAIN_HEADER": "Main title of the library page. - The library page shows all the explorations and collections available. It should be a single phrase and fit in one line.", diff --git a/assets/images/general/play_later_icon.svg b/assets/images/general/play_later_icon.svg deleted file mode 100644 index 432b7764f530..000000000000 --- a/assets/images/general/play_later_icon.svg +++ /dev/null @@ -1,5 +0,0 @@ - - - - - \ No newline at end of file diff --git a/core/templates/dev/head/css/oppia.css b/core/templates/dev/head/css/oppia.css index 0702173cb51f..f3752e5f0577 100644 --- a/core/templates/dev/head/css/oppia.css +++ b/core/templates/dev/head/css/oppia.css @@ -221,6 +221,17 @@ body { max-width: 1400px; } +.oppia-add-to-learner-playlist-icon { + color: white; + float: right; + font-size: 19px; + left: -11px; + margin-left: -16px; + margin-top: 12px; + position: relative; + z-index: 10; +} + .oppia-dashboard-container .exp-private-text { color: #aaa; font-style: italic; diff --git a/core/templates/dev/head/pages/library/Library.js b/core/templates/dev/head/pages/library/Library.js index 6036b44f6ea1..b5e8023a186b 100644 --- a/core/templates/dev/head/pages/library/Library.js +++ b/core/templates/dev/head/pages/library/Library.js @@ -113,6 +113,10 @@ oppia.controller('Library', [ $scope.activeGroupIndex = null; }; + $scope.addToLearnerPlaylist = function(activityType, activityId) { + ; + }; + // If the value below is changed, the following CSS values in oppia.css // must be changed: // - .oppia-exp-summary-tiles-container: max-width diff --git a/core/templates/dev/head/pages/library/library.html b/core/templates/dev/head/pages/library/library.html index 4ce7825b1514..6c333fe10ac7 100644 --- a/core/templates/dev/head/pages/library/library.html +++ b/core/templates/dev/head/pages/library/library.html @@ -116,7 +116,15 @@

From 26dca72083a0f7a38af91448a883b1a63ee0d2ef Mon Sep 17 00:00:00 2001 From: Arunabh98 Date: Sun, 13 Aug 2017 01:14:52 +0530 Subject: [PATCH 15/65] Add remove modal. --- .../learner_dashboard/LearnerDashboard.js | 2 +- .../dev/head/pages/library/Library.js | 81 +++++++++++++++++-- .../dev/head/pages/library/library.html | 18 +++++ 3 files changed, 94 insertions(+), 7 deletions(-) diff --git a/core/templates/dev/head/pages/learner_dashboard/LearnerDashboard.js b/core/templates/dev/head/pages/learner_dashboard/LearnerDashboard.js index 90c6337ec86a..ccbd533259f6 100644 --- a/core/templates/dev/head/pages/learner_dashboard/LearnerDashboard.js +++ b/core/templates/dev/head/pages/learner_dashboard/LearnerDashboard.js @@ -409,7 +409,7 @@ oppia.controller('LearnerDashboard', [ } } }); - } + }; $rootScope.loadingMessage = 'Loading'; LearnerDashboardBackendApiService.fetchLearnerDashboardData().then( diff --git a/core/templates/dev/head/pages/library/Library.js b/core/templates/dev/head/pages/library/Library.js index fc1c73959a90..47300ffd39f4 100644 --- a/core/templates/dev/head/pages/library/Library.js +++ b/core/templates/dev/head/pages/library/Library.js @@ -27,11 +27,11 @@ oppia.constant('LIBRARY_PAGE_MODES', { }); oppia.controller('Library', [ - '$scope', '$http', '$rootScope', '$window', '$timeout', 'i18nIdService', - 'urlService', 'ALL_CATEGORIES', 'searchService', 'windowDimensionsService', - 'UrlInterpolationService', 'LIBRARY_PAGE_MODES', 'LIBRARY_TILE_WIDTH_PX', - function( - $scope, $http, $rootScope, $window, $timeout, i18nIdService, + '$scope', '$http', '$modal', '$rootScope', '$window', '$timeout', + 'i18nIdService', 'urlService', 'ALL_CATEGORIES', 'searchService', + 'windowDimensionsService', 'UrlInterpolationService', 'LIBRARY_PAGE_MODES', + 'LIBRARY_TILE_WIDTH_PX', function( + $scope, $http, $modal, $rootScope, $window, $timeout, i18nIdService, urlService, ALL_CATEGORIES, searchService, windowDimensionsService, UrlInterpolationService, LIBRARY_PAGE_MODES, LIBRARY_TILE_WIDTH_PX) { $rootScope.loadingMessage = 'I18N_LIBRARY_LOADING'; @@ -152,9 +152,78 @@ oppia.controller('Library', [ var addActivityToLearnerPlaylistUrl = ( UrlInterpolationService.interpolateUrl( '/learnerplaylistactivityhandler//', { - activityType: activityType, activityId: activityId + activityType: activityType, + activityId: activityId })); $http.post(addActivityToLearnerPlaylistUrl, {}); + + if (activityType == constants.ACTIVITY_TYPE_EXPLORATION) { + $scope.learnerDashboardActivityIds.exploration_playlist_ids.push( + activityId); + } else { + $scope.learnerDashboardActivityIds.collection_playlist_ids.push( + activityId); + } + }; + + $scope.removeFromLearnerPlaylist = function( + activityId, activityType, activityTitle) { + $modal.open({ + templateUrl: 'modals/removeActivity', + backdrop: true, + resolve: { + activityId: function() { + return activityId; + }, + activityType: function() { + return activityType; + }, + activityTitle: function() { + return activityTitle; + } + }, + controller: [ + '$scope', '$modalInstance', '$http', 'UrlInterpolationService', + function($scope, $modalInstance, $http, UrlInterpolationService) { + $scope.sectionNameI18nId = ( + 'I18N_LEARNER_DASHBOARD_PLAYLIST_SECTION'); + $scope.activityTitle = activityTitle; + var removeFromLearnerPlaylistUrl = ( + UrlInterpolationService.interpolateUrl( + '/learnerplaylistactivityhandler//', { + activityType: activityType, + activityId: activityId + })); + + $scope.remove = function() { + $http['delete'](removeFromLearnerPlaylistUrl); + $modalInstance.close(); + }; + + $scope.cancel = function() { + $modalInstance.dismiss('cancel'); + }; + } + ] + }).result.then(function() { + if (activityType == constants.ACTIVITY_TYPE_EXPLORATION) { + var index = ( + $scope.learnerDashboardActivityIds.exploration_playlist_ids.indexOf( + activityId)); + if (index !== -1) { + $scope.learnerDashboardActivityIds.exploration_playlist_ids.splice( + index, 1); + } + } else { + var index = ( + $scope.learnerDashboardActivityIds.collection_playlist_ids.indexOf( + activityId)); + if (index !== -1) { + $scope.learnerDashboardActivityIds.collection_playlist_ids.splice( + index, 1); + } + } + }); }; // If the value below is changed, the following CSS values in oppia.css diff --git a/core/templates/dev/head/pages/library/library.html b/core/templates/dev/head/pages/library/library.html index 252a0fc34df7..f2b8056bf757 100644 --- a/core/templates/dev/head/pages/library/library.html +++ b/core/templates/dev/head/pages/library/library.html @@ -127,6 +127,7 @@

@@ -228,6 +229,23 @@

+ + + + + + + {% include 'pages/library/search_results_directive.html' %} {% endblock %} From 6e3711078a3b7ec8b89da9c7fd4d3fddb5f8473f Mon Sep 17 00:00:00 2001 From: Arunabh98 Date: Sun, 13 Aug 2017 21:17:30 +0530 Subject: [PATCH 16/65] Add playlist to dashboard. --- assets/i18n/en.json | 6 ++ assets/i18n/qqq.json | 6 ++ .../learner_dashboard/LearnerDashboard.js | 10 +- .../learner_dashboard/learner_dashboard.html | 101 ++++++++++++++++++ 4 files changed, 121 insertions(+), 2 deletions(-) diff --git a/assets/i18n/en.json b/assets/i18n/en.json index fbfcc2af3b8f..2b06a17dbf68 100644 --- a/assets/i18n/en.json +++ b/assets/i18n/en.json @@ -202,16 +202,22 @@ "I18N_LANGUAGE_FOOTER_VIEW_IN": "View Oppia in:", "I18N_LEARNER_DASHBOARD_COMPLETED_SECTION": "Completed", "I18N_LEARNER_DASHBOARD_COMPLETED_TO_INCOMPLETE_COLLECTIONS": "<[numberMoved]> of the collections you completed have been moved to the 'in progress' section as new explorations have been added to them!", + "I18N_LEARNER_DASHBOARD_DELETED_COLLECTIONS_FROM_PLAYLIST": "<[numberDeleted]> of the collections in your 'PLay Later' list have been recently deleted. We are sorry for the inconvenience", + "I18N_LEARNER_DASHBOARD_DELETED_COLLECTION_FROM_PLAYLIST": "<[numberDeleted]> of the collections in your 'PLay Later' list has been recently deleted. We are sorry for the inconvenience", "I18N_LEARNER_DASHBOARD_DELETED_COMPLETED_COLLECTION": "<[numberDeleted]> of the collections which you completed has been recently deleted. We are sorry for the inconvenience", "I18N_LEARNER_DASHBOARD_DELETED_COMPLETED_COLLECTIONS": "<[numberDeleted]> of the collections which you completed have been recently deleted. We are sorry for the inconvenience", "I18N_LEARNER_DASHBOARD_DELETED_COMPLETED_EXPLORATION": "<[numberDeleted]> of the explorations which you completed has been recently deleted. We are sorry for the inconvenience", "I18N_LEARNER_DASHBOARD_DELETED_COMPLETED_EXPLORATIONS": "<[numberDeleted]> of the explorations which you completed have been recently deleted. We are sorry for the inconvenience", + "I18N_LEARNER_DASHBOARD_DELETED_EXPLORATIONS_FROM_PLAYLIST": "<[numberDeleted]> of the explorations in your 'PLay Later' list have been recently deleted. We are sorry for the inconvenience", + "I18N_LEARNER_DASHBOARD_DELETED_EXPLORATION_FROM_PLAYLIST": "<[numberDeleted]> of the explorations in your 'PLay Later' list has been recently deleted. We are sorry for the inconvenience", "I18N_LEARNER_DASHBOARD_DELETED_INCOMPLETE_COLLECTION": "<[numberDeleted]> of the collections in progress has been recently deleted. We are sorry for the inconvenience", "I18N_LEARNER_DASHBOARD_DELETED_INCOMPLETE_COLLECTIONS": "<[numberDeleted]> of the collections in progress have been recently deleted. We are sorry for the inconvenience", "I18N_LEARNER_DASHBOARD_DELETED_INCOMPLETE_EXPLORATION": "<[numberDeleted]> of the explorations in progress has been recently deleted. We are sorry for the inconvenience", "I18N_LEARNER_DASHBOARD_DELETED_INCOMPLETE_EXPLORATIONS": "<[numberDeleted]> of the explorations in progress have been recently deleted. We are sorry for the inconvenience", + "I18N_LEARNER_DASHBOARD_EMPTY_COLLECTION_PLAYLIST": "It looks like there aren't any collections in your 'Play Later' list. Head over to the library and build your own curated playlist!", "I18N_LEARNER_DASHBOARD_EMPTY_COMPLETED_COLLECTIONS": "It looks like you haven't completed any collections yet. Head over to the library to start an exciting new collection!", "I18N_LEARNER_DASHBOARD_EMPTY_COMPLETED_EXPLORATIONS": "It looks like you haven't completed any explorations yet. Head over to the library to start an exciting new exploration!", + "I18N_LEARNER_DASHBOARD_EMPTY_EXPLORATION_PLAYLIST": "It looks like there aren't any explorations in your 'Play Later' list. Head over to the library and build your own curated playlist!", "I18N_LEARNER_DASHBOARD_EMPTY_FEEDBACK_THREADS": "It looks like you don't have any active feedback threads. Your feedback helps us improve the quality of our lessons. Head over to the library to learn something exciting and submit your valuable feedback!", "I18N_LEARNER_DASHBOARD_EMPTY_INCOMPLETE_COLLECTIONS": "It looks like you haven't started any collections yet. Head over to the library to start an exciting new collection!", "I18N_LEARNER_DASHBOARD_EMPTY_INCOMPLETE_EXPLORATIONS": "It looks like you haven't started any explorations yet. Head over to the library to start an exciting new exploration!", diff --git a/assets/i18n/qqq.json b/assets/i18n/qqq.json index 055205e57f86..087b821ff25c 100644 --- a/assets/i18n/qqq.json +++ b/assets/i18n/qqq.json @@ -202,16 +202,22 @@ "I18N_LANGUAGE_FOOTER_VIEW_IN": "Text for the site language selector. - When the user selects a different language, the site (not the explorations) is translated into that language.", "I18N_LEARNER_DASHBOARD_COMPLETED_SECTION": "Text for the completed section in the learner dashboard.", "I18N_LEARNER_DASHBOARD_COMPLETED_TO_INCOMPLETE_COLLECTIONS": "Text displayed in the learner dashboard. - The text is shown when new exporations are added to the collections the user has already completed.", + "I18N_LEARNER_DASHBOARD_DELETED_COLLECTIONS_FROM_PLAYLIST": "Text displayed in the learner dashboard. - This text is shown when more than one collections in the playlist have been deleted.", + "I18N_LEARNER_DASHBOARD_DELETED_COLLECTION_FROM_PLAYLIST": "Text displayed in the learner dashboard. - This text is shown when a collection in the playlist has been deleted.", "I18N_LEARNER_DASHBOARD_DELETED_COMPLETED_COLLECTION": "Text displayed in the learner dashboard. - This text is shown when a completed collection has been deleted.", "I18N_LEARNER_DASHBOARD_DELETED_COMPLETED_COLLECTIONS": "Text displayed in the learner dashboard. - This text is shown when more than one completed collection has been deleted.", "I18N_LEARNER_DASHBOARD_DELETED_COMPLETED_EXPLORATION": "Text displayed in the learner dashboard. - This text is shown when a completed exploration has been deleted.", "I18N_LEARNER_DASHBOARD_DELETED_COMPLETED_EXPLORATIONS": "Text displayed in the learner dashboard. - This text is shown when more than one completed exploration has been deleted.", + "I18N_LEARNER_DASHBOARD_DELETED_EXPLORATIONS_FROM_PLAYLIST": "Text displayed in the learner dashboard. - This text is shown when more than one explorations in the playlist have been deleted.", + "I18N_LEARNER_DASHBOARD_DELETED_EXPLORATION_FROM_PLAYLIST": "Text displayed in the learner dashboard. - This text is shown when an exploration in the playlist has been deleted.", "I18N_LEARNER_DASHBOARD_DELETED_INCOMPLETE_COLLECTION": "Text displayed in the learner dashboard. - This text is shown when a collection in progress has been deleted.", "I18N_LEARNER_DASHBOARD_DELETED_INCOMPLETE_COLLECTIONS": "Text displayed in the learner dashboard. - This text is shown when more than one collection in progress has been deleted.", "I18N_LEARNER_DASHBOARD_DELETED_INCOMPLETE_EXPLORATION": "Text displayed in the learner dashboard. - This text is shown when an exploration in progress has been deleted.", "I18N_LEARNER_DASHBOARD_DELETED_INCOMPLETE_EXPLORATIONS": "Text displayed in the learner dashboard. - This text is shown when more than one exploration in progress has been deleted.", + "I18N_LEARNER_DASHBOARD_EMPTY_COLLECTION_PLAYLIST": "Text displayed in the learner dashboard. - This text is shown when there are no collections in the playlist of the user.", "I18N_LEARNER_DASHBOARD_EMPTY_COMPLETED_COLLECTIONS": "Text displayed in the learner dashboard. - This text is shown when there are no collections in the completed section of the user.", "I18N_LEARNER_DASHBOARD_EMPTY_COMPLETED_EXPLORATIONS": "Text displayed in the learner dashboard. - This text is shown when there are no explorations in the completed section of the user.", + "I18N_LEARNER_DASHBOARD_EMPTY_EXPLORATION_PLAYLIST": "Text displayed in the learner dashboard. - This text is shown when there are no explorations in the playlist of the user.", "I18N_LEARNER_DASHBOARD_EMPTY_FEEDBACK_THREADS": "Text displayed in the learner dashboard. - This text is shown when there are no feedback threads to which the user is subscribed.", "I18N_LEARNER_DASHBOARD_EMPTY_INCOMPLETE_COLLECTIONS": "Text displayed in the learner dashboard. - This text is shown when there are no collections in the incomplete section of the user.", "I18N_LEARNER_DASHBOARD_EMPTY_INCOMPLETE_EXPLORATIONS": "Text displayed in the learner dashboard. - This text is shown when there are no explorations in the incomplete section of the user.", diff --git a/core/templates/dev/head/pages/learner_dashboard/LearnerDashboard.js b/core/templates/dev/head/pages/learner_dashboard/LearnerDashboard.js index ccbd533259f6..56d10fb7e45a 100644 --- a/core/templates/dev/head/pages/learner_dashboard/LearnerDashboard.js +++ b/core/templates/dev/head/pages/learner_dashboard/LearnerDashboard.js @@ -455,6 +455,12 @@ oppia.controller('LearnerDashboard', [ $scope.numberDeletedCompletedCollections = ( responseData.number_of_deleted_activities.completed_collections ); + $scope.numberDeletedExplorationPlaylist = ( + responseData.number_of_deleted_activities.exploration_playlist + ); + $scope.numberDeletedCollectionPlaylist = ( + responseData.number_of_deleted_activities.collection_playlist + ); $scope.completedToIncompleteCollections = ( responseData.completed_to_incomplete_collections ); @@ -466,8 +472,8 @@ oppia.controller('LearnerDashboard', [ threadSummaryDicts[index])); } $scope.numberOfUnreadThreads = responseData.number_of_unread_threads; - $scope.explorationPLaylist = responseData.exploration_playlist; - console.log($scope.explorationPLaylist); + $scope.explorationPlaylist = responseData.exploration_playlist; + $scope.collectionPlaylist = responseData.collection_playlist; $scope.activeSection = LEARNER_DASHBOARD_SECTION_I18N_IDS.INCOMPLETE; $scope.activeSubsection = ( LEARNER_DASHBOARD_SUBSECTION_I18N_IDS.EXPLORATIONS); diff --git a/core/templates/dev/head/pages/learner_dashboard/learner_dashboard.html b/core/templates/dev/head/pages/learner_dashboard/learner_dashboard.html index efc438a519d6..0d202a27c94a 100644 --- a/core/templates/dev/head/pages/learner_dashboard/learner_dashboard.html +++ b/core/templates/dev/head/pages/learner_dashboard/learner_dashboard.html @@ -326,6 +326,56 @@

<[subscriptionsList.length]>

+
+ + + + ☹ + + + +
+

+ + + +
+
+ +
+ + + +
+
+
@@ -381,6 +431,55 @@

<[subscriptionsList.length]>

+ +
+ + + + ☹ + + + +
+

+ + + +
+
+ +
+ + + +
+
+
@@ -442,6 +541,8 @@

<[subscriptionsList.length]>

+ +
Date: Tue, 15 Aug 2017 12:29:14 +0530 Subject: [PATCH 17/65] Add backend feedback. --- core/controllers/learner_playlist.py | 22 ++- core/domain/learner_playlist_services.py | 20 +++ core/domain/learner_progress_services.py | 28 ++- .../ExplorationPlaylistTileDirective.js | 162 ++++++++++++++++++ .../exploration_playlist_tile_directive.html | 68 ++++++++ .../learner_dashboard/learner_dashboard.html | 5 +- .../dev/head/pages/library/Library.js | 6 +- .../dev/head/pages/library/library.html | 6 +- 8 files changed, 303 insertions(+), 14 deletions(-) create mode 100644 core/templates/dev/head/components/playlist_tile/ExplorationPlaylistTileDirective.js create mode 100644 core/templates/dev/head/components/playlist_tile/exploration_playlist_tile_directive.html diff --git a/core/controllers/learner_playlist.py b/core/controllers/learner_playlist.py index 69e84b3a55d6..ff98ce5b7cb5 100644 --- a/core/controllers/learner_playlist.py +++ b/core/controllers/learner_playlist.py @@ -28,11 +28,25 @@ class LearnerPlaylistHandler(base.BaseHandler): def post(self, activity_type, activity_id): position_to_be_inserted_in = self.payload.get('index') if activity_type == constants.ACTIVITY_TYPE_EXPLORATION: - learner_progress_services.add_exp_to_learner_playlist( - self.user_id, activity_id, position_to_be_inserted_in) + (belongs_to_completed_or_incomplete_list, + playlist_limit_exceeded, + belongs_to_subscribed_activities) = ( + learner_progress_services.add_exp_to_learner_playlist( + self.user_id, activity_id, position_to_be_inserted_in)) elif activity_type == constants.ACTIVITY_TYPE_COLLECTION: - learner_progress_services.add_collection_to_learner_playlist( - self.user_id, activity_id, position_to_be_inserted_in) + (belongs_to_completed_or_incomplete_list, + playlist_limit_exceeded, + belongs_to_subscribed_activities) = ( + learner_progress_services.add_collection_to_learner_playlist( + self.user_id, activity_id, position_to_be_inserted_in)) + + self.values.update({ + 'belongs_to_completed_or_incomplete_list': ( + belongs_to_completed_or_incomplete_list), + 'playlist_limit_exceeded': playlist_limit_exceeded, + 'belongs_to_subscribed_activities': ( + belongs_to_subscribed_activities) + }) self.render_json(self.values) diff --git a/core/domain/learner_playlist_services.py b/core/domain/learner_playlist_services.py index ceb3077f4939..927c66eac1fa 100644 --- a/core/domain/learner_playlist_services.py +++ b/core/domain/learner_playlist_services.py @@ -92,22 +92,32 @@ def mark_exploration_to_be_played_later( 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 def mark_collection_to_be_played_later( @@ -140,22 +150,32 @@ def mark_collection_to_be_played_later( learner_playlist = get_learner_playlist_from_model( learner_playlist_model) + playlist_limit_exceeded = False + collection_belongs_to_subscribed_collections = False if collection_id not in subscribed_collection_ids: collection_ids_count = len(learner_playlist.collection_ids) if position_to_be_inserted is None: if collection_id not in learner_playlist.collection_ids: if collection_ids_count < MAX_LEARNER_PLAYLIST_ACTIVITY_COUNT: learner_playlist.add_collection_id_to_list(collection_id) + else: + playlist_limit_exceeded = True else: if collection_id not in learner_playlist.collection_ids: if collection_ids_count < MAX_LEARNER_PLAYLIST_ACTIVITY_COUNT: learner_playlist.insert_collection_id_at_given_position( collection_id, position_to_be_inserted) + else: + playlist_limit_exceeded = True else: learner_playlist.remove_collection_id(collection_id) learner_playlist.insert_collection_id_at_given_position( collection_id, position_to_be_inserted) save_learner_playlist(learner_playlist) + else: + collection_belongs_to_subscribed_collections = True + + return playlist_limit_exceeded, collection_belongs_to_subscribed_collections def remove_exploration_from_learner_playlist(user_id, exploration_id): diff --git a/core/domain/learner_progress_services.py b/core/domain/learner_progress_services.py index 16c27c809785..2b6358c04d66 100644 --- a/core/domain/learner_progress_services.py +++ b/core/domain/learner_progress_services.py @@ -324,14 +324,26 @@ def add_exp_to_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. It is true if the exploration being added belongs to the completed + or incomplete list. """ completed_exploration_ids = get_all_completed_exp_ids(user_id) incomplete_exploration_ids = get_all_incomplete_exp_ids(user_id) if (exploration_id not in completed_exploration_ids and exploration_id not in incomplete_exploration_ids): - learner_playlist_services.mark_exploration_to_be_played_later( - user_id, exploration_id, position_to_be_inserted) + playlist_limit_exceeded, belongs_to_subscribed_activities = ( + learner_playlist_services.mark_exploration_to_be_played_later( + user_id, exploration_id, position_to_be_inserted)) + belongs_to_completed_or_incomplete_list = False + else: + belongs_to_completed_or_incomplete_list = True + + return (belongs_to_completed_or_incomplete_list, + playlist_limit_exceeded, + belongs_to_subscribed_activities) def add_collection_to_learner_playlist( @@ -353,8 +365,16 @@ def add_collection_to_learner_playlist( if (collection_id not in completed_collection_ids and collection_id not in incomplete_collection_ids): - learner_playlist_services.mark_collection_to_be_played_later( - user_id, collection_id, position_to_be_inserted) + playlist_limit_exceeded, belongs_to_subscribed_activities = ( + learner_playlist_services.mark_collection_to_be_played_later( + user_id, collection_id, position_to_be_inserted)) + belongs_to_completed_or_incomplete_list = False + else: + belongs_to_completed_or_incomplete_list = True + + return (belongs_to_completed_or_incomplete_list, + playlist_limit_exceeded, + belongs_to_subscribed_activities) def _remove_activity_ids_from_playlist(user_id, exploration_ids, diff --git a/core/templates/dev/head/components/playlist_tile/ExplorationPlaylistTileDirective.js b/core/templates/dev/head/components/playlist_tile/ExplorationPlaylistTileDirective.js new file mode 100644 index 000000000000..ef5a9ec38d76 --- /dev/null +++ b/core/templates/dev/head/components/playlist_tile/ExplorationPlaylistTileDirective.js @@ -0,0 +1,162 @@ +// Copyright 2015 The Oppia Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS-IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/** + * @fileoverview Component for an exploration summary tile. + */ + +oppia.directive('explorationPlaylistTile', [ + 'UrlInterpolationService', function(UrlInterpolationService) { + return { + restrict: 'E', + scope: { + getCollectionId: '&collectionId', + getExplorationId: '&explorationId', + getExplorationTitle: '&explorationTitle', + getLastUpdatedMsec: '&lastUpdatedMsec', + getNumViews: '&numViews', + getObjective: '&objective', + getCategory: '&category', + getRatings: '&ratings', + getContributorsSummary: '&contributorsSummary', + getThumbnailIconUrl: '&thumbnailIconUrl', + getThumbnailBgColor: '&thumbnailBgColor', + // If this is not null, the new exploration opens in a new window when + // the summary tile is clicked. + openInNewWindow: '@openInNewWindow', + isCommunityOwned: '&isCommunityOwned', + // If this is not undefined, collection preview tile for mobile + // will be displayed. + isCollectionPreviewTile: '@isCollectionPreviewTile', + // If the screen width is below the threshold defined here, the mobile + // version of the summary tile is displayed. This attribute is optional: + // if it is not specified, it is treated as 0, which means that the + // desktop version of the summary tile is always displayed. + mobileCutoffPx: '@mobileCutoffPx' + }, + templateUrl: UrlInterpolationService.getDirectiveTemplateUrl( + '/components/summary_tile/' + + 'exploration_summary_tile_directive.html'), + link: function(scope, element) { + element.find('.exploration-summary-avatars').on('mouseenter', + function() { + element.find('.mask').attr('class', + 'exploration-summary-tile-mask mask'); + // As animation duration time may be 400ms, .stop(true) is used to + // prevent the effects queue falling behind the mouse movement. + // .hide(1) and .show(1) used to place the animation in the effects + // queue. + element.find('.avatars-num-minus-one').stop(true).hide(1, + function() { + element.find('.all-avatars').stop(true).slideDown(); + } + ); + } + ); + + element.find('.exploration-summary-avatars').on('mouseleave', + function() { + element.find('.mask').attr('class', 'top-section-mask mask'); + element.find('.all-avatars').stop(true).slideUp(400, function() { + element.find('.avatars-num-minus-one').stop(true).show(1); + }); + } + ); + }, + controller: [ + '$scope', '$http', + 'oppiaDatetimeFormatter', 'RatingComputationService', + 'windowDimensionsService', + function( + $scope, $http, + oppiaDatetimeFormatter, RatingComputationService, + windowDimensionsService) { + var contributorsSummary = $scope.getContributorsSummary() || {}; + $scope.contributors = Object.keys( + contributorsSummary).sort( + function(contributorUsername1, contributorUsername2) { + var commitsOfContributor1 = contributorsSummary[ + contributorUsername1].num_commits; + var commitsOfContributor2 = contributorsSummary[ + contributorUsername2].num_commits; + return commitsOfContributor2 - commitsOfContributor1; + } + ); + + $scope.avatarsList = []; + if ($scope.isCommunityOwned()) { + var COMMUNITY_OWNED_IMAGE_PATH = ( + UrlInterpolationService.getStaticImageUrl( + '/avatar/fa_globe_72px.png')); + + var COMMUNITY_OWNED_TOOLTIP_TEXT = 'Community Owned'; + + var communityOwnedAvatar = { + image: COMMUNITY_OWNED_IMAGE_PATH, + tooltipText: COMMUNITY_OWNED_TOOLTIP_TEXT + }; + + $scope.avatarsList.unshift(communityOwnedAvatar); + } + + $scope.MAX_AVATARS_TO_DISPLAY = 5; + + $scope.getAverageRating = function() { + if (!$scope.getRatings()) { + return null; + } + return RatingComputationService.computeAverageRating( + $scope.getRatings()); + }; + + $scope.getLastUpdatedDatetime = function() { + if (!$scope.getLastUpdatedMsec()) { + return null; + } + return oppiaDatetimeFormatter.getLocaleAbbreviatedDatetimeString( + $scope.getLastUpdatedMsec()); + }; + + $scope.getExplorationLink = function() { + if (!$scope.getExplorationId()) { + return '#'; + } else { + var result = '/explore/' + $scope.getExplorationId(); + if ($scope.getCollectionId()) { + result += ('?collection_id=' + $scope.getCollectionId()); + } + } + return result; + }; + + if (!$scope.mobileCutoffPx) { + $scope.mobileCutoffPx = 0; + } + $scope.isWindowLarge = ( + windowDimensionsService.getWidth() >= $scope.mobileCutoffPx); + + windowDimensionsService.registerOnResizeHook(function() { + $scope.isWindowLarge = ( + windowDimensionsService.getWidth() >= $scope.mobileCutoffPx); + $scope.$apply(); + }); + + $scope.getCompleteThumbnailIconUrl = function () { + return UrlInterpolationService.getStaticImageUrl( + $scope.getThumbnailIconUrl()); + }; + } + ] + }; + }]); diff --git a/core/templates/dev/head/components/playlist_tile/exploration_playlist_tile_directive.html b/core/templates/dev/head/components/playlist_tile/exploration_playlist_tile_directive.html new file mode 100644 index 000000000000..976ce2e595e9 --- /dev/null +++ b/core/templates/dev/head/components/playlist_tile/exploration_playlist_tile_directive.html @@ -0,0 +1,68 @@ + + +
+ <[getCategory()]> +

+ <[getExplorationTitle()|truncate:40]> + <[getExplorationTitle()|truncate:40]> +

+ + +
+
+ + +
+
+
+
+
+ <[getObjective() | truncateAndCapitalize: 95]> +
+
+ + +
+
    +
  • + + + <['I18N_LIBRARY_RATINGS_TOOLTIP' | translate]> + + + <[getAverageRating() | number:1]> + + + + +
  • +
  • + + <['I18N_LIBRARY_VIEWS_TOOLTIP' | translate]> + + + <[getNumViews() | summarizeNonnegativeNumber]> + + + +
  • +
  • + + Last Updated + <[getLastUpdatedDatetime()]> + + + +
  • +
+ +
+
+
diff --git a/core/templates/dev/head/pages/learner_dashboard/learner_dashboard.html b/core/templates/dev/head/pages/learner_dashboard/learner_dashboard.html index 0d202a27c94a..d9975cb57685 100644 --- a/core/templates/dev/head/pages/learner_dashboard/learner_dashboard.html +++ b/core/templates/dev/head/pages/learner_dashboard/learner_dashboard.html @@ -361,7 +361,7 @@

<[subscriptionsList.length]>

ng-click="openRemoveActivityModal(activeSection, activeSubsection, tile)" tooltip="Remove" tooltip-placement="top"> - <[subscriptionsList.length]>

thumbnail-icon-url="tile.thumbnail_icon_url" thumbnail-bg-color="tile.thumbnail_bg_color" class="protractor-test-exp-summary-tile"> - + @@ -793,6 +793,7 @@

+ diff --git a/core/templates/dev/head/pages/library/Library.js b/core/templates/dev/head/pages/library/Library.js index 47300ffd39f4..741a0c626b69 100644 --- a/core/templates/dev/head/pages/library/Library.js +++ b/core/templates/dev/head/pages/library/Library.js @@ -155,7 +155,11 @@ oppia.controller('Library', [ activityType: activityType, activityId: activityId })); - $http.post(addActivityToLearnerPlaylistUrl, {}); + $http.post(addActivityToLearnerPlaylistUrl, {}) + .then(function(response) { + // DO MODALS JOBS OVER HERE. + console.log(response.data.playlist_limit_exceeded); + }); if (activityType == constants.ACTIVITY_TYPE_EXPLORATION) { $scope.learnerDashboardActivityIds.exploration_playlist_ids.push( diff --git a/core/templates/dev/head/pages/library/library.html b/core/templates/dev/head/pages/library/library.html index 06371057b991..d4ed888d7478 100644 --- a/core/templates/dev/head/pages/library/library.html +++ b/core/templates/dev/head/pages/library/library.html @@ -126,18 +126,18 @@

" tooltip-placement="left"> From 35506ca9cbb9e23decf69af79d5697d3374c5654 Mon Sep 17 00:00:00 2001 From: Arunabh98 Date: Tue, 15 Aug 2017 13:44:27 +0530 Subject: [PATCH 18/65] Remove unncessary code. --- core/domain/rights_manager.py | 43 ----------------------------------- 1 file changed, 43 deletions(-) diff --git a/core/domain/rights_manager.py b/core/domain/rights_manager.py index b8bf03c33105..8388b4f1a946 100644 --- a/core/domain/rights_manager.py +++ b/core/domain/rights_manager.py @@ -849,49 +849,6 @@ def can_release_ownership(self, activity_type, activity_id): return False return self.can_modify_roles(activity_type, activity_id) - def can_publicize(self, activity_type, activity_id): - """Returns whether this user is allowed to publicize the given - activity. - - Args: - activity_type: str. The type of activity. Possible values: - constants.ACTIVITY_TYPE_EXPLORATION - constants.ACTIVITY_TYPE_COLLECTION - activity_id: str. ID of the activity. - - Returns: - bool. Whether the user has a right to publicize the given activity. - """ - activity_rights = _get_activity_rights(activity_type, activity_id) - if activity_rights is None: - return False - - if activity_rights.status != ACTIVITY_STATUS_PUBLIC: - return False - return self.is_moderator() - - def can_unpublicize(self, activity_type, activity_id): - """Returns whether this user is allowed to unpublicize the given - activity. - - Args: - activity_type: str. The type of activity. Possible values: - constants.ACTIVITY_TYPE_EXPLORATION - constants.ACTIVITY_TYPE_COLLECTION - activity_id: str. ID of the activity. - - Returns: - bool. Whether the user has a right to unpublicize the given - activity. - """ - activity_rights = _get_activity_rights(activity_type, activity_id) - if activity_rights is None: - return False - - if activity_rights.status != ACTIVITY_STATUS_PUBLICIZED: - return False - return self.is_moderator() - def _assign_role( committer_id, assignee_id, new_role, activity_id, activity_type): From e792b12737d5b3cb177dfd047e97102c7574dc3b Mon Sep 17 00:00:00 2001 From: Arunabh98 Date: Tue, 15 Aug 2017 13:56:57 +0530 Subject: [PATCH 19/65] Fix rights manager. --- core/domain/rights_manager.py | 236 ---------------------------------- 1 file changed, 236 deletions(-) diff --git a/core/domain/rights_manager.py b/core/domain/rights_manager.py index 8388b4f1a946..e9fe427f0a27 100644 --- a/core/domain/rights_manager.py +++ b/core/domain/rights_manager.py @@ -77,7 +77,6 @@ def __init__(self, exploration_id, owner_ids, editor_ids, viewer_ids, def validate(self): """Validates an ActivityRights object. - Raises: utils.ValidationError: if any of the owners, editors and viewers lists overlap, or if a community-owned exploration has owners, @@ -115,7 +114,6 @@ def validate(self): def to_dict(self): """Returns a dict suitable for use by the frontend. - Returns: dict. A dict version of ActivityRights suitable for use by the frontend. @@ -146,10 +144,8 @@ def to_dict(self): def is_owner(self, user_id): """Checks whether given user is owner of activity. - Args: user_id: str or None. Id of the user. - Returns: bool. Whether user is in activity owners. """ @@ -157,10 +153,8 @@ def is_owner(self, user_id): def is_editor(self, user_id): """Checks whether given user is editor of activity. - Args: user_id: str or None. Id of the user. - Returns: bool. Whether user is in activity editors. """ @@ -168,10 +162,8 @@ def is_editor(self, user_id): def is_viewer(self, user_id): """Checks whether given user is viewer of activity. - Args: user_id: str or None. Id of the user. - Returns: bool. Whether user is in activity viewers of. """ @@ -179,7 +171,6 @@ def is_viewer(self, user_id): def is_published(self): """Checks whether activity is published. - Returns: bool. Whether activity is published. """ @@ -187,7 +178,6 @@ def is_published(self): def is_private(self): """Checks whether activity is private. - Returns: bool. Whether activity is private. """ @@ -196,14 +186,12 @@ def is_private(self): def _get_activity_rights_from_model(activity_rights_model, activity_type): """Constructs an ActivityRights object from the given activity rights model. - Args: activity_rights_model: ActivityRightsModel. Activity rights from the datastore. activity_type: str. The type of activity. Possible values: constants.ACTIVITY_TYPE_EXPLORATION constants.ACTIVITY_TYPE_COLLECTION - Returns: ActivityRights. The rights object created from the model. """ @@ -227,7 +215,6 @@ def _save_activity_rights( commit_cmds): """Saves an ExplorationRights or CollectionRights domain object to the datastore. - Args: committer_id: str. ID of the committer. activity_rights: ActivityRights. The rights object for the given @@ -261,9 +248,7 @@ def _save_activity_rights( def _update_exploration_summary(activity_rights): """Updates the exploration summary for the activity associated with the given rights object. - The ID of rights object is the same as the ID of associated activity. - Args: activity_rights: ActivityRights. The rights object for the given activity. @@ -277,9 +262,7 @@ def _update_exploration_summary(activity_rights): def _update_collection_summary(activity_rights): """Updates the collection summary for the given activity associated with the given rights object. - The ID of rights object is the same as the ID of associated activity. - Args: activity_rights: ActivityRights. The rights object for the given activity. @@ -292,9 +275,7 @@ def _update_collection_summary(activity_rights): def _update_activity_summary(activity_type, activity_rights): """Updates the activity summary for the given activity associated with the given rights object. - The ID of rights object is the same as the ID of associated activity. - Args: activity_type: str. The type of activity. Possible values: constants.ACTIVITY_TYPE_EXPLORATION @@ -311,10 +292,8 @@ def _update_activity_summary(activity_type, activity_rights): def update_activity_first_published_msec( activity_type, activity_id, first_published_msec): """Updates the first_published_msec field for the given activity. - The caller is responsible for ensuring that this value is not already set before updating it. - Args: activity_type: str. The type of activity. Possible values: constants.ACTIVITY_TYPE_EXPLORATION @@ -338,7 +317,6 @@ def update_activity_first_published_msec( def create_new_exploration_rights(exploration_id, committer_id): """Creates a new exploration rights object and saves it to the datastore. Subscribes the committer to the new exploration. - Args: exploration_id: str. ID of the exploration. committer_id: str. ID of the committer. @@ -364,15 +342,12 @@ def create_new_exploration_rights(exploration_id, committer_id): def get_exploration_rights(exploration_id, strict=True): """Retrieves the rights for this exploration from the datastore. - Args: exploration_id: str. ID of the exploration. strict: bool. Whether to raise an error if there is no exploration matching the given ID. - Returns: ActivityRights. The rights object for the given exploration. - Raises: EntityNotFoundError. The exploration with ID exploration_id was not found in the datastore. @@ -387,10 +362,8 @@ def get_exploration_rights(exploration_id, strict=True): def is_exploration_private(exploration_id): """Returns whether exploration is private. - Args: exploration_id: str. ID of the exploration. - Returns: bool. Whether the exploration is private or not. """ @@ -400,10 +373,8 @@ def is_exploration_private(exploration_id): def is_exploration_public(exploration_id): """Returns whether exploration is public. - Args: exploration_id: str. ID of the exploration. - Returns: bool. Whether the exploration is public. """ @@ -413,10 +384,8 @@ def is_exploration_public(exploration_id): def is_exploration_cloned(exploration_id): """Returns whether the exploration is a clone of another exploration. - Args: exploration_id: str. ID of the exploration. - Returns: bool. Whether the exploration is a clone of another exploration. """ @@ -427,7 +396,6 @@ def is_exploration_cloned(exploration_id): def create_new_collection_rights(collection_id, committer_id): """Creates a new collection rights object and saves it to the datastore. Subscribes the committer to the new collection. - Args: collection_id: str. ID of the collection. committer_id: str. ID of the committer. @@ -451,14 +419,11 @@ def create_new_collection_rights(collection_id, committer_id): def get_collection_rights(collection_id, strict=True): """Retrieves the rights for this collection from the datastore. - Args: collection_id: str. ID of the collection. strict: bool. Whether to raise an error if ID is not found. - Returns: ActivityRights. The rights object for the collection. - Raises: EntityNotFoundError. The collection with ID collection_id is not found in the datastore. @@ -473,10 +438,8 @@ def get_collection_rights(collection_id, strict=True): def get_collection_owner_names(collection_id): """Retrieves the owners for this collection from the datastore. - Args: collection_id: str. ID of the collection. - Returns: list(str). Human-readable usernames (or truncated email addresses) of owners for this collection. @@ -488,10 +451,8 @@ def get_collection_owner_names(collection_id): def is_collection_private(collection_id): """Returns whether the collection is private. - Args: collection_id: str. ID of the collection. - Returns: bool. Whether the collection is private. """ @@ -501,10 +462,8 @@ def is_collection_private(collection_id): def is_collection_public(collection_id): """Returns whether the collection is public. - Args: collection_id: str. ID of the collection. - Returns: bool. Whether the collection is public. """ @@ -515,16 +474,13 @@ def is_collection_public(collection_id): def _get_activity_rights(activity_type, activity_id): """Retrieves the rights object for the given activity based on its type. - Args: activity_type: str. The type of activity. Possible values: constants.ACTIVITY_TYPE_EXPLORATION constants.ACTIVITY_TYPE_COLLECTION activity_id: str. ID of the activity. - Returns: ActivityRights. The rights object associated with the given activity. - Raises: Exception. activity_type provided is unknown. """ @@ -553,7 +509,6 @@ def __init__(self, user_id): def is_admin(self): """Returns whether this user is an administrator. - Returns: bool. Whether this user is an administrator. """ @@ -563,7 +518,6 @@ def is_admin(self): def is_moderator(self): """Returns whether this user is a moderator. - Returns: bool. Whether this user is a moderator. """ @@ -619,13 +573,11 @@ def _can_delete(self, rights_object): def is_owner(self, activity_type, activity_id): """Returns whether this user is an owner of the given activity. - Args: activity_type: str. The type of activity. Possible values: constants.ACTIVITY_TYPE_EXPLORATION constants.ACTIVITY_TYPE_COLLECTION activity_id: str. ID of the activity. - Returns: bool. Whether the user is an owner of the given activity. """ @@ -636,13 +588,11 @@ def is_owner(self, activity_type, activity_id): def has_editing_rights(self, activity_type, activity_id): """Returns whether this user has editing rights for the given activity. - Args: activity_type: str. The type of activity. Possible values: constants.ACTIVITY_TYPE_EXPLORATION constants.ACTIVITY_TYPE_COLLECTION activity_id: str. ID of the activity. - Returns: bool. Whether the user is in the owner/editor list for the given activity. @@ -654,13 +604,11 @@ def has_editing_rights(self, activity_type, activity_id): def has_viewing_rights(self, activity_type, activity_id): """Returns whether this user has viewing rights for the given activity. - Args: activity_type: str. The type of activity. Possible values: constants.ACTIVITY_TYPE_EXPLORATION constants.ACTIVITY_TYPE_COLLECTION activity_id: str. ID of the activity. - Returns: bool. Whether the user has the right to view the given activity. """ @@ -671,13 +619,11 @@ def has_viewing_rights(self, activity_type, activity_id): def can_play(self, activity_type, activity_id): """Returns whether this user has rights to play the given activity. - Args: activity_type: str. The type of activity. Possible values: constants.ACTIVITY_TYPE_EXPLORATION constants.ACTIVITY_TYPE_COLLECTION activity_id: str. ID of the activity. - Returns: bool. Whether the user has the right to play the given activity. """ @@ -688,13 +634,11 @@ def can_play(self, activity_type, activity_id): def can_view(self, activity_type, activity_id): """Returns whether this user has rights to view the given activity. - Args: activity_type: str. The type of activity. Possible values: constants.ACTIVITY_TYPE_EXPLORATION constants.ACTIVITY_TYPE_COLLECTION activity_id: str. ID of the activity. - Returns: bool. Whether the user has the right to view the given activity. """ @@ -704,13 +648,11 @@ def can_view(self, activity_type, activity_id): # rather than having this check in the controller. def can_edit(self, activity_type, activity_id): """Returns whether this user has rights to edit the given activity. - Args: activity_type: str. The type of activity. Possible values: constants.ACTIVITY_TYPE_EXPLORATION constants.ACTIVITY_TYPE_COLLECTION activity_id: str. ID of the activity. - Returns: bool. Whether the user has the right to edit the given activity. """ @@ -721,13 +663,11 @@ def can_edit(self, activity_type, activity_id): def can_delete(self, activity_type, activity_id): """Returns whether this user has rights to delete the given activity. - Args: activity_type: str. The type of activity. Possible values: constants.ACTIVITY_TYPE_EXPLORATION constants.ACTIVITY_TYPE_COLLECTION activity_id: str. ID of the activity. - Returns: bool. Whether the user has the right to delete the given activity. """ @@ -740,16 +680,13 @@ def can_change_private_viewability( self, activity_type, activity_id): """Returns whether this user is allowed to change the viewability of the given private activity. - The caller is responsible for ensuring that the given activity is private. - Args: activity_type: str. The type of activity. Possible values: constants.ACTIVITY_TYPE_EXPLORATION constants.ACTIVITY_TYPE_COLLECTION activity_id: str. ID of the activity. - Returns: bool. Whether the user is allowed to change the viewability of the given private activity. @@ -759,13 +696,11 @@ def can_change_private_viewability( def can_publish(self, activity_type, activity_id): """Returns whether this user is allowed to publish the given activity. - Args: activity_type: str. The type of activity. Possible values: constants.ACTIVITY_TYPE_EXPLORATION constants.ACTIVITY_TYPE_COLLECTION activity_id: str. ID of the activity. - Returns: bool. Whether the user is allowed to publish the given activity. """ @@ -783,13 +718,11 @@ def can_publish(self, activity_type, activity_id): def can_unpublish(self, activity_type, activity_id): """Returns whether this user is allowed to unpublish the given activity. - Args: activity_type: str. The type of activity. Possible values: constants.ACTIVITY_TYPE_EXPLORATION constants.ACTIVITY_TYPE_COLLECTION activity_id: str. ID of the activity. - Returns: bool. Whether the user is allowed to unpublish the given activity. @@ -808,13 +741,11 @@ def can_unpublish(self, activity_type, activity_id): def can_modify_roles(self, activity_type, activity_id): """Returns whether this user has the right to modify roles for the given activity. - Args: activity_type: str. The type of activity. Possible values: constants.ACTIVITY_TYPE_EXPLORATION constants.ACTIVITY_TYPE_COLLECTION activity_id: str. ID of the activity. - Returns: bool. Whether the user has the right to modify roles for the given activity. @@ -830,13 +761,11 @@ def can_modify_roles(self, activity_type, activity_id): def can_release_ownership(self, activity_type, activity_id): """Returns whether this user is allowed to release ownership of the given activity to the community. - Args: activity_type: str. The type of activity. Possible values: constants.ACTIVITY_TYPE_EXPLORATION constants.ACTIVITY_TYPE_COLLECTION activity_id: str. ID of the activity. - Returns: bool. Whether the user is allowed to release ownership of the given activity to the community. @@ -853,7 +782,6 @@ def can_release_ownership(self, activity_type, activity_id): def _assign_role( committer_id, assignee_id, new_role, activity_id, activity_type): """Assigns a new role to the user. - Args: committer_id: str. ID of the user who is performing the action. activity_rights: ExplorationRightsModel|CollectionRightsModel. The @@ -867,7 +795,6 @@ def _assign_role( activity_type: str. The type of activity. Possible values: constants.ACTIVITY_TYPE_EXPLORATION constants.ACTIVITY_TYPE_COLLECTION - Raises: Exception. The committer does not have rights to modify a role. Exception. The user already owns the activity. @@ -948,14 +875,12 @@ def _assign_role( def _release_ownership_of_activity(committer_id, activity_id, activity_type): """Releases ownership of the given activity to the community. - Args: committer_id: str. ID of the user who is performing the action. activity_id: str. ID of the activity. activity_type: str. The type of activity. Possible values: constants.ACTIVITY_TYPE_EXPLORATION constants.ACTIVITY_TYPE_COLLECTION - Raise: Exception. The committer does not have release rights. """ @@ -985,7 +910,6 @@ def _release_ownership_of_activity(committer_id, activity_id, activity_type): def _change_activity_status( committer_id, activity_id, activity_type, new_status, commit_message): """Changes the status of the given activity. - Args: committer_id: str. ID of the user who is performing the update action. activity_id: str. ID of the activity. @@ -1022,14 +946,12 @@ def _change_activity_status( def _publish_activity(committer_id, activity_id, activity_type): """Publishes the given activity. - Args: committer_id: str. ID of the committer. activity_id: str. ID of the activity. activity_type: str. The type of activity. Possible values: constants.ACTIVITY_TYPE_EXPLORATION constants.ACTIVITY_TYPE_COLLECTION - Raises: Exception. The committer does not have rights to publish the activity. @@ -1047,14 +969,12 @@ def _publish_activity(committer_id, activity_id, activity_type): def _unpublish_activity(committer_id, activity_id, activity_type): """Unpublishes the given activity. - Args: committer_id: str. ID of the committer. activity_id: str. ID of the activity. activity_type: str. The type of activity. Possible values: constants.ACTIVITY_TYPE_EXPLORATION constants.ACTIVITY_TYPE_COLLECTION - Raises: Exception. The committer does not have rights to unpublish the activity. @@ -1072,65 +992,13 @@ def _unpublish_activity(committer_id, activity_id, activity_type): activity_services.remove_featured_activity(activity_type, activity_id) -def _publicize_activity(committer_id, activity_id, activity_type): - """Publicizes the given activity. - - Args: - committer_id: str. ID of the committer. - activity_id: str. ID of the activity. - activity_type: str. The type of activity. Possible values: - constants.ACTIVITY_TYPE_EXPLORATION - constants.ACTIVITY_TYPE_COLLECTION - - Raises: - Exception. The committer does not have rights to publicize the activity. - """ - if not Actor(committer_id).can_publicize(activity_type, activity_id): - logging.error( - 'User %s tried to publicize %s %s but was refused ' - 'permission.' % (committer_id, activity_type, activity_id)) - raise Exception('This %s cannot be marked as "featured".' % ( - activity_type)) - - _change_activity_status( - committer_id, activity_id, activity_type, ACTIVITY_STATUS_PUBLICIZED, - '%s publicized.' % activity_type) - - -def _unpublicize_activity(committer_id, activity_id, activity_type): - """Unpublicizes the given activity. - - Args: - committer_id: str. ID of the committer. - activity_id: str. ID of the activity. - activity_type: str. The type of activity. Possible values: - constants.ACTIVITY_TYPE_EXPLORATION - constants.ACTIVITY_TYPE_COLLECTION - - Raises: - Exception. The committer does not have rights to unpublicize the - activity. - """ - if not Actor(committer_id).can_unpublicize(activity_type, activity_id): - logging.error( - 'User %s tried to unpublicize exploration %s but was refused ' - 'permission.' % (committer_id, activity_id)) - raise Exception('This exploration cannot be unmarked as "featured".') - - _change_activity_status( - committer_id, activity_id, activity_type, ACTIVITY_STATUS_PUBLIC, - 'Exploration unpublicized.') - - # Rights functions for activities. def assign_role_for_exploration( committer_id, exploration_id, assignee_id, new_role): """Assigns a user to the given role and subscribes the assignee to future exploration updates. - The caller should ensure that assignee_id corresponds to a valid user in the system. - Args: committer_id: str. ID of the committer. exploration_id: str. ID of the exploration. @@ -1138,7 +1006,6 @@ def assign_role_for_exploration( new_role: str. The name of the new role: One of ROLE_OWNER ROLE_EDITOR - Raises: Exception. This could potentially throw an exception from _assign_role. @@ -1153,11 +1020,9 @@ def assign_role_for_exploration( def release_ownership_of_exploration(committer_id, exploration_id): """Releases ownership of the given exploration to the community. - Args: committer_id: str. ID of the committer. exploration_id: str. ID of the exploration. - Raises: Exception. This could potentially throw an exception from _release_ownership_of_activity. @@ -1170,16 +1035,13 @@ def set_private_viewability_of_exploration( committer_id, exploration_id, viewable_if_private): """Sets the viewable_if_private attribute for the given exploration's rights object. - If viewable_if_private is True, this allows a private exploration to be viewed by anyone with the link. - Args: committer_id: str. ID of the committer. exploration_id: str. ID of the exploration. viewable_if_private: bool. Whether the exploration should be made viewable (by anyone with the link). - Raises: Exception. The committer does not have the permission to perform change action. @@ -1219,14 +1081,11 @@ def set_private_viewability_of_exploration( def publish_exploration(committer_id, exploration_id): """Publishes the given exploration. - It is the responsibility of the caller to check that the exploration is valid prior to publication. - Args: committer_id: str. ID of the committer. exploration_id: str. ID of the exploration. - Raises: Exception. This could potentially throw an exception from _publish_activity. @@ -1237,11 +1096,9 @@ def publish_exploration(committer_id, exploration_id): def unpublish_exploration(committer_id, exploration_id): """Unpublishes the given exploration. - Args: committer_id: str. ID of the committer. exploration_id: str. ID of the exploration. - Raises: Exception. This could potentially throw an exception from _unpublish_activity. @@ -1250,48 +1107,13 @@ def unpublish_exploration(committer_id, exploration_id): committer_id, exploration_id, constants.ACTIVITY_TYPE_EXPLORATION) -def publicize_exploration(committer_id, exploration_id): - """Publicizes the given exploration. - - It is the responsibility of the caller to check that the exploration is - valid prior to publicizing it. - - Args: - committer_id: str. ID of the committer. - exploration_id: str. ID of the exploration. - - Raises: - Exception. This could potentially throw an exception from - _publicize_activity. - """ - _publicize_activity( - committer_id, exploration_id, constants.ACTIVITY_TYPE_EXPLORATION) - - -def unpublicize_exploration(committer_id, exploration_id): - """Unpublicizes the given exploration. - - Args: - committer_id: str. ID of the committer. - exploration_id: str. ID of the exploration. - - Raises: - Exception. This could potentially throw an exception from - _unpublicize_activity. - """ - _unpublicize_activity( - committer_id, exploration_id, constants.ACTIVITY_TYPE_EXPLORATION) - - # Rights functions for collections. def assign_role_for_collection( committer_id, collection_id, assignee_id, new_role): """Assign the given user to the given role and subscribes the assignee to future collection updates. - The caller should ensure that assignee_id corresponds to a valid user in the system. - Args: committer_id: str. ID of the committer. collection_id: str. ID of the collection. @@ -1299,7 +1121,6 @@ def assign_role_for_collection( new_role: str. The name of the new role: One of ROLE_OWNER ROLE_EDITOR - Raises: Exception. This could potentially throw an exception from _assign_role. @@ -1314,11 +1135,9 @@ def assign_role_for_collection( def release_ownership_of_collection(committer_id, collection_id): """Releases ownership of the given collection to the community. - Args: committer_id: str. ID of the committer. collection_id: str. ID of the collection. - Raises: Exception. This could potentially throw an exception from _release_ownership_of_activity. @@ -1329,14 +1148,11 @@ def release_ownership_of_collection(committer_id, collection_id): def publish_collection(committer_id, collection_id): """Publishes the given collection. - It is the responsibility of the caller to check that the collection is valid prior to publication. - Args: committer_id: str. ID of the committer. collection_id: str. ID of the collection. - Raises: Exception. This could potentially throw an exception from _publish_activity. @@ -1347,57 +1163,20 @@ def publish_collection(committer_id, collection_id): def unpublish_collection(committer_id, collection_id): """Unpublishes the given collection. - Args: committer_id: str. ID of the committer. collection_id: str. ID of the collection. - Raises: Exception. This could potentially throw an exception from _unpublish_activity. - """ _unpublish_activity( committer_id, collection_id, constants.ACTIVITY_TYPE_COLLECTION) -def publicize_collection(committer_id, collection_id): - """Publicizes the given collection. - - It is the responsibility of the caller to check that the collection is - valid prior to publicizing it. - - Args: - committer_id: str. ID of the committer. - collection_id: str. ID of the collection. - - Raises: - Exception. This could potentially throw an exception from - _publicize_activity. - """ - _publicize_activity( - committer_id, collection_id, constants.ACTIVITY_TYPE_COLLECTION) - - -def unpublicize_collection(committer_id, collection_id): - """Unpublicizes the given collection. - - Args: - committer_id: str. ID of the committer. - collection_id: str. ID of the collection. - - Raises: - Exception. This could potentially throw an exception from - _unpublicize_activity. - """ - _unpublicize_activity( - committer_id, collection_id, constants.ACTIVITY_TYPE_COLLECTION) - - def check_can_access_activity( user_id, user_actions, activity_type, activity_rights): """Checks whether the user can access given activity. - Args: user_id: str or None. Id of the given user. user_actions: list(str). List of actions given user can perform. @@ -1405,7 +1184,6 @@ def check_can_access_activity( collection. activity_rights: rights_object or None. Rights object of the given activity. - Returns: bool. Whether the given activity can be accessed. """ @@ -1435,7 +1213,6 @@ def check_can_access_activity( def check_can_edit_activity( user_id, user_actions, activity_type, activity_rights): """Checks whether the user can edit given activity. - Args: user_id: str or None. Id of the given user. user_actions: list(str). List of actions the user can perform. @@ -1443,7 +1220,6 @@ def check_can_edit_activity( collection. activity_rights: rights_object or None. Rights object of the given activity. - Returns: bool. Whether the given user can edit this activity. """ @@ -1480,12 +1256,10 @@ def check_can_edit_activity( def check_can_unpublish_collection(user_actions, collection_rights): """Checks whether the user can unpublish given collection. - Args: user_actions: list(str). List of actions the user can perform. collection_rights: rights_object or None. Rights object of given collection. - Returns: bool. Whether the user can unpublish given collection. """ @@ -1501,13 +1275,11 @@ def check_can_unpublish_collection(user_actions, collection_rights): def check_can_delete_exploration(user_id, user_actions, exploration_rights): """Checks whether the user can delete given exploration. - Args: user_id: str or None. Id of the user. user_actions: list(str). List of actions the user can perform. exploration_rights: rights_object or None. Rights object of given exploration. - Returns: bool. Whether the user can delete given exploration. """ @@ -1529,13 +1301,11 @@ def check_can_delete_exploration(user_id, user_actions, exploration_rights): def check_can_modify_exploration_roles( user_id, user_actions, exploration_rights): """Checks whether the user can modify roles for given exploration. - Args: user_id: str or None. Id of the user. user_actions: list(str). List of actions the user can perform. exploration_rights: rights_object or None. Rights Object of given exploration. - Returns: bool. Whether the user can modify roles for given exploration. """ @@ -1558,13 +1328,11 @@ def check_can_modify_exploration_roles( def check_can_release_ownership(user_id, user_actions, exploration_rights): """Checks whether the user can release ownership for given exploration. - Args: user_id: str or None. Id of the user. user_actions: list(str). List of actions the user can perform. exploration_rights: rights_object or None. Rights Object of given exploration. - Returns: bool. Whether the user can release ownership for given exploration. """ @@ -1580,13 +1348,11 @@ def check_can_release_ownership(user_id, user_actions, exploration_rights): def check_can_publish_exploration(user_id, user_actions, exploration_rights): """Checks whether the user can publish given exploration. - Args: user_id: str or None. Id of the user. user_actions: list(str). List of actions the user can perform. exploration_rights: rights_object or None. Rights Object of given exploration. - Returns: bool. Whether the user can publish given exploration. """ @@ -1609,12 +1375,10 @@ def check_can_publish_exploration(user_id, user_actions, exploration_rights): def check_can_unpublish_exploration(user_actions, exploration_rights): """Checks whether the user can unpublish given exploration. - Args: user_actions: list(str). List of actions the user can perform. exploration_rights: rights_object or None. Rights object of given exploration. - Returns: bool. Whether the user can unpublish given exploration. """ From 1f9287e19f33ac457ecfbc0f4f840a62bf71f9d2 Mon Sep 17 00:00:00 2001 From: Arunabh98 Date: Tue, 15 Aug 2017 23:10:06 +0530 Subject: [PATCH 20/65] Add list. --- assets/images/activity/exploration.svg | 2 +- core/controllers/learner_playlist.py | 1 + core/domain/user_domain.py | 1 - .../ExplorationPlaylistTileDirective.js | 4 +- .../exploration_playlist_tile_directive.html | 12 +- core/templates/dev/head/css/oppia.css | 35 +++- .../learner_dashboard/LearnerDashboard.js | 156 ++++++++++++++---- .../learner_dashboard/learner_dashboard.html | 88 +++++----- 8 files changed, 221 insertions(+), 78 deletions(-) diff --git a/assets/images/activity/exploration.svg b/assets/images/activity/exploration.svg index e335b43ef3c8..607e91684c80 100644 --- a/assets/images/activity/exploration.svg +++ b/assets/images/activity/exploration.svg @@ -1 +1 @@ -exploration \ No newline at end of file +exploration diff --git a/core/controllers/learner_playlist.py b/core/controllers/learner_playlist.py index ff98ce5b7cb5..50117010c9fd 100644 --- a/core/controllers/learner_playlist.py +++ b/core/controllers/learner_playlist.py @@ -27,6 +27,7 @@ class LearnerPlaylistHandler(base.BaseHandler): @acl_decorators.can_access_learner_dashboard def post(self, activity_type, activity_id): position_to_be_inserted_in = self.payload.get('index') + print "Hello", position_to_be_inserted_in if activity_type == constants.ACTIVITY_TYPE_EXPLORATION: (belongs_to_completed_or_incomplete_list, playlist_limit_exceeded, diff --git a/core/domain/user_domain.py b/core/domain/user_domain.py index 446ace60c0e9..0db8bfad2e38 100644 --- a/core/domain/user_domain.py +++ b/core/domain/user_domain.py @@ -217,7 +217,6 @@ def insert_exploration_id_at_given_position( play later list. position_to_be_inserted: The position at which it is to be inserted. """ - print "ello", position_to_be_inserted self.exploration_ids.insert(position_to_be_inserted, exploration_id) def add_exploration_id_to_list(self, exploration_id): diff --git a/core/templates/dev/head/components/playlist_tile/ExplorationPlaylistTileDirective.js b/core/templates/dev/head/components/playlist_tile/ExplorationPlaylistTileDirective.js index ef5a9ec38d76..0aa07653cf61 100644 --- a/core/templates/dev/head/components/playlist_tile/ExplorationPlaylistTileDirective.js +++ b/core/templates/dev/head/components/playlist_tile/ExplorationPlaylistTileDirective.js @@ -46,8 +46,8 @@ oppia.directive('explorationPlaylistTile', [ mobileCutoffPx: '@mobileCutoffPx' }, templateUrl: UrlInterpolationService.getDirectiveTemplateUrl( - '/components/summary_tile/' + - 'exploration_summary_tile_directive.html'), + '/components/playlist_tile/' + + 'exploration_playlist_tile_directive.html'), link: function(scope, element) { element.find('.exploration-summary-avatars').on('mouseenter', function() { diff --git a/core/templates/dev/head/components/playlist_tile/exploration_playlist_tile_directive.html b/core/templates/dev/head/components/playlist_tile/exploration_playlist_tile_directive.html index 976ce2e595e9..81760b27643e 100644 --- a/core/templates/dev/head/components/playlist_tile/exploration_playlist_tile_directive.html +++ b/core/templates/dev/head/components/playlist_tile/exploration_playlist_tile_directive.html @@ -1,7 +1,10 @@ - +
- <[getCategory()]> + <[getCategory()]>

<[getExplorationTitle()|truncate:40]> <[getExplorationTitle()|truncate:40]> @@ -19,8 +22,9 @@

-
-
+
+
<[getObjective() | truncateAndCapitalize: 95]>
diff --git a/core/templates/dev/head/css/oppia.css b/core/templates/dev/head/css/oppia.css index f65cce791cc7..7f5e0f6401d3 100644 --- a/core/templates/dev/head/css/oppia.css +++ b/core/templates/dev/head/css/oppia.css @@ -211,6 +211,13 @@ body { width: auto !important; } +.oppia-learner-playlist-tiles { + display: inline-block; + margin-left: 1px; + padding-right: 21px; + width: 100%; +} + .oppia-dashboard-container { margin: 0 auto 30px auto; max-width: 800px; @@ -244,6 +251,13 @@ body { text-align: right; } +.oppia-exploration-playlist-tile { + border-bottom: 1px solid #C0C0C0; + height: 145px; + margin: 0; + width: 100%; +} + .oppia-learner-dashboard-title { color: #01645c; font-family: 'Capriola', 'Roboto', Arial, sans-serif; @@ -2452,7 +2466,7 @@ pre.oppia-pre-wrapped-text { z-index: 1; } -.oppia-rule-sort-handle, .oppia-fallback-sort-handle, .oppia-hint-sort-handle { +.oppia-rule-sort-handle, .oppia-fallback-sort-handle, .oppia-hint-sort-handle, .oppia-learner-playlist-sort-handle { cursor: move; left: 10px; margin-left: 5px; @@ -4006,6 +4020,25 @@ md-card.preview-conversation-skin-supplemental-card { box-shadow: 0 6px 13px rgba(0,0,0,0.17), 0 4px 6px rgba(0,0,0,0.23); } +.oppia-exploration-playlist-tile .title-section { + display: inline-block; + height: 7em; + margin: 16px 0 10px 16px; + width: 27%; +} + +.oppia-exploration-playlist-tile .summary-section { + display: inline-block; + float: right; + margin-top: 3%; + width: 67%; +} + +.oppia-exploration-playlist-tile .activity-title { + font-size: 0.85em; + text-align: center; +} + .oppia-activity-summary-tile .title-section { height: 10em; position: relative; diff --git a/core/templates/dev/head/pages/learner_dashboard/LearnerDashboard.js b/core/templates/dev/head/pages/learner_dashboard/LearnerDashboard.js index 77a797f63b54..073e803d355c 100644 --- a/core/templates/dev/head/pages/learner_dashboard/LearnerDashboard.js +++ b/core/templates/dev/head/pages/learner_dashboard/LearnerDashboard.js @@ -251,6 +251,58 @@ oppia.controller('LearnerDashboard', [ return feedbackThread[$scope.currentFeedbackThreadsSortType]; }; + $scope.explorationPlaylistSortableOptions = { + start: function(e, ui) { + ui.placeholder.height(ui.item.height()); + $scope.$apply(); + }, + update: function(e, ui) { + var insertExpInLearnerPlaylistUrl = ( + UrlInterpolationService.interpolateUrl( + '/learnerplaylistactivityhandler//', { + activityType: constants.ACTIVITY_TYPE_EXPLORATION, + activityId: ( + $scope.explorationPlaylist[ui.item.sortable.dropindex].id) + })); + + $http.post(insertExpInLearnerPlaylistUrl, { + index: ui.item.sortable.dropindex + }); + $scope.$apply(); + }, + stop: function(e, ui) { + $scope.$apply(); + }, + axis: 'y', + 'ui-floating': false + }; + + $scope.collectionPlaylistSortableOptions = { + start: function(e, ui) { + ui.placeholder.height(ui.item.height()); + $scope.$apply(); + }, + update: function(e, ui) { + var insertCollectionInLearnerPlaylistUrl = ( + UrlInterpolationService.interpolateUrl( + '/learnerplaylistactivityhandler//', { + activityType: constants.ACTIVITY_TYPE_COLLECTION, + activityId: ( + $scope.collectionPlaylist[ui.item.sortable.dropindex].id) + })); + + $http.post(insertCollectionInLearnerPlaylistUrl, { + index: ui.item.sortable.dropindex + }); + $scope.$apply(); + }, + stop: function(e, ui) { + $scope.$apply(); + }, + axis: 'y', + 'ui-floating': false + }; + $scope.onClickThread = function( threadStatus, explorationId, threadId, explorationTitle) { var threadDataUrl = UrlInterpolationService.interpolateUrl( @@ -372,25 +424,53 @@ oppia.controller('LearnerDashboard', [ $scope.subsectionName = subsectionName; $scope.activityTitle = activity.title; $scope.remove = function() { - if (subsectionName === - LEARNER_DASHBOARD_SUBSECTION_I18N_IDS.EXPLORATIONS) { - var removeExpUrl = UrlInterpolationService.interpolateUrl( - '/learnerincompleteactivityhandler/' + - '/', { - activityType: constants.ACTIVITY_TYPE_EXPLORATION, - activityId: activity.id - }); - $http['delete'](removeExpUrl); - } else if (subsectionName === - LEARNER_DASHBOARD_SUBSECTION_I18N_IDS.COLLECTIONS) { - var removeCollectionUrl = ( - UrlInterpolationService.interpolateUrl( - '/learnerincompleteactivityhandler/' + - '/', { - activityType: constants.ACTIVITY_TYPE_COLLECTION, - activityId: activity.id - })); - $http['delete'](removeCollectionUrl); + if (sectionNameI18nId === + LEARNER_DASHBOARD_SECTION_I18N_IDS.PLAYLIST) { + if (subsectionName === + LEARNER_DASHBOARD_SUBSECTION_I18N_IDS.EXPLORATIONS) { + /* eslint-disable max-len */ + var removeFromLearnerPlaylistUrl = ( + UrlInterpolationService.interpolateUrl( + '/learnerplaylistactivityhandler//', { + activityType: constants.ACTIVITY_TYPE_EXPLORATION, + activityId: activity.id + })); + /* eslint-enable max-len */ + $http['delete'](removeFromLearnerPlaylistUrl); + } else if (subsectionName === + LEARNER_DASHBOARD_SUBSECTION_I18N_IDS.COLLECTIONS) { + /* eslint-disable max-len */ + var removeFromLearnerPlaylistUrl = ( + UrlInterpolationService.interpolateUrl( + '/learnerplaylistactivityhandler//', { + activityType: constants.ACTIVITY_TYPE_COLLECTION, + activityId: activity.id + })); + /* eslint-enable max-len */ + $http['delete'](removeFromLearnerPlaylistUrl); + } + } else if (sectionNameI18nId === + LEARNER_DASHBOARD_SECTION_I18N_IDS.INCOMPLETE) { + if (subsectionName === + LEARNER_DASHBOARD_SUBSECTION_I18N_IDS.EXPLORATIONS) { + var removeExpUrl = UrlInterpolationService.interpolateUrl( + '/learnerincompleteactivityhandler/' + + '/', { + activityType: constants.ACTIVITY_TYPE_EXPLORATION, + activityId: activity.id + }); + $http['delete'](removeExpUrl); + } else if (subsectionName === + LEARNER_DASHBOARD_SUBSECTION_I18N_IDS.COLLECTIONS) { + var removeCollectionUrl = ( + UrlInterpolationService.interpolateUrl( + '/learnerincompleteactivityhandler/' + + '/', { + activityType: constants.ACTIVITY_TYPE_COLLECTION, + activityId: activity.id + })); + $http['delete'](removeCollectionUrl); + } } $modalInstance.close(); }; @@ -401,17 +481,35 @@ oppia.controller('LearnerDashboard', [ } ] }).result.then(function() { - if (subsectionName === - LEARNER_DASHBOARD_SUBSECTION_I18N_IDS.EXPLORATIONS) { - var index = $scope.incompleteExplorationsList.indexOf(activity); - if (index !== -1) { - $scope.incompleteExplorationsList.splice(index, 1); + if (sectionNameI18nId === + LEARNER_DASHBOARD_SECTION_I18N_IDS.INCOMPLETE) { + if (subsectionName === + LEARNER_DASHBOARD_SUBSECTION_I18N_IDS.EXPLORATIONS) { + var index = $scope.incompleteExplorationsList.indexOf(activity); + if (index !== -1) { + $scope.incompleteExplorationsList.splice(index, 1); + } + } else if (subsectionName === + LEARNER_DASHBOARD_SUBSECTION_I18N_IDS.COLLECTIONS) { + var index = $scope.incompleteCollectionsList.indexOf(activity); + if (index !== -1) { + $scope.incompleteCollectionsList.splice(index, 1); + } } - } else if (subsectionName === - LEARNER_DASHBOARD_SUBSECTION_I18N_IDS.COLLECTIONS) { - var index = $scope.incompleteCollectionsList.indexOf(activity); - if (index !== -1) { - $scope.incompleteCollectionsList.splice(index, 1); + } else if (sectionNameI18nId === + LEARNER_DASHBOARD_SECTION_I18N_IDS.PLAYLIST){ + if (subsectionName === + LEARNER_DASHBOARD_SUBSECTION_I18N_IDS.EXPLORATIONS) { + var index = $scope.explorationPlaylist.indexOf(activity); + if (index !== -1) { + $scope.explorationPlaylist.splice(index, 1); + } + } else if (subsectionName === + LEARNER_DASHBOARD_SUBSECTION_I18N_IDS.COLLECTIONS) { + var index = $scope.collectionPlaylist.indexOf(activity); + if (index !== -1) { + $scope.collectionPlaylist.splice(index, 1); + } } } }); diff --git a/core/templates/dev/head/pages/learner_dashboard/learner_dashboard.html b/core/templates/dev/head/pages/learner_dashboard/learner_dashboard.html index d9975cb57685..118fb733ec01 100644 --- a/core/templates/dev/head/pages/learner_dashboard/learner_dashboard.html +++ b/core/templates/dev/head/pages/learner_dashboard/learner_dashboard.html @@ -352,28 +352,34 @@

<[subscriptionsList.length]>

-
- - - +
+
+ + + +
+
@@ -458,25 +464,27 @@

<[subscriptionsList.length]>

-
- - - +
+
+ + + +
From 08c77d47e200b616b5b0dd3789b25ccfd8c31591 Mon Sep 17 00:00:00 2001 From: Arunabh98 Date: Wed, 16 Aug 2017 00:12:01 +0530 Subject: [PATCH 21/65] Fix big in sortable list. --- core/controllers/learner_playlist.py | 1 - core/templates/dev/head/css/oppia.css | 8 ++++---- .../dev/head/pages/learner_dashboard/LearnerDashboard.js | 2 +- .../head/pages/learner_dashboard/learner_dashboard.html | 4 ++-- 4 files changed, 7 insertions(+), 8 deletions(-) diff --git a/core/controllers/learner_playlist.py b/core/controllers/learner_playlist.py index 50117010c9fd..ff98ce5b7cb5 100644 --- a/core/controllers/learner_playlist.py +++ b/core/controllers/learner_playlist.py @@ -27,7 +27,6 @@ class LearnerPlaylistHandler(base.BaseHandler): @acl_decorators.can_access_learner_dashboard def post(self, activity_type, activity_id): position_to_be_inserted_in = self.payload.get('index') - print "Hello", position_to_be_inserted_in if activity_type == constants.ACTIVITY_TYPE_EXPLORATION: (belongs_to_completed_or_incomplete_list, playlist_limit_exceeded, diff --git a/core/templates/dev/head/css/oppia.css b/core/templates/dev/head/css/oppia.css index 7f5e0f6401d3..3ad2eac12d0b 100644 --- a/core/templates/dev/head/css/oppia.css +++ b/core/templates/dev/head/css/oppia.css @@ -251,7 +251,7 @@ body { text-align: right; } -.oppia-exploration-playlist-tile { +.oppia-activity-summary-tile.oppia-exploration-playlist-tile { border-bottom: 1px solid #C0C0C0; height: 145px; margin: 0; @@ -4020,21 +4020,21 @@ md-card.preview-conversation-skin-supplemental-card { box-shadow: 0 6px 13px rgba(0,0,0,0.17), 0 4px 6px rgba(0,0,0,0.23); } -.oppia-exploration-playlist-tile .title-section { +.oppia-activity-summary-tile.oppia-exploration-playlist-tile .title-section { display: inline-block; height: 7em; margin: 16px 0 10px 16px; width: 27%; } -.oppia-exploration-playlist-tile .summary-section { +.oppia-activity-summary-tile.oppia-exploration-playlist-tile .summary-section { display: inline-block; float: right; margin-top: 3%; width: 67%; } -.oppia-exploration-playlist-tile .activity-title { +.oppia-activity-summary-tile.oppia-exploration-playlist-tile .activity-title { font-size: 0.85em; text-align: center; } diff --git a/core/templates/dev/head/pages/learner_dashboard/LearnerDashboard.js b/core/templates/dev/head/pages/learner_dashboard/LearnerDashboard.js index 073e803d355c..46d82bfb49dc 100644 --- a/core/templates/dev/head/pages/learner_dashboard/LearnerDashboard.js +++ b/core/templates/dev/head/pages/learner_dashboard/LearnerDashboard.js @@ -262,7 +262,7 @@ oppia.controller('LearnerDashboard', [ '/learnerplaylistactivityhandler//', { activityType: constants.ACTIVITY_TYPE_EXPLORATION, activityId: ( - $scope.explorationPlaylist[ui.item.sortable.dropindex].id) + $scope.explorationPlaylist[ui.item.sortable.index].id) })); $http.post(insertExpInLearnerPlaylistUrl, { diff --git a/core/templates/dev/head/pages/learner_dashboard/learner_dashboard.html b/core/templates/dev/head/pages/learner_dashboard/learner_dashboard.html index 118fb733ec01..754cf2024b86 100644 --- a/core/templates/dev/head/pages/learner_dashboard/learner_dashboard.html +++ b/core/templates/dev/head/pages/learner_dashboard/learner_dashboard.html @@ -354,7 +354,7 @@

<[subscriptionsList.length]>

<[subscriptionsList.length]>

-
Date: Thu, 17 Aug 2017 18:17:17 +0530 Subject: [PATCH 22/65] Further progress. --- assets/i18n/en.json | 1 + assets/i18n/qqq.json | 1 + .../learner_dashboard/learner_dashboard.html | 4 ++++ .../dev/head/pages/library/Library.js | 18 ++++++++++++++---- .../pages/library/SearchResultsDirective.js | 7 +++++++ .../dev/head/pages/library/library.html | 5 +++-- core/tests/protractor/learnerDashboard.js | 7 +++++++ 7 files changed, 37 insertions(+), 6 deletions(-) diff --git a/assets/i18n/en.json b/assets/i18n/en.json index 2090c1e39024..43b0e42fda8f 100644 --- a/assets/i18n/en.json +++ b/assets/i18n/en.json @@ -231,6 +231,7 @@ "I18N_LEARNER_DASHBOARD_INTRO_MESSAGE_PART_ONE": "It looks like you haven't tried any of our explorations yet.", "I18N_LEARNER_DASHBOARD_INTRO_MESSAGE_PART_TWO": "Let's get started on this exciting journey!", "I18N_LEARNER_DASHBOARD_PLAYLIST_SECTION": "Play Later", + "I18N_LEARNER_DASHBOARD_REARRANGE_LEARNER_PLAYLIST_MESSAGE": "Drag and rearrange the activities in the order in which you want to play them!", "I18N_LEARNER_DASHBOARD_REMOVE_ACTIVITY_MODAL_BODY": "Are you sure you want to remove '<[entityTitle]>' from your '<[sectionNameI18nId | translate]>' list?", "I18N_LEARNER_DASHBOARD_REMOVE_ACTIVITY_MODAL_HEADER": "Remove from '<[sectionNameI18nId | translate]>' list?", "I18N_LEARNER_DASHBOARD_REMOVE_BUTTON": "Remove", diff --git a/assets/i18n/qqq.json b/assets/i18n/qqq.json index 75f08338eb98..ab5ae50eaf0c 100644 --- a/assets/i18n/qqq.json +++ b/assets/i18n/qqq.json @@ -231,6 +231,7 @@ "I18N_LEARNER_DASHBOARD_INTRO_MESSAGE_PART_ONE": "First part of the introductory message that appears on the learner dashboard when there is no activity.", "I18N_LEARNER_DASHBOARD_INTRO_MESSAGE_PART_TWO": "Second part of the introductory message that appears on the learner dashboard when there is no activity.", "I18N_LEARNER_DASHBOARD_PLAYLIST_SECTION": "Text for the playlist section in the learner dashboard. Will contain all the explorations and collections which the user wants to play later but doesn't have the time at the moment.", + "I18N_LEARNER_DASHBOARD_REARRANGE_LEARNER_PLAYLIST_MESSAGE": "Text that appears in the learner playlist section. It tells the learner that he/she can rearrage the activities in the order he/she wants to play them.", "I18N_LEARNER_DASHBOARD_REMOVE_ACTIVITY_MODAL_BODY": "Text that appears in the body of the remove modal in the learner dashboard. It asks the user if he/she is sure to remove the activity from the learner dashboard. The 'sectionNameI18nId' describes which section of the learner dashboard the user is in. The 'entityTitle' is the name of the lesson the user wants to remove from the learner dashboard.", "I18N_LEARNER_DASHBOARD_REMOVE_ACTIVITY_MODAL_HEADER": "Text that appears as the header of the remove modal in the learner dashboard. The 'sectionNameI18nId' describes which section of the learner dashboard the user is in.", "I18N_LEARNER_DASHBOARD_REMOVE_BUTTON": "Text that appears in a button in a modal in the learner dashboard. Clicking on it, the user confirms his/her action of removing a activity from the learner dashboard.\n{{Identical|Remove}}", diff --git a/core/templates/dev/head/pages/learner_dashboard/learner_dashboard.html b/core/templates/dev/head/pages/learner_dashboard/learner_dashboard.html index 754cf2024b86..1bf91d96c7d3 100644 --- a/core/templates/dev/head/pages/learner_dashboard/learner_dashboard.html +++ b/core/templates/dev/head/pages/learner_dashboard/learner_dashboard.html @@ -327,6 +327,10 @@

<[subscriptionsList.length]>

+ + +
- + <[learnerDashboardActivityIds.incomplete_exploration_ids]> +
-

- <[subscriptionsList.length]> num-views="tile.num_views" thumbnail-icon-url="tile.thumbnail_icon_url" thumbnail-bg-color="tile.thumbnail_bg_color" - class="protractor-test-exp-summary-tile"> - + class="protractor-test-exp-summary-tile" + playlist-mode="true"> +
@@ -484,7 +485,7 @@

<[subscriptionsList.length]>

ng-click="openRemoveActivityModal(activeSection, activeSubsection, tile)" tooltip="Remove" tooltip-placement="top">
- <[subscriptionsList.length]> node-count="tile.node_count" category="tile.category" thumbnail-icon-url="tile.thumbnail_icon_url" - thumbnail-bg-color="tile.thumbnail_bg_color"> - + thumbnail-bg-color="tile.thumbnail_bg_color" + playlist-mode="true"> +
@@ -812,8 +814,6 @@

- - diff --git a/core/templates/dev/head/pages/library/ActivityTilesInfinityGridDirective.js b/core/templates/dev/head/pages/library/ActivityTilesInfinityGridDirective.js index dcad140d198f..7dcdbd5cb77b 100644 --- a/core/templates/dev/head/pages/library/ActivityTilesInfinityGridDirective.js +++ b/core/templates/dev/head/pages/library/ActivityTilesInfinityGridDirective.js @@ -21,7 +21,7 @@ oppia.directive('activityTilesInfinityGrid', [ return { restrict: 'E', scope: { - learnerDashboardActivityIds: '=learnerDashboardActivityIds', + learnerDashboardActivityIds: '&learnerDashboardActivityIds', }, templateUrl: UrlInterpolationService.getDirectiveTemplateUrl( '/pages/library/' + @@ -29,7 +29,8 @@ oppia.directive('activityTilesInfinityGrid', [ controller: [ '$scope', '$rootScope', '$http', 'searchService', 'alertsService', '$modal', function( - $scope, $rootScope, $http, searchService, alertsService, $modal) { + $scope, $rootScope, $http, searchService, alertsService, + $modal) { $scope.endOfPageIsReached = false; $scope.allActivitiesInOrder = []; var hoverOverActivity = false; @@ -51,17 +52,20 @@ oppia.directive('activityTilesInfinityGrid', [ $scope.showAddToLearnerPlaylistIcon = function(activityId) { var incompleteExplorationIds = ( - $scope.learnerDashboardActivityIds.incomplete_exploration_ids); + $scope.getLearnerDashboardActivityIds( + ).incomplete_exploration_ids); var incompleteCollectionIds = ( - $scope.learnerDashboardActivityIds.incomplete_collection_ids); + $scope.getLearnerDashboardActivityIds( + ).incomplete_collection_ids); var completedExplorationIds = ( - $scope.learnerDashboardActivityIds.completed_exploration_ids); + $scope.getLearnerDashboardActivityIds( + ).completed_exploration_ids); var completedCollectionIds = ( - $scope.learnerDashboardActivityIds.completed_collection_ids); + $scope.getLearnerDashboardActivityIds().completed_collection_ids); var explorationPlaylistIds = ( - $scope.learnerDashboardActivityIds.exploration_playlist_ids); + $scope.getLearnerDashboardActivityIds().exploration_playlist_ids); var collectionPlaylistIds = ( - $scope.learnerDashboardActivityIds.collection_playlist_ids); + $scope.getLearnerDashboardActivityIds().collection_playlist_ids); if (incompleteExplorationIds.indexOf(activityId) !== -1 || incompleteCollectionIds.indexOf(activityId) !== -1 || @@ -71,7 +75,7 @@ oppia.directive('activityTilesInfinityGrid', [ collectionPlaylistIds.indexOf(activityId) !== -1) { return false; } else { - return hoverOverActivity && (activeActivityId == activityId); + return hoverOverActivity && (activeActivityId === activityId); } }; @@ -87,7 +91,7 @@ oppia.directive('activityTilesInfinityGrid', [ if (response.data.belongs_to_completed_or_incomplete_list) { alertsService.addInfoMessage( 'You have already completed or are completing this ' + - ' activity.'); + 'activity.'); } else if (response.data.belongs_to_subscribed_activities) { alertsService.addInfoMessage( 'This is present in your creator dashboard'); @@ -98,16 +102,16 @@ oppia.directive('activityTilesInfinityGrid', [ 'and remove some.'); } else { alertsService.addSuccessMessage( - 'Succesfully added to your \'Play Later\' list.'); + 'Successfully added to your \'Play Later\' list.'); } }); if (activityType == constants.ACTIVITY_TYPE_EXPLORATION) { - $scope.learnerDashboardActivityIds.exploration_playlist_ids.push( - activityId); + $scope.getLearnerDashboardActivityIds( + ).exploration_playlist_ids.push(activityId); } else { - $scope.learnerDashboardActivityIds.collection_playlist_ids.push( - activityId); + $scope.getLearnerDashboardActivityIds( + ).collection_playlist_ids.push(activityId); } }; @@ -156,18 +160,18 @@ oppia.directive('activityTilesInfinityGrid', [ if (activityType == constants.ACTIVITY_TYPE_EXPLORATION) { /* eslint-disable max-len */ var index = ( - $scope.learnerDashboardActivityIds.exploration_playlist_ids.indexOf( + $scope.getLearnerDashboardActivityIds().exploration_playlist_ids.indexOf( activityId)); if (index !== -1) { - $scope.learnerDashboardActivityIds.exploration_playlist_ids.splice( + $scope.getLearnerDashboardActivityIds().exploration_playlist_ids.splice( index, 1); } } else { var index = ( - $scope.learnerDashboardActivityIds.collection_playlist_ids.indexOf( + $scope.getLearnerDashboardActivityIds().collection_playlist_ids.indexOf( activityId)); if (index !== -1) { - $scope.learnerDashboardActivityIds.collection_playlist_ids.splice( + $scope.getLearnerDashboardActivityIds().collection_playlist_ids.splice( index, 1); } } diff --git a/core/templates/dev/head/pages/library/Library.js b/core/templates/dev/head/pages/library/Library.js index d5e17bb55e59..4a7437ac24ff 100644 --- a/core/templates/dev/head/pages/library/Library.js +++ b/core/templates/dev/head/pages/library/Library.js @@ -31,10 +31,10 @@ oppia.controller('Library', [ 'i18nIdService', 'urlService', 'ALL_CATEGORIES', 'searchService', 'windowDimensionsService', 'UrlInterpolationService', 'LIBRARY_PAGE_MODES', 'LIBRARY_TILE_WIDTH_PX', 'alertsService', function( - $scope, $http, $modal, $rootScope, $window, $timeout, i18nIdService, - urlService, ALL_CATEGORIES, searchService, windowDimensionsService, - UrlInterpolationService, LIBRARY_PAGE_MODES, LIBRARY_TILE_WIDTH_PX, - alertsService) { + $scope, $http, $modal, $rootScope, $window, $timeout, + i18nIdService, urlService, ALL_CATEGORIES, searchService, + windowDimensionsService, UrlInterpolationService, LIBRARY_PAGE_MODES, + LIBRARY_TILE_WIDTH_PX, alertsService) { $rootScope.loadingMessage = 'I18N_LIBRARY_LOADING'; var possibleBannerFilenames = [ 'banner1.svg', 'banner2.svg', 'banner3.svg', 'banner4.svg']; @@ -170,7 +170,7 @@ oppia.controller('Library', [ 'some or you can head to the learner dashboard and remove some.'); } else { alertsService.addSuccessMessage( - 'Succesfully added to your \'Play Later\' list.'); + 'Successfully added to your \'Play Later\' list.'); } }); diff --git a/core/templates/dev/head/pages/library/activity_tiles_infinity_grid_directive.html b/core/templates/dev/head/pages/library/activity_tiles_infinity_grid_directive.html index 6367555359a6..e011f8de05ee 100644 --- a/core/templates/dev/head/pages/library/activity_tiles_infinity_grid_directive.html +++ b/core/templates/dev/head/pages/library/activity_tiles_infinity_grid_directive.html @@ -10,20 +10,20 @@ tooltip-placement="left" ng-style="activity.community_owned && {'left': '-45px'}">
- <[getCategory()]> + <[getCategory()]>

<[getExplorationTitle()|truncate:40]> <[getExplorationTitle()|truncate:40]> diff --git a/core/templates/dev/head/css/oppia.css b/core/templates/dev/head/css/oppia.css index 123b39d46a31..7db0f6d59eea 100644 --- a/core/templates/dev/head/css/oppia.css +++ b/core/templates/dev/head/css/oppia.css @@ -4024,6 +4024,7 @@ md-card.preview-conversation-skin-supplemental-card { display: inline-block; height: 7em; margin: 16px 0 10px 16px; + min-width: 163px; width: 27%; } @@ -4039,6 +4040,42 @@ md-card.preview-conversation-skin-supplemental-card { text-align: center; } +@media(max-width: 895px) { + .oppia-activity-summary-tile.oppia-activity-playlist-tile .summary-section { + width: 55%; + } +} + +@media(max-width: 743px) { + .oppia-activity-summary-tile.oppia-activity-playlist-tile .thumbnail-image { + width: 45px; + } + + .oppia-activity-summary-tile.oppia-activity-playlist-tile .activity-title { + font-size: 0.75em; + } + + .oppia-activity-summary-tile.oppia-activity-playlist-tile .title-section { + height: 7em; + min-width: 140px; + } + + .oppia-activity-summary-tile.oppia-activity-playlist-tile .summary-section { + width: 50%; + } +} + +@media(max-width: 629px) { + .oppia-activity-summary-tile.oppia-activity-playlist-tile .title-section { + height: 7em; + min-width: 115px; + } + + .oppia-activity-summary-tile.oppia-activity-playlist-tile .summary-section { + width: 47%; + } +} + .oppia-activity-summary-tile .title-section { height: 10em; position: relative; diff --git a/core/templates/dev/head/pages/learner_dashboard/LearnerDashboard.js b/core/templates/dev/head/pages/learner_dashboard/LearnerDashboard.js index 143837287ef9..7051fb955e4e 100644 --- a/core/templates/dev/head/pages/learner_dashboard/LearnerDashboard.js +++ b/core/templates/dev/head/pages/learner_dashboard/LearnerDashboard.js @@ -572,7 +572,9 @@ oppia.controller('LearnerDashboard', [ ($scope.completedExplorationsList.length === 0) && ($scope.completedCollectionsList.length === 0) && ($scope.incompleteExplorationsList.length === 0) && - ($scope.incompleteCollectionsList.length === 0)); + ($scope.incompleteCollectionsList.length === 0) && + ($scope.explorationPlaylist.length === 0) && + ($scope.collectionPlaylist.length === 0)); $rootScope.loadingMessage = ''; }, function(errorResponse) { diff --git a/core/templates/dev/head/pages/library/ActivityTilesInfinityGridDirective.js b/core/templates/dev/head/pages/library/ActivityTilesInfinityGridDirective.js index a056c0ab01ad..08f680050b49 100644 --- a/core/templates/dev/head/pages/library/ActivityTilesInfinityGridDirective.js +++ b/core/templates/dev/head/pages/library/ActivityTilesInfinityGridDirective.js @@ -33,7 +33,7 @@ oppia.directive('activityTilesInfinityGrid', [ $modal) { $scope.endOfPageIsReached = false; $scope.allActivitiesInOrder = []; - var hoverOverActivity = false; + var currentlyHoveringOverActivity = false; var activeActivityId = ''; console.log($scope.getLearnerDashboardActivityIds()); // Called when the first batch of search results is retrieved from the @@ -45,9 +45,9 @@ oppia.directive('activityTilesInfinityGrid', [ } ); - $scope.setHoverOverActivity = function(activityId) { + $scope.setCurrentlyHoveringOverActivity = function(activityId) { activeActivityId = activityId; - hoverOverActivity = !hoverOverActivity; + currentlyHoveringOverActivity = !currentlyHoveringOverActivity; }; $scope.showAddToLearnerPlaylistIcon = function(activityId) { @@ -75,7 +75,8 @@ oppia.directive('activityTilesInfinityGrid', [ collectionPlaylistIds.indexOf(activityId) !== -1) { return false; } else { - return hoverOverActivity && (activeActivityId === activityId); + return (currentlyHoveringOverActivity && + (activeActivityId === activityId)); } }; diff --git a/core/templates/dev/head/pages/library/activity_tiles_infinity_grid_directive.html b/core/templates/dev/head/pages/library/activity_tiles_infinity_grid_directive.html index 2eb336c44305..3e0ced6b83fb 100644 --- a/core/templates/dev/head/pages/library/activity_tiles_infinity_grid_directive.html +++ b/core/templates/dev/head/pages/library/activity_tiles_infinity_grid_directive.html @@ -1,7 +1,7 @@
-
+
Date: Wed, 23 Aug 2017 22:48:03 +0530 Subject: [PATCH 40/65] Address all review comments. --- core/controllers/learner_dashboard.py | 32 ++++ core/controllers/learner_dashboard_test.py | 128 +++++++++++---- core/controllers/library.py | 32 ---- .../ActivityTilesInfinityGridDirective.js | 147 ++---------------- .../LearnerDashboardIdsBackendApiService.js | 28 ++++ .../dev/head/pages/library/Library.js | 17 +- .../pages/library/SearchResultsDirective.js | 3 - ...ctivity_tiles_infinity_grid_directive.html | 4 +- .../dev/head/pages/library/library.html | 3 +- .../library/search_results_directive.html | 2 +- feconf.py | 1 + main.py | 3 + 12 files changed, 188 insertions(+), 212 deletions(-) create mode 100644 core/templates/dev/head/pages/library/LearnerDashboardIdsBackendApiService.js diff --git a/core/controllers/learner_dashboard.py b/core/controllers/learner_dashboard.py index 6c448a493b89..34c8a2e68645 100644 --- a/core/controllers/learner_dashboard.py +++ b/core/controllers/learner_dashboard.py @@ -117,6 +117,38 @@ def get(self): self.render_json(self.values) +class LearnerDashboardIdsHandler(base.BaseHandler): + + @acl_decorators.can_access_learner_dashboard + def get(self): + # Get the progress of the learner - the ids of the explorations and + # collections completed by the user, the activities currently being + # completed and the ones present in the playlist of the user. + activity_ids = ( + learner_progress_services.get_ids_of_activities_in_learner_dashboard( # pylint: disable=line-too-long + self.user_id)) + + learner_dashboard_activity_ids = { + 'completed_exploration_ids': ( + activity_ids.completed_exploration_ids), + 'completed_collection_ids': ( + activity_ids.completed_collection_ids), + 'incomplete_exploration_ids': ( + activity_ids.incomplete_exploration_ids), + 'incomplete_collection_ids': ( + activity_ids.incomplete_collection_ids), + 'exploration_playlist_ids': ( + activity_ids.exploration_playlist_ids), + 'collection_playlist_ids': activity_ids.collection_playlist_ids + } + + self.values.update({ + 'learner_dashboard_activity_ids': ( + learner_dashboard_activity_ids) + }) + self.render_json(self.values) + + class LearnerDashboardFeedbackThreadHandler(base.BaseHandler): """Gets all the messages in a thread.""" diff --git a/core/controllers/learner_dashboard_test.py b/core/controllers/learner_dashboard_test.py index 825abc5e2fda..d3af4ea19a1a 100644 --- a/core/controllers/learner_dashboard_test.py +++ b/core/controllers/learner_dashboard_test.py @@ -25,11 +25,19 @@ class LearnerDashboardHandlerTest(test_utils.GenericTestBase): OWNER_EMAIL = 'owner@example.com' OWNER_USERNAME = 'owner' - EXP_ID = 'exp_id' - EXP_TITLE = 'Exploration title' - - COL_ID = 'col_id' - COL_TITLE = 'Collection title' + EXP_ID_1 = 'EXP_ID_1' + EXP_TITLE_1 = 'Exploration title 1' + EXP_ID_2 = 'EXP_ID_2' + EXP_TITLE_2 = 'Exploration title 2' + EXP_ID_3 = 'EXP_ID_3' + EXP_TITLE_3 = 'Exploration title 3' + + COL_ID_1 = 'COL_ID_1' + COL_TITLE_1 = 'Collection title 1' + COL_ID_2 = 'COL_ID_2' + COL_TITLE_2 = 'Collection title 2' + COL_ID_3 = 'COL_ID_3' + COL_TITLE_3 = 'Collection title 3' def setUp(self): super(LearnerDashboardHandlerTest, self).setUp() @@ -46,14 +54,14 @@ def test_can_see_completed_explorations(self): self.assertEqual(len(response['completed_explorations_list']), 0) self.save_new_default_exploration( - self.EXP_ID, self.owner_id, title=self.EXP_TITLE) + self.EXP_ID_1, self.owner_id, title=self.EXP_TITLE_1) learner_progress_services.mark_exploration_as_completed( - self.viewer_id, self.EXP_ID) + self.viewer_id, self.EXP_ID_1) response = self.get_json(feconf.LEARNER_DASHBOARD_DATA_URL) self.assertEqual(len(response['completed_explorations_list']), 1) self.assertEqual( - response['completed_explorations_list'][0]['id'], self.EXP_ID) + response['completed_explorations_list'][0]['id'], self.EXP_ID_1) self.logout() def test_can_see_completed_collections(self): @@ -63,14 +71,14 @@ def test_can_see_completed_collections(self): self.assertEqual(len(response['completed_collections_list']), 0) self.save_new_default_collection( - self.COL_ID, self.owner_id, title=self.COL_TITLE) + self.COL_ID_1, self.owner_id, title=self.COL_TITLE_1) learner_progress_services.mark_collection_as_completed( - self.viewer_id, self.COL_ID) + self.viewer_id, self.COL_ID_1) response = self.get_json(feconf.LEARNER_DASHBOARD_DATA_URL) self.assertEqual(len(response['completed_collections_list']), 1) self.assertEqual( - response['completed_collections_list'][0]['id'], self.COL_ID) + response['completed_collections_list'][0]['id'], self.COL_ID_1) self.logout() def test_can_see_incomplete_explorations(self): @@ -80,17 +88,17 @@ def test_can_see_incomplete_explorations(self): self.assertEqual(len(response['incomplete_explorations_list']), 0) self.save_new_default_exploration( - self.EXP_ID, self.owner_id, title=self.EXP_TITLE) + self.EXP_ID_1, self.owner_id, title=self.EXP_TITLE_1) state_name = 'state_name' version = 1 learner_progress_services.mark_exploration_as_incomplete( - self.viewer_id, self.EXP_ID, state_name, version) + self.viewer_id, self.EXP_ID_1, state_name, version) response = self.get_json(feconf.LEARNER_DASHBOARD_DATA_URL) self.assertEqual(len(response['incomplete_explorations_list']), 1) self.assertEqual( - response['incomplete_explorations_list'][0]['id'], self.EXP_ID) + response['incomplete_explorations_list'][0]['id'], self.EXP_ID_1) self.logout() def test_can_see_incomplete_collections(self): @@ -100,14 +108,14 @@ def test_can_see_incomplete_collections(self): self.assertEqual(len(response['incomplete_collections_list']), 0) self.save_new_default_collection( - self.COL_ID, self.owner_id, title=self.COL_TITLE) + self.COL_ID_1, self.owner_id, title=self.COL_TITLE_1) learner_progress_services.mark_collection_as_incomplete( - self.viewer_id, self.COL_ID) + self.viewer_id, self.COL_ID_1) response = self.get_json(feconf.LEARNER_DASHBOARD_DATA_URL) self.assertEqual(len(response['incomplete_collections_list']), 1) self.assertEqual( - response['incomplete_collections_list'][0]['id'], self.COL_ID) + response['incomplete_collections_list'][0]['id'], self.COL_ID_1) self.logout() def test_can_see_exploration_playlist(self): @@ -117,14 +125,14 @@ def test_can_see_exploration_playlist(self): self.assertEqual(len(response['exploration_playlist']), 0) self.save_new_default_exploration( - self.EXP_ID, self.owner_id, title=self.EXP_TITLE) + self.EXP_ID_1, self.owner_id, title=self.EXP_TITLE_1) learner_progress_services.add_exp_to_learner_playlist( - self.viewer_id, self.EXP_ID) + self.viewer_id, self.EXP_ID_1) response = self.get_json(feconf.LEARNER_DASHBOARD_DATA_URL) self.assertEqual(len(response['exploration_playlist']), 1) self.assertEqual( - response['exploration_playlist'][0]['id'], self.EXP_ID) + response['exploration_playlist'][0]['id'], self.EXP_ID_1) self.logout() def test_can_see_collection_playlist(self): @@ -134,14 +142,14 @@ def test_can_see_collection_playlist(self): self.assertEqual(len(response['collection_playlist']), 0) self.save_new_default_collection( - self.COL_ID, self.owner_id, title=self.COL_TITLE) + self.COL_ID_1, self.owner_id, title=self.COL_TITLE_1) learner_progress_services.add_collection_to_learner_playlist( - self.viewer_id, self.COL_ID) + self.viewer_id, self.COL_ID_1) response = self.get_json(feconf.LEARNER_DASHBOARD_DATA_URL) self.assertEqual(len(response['collection_playlist']), 1) self.assertEqual( - response['collection_playlist'][0]['id'], self.COL_ID) + response['collection_playlist'][0]['id'], self.COL_ID_1) self.logout() def test_can_see_subscription(self): @@ -159,24 +167,82 @@ def test_can_see_subscription(self): self.OWNER_USERNAME) self.logout() + def test_get_learner_dashboard_ids(self): + self.login(self.VIEWER_EMAIL) + + self.save_new_default_exploration( + self.EXP_ID_1, self.owner_id, title=self.EXP_TITLE_1) + self.save_new_default_exploration( + self.EXP_ID_2, self.owner_id, title=self.EXP_TITLE_2) + self.save_new_default_exploration( + self.EXP_ID_3, self.owner_id, title=self.EXP_TITLE_3) + + self.save_new_default_collection( + self.COL_ID_1, self.owner_id, title=self.COL_TITLE_1) + self.save_new_default_collection( + self.COL_ID_2, self.owner_id, title=self.COL_TITLE_2) + self.save_new_default_collection( + self.COL_ID_3, self.owner_id, title=self.COL_TITLE_3) + + state_name = 'state_name' + version = 1 + + learner_progress_services.mark_exploration_as_completed( + self.viewer_id, self.EXP_ID_1) + learner_progress_services.mark_exploration_as_incomplete( + self.viewer_id, self.EXP_ID_2, state_name, version) + learner_progress_services.add_exp_to_learner_playlist( + self.viewer_id, self.EXP_ID_3) + + learner_progress_services.mark_collection_as_completed( + self.viewer_id, self.COL_ID_1) + learner_progress_services.mark_collection_as_incomplete( + self.viewer_id, self.COL_ID_2) + learner_progress_services.add_collection_to_learner_playlist( + self.viewer_id, self.COL_ID_3) + + response = self.get_json(feconf.LEARNER_DASHBOARD_IDS_DATA_URL) + learner_dashboard_activity_ids = ( + response['learner_dashboard_activity_ids']) + + self.assertEqual( + learner_dashboard_activity_ids['completed_exploration_ids'], + [self.EXP_ID_1]) + self.assertEqual( + learner_dashboard_activity_ids['incomplete_exploration_ids'], + [self.EXP_ID_2]) + self.assertEqual( + learner_dashboard_activity_ids['exploration_playlist_ids'], + [self.EXP_ID_3]) + + self.assertEqual( + learner_dashboard_activity_ids['completed_collection_ids'], + [self.COL_ID_1]) + self.assertEqual( + learner_dashboard_activity_ids['incomplete_collection_ids'], + [self.COL_ID_2]) + self.assertEqual( + learner_dashboard_activity_ids['collection_playlist_ids'], + [self.COL_ID_3]) + class LearnerDashboardFeedbackThreadHandlerTest(test_utils.GenericTestBase): - EXP_ID = '0' + EXP_ID_1 = '0' def setUp(self): super(LearnerDashboardFeedbackThreadHandlerTest, self).setUp() self.signup(self.EDITOR_EMAIL, self.EDITOR_USERNAME) # Load exploration 0. - exp_services.load_demo(self.EXP_ID) + exp_services.load_demo(self.EXP_ID_1) # Get the CSRF token and create a single thread with a single message. self.login(self.EDITOR_EMAIL) - response = self.testapp.get('/create/%s' % self.EXP_ID) + response = self.testapp.get('/create/%s' % self.EXP_ID_1) self.csrf_token = self.get_csrf_token_from_response(response) self.post_json('%s/%s' % ( - feconf.FEEDBACK_THREADLIST_URL_PREFIX, self.EXP_ID + feconf.FEEDBACK_THREADLIST_URL_PREFIX, self.EXP_ID_1 ), { 'state_name': self._get_unicode_test_string('statename'), 'subject': self._get_unicode_test_string('subject'), @@ -188,14 +254,14 @@ def test_get_message_summaries(self): self.login(self.EDITOR_EMAIL) # Fetch all the feedback threads of that exploration. response_dict = self.get_json( - '%s/%s' % (feconf.FEEDBACK_THREADLIST_URL_PREFIX, self.EXP_ID)) + '%s/%s' % (feconf.FEEDBACK_THREADLIST_URL_PREFIX, self.EXP_ID_1)) # Get the id of the thread. thread_id = response_dict['threads'][0]['thread_id'] # Get the message summary of the thread. thread_url = '%s/%s/%s' % ( - feconf.LEARNER_DASHBOARD_FEEDBACK_THREAD_DATA_URL, self.EXP_ID, + feconf.LEARNER_DASHBOARD_FEEDBACK_THREAD_DATA_URL, self.EXP_ID_1, thread_id) response_dict = self.get_json(thread_url) messages_summary = response_dict['message_summary_list'] @@ -208,7 +274,7 @@ def test_get_message_summaries(self): # Add another message. thread_url = '%s/%s/%s' % ( - feconf.FEEDBACK_THREAD_URL_PREFIX, self.EXP_ID, thread_id) + feconf.FEEDBACK_THREAD_URL_PREFIX, self.EXP_ID_1, thread_id) self.post_json(thread_url, { 'updated_status': None, 'updated_subject': None, @@ -217,7 +283,7 @@ def test_get_message_summaries(self): # Again fetch the thread message summary. thread_url = '%s/%s/%s' % ( - feconf.LEARNER_DASHBOARD_FEEDBACK_THREAD_DATA_URL, self.EXP_ID, + feconf.LEARNER_DASHBOARD_FEEDBACK_THREAD_DATA_URL, self.EXP_ID_1, thread_id) response_dict = self.get_json(thread_url) messages_summary = response_dict['message_summary_list'] diff --git a/core/controllers/library.py b/core/controllers/library.py index 8df77edbe4a8..6adcd7eef8ce 100644 --- a/core/controllers/library.py +++ b/core/controllers/library.py @@ -23,7 +23,6 @@ from core.controllers import base from core.domain import collection_services from core.domain import exp_services -from core.domain import learner_progress_services from core.domain import summary_services from core.domain import user_services from core.platform import models @@ -118,39 +117,10 @@ def get(self): [constants.DEFAULT_LANGUAGE_CODE])) preferred_language_codes = [constants.DEFAULT_LANGUAGE_CODE] - learner_dashboard_activity_ids = { - 'completed_exploration_ids': [], - 'completed_collection_ids': [], - 'incomplete_exploration_ids': [], - 'incomplete_collection_ids': [], - 'exploration_playlist_ids': [], - 'collection_playlist_ids': [] - } if self.user_id: user_settings = user_services.get_user_settings(self.user_id) preferred_language_codes = user_settings.preferred_language_codes - # Get the progress of the learner - the ids of the explorations and - # collections completed by the user, the activities currently being - # completed and the ones present in the playlist of the user. - activity_ids = ( - learner_progress_services.get_ids_of_activities_in_learner_dashboard( # pylint: disable=line-too-long - self.user_id)) - - learner_dashboard_activity_ids = { - 'completed_exploration_ids': ( - activity_ids.completed_exploration_ids), - 'completed_collection_ids': ( - activity_ids.completed_collection_ids), - 'incomplete_exploration_ids': ( - activity_ids.incomplete_exploration_ids), - 'incomplete_collection_ids': ( - activity_ids.incomplete_collection_ids), - 'exploration_playlist_ids': ( - activity_ids.exploration_playlist_ids), - 'collection_playlist_ids': activity_ids.collection_playlist_ids - } - if top_rated_activity_summary_dicts: summary_dicts_by_category.insert(0, { 'activity_summary_dicts': top_rated_activity_summary_dicts, @@ -173,8 +143,6 @@ def get(self): self.values.update({ 'activity_summary_dicts_by_category': ( summary_dicts_by_category), - 'learner_dashboard_activity_ids': ( - learner_dashboard_activity_ids), 'preferred_language_codes': preferred_language_codes, }) self.render_json(self.values) diff --git a/core/templates/dev/head/pages/library/ActivityTilesInfinityGridDirective.js b/core/templates/dev/head/pages/library/ActivityTilesInfinityGridDirective.js index 08f680050b49..ef9dd9d6ecc6 100644 --- a/core/templates/dev/head/pages/library/ActivityTilesInfinityGridDirective.js +++ b/core/templates/dev/head/pages/library/ActivityTilesInfinityGridDirective.js @@ -20,22 +20,18 @@ oppia.directive('activityTilesInfinityGrid', [ 'UrlInterpolationService', function(UrlInterpolationService) { return { restrict: 'E', - scope: { - getLearnerDashboardActivityIds: '&learnerDashboardActivityIds', - }, templateUrl: UrlInterpolationService.getDirectiveTemplateUrl( '/pages/library/' + 'activity_tiles_infinity_grid_directive.html'), controller: [ '$scope', '$rootScope', '$http', 'searchService', 'alertsService', - '$modal', function( + '$modal', 'LearnerDashboardIdsBackendApiService', function( $scope, $rootScope, $http, searchService, alertsService, - $modal) { + $modal, LearnerDashboardIdsBackendApiService) { $scope.endOfPageIsReached = false; $scope.allActivitiesInOrder = []; var currentlyHoveringOverActivity = false; var activeActivityId = ''; - console.log($scope.getLearnerDashboardActivityIds()); // Called when the first batch of search results is retrieved from the // server. $scope.$on( @@ -45,143 +41,18 @@ oppia.directive('activityTilesInfinityGrid', [ } ); + LearnerDashboardIdsBackendApiService.fetchLearnerDashboardIds().then( + function(response) { + $scope.learnerDashboardActivityIds = ( + response.data.learner_dashboard_activity_ids); + } + ); + $scope.setCurrentlyHoveringOverActivity = function(activityId) { activeActivityId = activityId; currentlyHoveringOverActivity = !currentlyHoveringOverActivity; }; - $scope.showAddToLearnerPlaylistIcon = function(activityId) { - var incompleteExplorationIds = ( - $scope.getLearnerDashboardActivityIds( - ).incomplete_exploration_ids); - var incompleteCollectionIds = ( - $scope.getLearnerDashboardActivityIds( - ).incomplete_collection_ids); - var completedExplorationIds = ( - $scope.getLearnerDashboardActivityIds( - ).completed_exploration_ids); - var completedCollectionIds = ( - $scope.getLearnerDashboardActivityIds().completed_collection_ids); - var explorationPlaylistIds = ( - $scope.getLearnerDashboardActivityIds().exploration_playlist_ids); - var collectionPlaylistIds = ( - $scope.getLearnerDashboardActivityIds().collection_playlist_ids); - - if (incompleteExplorationIds.indexOf(activityId) !== -1 || - incompleteCollectionIds.indexOf(activityId) !== -1 || - completedExplorationIds.indexOf(activityId) !== -1 || - completedCollectionIds.indexOf(activityId) !== -1 || - explorationPlaylistIds.indexOf(activityId) !== -1 || - collectionPlaylistIds.indexOf(activityId) !== -1) { - return false; - } else { - return (currentlyHoveringOverActivity && - (activeActivityId === activityId)); - } - }; - - $scope.addToLearnerPlaylist = function(activityType, activityId) { - var addActivityToLearnerPlaylistUrl = ( - UrlInterpolationService.interpolateUrl( - '/learnerplaylistactivityhandler//', { - activityType: activityType, - activityId: activityId - })); - $http.post(addActivityToLearnerPlaylistUrl, {}) - .then(function(response) { - if (response.data.belongs_to_completed_or_incomplete_list) { - alertsService.addInfoMessage( - 'You have already completed or are completing this ' + - 'activity.'); - } else if (response.data.belongs_to_subscribed_activities) { - alertsService.addInfoMessage( - 'This is present in your creator dashboard'); - } else if (response.data.playlist_limit_exceeded) { - alertsService.addInfoMessage( - 'Your \'Play Later\' list is full! Either you can ' + - 'complete some or you can head to the learner dashboard ' + - 'and remove some.'); - } else { - alertsService.addSuccessMessage( - 'Successfully added to your \'Play Later\' list.'); - } - }); - - if (activityType == constants.ACTIVITY_TYPE_EXPLORATION) { - $scope.getLearnerDashboardActivityIds( - ).exploration_playlist_ids.push(activityId); - } else { - $scope.getLearnerDashboardActivityIds( - ).collection_playlist_ids.push(activityId); - } - }; - - $scope.removeFromLearnerPlaylist = function( - activityId, activityType, activityTitle) { - $modal.open({ - templateUrl: UrlInterpolationService.getDirectiveTemplateUrl( - '/pages/learner_dashboard/' + - 'remove_activity_from_learner_dashboard_modal_directive.html'), - backdrop: true, - resolve: { - activityId: function() { - return activityId; - }, - activityType: function() { - return activityType; - }, - activityTitle: function() { - return activityTitle; - } - }, - controller: [ - '$scope', '$modalInstance', '$http', 'UrlInterpolationService', - function( - $scope, $modalInstance, $http, UrlInterpolationService) { - $scope.sectionNameI18nId = ( - 'I18N_LEARNER_DASHBOARD_PLAYLIST_SECTION'); - $scope.activityTitle = activityTitle; - var removeFromLearnerPlaylistUrl = ( - /* eslint-disable max-len */ - UrlInterpolationService.interpolateUrl( - '/learnerplaylistactivityhandler//', { - activityType: activityType, - activityId: activityId - })); - /* eslint-enable max-len */ - $scope.remove = function() { - $http['delete'](removeFromLearnerPlaylistUrl); - $modalInstance.close(); - }; - - $scope.cancel = function() { - $modalInstance.dismiss('cancel'); - }; - } - ] - }).result.then(function() { - if (activityType == constants.ACTIVITY_TYPE_EXPLORATION) { - /* eslint-disable max-len */ - var index = ( - $scope.getLearnerDashboardActivityIds().exploration_playlist_ids.indexOf( - activityId)); - if (index !== -1) { - $scope.getLearnerDashboardActivityIds().exploration_playlist_ids.splice( - index, 1); - } - } else { - var index = ( - $scope.getLearnerDashboardActivityIds().collection_playlist_ids.indexOf( - activityId)); - if (index !== -1) { - $scope.getLearnerDashboardActivityIds().collection_playlist_ids.splice( - index, 1); - } - } - /* eslint-enable max-len */ - }); - }; - $scope.showMoreActivities = function() { if (!$rootScope.loadingMessage && !$scope.endOfPageIsReached) { $scope.searchResultsAreLoading = true; diff --git a/core/templates/dev/head/pages/library/LearnerDashboardIdsBackendApiService.js b/core/templates/dev/head/pages/library/LearnerDashboardIdsBackendApiService.js new file mode 100644 index 000000000000..66ba103b83a6 --- /dev/null +++ b/core/templates/dev/head/pages/library/LearnerDashboardIdsBackendApiService.js @@ -0,0 +1,28 @@ +// Copyright 2016 The Oppia Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS-IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/** + * @fileoverview get the activity ids that are present in the learner + * dashboard. + */ + +oppia.factory('LearnerDashboardIdsBackendApiService', ['$http', function($http) { + var _fetchLearnerDashboardIds = function() { + return $http.get('/learnerdashboardidshandler/data'); + }; + + return { + fetchLearnerDashboardIds: _fetchLearnerDashboardIds + }; +}]); \ No newline at end of file diff --git a/core/templates/dev/head/pages/library/Library.js b/core/templates/dev/head/pages/library/Library.js index 85695bc9133b..1cad493a3f76 100644 --- a/core/templates/dev/head/pages/library/Library.js +++ b/core/templates/dev/head/pages/library/Library.js @@ -30,11 +30,13 @@ oppia.controller('Library', [ '$scope', '$http', '$modal', '$rootScope', '$window', '$timeout', 'i18nIdService', 'urlService', 'ALL_CATEGORIES', 'searchService', 'windowDimensionsService', 'UrlInterpolationService', 'LIBRARY_PAGE_MODES', - 'LIBRARY_TILE_WIDTH_PX', 'alertsService', function( + 'LIBRARY_TILE_WIDTH_PX', 'alertsService', + 'LearnerDashboardIdsBackendApiService', function( $scope, $http, $modal, $rootScope, $window, $timeout, i18nIdService, urlService, ALL_CATEGORIES, searchService, windowDimensionsService, UrlInterpolationService, LIBRARY_PAGE_MODES, - LIBRARY_TILE_WIDTH_PX, alertsService) { + LIBRARY_TILE_WIDTH_PX, alertsService, + LearnerDashboardIdsBackendApiService) { $rootScope.loadingMessage = 'I18N_LIBRARY_LOADING'; var possibleBannerFilenames = [ 'banner1.svg', 'banner2.svg', 'banner3.svg', 'banner4.svg']; @@ -74,8 +76,15 @@ oppia.controller('Library', [ } else { $http.get('/libraryindexhandler').success(function(data) { $scope.libraryGroups = data.activity_summary_dicts_by_category; - $scope.learnerDashboardActivityIds = ( - data.learner_dashboard_activity_ids); + + if (data.user_email) { + LearnerDashboardIdsBackendApiService.fetchLearnerDashboardIds().then( + function(response) { + $scope.learnerDashboardActivityIds = ( + response.data.learner_dashboard_activity_ids); + } + ); + } $rootScope.$broadcast( 'preferredLanguageCodesLoaded', data.preferred_language_codes); diff --git a/core/templates/dev/head/pages/library/SearchResultsDirective.js b/core/templates/dev/head/pages/library/SearchResultsDirective.js index 197fc07f194d..f85cf5afab69 100644 --- a/core/templates/dev/head/pages/library/SearchResultsDirective.js +++ b/core/templates/dev/head/pages/library/SearchResultsDirective.js @@ -20,9 +20,6 @@ oppia.directive('searchResults', [ 'UrlInterpolationService', function(UrlInterpolationService) { return { restrict: 'E', - scope: { - learnerDashboardActivityIds: '=learnerDashboardActivityIds', - }, templateUrl: 'components/searchResults', controller: [ '$scope', '$rootScope', '$timeout', '$window', 'siteAnalyticsService', diff --git a/core/templates/dev/head/pages/library/activity_tiles_infinity_grid_directive.html b/core/templates/dev/head/pages/library/activity_tiles_infinity_grid_directive.html index 3e0ced6b83fb..66cd346c6dcc 100644 --- a/core/templates/dev/head/pages/library/activity_tiles_infinity_grid_directive.html +++ b/core/templates/dev/head/pages/library/activity_tiles_infinity_grid_directive.html @@ -10,7 +10,7 @@ objective="activity.objective" thumbnail-icon-url="activity.thumbnail_icon_url" thumbnail-bg-color="activity.thumbnail_bg_color" - learner-dashboard-activity-ids="getLearnerDashboardActivityIds()"> + learner-dashboard-activity-ids="learnerDashboardActivityIds"> + learner-dashboard-activity-ids="learnerDashboardActivityIds">
diff --git a/core/templates/dev/head/pages/library/library.html b/core/templates/dev/head/pages/library/library.html index 4a4ad27ae193..f816dc80227d 100644 --- a/core/templates/dev/head/pages/library/library.html +++ b/core/templates/dev/head/pages/library/library.html @@ -41,7 +41,7 @@
- +
+ diff --git a/core/templates/dev/head/pages/library/search_results_directive.html b/core/templates/dev/head/pages/library/search_results_directive.html index c690d9befeee..e3ce0ae8b094 100644 --- a/core/templates/dev/head/pages/library/search_results_directive.html +++ b/core/templates/dev/head/pages/library/search_results_directive.html @@ -32,6 +32,6 @@
- +
diff --git a/feconf.py b/feconf.py index 2d99a77f3860..91ded02d2f49 100644 --- a/feconf.py +++ b/feconf.py @@ -591,6 +591,7 @@ def get_empty_ratings(): FRACTIONS_LANDING_PAGE_URL = '/fractions' LEARNER_DASHBOARD_URL = '/learner_dashboard' LEARNER_DASHBOARD_DATA_URL = '/learnerdashboardhandler/data' +LEARNER_DASHBOARD_IDS_DATA_URL = '/learnerdashboardidshandler/data' LEARNER_DASHBOARD_FEEDBACK_THREAD_DATA_URL = '/learnerdashboardthreadhandler' LEARNER_PLAYLIST_DATA_URL = '/learnerplaylistactivityhandler' LEARNER_INCOMPLETE_ACTIVITY_DATA_URL = '/learnerincompleteactivityhandler' diff --git a/main.py b/main.py index 1179e944429d..6e4daf4c4001 100644 --- a/main.py +++ b/main.py @@ -212,6 +212,9 @@ def ui_access_wrapper(self, *args, **kwargs): get_redirect_route( r'%s' % feconf.LEARNER_DASHBOARD_DATA_URL, learner_dashboard.LearnerDashboardHandler), + get_redirect_route( + r'%s' % feconf.LEARNER_DASHBOARD_IDS_DATA_URL, + learner_dashboard.LearnerDashboardIdsHandler), get_redirect_route( r'%s//' % feconf.LEARNER_DASHBOARD_FEEDBACK_THREAD_DATA_URL, From 3f866f0a78ea994a2bf099a09b673bb88f27da9d Mon Sep 17 00:00:00 2001 From: Arunabh98 Date: Wed, 23 Aug 2017 22:50:57 +0530 Subject: [PATCH 41/65] Fix lint errors. --- .../LearnerDashboardIdsBackendApiService.js | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/core/templates/dev/head/pages/library/LearnerDashboardIdsBackendApiService.js b/core/templates/dev/head/pages/library/LearnerDashboardIdsBackendApiService.js index 66ba103b83a6..cf1d77890726 100644 --- a/core/templates/dev/head/pages/library/LearnerDashboardIdsBackendApiService.js +++ b/core/templates/dev/head/pages/library/LearnerDashboardIdsBackendApiService.js @@ -17,12 +17,14 @@ * dashboard. */ -oppia.factory('LearnerDashboardIdsBackendApiService', ['$http', function($http) { - var _fetchLearnerDashboardIds = function() { - return $http.get('/learnerdashboardidshandler/data'); - }; +oppia.factory('LearnerDashboardIdsBackendApiService',[ + '$http',function($http) { + var _fetchLearnerDashboardIds = function() { + return $http.get('/learnerdashboardidshandler/data'); + }; - return { - fetchLearnerDashboardIds: _fetchLearnerDashboardIds - }; -}]); \ No newline at end of file + return { + fetchLearnerDashboardIds: _fetchLearnerDashboardIds + }; + } +]); From 0a2c0496dd991a978c6f8334641014ad3db3dd9f Mon Sep 17 00:00:00 2001 From: Arunabh98 Date: Thu, 24 Aug 2017 14:50:00 +0530 Subject: [PATCH 42/65] Add e2e test for plurals. --- assets/i18n/en.json | 18 +++---- .../learner_dashboard/learner_dashboard.html | 54 +++++++------------ 2 files changed, 24 insertions(+), 48 deletions(-) diff --git a/assets/i18n/en.json b/assets/i18n/en.json index d7ad7ce6d188..bafaef2e9512 100644 --- a/assets/i18n/en.json +++ b/assets/i18n/en.json @@ -202,18 +202,12 @@ "I18N_LANGUAGE_FOOTER_VIEW_IN": "View Oppia in:", "I18N_LEARNER_DASHBOARD_COMPLETED_SECTION": "Completed", "I18N_LEARNER_DASHBOARD_COMPLETED_TO_INCOMPLETE_COLLECTIONS": "<[numberMoved]> of the collections you completed have been moved to the 'in progress' section as new explorations have been added to them!", - "I18N_LEARNER_DASHBOARD_DELETED_COLLECTIONS_FROM_PLAYLIST": "<[numberDeleted]> of the collections in your 'Play Later' list have been deleted by the owner. We are sorry for the inconvenience", - "I18N_LEARNER_DASHBOARD_DELETED_COLLECTION_FROM_PLAYLIST": "<[numberDeleted]> of the collections in your 'Play Later' list has been deleted by the owner. We are sorry for the inconvenience", - "I18N_LEARNER_DASHBOARD_DELETED_COMPLETED_COLLECTION": "<[numberDeleted]> of the collections which you completed has been deleted by the owner. We are sorry for the inconvenience", - "I18N_LEARNER_DASHBOARD_DELETED_COMPLETED_COLLECTIONS": "<[numberDeleted]> of the collections which you completed have been deleted by the owner. We are sorry for the inconvenience", - "I18N_LEARNER_DASHBOARD_DELETED_COMPLETED_EXPLORATION": "<[numberDeleted]> of the explorations which you completed has been deleted by the owner. We are sorry for the inconvenience", - "I18N_LEARNER_DASHBOARD_DELETED_COMPLETED_EXPLORATIONS": "<[numberDeleted]> of the explorations which you completed have been deleted by the owner. We are sorry for the inconvenience", - "I18N_LEARNER_DASHBOARD_DELETED_EXPLORATIONS_FROM_PLAYLIST": "<[numberDeleted]> of the explorations in your 'Play Later' list have been deleted by the owner. We are sorry for the inconvenience", - "I18N_LEARNER_DASHBOARD_DELETED_EXPLORATION_FROM_PLAYLIST": "<[numberDeleted]> of the explorations in your 'Play Later' list has been deleted by the owner. We are sorry for the inconvenience", - "I18N_LEARNER_DASHBOARD_DELETED_INCOMPLETE_COLLECTION": "<[numberDeleted]> of the collections in progress has been deleted by the owner. We are sorry for the inconvenience", - "I18N_LEARNER_DASHBOARD_DELETED_INCOMPLETE_COLLECTIONS": "<[numberDeleted]> of the collections in progress have been deleted by the owner. We are sorry for the inconvenience", - "I18N_LEARNER_DASHBOARD_DELETED_INCOMPLETE_EXPLORATION": "<[numberDeleted]> of the explorations in progress has been deleted by the owner. We are sorry for the inconvenience", - "I18N_LEARNER_DASHBOARD_DELETED_INCOMPLETE_EXPLORATIONS": "<[numberDeleted]> of the explorations in progress have been deleted by the owner. We are sorry for the inconvenience", + "I18N_LEARNER_DASHBOARD_DELETED_COLLECTIONS_FROM_PLAYLIST": "{numberDeleted, plural, one{1 of the collections in your 'Play Later' list has been deleted by the owner. We are sorry for the inconvenience} other{# of the collections in your 'Play Later' list have been deleted by the owner. We are sorry for the inconvenience}}", + "I18N_LEARNER_DASHBOARD_DELETED_COMPLETED_COLLECTIONS": "{numberDeleted, plural, one{1 of the collections which you completed has been deleted by the owner. We are sorry for the inconvenience} other{# of the collections which you completed have been deleted by the owner. We are sorry for the inconvenience}}", + "I18N_LEARNER_DASHBOARD_DELETED_COMPLETED_EXPLORATIONS": "{numberDeleted, plural, one{1 of the explorations which you completed has been deleted by the owner. We are sorry for the inconvenience} other{# of the explorations which you completed have been deleted by the owner. We are sorry for the inconvenience}}", + "I18N_LEARNER_DASHBOARD_DELETED_EXPLORATIONS_FROM_PLAYLIST": "{numberDeleted, plural, one{1 of the explorations in your 'Play Later' list has been deleted by the owner. We are sorry for the inconvenience} other{# of the explorations in your 'Play Later' list have been deleted by the owner. We are sorry for the inconvenience}}", + "I18N_LEARNER_DASHBOARD_DELETED_INCOMPLETE_COLLECTIONS": "{numberDeleted, plural, one{1 of the collections in progress has been deleted by the owner. We are sorry for the inconvenience} other{# of the collections in progress have been deleted by the owner. We are sorry for the inconvenience}}", + "I18N_LEARNER_DASHBOARD_DELETED_INCOMPLETE_EXPLORATIONS": "{numberDeleted, plural, one{1 of the explorations in progress has been deleted by the owner. We are sorry for the inconvenience} other{# of the explorations in progress have been deleted by the owner. We are sorry for the inconvenience}}", "I18N_LEARNER_DASHBOARD_EMPTY_COLLECTION_PLAYLIST": "It looks like there aren't any collections in your 'Play Later' list. Head over to the library and build your own curated playlist!", "I18N_LEARNER_DASHBOARD_EMPTY_COMPLETED_COLLECTIONS": "It looks like you haven't completed any collections yet. Head over to the library to start an exciting new collection!", "I18N_LEARNER_DASHBOARD_EMPTY_COMPLETED_EXPLORATIONS": "It looks like you haven't completed any explorations yet. Head over to the library to start an exciting new exploration!", diff --git a/core/templates/dev/head/pages/learner_dashboard/learner_dashboard.html b/core/templates/dev/head/pages/learner_dashboard/learner_dashboard.html index 6649a701ce2b..5f87631b3098 100644 --- a/core/templates/dev/head/pages/learner_dashboard/learner_dashboard.html +++ b/core/templates/dev/head/pages/learner_dashboard/learner_dashboard.html @@ -220,12 +220,9 @@

<[subscriptionsList.length]>

- - + @@ -278,12 +275,9 @@

<[subscriptionsList.length]>

- - + @@ -333,12 +327,9 @@

<[subscriptionsList.length]>

- - + @@ -390,12 +381,9 @@

<[subscriptionsList.length]>

- - + @@ -450,12 +438,9 @@

<[subscriptionsList.length]>

- - + @@ -516,12 +501,9 @@

<[subscriptionsList.length]>

- - + From 881d846fec318620a5085f146e512d3a1fd3f3e1 Mon Sep 17 00:00:00 2001 From: Arunabh98 Date: Fri, 25 Aug 2017 07:49:40 +0530 Subject: [PATCH 43/65] Address review comments 2. --- assets/i18n/de.json | 12 +-- assets/i18n/fr.json | 12 +-- assets/i18n/hi.json | 12 +-- assets/i18n/qqq.json | 18 ++-- assets/i18n/sv.json | 4 +- assets/i18n/zh-hant.json | 12 +-- core/controllers/learner_dashboard.py | 17 ++-- core/controllers/learner_playlist_test.py | 87 ++++++++++++++++++- core/domain/learner_progress_services.py | 4 +- core/domain/learner_progress_services_test.py | 2 +- 10 files changed, 120 insertions(+), 60 deletions(-) diff --git a/assets/i18n/de.json b/assets/i18n/de.json index 41b29c495080..905a75b42bfa 100644 --- a/assets/i18n/de.json +++ b/assets/i18n/de.json @@ -202,14 +202,10 @@ "I18N_LANGUAGE_FOOTER_VIEW_IN": "Oppia ansehen auf:", "I18N_LEARNER_DASHBOARD_COMPLETED_SECTION": "Vervollständigt", "I18N_LEARNER_DASHBOARD_COMPLETED_TO_INCOMPLETE_COLLECTIONS": "<[numberMoved]> der vervollständigten Sammlungen wurden in den Abschnitt „In Bearbeitung“ verschoben, da neue Erforschungen zu ihnen hinzugefügt wurden!", - "I18N_LEARNER_DASHBOARD_DELETED_COMPLETED_COLLECTION": "<[numberDeleted]> der vervollständigten Sammlungen wurde kürzlich gelöscht. Das tut uns leid.", - "I18N_LEARNER_DASHBOARD_DELETED_COMPLETED_COLLECTIONS": "<[numberDeleted]> der vervollständigten Sammlungen wurden kürzlich gelöscht. Das tut uns leid.", - "I18N_LEARNER_DASHBOARD_DELETED_COMPLETED_EXPLORATION": "<[numberDeleted]> der vervollständigten Erforschungen wurde kürzlich gelöscht. Das tut uns leid.", - "I18N_LEARNER_DASHBOARD_DELETED_COMPLETED_EXPLORATIONS": "<[numberDeleted]> der vervollständigten Erforschungen wurden kürzlich gelöscht. Das tut uns leid.", - "I18N_LEARNER_DASHBOARD_DELETED_INCOMPLETE_COLLECTION": "<[numberDeleted]> der in Bearbeitung befindlichen Sammlungen wurde kürzlich gelöscht. Das tut uns leid.", - "I18N_LEARNER_DASHBOARD_DELETED_INCOMPLETE_COLLECTIONS": "<[numberDeleted]> der in Bearbeitung befindlichen Sammlungen wurden kürzlich gelöscht. Das tut uns leid.", - "I18N_LEARNER_DASHBOARD_DELETED_INCOMPLETE_EXPLORATION": "<[numberDeleted]> der in Bearbeitung befindlichen Erforschungen wurde kürzlich gelöscht. Das tut uns leid.", - "I18N_LEARNER_DASHBOARD_DELETED_INCOMPLETE_EXPLORATIONS": "<[numberDeleted]> der in Bearbeitung befindlichen Erforschungen wurden kürzlich gelöscht. Das tut uns leid.", + "I18N_LEARNER_DASHBOARD_DELETED_COMPLETED_COLLECTIONS": "{numberDeleted, plural, one{1 der vervollständigten Sammlungen wurde kürzlich gelöscht. Das tut uns leid.} other{# der vervollständigten Sammlungen wurden kürzlich gelöscht. Das tut uns leid.}}", + "I18N_LEARNER_DASHBOARD_DELETED_COMPLETED_EXPLORATIONS": "{numberDeleted, plural, one{1 der vervollständigten Erforschungen wurde kürzlich gelöscht. Das tut uns leid.} other{# der vervollständigten Erforschungen wurden kürzlich gelöscht. Das tut uns leid.}}", + "I18N_LEARNER_DASHBOARD_DELETED_INCOMPLETE_COLLECTIONS": "{numberDeleted, plural, one{1 der in Bearbeitung befindlichen Sammlungen wurde kürzlich gelöscht. Das tut uns leid.} other{# der in Bearbeitung befindlichen Sammlungen wurden kürzlich gelöscht. Das tut uns leid.}}", + "I18N_LEARNER_DASHBOARD_DELETED_INCOMPLETE_EXPLORATIONS": "{numberDeleted, plural, one{1 der in Bearbeitung befindlichen Erforschungen wurde kürzlich gelöscht. Das tut uns leid.} other{# der in Bearbeitung befindlichen Erforschungen wurden kürzlich gelöscht. Das tut uns leid.}}", "I18N_LEARNER_DASHBOARD_EMPTY_COMPLETED_COLLECTIONS": "Es sieht so aus, als ob du noch keine Sammlungen vervollständigt hast. Schau in der Bibliothek nach, um eine neue aufregende Sammlung zu starten!", "I18N_LEARNER_DASHBOARD_EMPTY_COMPLETED_EXPLORATIONS": "Es sieht so aus, als ob du noch keine Erforschungen vervollständigt hast. Schau in der Bibliothek nach, um eine neue aufregende Erforschung zu starten!", "I18N_LEARNER_DASHBOARD_EMPTY_FEEDBACK_THREADS": "Es sieht so aus, als ob du keine aktiven Rückmeldungs-Threads hast. Deine Rückmeldung hilft uns bei der Verbesserung der Qualität unserer Lektionen. Fahre mit der Maus über die Bibliothek, um etwas Aufregendes zu lernen und deine geschätzte Rückmeldung zu hinterlassen!", diff --git a/assets/i18n/fr.json b/assets/i18n/fr.json index 54e7cf519555..13f570b75fb9 100644 --- a/assets/i18n/fr.json +++ b/assets/i18n/fr.json @@ -202,14 +202,10 @@ "I18N_LANGUAGE_FOOTER_VIEW_IN": "Afficher Oppia en :", "I18N_LEARNER_DASHBOARD_COMPLETED_SECTION": "Terminé", "I18N_LEARNER_DASHBOARD_COMPLETED_TO_INCOMPLETE_COLLECTIONS": "<[numberMoved]> des collections que vous avez terminées ont été déplacées vers la section 'en cours' parce que de nouvelles explorations leur ont été ajoutées !", - "I18N_LEARNER_DASHBOARD_DELETED_COMPLETED_COLLECTION": "Suppression récente de <[numberDeleted]> des collections que vous avez terminées. Veuillez nous excuser pour le désagrément", - "I18N_LEARNER_DASHBOARD_DELETED_COMPLETED_COLLECTIONS": "Suppression récente de <[numberDeleted]> des collections que vous avez terminées. Veuillez nous excuser pour le désagrément", - "I18N_LEARNER_DASHBOARD_DELETED_COMPLETED_EXPLORATION": "Suppression récente de <[numberDeleted]> des explorations que vous avez terminées. Veuillez nous excuser pour le désagrément", - "I18N_LEARNER_DASHBOARD_DELETED_COMPLETED_EXPLORATIONS": "Suppression récente de <[numberDeleted]> des explorations que vous avez terminées. Veuillez nous excuser pour le désagrément", - "I18N_LEARNER_DASHBOARD_DELETED_INCOMPLETE_COLLECTION": "Suppression récente de <[numberDeleted]> des collections en cours. Veuillez nous excuser du dérangement", - "I18N_LEARNER_DASHBOARD_DELETED_INCOMPLETE_COLLECTIONS": "Suppression récente de <[numberDeleted]> des collections en cours. Veuillez nous excuser pour le désagrément", - "I18N_LEARNER_DASHBOARD_DELETED_INCOMPLETE_EXPLORATION": "Suppression récente de <[numberDeleted]> des explorations en cours. Veuillez nous excuser du pour le désagrément", - "I18N_LEARNER_DASHBOARD_DELETED_INCOMPLETE_EXPLORATIONS": "Suppression récente de <[numberDeleted]> des explorations en cours. Veuillez nous excuser du pour le désagrément", + "I18N_LEARNER_DASHBOARD_DELETED_COMPLETED_COLLECTIONS": "{numberDeleted, plural, one{Suppression récente de 1 des collections que vous avez terminées. Veuillez nous excuser pour le désagrément} other{Suppression récente de # des collections que vous avez terminées. Veuillez nous excuser pour le désagrément}}", + "I18N_LEARNER_DASHBOARD_DELETED_COMPLETED_EXPLORATIONS": "{numberDeleted, plural, one{Suppression récente de 1 des explorations que vous avez terminées. Veuillez nous excuser pour le désagrément} other{Suppression récente de # des explorations que vous avez terminées. Veuillez nous excuser pour le désagrément}}", + "I18N_LEARNER_DASHBOARD_DELETED_INCOMPLETE_COLLECTIONS": "{numberDeleted, plural, one{Suppression récente de 1 des collections en cours. Veuillez nous excuser du dérangement} other{Suppression récente de # des collections en cours. Veuillez nous excuser pour le désagrément}}", + "I18N_LEARNER_DASHBOARD_DELETED_INCOMPLETE_EXPLORATIONS": "{numberDeleted, plural, one{Suppression récente de 1 des explorations en cours. Veuillez nous excuser du pour le désagrément} other{Suppression récente de # des explorations en cours. Veuillez nous excuser du pour le désagrément}}", "I18N_LEARNER_DASHBOARD_EMPTY_COMPLETED_COLLECTIONS": "Il semble que vous n'ayez pas encore terminé de collection. Allez voir à la bibliothèque pour commencer une nouvelle collection excitante !", "I18N_LEARNER_DASHBOARD_EMPTY_COMPLETED_EXPLORATIONS": "Il semble que vous n'ayez pas encore terminé d'exploration. Allez voir à la bibliothèque pour commencer une nouvelle exploration excitante !", "I18N_LEARNER_DASHBOARD_EMPTY_FEEDBACK_THREADS": "Il semblerait que vous n’avez pas de fil de commentaire actif. Votre avis nous aide à améliorer la qualité de nos leçons. Parcourez la bibliothèque pour apprendre quelque chose d’intéressant et envoyez votre avis précieux !", diff --git a/assets/i18n/hi.json b/assets/i18n/hi.json index b5a10aa17d44..1bd9866c84ba 100644 --- a/assets/i18n/hi.json +++ b/assets/i18n/hi.json @@ -201,14 +201,10 @@ "I18N_LANGUAGE_FOOTER_VIEW_IN": "Oppia को देखे:", "I18N_LEARNER_DASHBOARD_COMPLETED_SECTION": "पूर्ण", "I18N_LEARNER_DASHBOARD_COMPLETED_TO_INCOMPLETE_COLLECTIONS": "आपके द्वारा किए गए संग्रह में से <[numberMoved]> को 'प्रगति' अनुभाग में स्थानांतरित किया गया क्योंकि उन्हें नए अन्वेषण जोड़े गए हैं!", - "I18N_LEARNER_DASHBOARD_DELETED_COMPLETED_COLLECTION": "आपके द्वारा पूरा किए गए संग्रह में से <[numberDeleted]> को हाल ही में हटा दिया गया है असुविधा के लिए खेद है", - "I18N_LEARNER_DASHBOARD_DELETED_COMPLETED_COLLECTIONS": "आपके द्वारा पूरा किए गए संग्रहों में से <[numberDeleted]> हाल ही में हटाए गए हैं असुविधा के लिए खेद है", - "I18N_LEARNER_DASHBOARD_DELETED_COMPLETED_EXPLORATION": "आपके द्वारा पूरी की गई अन्वेषण में से <[numberDeleted]> को हाल ही में हटा दिया गया है असुविधा के लिए खेद है", - "I18N_LEARNER_DASHBOARD_DELETED_COMPLETED_EXPLORATIONS": "आपके द्वारा पूरा किए गए अन्वेषण के <[numberDeleted]> हाल ही में हटाए गए हैं असुविधा के लिए खेद है", - "I18N_LEARNER_DASHBOARD_DELETED_INCOMPLETE_COLLECTION": "<[numberDeleted]> संग्रह की प्रगति में हाल ही में हटा दिया गया है असुविधा के लिए खेद है", - "I18N_LEARNER_DASHBOARD_DELETED_INCOMPLETE_COLLECTIONS": "प्रगति में <[numberDeleted]> संग्रह हाल ही में हटाए गए हैं असुविधा के लिए खेद है", - "I18N_LEARNER_DASHBOARD_DELETED_INCOMPLETE_EXPLORATION": "<[numberDeleted]> प्रगति में अन्वेषण हाल ही में हटा दिया गया है असुविधा के लिए खेद है", - "I18N_LEARNER_DASHBOARD_DELETED_INCOMPLETE_EXPLORATIONS": "<[numberDeleted]> प्रगति में अन्वेषण हाल ही में हटाए गए हैं असुविधा के लिए खेद है", + "I18N_LEARNER_DASHBOARD_DELETED_COMPLETED_COLLECTIONS": "{numberDeleted, plural, one{आपके द्वारा पूरा किए गए संग्रह में से 1 को हाल ही में हटा दिया गया है असुविधा के लिए खेद है} other{आपके द्वारा पूरा किए गए संग्रहों में से # हाल ही में हटाए गए हैं असुविधा के लिए खेद है}}", + "I18N_LEARNER_DASHBOARD_DELETED_COMPLETED_EXPLORATIONS": "{numberDeleted, plural, one{आपके द्वारा पूरी की गई अन्वेषण में से 1 को हाल ही में हटा दिया गया है असुविधा के लिए खेद है} other{आपके द्वारा पूरा किए गए अन्वेषण के # हाल ही में हटाए गए हैं असुविधा के लिए खेद है}}", + "I18N_LEARNER_DASHBOARD_DELETED_INCOMPLETE_COLLECTIONS": "{numberDeleted, plural, one{1 संग्रह की प्रगति में हाल ही में हटा दिया गया है असुविधा के लिए खेद है} other{प्रगति में # संग्रह हाल ही में हटाए गए हैं असुविधा के लिए खेद है}}", + "I18N_LEARNER_DASHBOARD_DELETED_INCOMPLETE_EXPLORATIONS": "{numberDeleted, plural, one{1 प्रगति में अन्वेषण हाल ही में हटा दिया गया है असुविधा के लिए खेद है} other{# प्रगति में अन्वेषण हाल ही में हटाए गए हैं असुविधा के लिए खेद है}}", "I18N_LEARNER_DASHBOARD_EMPTY_COMPLETED_COLLECTIONS": "ऐसा लगता है कि आपने अभी तक कोई भी कलेक्शन्स पूरा नहीं किया है। एक नया रोमांचक कलेक्शन्स शुरू करने के लिए पुस्तकालय में जाएं!", "I18N_LEARNER_DASHBOARD_EMPTY_COMPLETED_EXPLORATIONS": "ऐसा लगता है कि आपने अभी तक कोई अन्वेषण पूरा नहीं किया है। एक रोमांचक नई अन्वेषण शुरू करने के लिए पुस्तकालय पर जाएं!", "I18N_LEARNER_DASHBOARD_EMPTY_FEEDBACK_THREADS": "ऐसा लगता है कि आपके पास कोई सक्रिय प्रतिक्रिया थ्रेड्स नहीं है। आपकी प्रतिक्रिया हमें हमारे सबक की गुणवत्ता में सुधार करने में सहायता करती है। कुछ रोमांचक जानने के लिए लाइब्रेरी पर जाएं और अपनी बहुमूल्य फ़ीडबैक सबमिट करें!", diff --git a/assets/i18n/qqq.json b/assets/i18n/qqq.json index 1bc2d77a5aac..bbaa5b77084f 100644 --- a/assets/i18n/qqq.json +++ b/assets/i18n/qqq.json @@ -202,18 +202,12 @@ "I18N_LANGUAGE_FOOTER_VIEW_IN": "Text for the site language selector. - When the user selects a different language, the site (not the explorations) is translated into that language.", "I18N_LEARNER_DASHBOARD_COMPLETED_SECTION": "Text for the completed section in the learner dashboard.", "I18N_LEARNER_DASHBOARD_COMPLETED_TO_INCOMPLETE_COLLECTIONS": "Text displayed in the learner dashboard. - The text is shown when new exporations are added to the collections the user has already completed.", - "I18N_LEARNER_DASHBOARD_DELETED_COLLECTIONS_FROM_PLAYLIST": "Text displayed in the learner dashboard. - This text is shown when more than one collection in the playlist have been deleted.", - "I18N_LEARNER_DASHBOARD_DELETED_COLLECTION_FROM_PLAYLIST": "Text displayed in the learner dashboard. - This text is shown when a collection in the playlist has been deleted.", - "I18N_LEARNER_DASHBOARD_DELETED_COMPLETED_COLLECTION": "Text displayed in the learner dashboard. - This text is shown when a completed collection has been deleted.", - "I18N_LEARNER_DASHBOARD_DELETED_COMPLETED_COLLECTIONS": "Text displayed in the learner dashboard. - This text is shown when more than one completed collection has been deleted.", - "I18N_LEARNER_DASHBOARD_DELETED_COMPLETED_EXPLORATION": "Text displayed in the learner dashboard. - This text is shown when a completed exploration has been deleted.", - "I18N_LEARNER_DASHBOARD_DELETED_COMPLETED_EXPLORATIONS": "Text displayed in the learner dashboard. - This text is shown when more than one completed exploration has been deleted.", - "I18N_LEARNER_DASHBOARD_DELETED_EXPLORATIONS_FROM_PLAYLIST": "Text displayed in the learner dashboard. - This text is shown when more than one explorations in the playlist have been deleted.", - "I18N_LEARNER_DASHBOARD_DELETED_EXPLORATION_FROM_PLAYLIST": "Text displayed in the learner dashboard. - This text is shown when an exploration in the playlist has been deleted.", - "I18N_LEARNER_DASHBOARD_DELETED_INCOMPLETE_COLLECTION": "Text displayed in the learner dashboard. - This text is shown when a collection in progress has been deleted.", - "I18N_LEARNER_DASHBOARD_DELETED_INCOMPLETE_COLLECTIONS": "Text displayed in the learner dashboard. - This text is shown when more than one collection in progress has been deleted.", - "I18N_LEARNER_DASHBOARD_DELETED_INCOMPLETE_EXPLORATION": "Text displayed in the learner dashboard. - This text is shown when an exploration in progress has been deleted.", - "I18N_LEARNER_DASHBOARD_DELETED_INCOMPLETE_EXPLORATIONS": "Text displayed in the learner dashboard. - This text is shown when more than one exploration in progress has been deleted.", + "I18N_LEARNER_DASHBOARD_DELETED_COLLECTIONS_FROM_PLAYLIST": "Text displayed in the learner dashboard. - This text is shown when one or more than one collection in the playlist has been deleted.", + "I18N_LEARNER_DASHBOARD_DELETED_COMPLETED_COLLECTIONS": "Text displayed in the learner dashboard. - This text is shown when one or more than one completed collection has been deleted.", + "I18N_LEARNER_DASHBOARD_DELETED_COMPLETED_EXPLORATIONS": "Text displayed in the learner dashboard. - This text is shown when one or more than one completed exploration has been deleted.", + "I18N_LEARNER_DASHBOARD_DELETED_EXPLORATIONS_FROM_PLAYLIST": "Text displayed in the learner dashboard. - This text is shown when one or more than one explorations in the playlist have been deleted.", + "I18N_LEARNER_DASHBOARD_DELETED_INCOMPLETE_COLLECTIONS": "Text displayed in the learner dashboard. - This text is shown when one or more than one collection in progress has been deleted.", + "I18N_LEARNER_DASHBOARD_DELETED_INCOMPLETE_EXPLORATIONS": "Text displayed in the learner dashboard. - This text is shown when one or more than one exploration in progress has been deleted.", "I18N_LEARNER_DASHBOARD_EMPTY_COLLECTION_PLAYLIST": "Text displayed in the learner dashboard. - This text is shown when there are no collections in the playlist of the user.", "I18N_LEARNER_DASHBOARD_EMPTY_COMPLETED_COLLECTIONS": "Text displayed in the learner dashboard. - This text is shown when there are no collections in the completed section of the user.", "I18N_LEARNER_DASHBOARD_EMPTY_COMPLETED_EXPLORATIONS": "Text displayed in the learner dashboard. - This text is shown when there are no explorations in the completed section of the user.", diff --git a/assets/i18n/sv.json b/assets/i18n/sv.json index 30325881d297..33a480af0522 100644 --- a/assets/i18n/sv.json +++ b/assets/i18n/sv.json @@ -174,9 +174,7 @@ "I18N_INTERACTIONS_SET_INPUT_SUBMIT": "Skicka", "I18N_LANGUAGE_FOOTER_VIEW_IN": "Visa Oppia på:", "I18N_LEARNER_DASHBOARD_COMPLETED_SECTION": "Slutförd", - "I18N_LEARNER_DASHBOARD_DELETED_INCOMPLETE_COLLECTIONS": "<[numberDeleted]> av de pågående samlingarna har nyligen raderats. Vi beklagar besväret", - "I18N_LEARNER_DASHBOARD_DELETED_INCOMPLETE_EXPLORATION": "<[numberDeleted]> av de pågående utforskningarna har nyligen raderats. Vi beklagar besväret", - "I18N_LEARNER_DASHBOARD_DELETED_INCOMPLETE_EXPLORATIONS": "<[numberDeleted]> av de pågående utforskningarna har nyligen raderats. Vi beklagar besväret", + "I18N_LEARNER_DASHBOARD_DELETED_INCOMPLETE_EXPLORATIONS": "{numberDeleted, plural, one{1 av de pågående utforskningarna har nyligen raderats. Vi beklagar besväret} other{# av de pågående utforskningarna har nyligen raderats. Vi beklagar besväret}}", "I18N_LEARNER_DASHBOARD_EXPLORATIONS_SORT_BY_LAST_PLAYED": "Senast uppspelad", "I18N_LEARNER_DASHBOARD_FEEDBACK_SECTION": "Återkopplingsuppdateringar", "I18N_LEARNER_DASHBOARD_FEEDBACK_THREAD_DEFAULT_MESSAGE": "Svara", diff --git a/assets/i18n/zh-hant.json b/assets/i18n/zh-hant.json index a788507f8bd7..b6af8110faf6 100644 --- a/assets/i18n/zh-hant.json +++ b/assets/i18n/zh-hant.json @@ -202,14 +202,10 @@ "I18N_LANGUAGE_FOOTER_VIEW_IN": "檢視 Oppia 以:", "I18N_LEARNER_DASHBOARD_COMPLETED_SECTION": "已完成", "I18N_LEARNER_DASHBOARD_COMPLETED_TO_INCOMPLETE_COLLECTIONS": "您過去所完成的 <[numberMoved]> 個收藏,已被移動至「進行中」區域以作為新添增的探索!", - "I18N_LEARNER_DASHBOARD_DELETED_COMPLETED_COLLECTION": "您過去所完成的 <[numberDeleted]> 個收藏近期已被刪除。對此我們深表歉意", - "I18N_LEARNER_DASHBOARD_DELETED_COMPLETED_COLLECTIONS": "您過去所完成的 <[numberDeleted]> 個收藏近期已被刪除。對此我們深表歉意", - "I18N_LEARNER_DASHBOARD_DELETED_COMPLETED_EXPLORATION": "您過去所完成的 <[numberDeleted]> 個探索近期已被刪除。對此我們深表歉意", - "I18N_LEARNER_DASHBOARD_DELETED_COMPLETED_EXPLORATIONS": "您過去所完成的 <[numberDeleted]> 個探索近期已被刪除。對此我們深表歉意", - "I18N_LEARNER_DASHBOARD_DELETED_INCOMPLETE_COLLECTION": "<[numberDeleted]> 個進行中的收藏近期已被刪除。對此我們深表歉意", - "I18N_LEARNER_DASHBOARD_DELETED_INCOMPLETE_COLLECTIONS": "<[numberDeleted]> 個進行中的收藏近期已被刪除。對此我們深表歉意", - "I18N_LEARNER_DASHBOARD_DELETED_INCOMPLETE_EXPLORATION": "<[numberDeleted]> 個進行中的探索近期已被刪除。對此我們深表歉意", - "I18N_LEARNER_DASHBOARD_DELETED_INCOMPLETE_EXPLORATIONS": "<[numberDeleted]> 個進行中的探索近期已被刪除。對此我們深表歉意", + "I18N_LEARNER_DASHBOARD_DELETED_COMPLETED_COLLECTIONS": "{numberDeleted, plural, one{您過去所完成的 1 個收藏近期已被刪除。對此我們深表歉意} other{您過去所完成的 # 個收藏近期已被刪除。對此我們深表歉意}}", + "I18N_LEARNER_DASHBOARD_DELETED_COMPLETED_EXPLORATIONS": "{numberDeleted, plural, one{您過去所完成的 1 個探索近期已被刪除。對此我們深表歉意} other{您過去所完成的 # 個探索近期已被刪除。對此我們深表歉意}}", + "I18N_LEARNER_DASHBOARD_DELETED_INCOMPLETE_COLLECTIONS": "{numberDeleted, plural, one{1 個進行中的收藏近期已被刪除。對此我們深表歉意} other{# 個進行中的收藏近期已被刪除。對此我們深表歉意}}", + "I18N_LEARNER_DASHBOARD_DELETED_INCOMPLETE_EXPLORATIONS": "{numberDeleted, plural, one{1 個進行中的探索近期已被刪除。對此我們深表歉意} other{# 個進行中的探索近期已被刪除。對此我們深表歉意}}", "I18N_LEARNER_DASHBOARD_EMPTY_COMPLETED_COLLECTIONS": "看起來似乎您尚未完成任何收藏,來前往圖書館開始進行令人興奮的新收藏吧!", "I18N_LEARNER_DASHBOARD_EMPTY_COMPLETED_EXPLORATIONS": "看起來似乎您尚未完成任何探索,來前往圖書館開始進行一場令人興奮的新探索吧!", "I18N_LEARNER_DASHBOARD_EMPTY_FEEDBACK_THREADS": "看起來您似乎不積極於意見回饋。您的意見回饋對於改進我們課程的品質有著重要幫助。現在就起身出發到圖書館看看學習一些有趣的事情;並提交您寶貴的意見回饋吧!", diff --git a/core/controllers/learner_dashboard.py b/core/controllers/learner_dashboard.py index 34c8a2e68645..5908ab2642dc 100644 --- a/core/controllers/learner_dashboard.py +++ b/core/controllers/learner_dashboard.py @@ -124,22 +124,23 @@ def get(self): # Get the progress of the learner - the ids of the explorations and # collections completed by the user, the activities currently being # completed and the ones present in the playlist of the user. - activity_ids = ( - learner_progress_services.get_ids_of_activities_in_learner_dashboard( # pylint: disable=line-too-long + learner_dashboard_activities = ( + learner_progress_services.get_learner_dashboard_activities( # pylint: disable=line-too-long self.user_id)) learner_dashboard_activity_ids = { 'completed_exploration_ids': ( - activity_ids.completed_exploration_ids), + learner_dashboard_activities.completed_exploration_ids), 'completed_collection_ids': ( - activity_ids.completed_collection_ids), + learner_dashboard_activities.completed_collection_ids), 'incomplete_exploration_ids': ( - activity_ids.incomplete_exploration_ids), + learner_dashboard_activities.incomplete_exploration_ids), 'incomplete_collection_ids': ( - activity_ids.incomplete_collection_ids), + learner_dashboard_activities.incomplete_collection_ids), 'exploration_playlist_ids': ( - activity_ids.exploration_playlist_ids), - 'collection_playlist_ids': activity_ids.collection_playlist_ids + learner_dashboard_activities.exploration_playlist_ids), + 'collection_playlist_ids': ( + learner_dashboard_activities.collection_playlist_ids) } self.values.update({ diff --git a/core/controllers/learner_playlist_test.py b/core/controllers/learner_playlist_test.py index af3c656d6e1b..f5346320bd6f 100644 --- a/core/controllers/learner_playlist_test.py +++ b/core/controllers/learner_playlist_test.py @@ -31,12 +31,16 @@ class LearnerPlaylistHandlerTests(test_utils.GenericTestBase): EXP_TITLE_2 = 'exp title 2' EXP_ID_3 = 'exp_id_3' EXP_TITLE_3 = 'exp title 3' + EXP_ID_4 = 'exp_id_4' + EXP_TITLE_4 = 'exp title 4' COL_ID_1 = 'col_id_1' COL_TITLE_1 = 'col title 1' COL_ID_2 = 'col_id_2' COL_TITLE_2 = 'col title 2' COL_ID_3 = 'col_id_3' COL_TITLE_3 = 'col title 3' + COL_ID_4 = 'col_id_4' + COL_TITLE_4 = 'col title 4' def setUp(self): super(LearnerPlaylistHandlerTests, self).setUp() @@ -53,6 +57,8 @@ def setUp(self): self.EXP_ID_2, self.owner_id, title=self.EXP_TITLE_2) self.save_new_default_exploration( self.EXP_ID_3, self.owner_id, title=self.EXP_TITLE_3) + self.save_new_default_exploration( + self.EXP_ID_4, self.viewer_id, title=self.EXP_TITLE_3) # Save the collections. self.save_new_default_collection( self.COL_ID_1, self.owner_id, title=self.COL_TITLE_1) @@ -60,6 +66,8 @@ def setUp(self): self.COL_ID_2, self.owner_id, title=self.COL_TITLE_2) self.save_new_default_collection( self.COL_ID_3, self.owner_id, title=self.COL_TITLE_3) + self.save_new_default_collection( + self.COL_ID_4, self.viewer_id, title=self.COL_TITLE_4) def test_add_exploration_to_learner_playlist(self): self.login(self.VIEWER_EMAIL) @@ -104,15 +112,53 @@ def test_add_exploration_to_learner_playlist(self): # should not be added. Here we test for the completed case. learner_progress_services.mark_exploration_as_completed( self.viewer_id, self.EXP_ID_3) - self.post_json( + response = self.post_json( '%s/%s/%s' % ( feconf.LEARNER_PLAYLIST_DATA_URL, constants.ACTIVITY_TYPE_EXPLORATION, self.EXP_ID_3), {}, csrf_token) + self.assertEqual( + response['belongs_to_completed_or_incomplete_list'], True) self.assertEqual( learner_playlist_services.get_all_exp_ids_in_learner_playlist( self.viewer_id), [self.EXP_ID_2, self.EXP_ID_1]) + # If an exploration belongs to one of the subscribed explorations, + # it should not be added to the learner playlist. + response = self.post_json( + '%s/%s/%s' % ( + feconf.LEARNER_PLAYLIST_DATA_URL, + constants.ACTIVITY_TYPE_EXPLORATION, + self.EXP_ID_4), {}, csrf_token) + self.assertEqual( + response['belongs_to_subscribed_activities'], True) + self.assertEqual( + learner_playlist_services.get_all_exp_ids_in_learner_playlist( + self.viewer_id), [self.EXP_ID_2, self.EXP_ID_1]) + + # Now we begin testing of not exceeding the limit of activities in the + # learner playlist. + # Add feconf.MAX_LEARNER_PLAYLIST_ACTIVITY_COUNT - 2 activities to reach + # the maximum limit. + for exp_id in range(5, feconf.MAX_LEARNER_PLAYLIST_ACTIVITY_COUNT + 3): + self.post_json( + '%s/%s/%s' % ( + feconf.LEARNER_PLAYLIST_DATA_URL, + constants.ACTIVITY_TYPE_EXPLORATION, + 'exp_id_%s' % exp_id), {}, csrf_token) + + + # Now if we try and add an activity we should get a message saying we + # are exceeding the limit. + response = self.post_json( + '%s/%s/%s' % ( + feconf.LEARNER_PLAYLIST_DATA_URL, + constants.ACTIVITY_TYPE_EXPLORATION, + 'exp_id_%s' % + str(feconf.MAX_LEARNER_PLAYLIST_ACTIVITY_COUNT + 3)), + {}, csrf_token) + self.assertEqual(response['playlist_limit_exceeded'], True) + self.logout() def test_add_collection_to_learner_playlist(self): @@ -157,14 +203,51 @@ def test_add_collection_to_learner_playlist(self): # should not be added. Here we test for the completed case. learner_progress_services.mark_collection_as_completed( self.viewer_id, self.COL_ID_3) - self.post_json('%s/%s/%s' % ( + response = self.post_json('%s/%s/%s' % ( feconf.LEARNER_PLAYLIST_DATA_URL, constants.ACTIVITY_TYPE_COLLECTION, self.COL_ID_3), {}, csrf_token) + self.assertEqual( + response['belongs_to_completed_or_incomplete_list'], True) self.assertEqual( learner_playlist_services.get_all_collection_ids_in_learner_playlist( # pylint: disable=line-too-long self.viewer_id), [self.COL_ID_2, self.COL_ID_1]) + # If a collection belongs to one of the subscribed collections, + # it should not be added to the learner playlist. + response = self.post_json( + '%s/%s/%s' % ( + feconf.LEARNER_PLAYLIST_DATA_URL, + constants.ACTIVITY_TYPE_COLLECTION, + self.COL_ID_4), {}, csrf_token) + self.assertEqual( + response['belongs_to_subscribed_activities'], True) + self.assertEqual( + learner_playlist_services.get_all_collection_ids_in_learner_playlist( # pylint: disable=line-too-long + self.viewer_id), [self.COL_ID_2, self.COL_ID_1]) + + # Now we begin testing of not exceeding the limit of activities in the + # learner playlist. + # Add feconf.MAX_LEARNER_PLAYLIST_ACTIVITY_COUNT - 2 activities to reach + # the maximum limit. + for exp_id in range(5, feconf.MAX_LEARNER_PLAYLIST_ACTIVITY_COUNT + 3): + response = self.post_json( + '%s/%s/%s' % ( + feconf.LEARNER_PLAYLIST_DATA_URL, + constants.ACTIVITY_TYPE_COLLECTION, + 'col_id_%s' % exp_id), {}, csrf_token) + + # Now if we try and add an activity we should get a message saying we + # are exceeding the limit. + response = self.post_json( + '%s/%s/%s' % ( + feconf.LEARNER_PLAYLIST_DATA_URL, + constants.ACTIVITY_TYPE_COLLECTION, + 'exp_id_%s' % + str(feconf.MAX_LEARNER_PLAYLIST_ACTIVITY_COUNT + 3)), + {}, csrf_token) + self.assertEqual(response['playlist_limit_exceeded'], True) + self.logout() def test_remove_exploration_from_learner_playlist(self): diff --git a/core/domain/learner_progress_services.py b/core/domain/learner_progress_services.py index 3cd828ddb9f6..be6b55ebd513 100644 --- a/core/domain/learner_progress_services.py +++ b/core/domain/learner_progress_services.py @@ -893,7 +893,7 @@ def get_collection_summary_dicts(collection_summaries): return summary_dicts -def get_ids_of_activities_in_learner_dashboard(user_id): +def get_learner_dashboard_activities(user_id): """Returns the ids of each of the activities that are present in the various sections of the learner dashboard, namely the completed section, the incomplete section and the playlist section. @@ -977,7 +977,7 @@ def get_activity_progress(user_id): """ activity_ids_in_learner_dashboard = ( - get_ids_of_activities_in_learner_dashboard(user_id)) + get_learner_dashboard_activities(user_id)) completed_exploration_ids = ( activity_ids_in_learner_dashboard.completed_exploration_ids) completed_collection_ids = ( diff --git a/core/domain/learner_progress_services_test.py b/core/domain/learner_progress_services_test.py index 64c11e53f3af..7fde5feea1ce 100644 --- a/core/domain/learner_progress_services_test.py +++ b/core/domain/learner_progress_services_test.py @@ -537,7 +537,7 @@ def test_get_ids_of_activities_in_learner_dashboard(self): # Get the ids of all the activities. activity_ids = ( - learner_progress_services.get_ids_of_activities_in_learner_dashboard( # pylint: disable=line-too-long + learner_progress_services.get_learner_dashboard_activities( # pylint: disable=line-too-long self.user_id)) self.assertEqual( From 43ac635451f3c3cb24604b426bdb175718a27054 Mon Sep 17 00:00:00 2001 From: Arunabh98 Date: Fri, 25 Aug 2017 08:22:26 +0530 Subject: [PATCH 44/65] Add hindi translations. --- assets/i18n/hi.json | 2 ++ .../summary_tile/CollectionSummaryTileDirective.js | 13 ++++++++++--- .../summary_tile/ExplorationSummaryTileDirective.js | 13 ++++++++++--- 3 files changed, 22 insertions(+), 6 deletions(-) diff --git a/assets/i18n/hi.json b/assets/i18n/hi.json index 1bd9866c84ba..c29b6241fd8d 100644 --- a/assets/i18n/hi.json +++ b/assets/i18n/hi.json @@ -201,8 +201,10 @@ "I18N_LANGUAGE_FOOTER_VIEW_IN": "Oppia को देखे:", "I18N_LEARNER_DASHBOARD_COMPLETED_SECTION": "पूर्ण", "I18N_LEARNER_DASHBOARD_COMPLETED_TO_INCOMPLETE_COLLECTIONS": "आपके द्वारा किए गए संग्रह में से <[numberMoved]> को 'प्रगति' अनुभाग में स्थानांतरित किया गया क्योंकि उन्हें नए अन्वेषण जोड़े गए हैं!", + "I18N_LEARNER_DASHBOARD_DELETED_COLLECTIONS_FROM_PLAYLIST": "{numberDeleted, plural, one{अपने 'बाद में प्ले' सूची में संग्रह में से 1 मालिक द्वारा हटा दिया गया है। असुविधा के लिए खेद है} other{अपने 'बाद में देखें' सूची में संग्रह के # मालिकों को हटा दिया गया है। असुविधा के लिए खेद है}}", "I18N_LEARNER_DASHBOARD_DELETED_COMPLETED_COLLECTIONS": "{numberDeleted, plural, one{आपके द्वारा पूरा किए गए संग्रह में से 1 को हाल ही में हटा दिया गया है असुविधा के लिए खेद है} other{आपके द्वारा पूरा किए गए संग्रहों में से # हाल ही में हटाए गए हैं असुविधा के लिए खेद है}}", "I18N_LEARNER_DASHBOARD_DELETED_COMPLETED_EXPLORATIONS": "{numberDeleted, plural, one{आपके द्वारा पूरी की गई अन्वेषण में से 1 को हाल ही में हटा दिया गया है असुविधा के लिए खेद है} other{आपके द्वारा पूरा किए गए अन्वेषण के # हाल ही में हटाए गए हैं असुविधा के लिए खेद है}}", + "I18N_LEARNER_DASHBOARD_DELETED_EXPLORATIONS_FROM_PLAYLIST": "{numberDeleted, plural, one{अपने 'बाद में प्ले' सूची में एक्सप्लोरेशन में 1 मालिक द्वारा हटा दिया गया है। असुविधा के लिए खेद है} other{आपके 'प्ले बाद में' सूची में एक्सप्लोरेशन के # मालिकों द्वारा हटा दिया गया है। असुविधा के लिए खेद है}}", "I18N_LEARNER_DASHBOARD_DELETED_INCOMPLETE_COLLECTIONS": "{numberDeleted, plural, one{1 संग्रह की प्रगति में हाल ही में हटा दिया गया है असुविधा के लिए खेद है} other{प्रगति में # संग्रह हाल ही में हटाए गए हैं असुविधा के लिए खेद है}}", "I18N_LEARNER_DASHBOARD_DELETED_INCOMPLETE_EXPLORATIONS": "{numberDeleted, plural, one{1 प्रगति में अन्वेषण हाल ही में हटा दिया गया है असुविधा के लिए खेद है} other{# प्रगति में अन्वेषण हाल ही में हटाए गए हैं असुविधा के लिए खेद है}}", "I18N_LEARNER_DASHBOARD_EMPTY_COMPLETED_COLLECTIONS": "ऐसा लगता है कि आपने अभी तक कोई भी कलेक्शन्स पूरा नहीं किया है। एक नया रोमांचक कलेक्शन्स शुरू करने के लिए पुस्तकालय में जाएं!", diff --git a/core/templates/dev/head/components/summary_tile/CollectionSummaryTileDirective.js b/core/templates/dev/head/components/summary_tile/CollectionSummaryTileDirective.js index b6618fdc884a..a197087ab766 100644 --- a/core/templates/dev/head/components/summary_tile/CollectionSummaryTileDirective.js +++ b/core/templates/dev/head/components/summary_tile/CollectionSummaryTileDirective.js @@ -113,19 +113,26 @@ oppia.directive('collectionSummaryTile', [ })); $http.post(addActivityToLearnerPlaylistUrl, {}) .then(function(response) { + var successfullyAdded = true; if (response.data.belongs_to_completed_or_incomplete_list) { + successfullyAdded = false; alertsService.addInfoMessage( 'You have already completed or are completing this ' + 'activity.'); - } else if (response.data.belongs_to_subscribed_activities) { + } + if (response.data.belongs_to_subscribed_activities) { + successfullyAdded = false; alertsService.addInfoMessage( 'This is present in your creator dashboard'); - } else if (response.data.playlist_limit_exceeded) { + } + if (response.data.playlist_limit_exceeded) { + successfullyAdded = false; alertsService.addInfoMessage( 'Your \'Play Later\' list is full! Either you can ' + 'complete some or you can head to the learner dashboard ' + 'and remove some.'); - } else { + } + if (successfullyAdded) { alertsService.addSuccessMessage( 'Successfully added to your \'Play Later\' list.'); /* eslint-disable max-len */ diff --git a/core/templates/dev/head/components/summary_tile/ExplorationSummaryTileDirective.js b/core/templates/dev/head/components/summary_tile/ExplorationSummaryTileDirective.js index aab5c0f9b10a..6f315e3e055f 100644 --- a/core/templates/dev/head/components/summary_tile/ExplorationSummaryTileDirective.js +++ b/core/templates/dev/head/components/summary_tile/ExplorationSummaryTileDirective.js @@ -153,19 +153,26 @@ oppia.directive('explorationSummaryTile', [ })); $http.post(addActivityToLearnerPlaylistUrl, {}) .then(function(response) { + var successfullyAdded = true; if (response.data.belongs_to_completed_or_incomplete_list) { + successfullyAdded = false; alertsService.addInfoMessage( 'You have already completed or are completing this ' + 'activity.'); - } else if (response.data.belongs_to_subscribed_activities) { + } + if (response.data.belongs_to_subscribed_activities) { + successfullyAdded = false; alertsService.addInfoMessage( 'This is present in your creator dashboard'); - } else if (response.data.playlist_limit_exceeded) { + } + if (response.data.playlist_limit_exceeded) { + successfullyAdded = false; alertsService.addInfoMessage( 'Your \'Play Later\' list is full! Either you can ' + 'complete some or you can head to the learner dashboard ' + 'and remove some.'); - } else { + } + if (successfullyAdded) { alertsService.addSuccessMessage( 'Successfully added to your \'Play Later\' list.'); /* eslint-disable max-len */ From 6fa3718144e92366a60d658f253ec9289dcdc4a2 Mon Sep 17 00:00:00 2001 From: Arunabh98 Date: Fri, 25 Aug 2017 17:42:29 +0530 Subject: [PATCH 45/65] Partially address review comments. --- core/controllers/learner_dashboard.py | 17 +------------- core/domain/learner_playlist_services.py | 16 +++++++------- core/domain/learner_progress_domain.py | 28 ++++++++++++++++++++++++ core/domain/learner_progress_services.py | 6 ++--- 4 files changed, 40 insertions(+), 27 deletions(-) diff --git a/core/controllers/learner_dashboard.py b/core/controllers/learner_dashboard.py index 5908ab2642dc..82fcce022760 100644 --- a/core/controllers/learner_dashboard.py +++ b/core/controllers/learner_dashboard.py @@ -128,24 +128,9 @@ def get(self): learner_progress_services.get_learner_dashboard_activities( # pylint: disable=line-too-long self.user_id)) - learner_dashboard_activity_ids = { - 'completed_exploration_ids': ( - learner_dashboard_activities.completed_exploration_ids), - 'completed_collection_ids': ( - learner_dashboard_activities.completed_collection_ids), - 'incomplete_exploration_ids': ( - learner_dashboard_activities.incomplete_exploration_ids), - 'incomplete_collection_ids': ( - learner_dashboard_activities.incomplete_collection_ids), - 'exploration_playlist_ids': ( - learner_dashboard_activities.exploration_playlist_ids), - 'collection_playlist_ids': ( - learner_dashboard_activities.collection_playlist_ids) - } - self.values.update({ 'learner_dashboard_activity_ids': ( - learner_dashboard_activity_ids) + learner_dashboard_activities.to_dict()) }) self.render_json(self.values) diff --git a/core/domain/learner_playlist_services.py b/core/domain/learner_playlist_services.py index ce44b1816022..f96bd287eae6 100644 --- a/core/domain/learner_playlist_services.py +++ b/core/domain/learner_playlist_services.py @@ -80,10 +80,10 @@ def mark_exploration_to_be_played_later( gets inserted at the given position. Otherwise it gets added at the end. - Returns - bool. Indicates whether the playlist limit of the user has been - exceeded. - bool. Indicates whether the exploration is among one of the created or + 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( @@ -145,10 +145,10 @@ def mark_collection_to_be_played_later( the end. Returns: - bool. Indicates whether the playlist limit of the user has been - exceeded. - bool. Indicates whether the collection is among one of the created or - edited collections of the user. + (bool, bool). The first boolean indicates whether the playlist limit of + the user has been exceeded, and the second boolean indicates whether + the collection is among one of the created or edited collections of + the user. """ learner_playlist_model = user_models.LearnerPlaylistModel.get( user_id, strict=False) diff --git a/core/domain/learner_progress_domain.py b/core/domain/learner_progress_domain.py index ef07e88f3c38..635010c3fab2 100644 --- a/core/domain/learner_progress_domain.py +++ b/core/domain/learner_progress_domain.py @@ -79,3 +79,31 @@ def __init__( self.incomplete_collection_ids = incomplete_collection_ids self.exploration_playlist_ids = exploration_playlist_ids self.collection_playlist_ids = collection_playlist_ids + + def to_dict(self): + """Return dictionary representation of ActivityIdsInLearnerDashboard. + + Return: + dict. The keys of the dict are: + 'completed_exploration_ids': list(str). The ids of the + explorations that are completed. + 'completed_collection_ids': list(str). The ids of the + collections that are completed. + 'incomplete_exploration_ids': list(str). The ids of the + explorations that are incomplete. + 'incomplete_collection_ids': list(str). The ids of the + collections that are incomplete. + 'exploration_playlist_ids': list(str). The ids of the + explorations that are in the playlist + 'collection_playlist_ids': list(str). The ids of the + collections that are in the playlist. + """ + + return { + 'completed_exploration_ids': self.completed_exploration_ids, + 'completed_collection_ids': self.completed_collection_ids, + 'incomplete_exploration_ids': self.incomplete_exploration_ids, + 'incomplete_collection_ids': self.incomplete_collection_ids, + 'exploration_playlist_ids': self.exploration_playlist_ids, + 'collection_playlist_ids': self.collection_playlist_ids + } diff --git a/core/domain/learner_progress_services.py b/core/domain/learner_progress_services.py index be6b55ebd513..58b31bda5be6 100644 --- a/core/domain/learner_progress_services.py +++ b/core/domain/learner_progress_services.py @@ -326,8 +326,8 @@ def add_collection_to_learner_playlist( end. Returns: - bool. Indicates whether the collection belongs to the completed or - incomplete list of collections. + bool. Indicates whether the collection already exists in either of the + "completed collections" or "incomplete collections" lists. bool. Indicates whether the playlist limit of the user has been exceeded. bool. Indicates whether the collection belongs to the created or edited @@ -902,7 +902,7 @@ def get_learner_dashboard_activities(user_id): user_id: str. The id of the learner. Returns: - activity_ids. The domain object containing the ids of all activities + ActivityIdsInLearnerDashboard. The domain object containing the ids of all activities in the learner dashboard. """ learner_progress_models = ( From 7d96b5c437cd2ce166fc26ffc9de8d992ed23a48 Mon Sep 17 00:00:00 2001 From: Arunabh98 Date: Fri, 25 Aug 2017 19:33:42 +0530 Subject: [PATCH 46/65] Address more review comments. --- .../CollectionSummaryTileDirective.js | 90 ++++++++----------- .../ExplorationSummaryTileDirective.js | 84 ++++++++--------- .../collection_summary_tile_directive.html | 28 +++--- .../exploration_summary_tile_directive.html | 26 +++--- 4 files changed, 103 insertions(+), 125 deletions(-) diff --git a/core/templates/dev/head/components/summary_tile/CollectionSummaryTileDirective.js b/core/templates/dev/head/components/summary_tile/CollectionSummaryTileDirective.js index a197087ab766..6d07bc87d7a3 100644 --- a/core/templates/dev/head/components/summary_tile/CollectionSummaryTileDirective.js +++ b/core/templates/dev/head/components/summary_tile/CollectionSummaryTileDirective.js @@ -35,8 +35,8 @@ oppia.directive('collectionSummaryTile', [ getThumbnailBgColor: '&thumbnailBgColor', isLinkedToEditorPage: '=?isLinkedToEditorPage', getCategory: '&category', - playlistMode: '=?playlistMode', - learnerDashboardActivityIds: '=?learnerDashboardActivityIds', + isPlaylistMode: '&playlistMode', + getLearnerDashboardActivityIds: '&learnerDashboardActivityIds', }, templateUrl: UrlInterpolationService.getDirectiveTemplateUrl( '/components/summary_tile/' + @@ -49,7 +49,6 @@ oppia.directive('collectionSummaryTile', [ COLLECTION_VIEWER_URL, COLLECTION_EDITOR_URL, UrlInterpolationService, alertsService) { $scope.DEFAULT_EMPTY_TITLE = 'Untitled'; - $scope.collectionType = constants.ACTIVITY_TYPE_COLLECTION; $scope.getLastUpdatedDatetime = function() { return oppiaDatetimeFormatter.getLocaleAbbreviatedDatetimeString( @@ -76,42 +75,39 @@ oppia.directive('collectionSummaryTile', [ return UrlInterpolationService.getStaticImageUrl(url); }; - var currentlyHoveringOverActivity = false; - var activeActivityId = ''; + var collectionIsActive = false; - $scope.setCurrentlyHoveringOverActivity = function(activityId) { - activeActivityId = activityId; - currentlyHoveringOverActivity = !currentlyHoveringOverActivity; + $scope.toggleCollectionIsActive = function() { + collectionIsActive = !collectionIsActive; }; - $scope.showAddToLearnerPlaylistIcon = function(activityId) { - if ($scope.learnerDashboardActivityIds) { + $scope.canCollectionBeAddedToLearnerPlaylist = function(collectionId) { + if ($scope.getLearnerDashboardActivityIds()) { var incompleteCollectionIds = ( - $scope.learnerDashboardActivityIds.incomplete_collection_ids); + $scope.getLearnerDashboardActivityIds().incomplete_collection_ids); var completedCollectionIds = ( - $scope.learnerDashboardActivityIds.completed_collection_ids); + $scope.getLearnerDashboardActivityIds().completed_collection_ids); var collectionPlaylistIds = ( - $scope.learnerDashboardActivityIds.collection_playlist_ids); + $scope.getLearnerDashboardActivityIds().collection_playlist_ids); - if (incompleteCollectionIds.indexOf(activityId) !== -1 || - completedCollectionIds.indexOf(activityId) !== -1 || - collectionPlaylistIds.indexOf(activityId) !== -1) { + if (incompleteCollectionIds.indexOf(collectionId) !== -1 || + completedCollectionIds.indexOf(collectionId) !== -1 || + collectionPlaylistIds.indexOf(collectionId) !== -1) { return false; } else { - return (currentlyHoveringOverActivity && - (activeActivityId == activityId)); + return collectionIsActive; } } }; - $scope.addToLearnerPlaylist = function(activityType, activityId) { - var addActivityToLearnerPlaylistUrl = ( + $scope.addToLearnerPlaylist = function(collectionId) { + var addCollectionToLearnerPlaylistUrl = ( UrlInterpolationService.interpolateUrl( - '/learnerplaylistactivityhandler//', { - activityType: activityType, - activityId: activityId + '/learnerplaylistactivityhandler//', { + activityType: constants.ACTIVITY_TYPE_COLLECTION, + collectionId: collectionId })); - $http.post(addActivityToLearnerPlaylistUrl, {}) + $http.post(addCollectionToLearnerPlaylistUrl, {}) .then(function(response) { var successfullyAdded = true; if (response.data.belongs_to_completed_or_incomplete_list) { @@ -136,34 +132,28 @@ oppia.directive('collectionSummaryTile', [ alertsService.addSuccessMessage( 'Successfully added to your \'Play Later\' list.'); /* eslint-disable max-len */ - $scope.learnerDashboardActivityIds.collection_playlist_ids.push( - activityId); + $scope.getLearnerDashboardActivityIds().collection_playlist_ids.push( + collectionId); /* eslint-enable max-len */ } }); - - if (activityType == constants.ACTIVITY_TYPE_COLLECTION) { - $scope.learnerDashboardActivityIds.collection_playlist_ids.push( - activityId); - } + $scope.getLearnerDashboardActivityIds().collection_playlist_ids.push( + collectionId); }; $scope.removeFromLearnerPlaylist = function( - activityId, activityType, activityTitle) { + collectionId, collectionTitle) { $modal.open({ templateUrl: UrlInterpolationService.getDirectiveTemplateUrl( '/pages/learner_dashboard/' + 'remove_activity_from_learner_dashboard_modal_directive.html'), backdrop: true, resolve: { - activityId: function() { - return activityId; + collectionId: function() { + return collectionId; }, - activityType: function() { - return activityType; - }, - activityTitle: function() { - return activityTitle; + collectionTitle: function() { + return collectionTitle; } }, controller: [ @@ -172,13 +162,13 @@ oppia.directive('collectionSummaryTile', [ $http, UrlInterpolationService) { $scope.sectionNameI18nId = ( 'I18N_LEARNER_DASHBOARD_PLAYLIST_SECTION'); - $scope.activityTitle = activityTitle; + $scope.collectionTitle = collectionTitle; var removeFromLearnerPlaylistUrl = ( UrlInterpolationService.interpolateUrl( '/learnerplaylistactivityhandler/' + - '/', { - activityType: activityType, - activityId: activityId + '/', { + activityType: constants.ACTIVITY_TYPE_COLLECTION, + collectionId: collectionId })); $scope.remove = function() { $http['delete'](removeFromLearnerPlaylistUrl); @@ -192,14 +182,12 @@ oppia.directive('collectionSummaryTile', [ ] }).result.then(function() { /* eslint-disable max-len */ - if (activityType == constants.ACTIVITY_TYPE_COLLECTION) { - var index = ( - $scope.learnerDashboardActivityIds.collection_playlist_ids.indexOf( - activityId)); - if (index !== -1) { - $scope.learnerDashboardActivityIds.collection_playlist_ids.splice( - index, 1); - } + var index = ( + $scope.getLearnerDashboardActivityIds().collection_playlist_ids.indexOf( + collectionId)); + if (index !== -1) { + $scope.getLearnerDashboardActivityIds().collection_playlist_ids.splice( + index, 1); } /* eslint-enable max-len */ }); diff --git a/core/templates/dev/head/components/summary_tile/ExplorationSummaryTileDirective.js b/core/templates/dev/head/components/summary_tile/ExplorationSummaryTileDirective.js index 6f315e3e055f..ea6a525ba3ef 100644 --- a/core/templates/dev/head/components/summary_tile/ExplorationSummaryTileDirective.js +++ b/core/templates/dev/head/components/summary_tile/ExplorationSummaryTileDirective.js @@ -44,8 +44,8 @@ oppia.directive('explorationSummaryTile', [ // if it is not specified, it is treated as 0, which means that the // desktop version of the summary tile is always displayed. mobileCutoffPx: '@mobileCutoffPx', - playlistMode: '=?playlistMode', - learnerDashboardActivityIds: '=?learnerDashboardActivityIds', + isPlaylistMode: '&playlistMode', + getLearnerDashboardActivityIds: '&learnerDashboardActivityIds', }, templateUrl: UrlInterpolationService.getDirectiveTemplateUrl( '/components/summary_tile/' + @@ -87,7 +87,6 @@ oppia.directive('explorationSummaryTile', [ windowDimensionsService, UrlInterpolationService, alertsService) { var contributorsSummary = $scope.getContributorsSummary() || {}; - $scope.explorationType = constants.ACTIVITY_TYPE_EXPLORATION; $scope.contributors = Object.keys( contributorsSummary).sort( function(contributorUsername1, contributorUsername2) { @@ -116,42 +115,39 @@ oppia.directive('explorationSummaryTile', [ } $scope.MAX_AVATARS_TO_DISPLAY = 5; - var currentlyHoveringOverActivity = false; - var activeActivityId = ''; + var explorationIsActive = false; - $scope.setCurrentlyHoveringOverActivity = function(activityId) { - activeActivityId = activityId; - currentlyHoveringOverActivity = !currentlyHoveringOverActivity; + $scope.toggleExplorationIsActive = function(explorationId) { + explorationIsActive = !explorationIsActive; }; - $scope.showAddToLearnerPlaylistIcon = function(activityId) { - if ($scope.learnerDashboardActivityIds) { + $scope.canExplorationBeAddedToLearnerPlaylist = function(explorationId) { + if ($scope.getLearnerDashboardActivityIds()) { var incompleteExplorationIds = ( - $scope.learnerDashboardActivityIds.incomplete_exploration_ids); + $scope.getLearnerDashboardActivityIds().incomplete_exploration_ids); var completedExplorationIds = ( - $scope.learnerDashboardActivityIds.completed_exploration_ids); + $scope.getLearnerDashboardActivityIds().completed_exploration_ids); var explorationPlaylistIds = ( - $scope.learnerDashboardActivityIds.exploration_playlist_ids); + $scope.getLearnerDashboardActivityIds().exploration_playlist_ids); - if (incompleteExplorationIds.indexOf(activityId) !== -1 || - completedExplorationIds.indexOf(activityId) !== -1 || - explorationPlaylistIds.indexOf(activityId) !== -1) { + if (incompleteExplorationIds.indexOf(explorationId) !== -1 || + completedExplorationIds.indexOf(explorationId) !== -1 || + explorationPlaylistIds.indexOf(explorationId) !== -1) { return false; } else { - return (currentlyHoveringOverActivity && - (activeActivityId == activityId)); + return explorationIsActive; } } }; - $scope.addToLearnerPlaylist = function(activityType, activityId) { - var addActivityToLearnerPlaylistUrl = ( + $scope.addToLearnerPlaylist = function(explorationId) { + var addExplorationToLearnerPlaylistUrl = ( UrlInterpolationService.interpolateUrl( - '/learnerplaylistactivityhandler//', { - activityType: activityType, - activityId: activityId + '/learnerplaylistactivityhandler//', { + activityType: constants.ACTIVITY_TYPE_EXPLORATION, + explorationId: explorationId })); - $http.post(addActivityToLearnerPlaylistUrl, {}) + $http.post(addExplorationToLearnerPlaylistUrl, {}) .then(function(response) { var successfullyAdded = true; if (response.data.belongs_to_completed_or_incomplete_list) { @@ -176,29 +172,25 @@ oppia.directive('explorationSummaryTile', [ alertsService.addSuccessMessage( 'Successfully added to your \'Play Later\' list.'); /* eslint-disable max-len */ - $scope.learnerDashboardActivityIds.exploration_playlist_ids.push( - activityId); + $scope.getLearnerDashboardActivityIds().exploration_playlist_ids.push( + explorationId); /* eslint-enable max-len */ } }); }; - $scope.removeFromLearnerPlaylist = function( - activityId, activityType, activityTitle) { + $scope.removeFromLearnerPlaylist = function(explorationId, explorationTitle) { $modal.open({ templateUrl: UrlInterpolationService.getDirectiveTemplateUrl( '/pages/learner_dashboard/' + 'remove_activity_from_learner_dashboard_modal_directive.html'), backdrop: true, resolve: { - activityId: function() { - return activityId; + explorationId: function() { + return explorationId; }, - activityType: function() { - return activityType; - }, - activityTitle: function() { - return activityTitle; + explorationTitle: function() { + return explorationTitle; } }, controller: [ @@ -207,13 +199,13 @@ oppia.directive('explorationSummaryTile', [ $http, UrlInterpolationService) { $scope.sectionNameI18nId = ( 'I18N_LEARNER_DASHBOARD_PLAYLIST_SECTION'); - $scope.activityTitle = activityTitle; + $scope.explorationTitle = explorationTitle; var removeFromLearnerPlaylistUrl = ( UrlInterpolationService.interpolateUrl( '/learnerplaylistactivityhandler/' + - '/', { - activityType: activityType, - activityId: activityId + '/', { + activityType: constants.ACTIVITY_TYPE_EXPLORATION, + explorationId: explorationId })); $scope.remove = function() { $http['delete'](removeFromLearnerPlaylistUrl); @@ -227,14 +219,12 @@ oppia.directive('explorationSummaryTile', [ ] }).result.then(function() { /* eslint-disable max-len */ - if (activityType == constants.ACTIVITY_TYPE_EXPLORATION) { - var index = ( - $scope.learnerDashboardActivityIds.exploration_playlist_ids.indexOf( - activityId)); - if (index !== -1) { - $scope.learnerDashboardActivityIds.exploration_playlist_ids.splice( - index, 1); - } + var index = ( + $scope.getLearnerDashboardActivityIds().exploration_playlist_ids.indexOf( + explorationId)); + if (index !== -1) { + $scope.getLearnerDashboardActivityIds().exploration_playlist_ids.splice( + index, 1); } /* eslint-enable max-len */ }); diff --git a/core/templates/dev/head/components/summary_tile/collection_summary_tile_directive.html b/core/templates/dev/head/components/summary_tile/collection_summary_tile_directive.html index 60c6ac0cbfa3..f0ab1431f2ee 100644 --- a/core/templates/dev/head/components/summary_tile/collection_summary_tile_directive.html +++ b/core/templates/dev/head/components/summary_tile/collection_summary_tile_directive.html @@ -1,40 +1,40 @@ - +
- <[getCategory()]> -

<[getCollectionTitle() || DEFAULT_EMPTY_TITLE]>

+ <[getCategory()]> +

<[getCollectionTitle() || DEFAULT_EMPTY_TITLE]>

-
+
<[getObjective() | truncateAndCapitalize: 95]> No objective specified. @@ -53,7 +53,7 @@

-
+
diff --git a/core/templates/dev/head/components/summary_tile/exploration_summary_tile_directive.html b/core/templates/dev/head/components/summary_tile/exploration_summary_tile_directive.html index e7d57ec02d28..cf8babbe4cf3 100644 --- a/core/templates/dev/head/components/summary_tile/exploration_summary_tile_directive.html +++ b/core/templates/dev/head/components/summary_tile/exploration_summary_tile_directive.html @@ -1,35 +1,35 @@ - + -
- <[getCategory()]> -

+ <[getCategory()]> +

<[getExplorationTitle()|truncate:40]> <[getExplorationTitle()|truncate:40]>

@@ -37,7 +37,7 @@

+
<[getObjective() | truncateAndCapitalize: 95]> From 45a4cb3a20f827d9e3cb7d2f5b53e37a608a62a0 Mon Sep 17 00:00:00 2001 From: Arunabh98 Date: Fri, 25 Aug 2017 23:08:48 +0530 Subject: [PATCH 47/65] Add domain object. --- core/domain/learner_progress_services.py | 4 +- .../CollectionSummaryTileDirective.js | 29 +---- .../ExplorationSummaryTileDirective.js | 27 +---- .../collection_summary_tile_directive.html | 6 +- .../exploration_summary_tile_directive.html | 6 +- ...earnerDashboardActivityIdsObjectFactory.js | 85 ++++++++++++++ .../learner_dashboard/LearnerDashboard.js | 104 +++++++----------- .../ActivityTilesInfinityGridDirective.js | 16 +-- .../dev/head/pages/library/Library.js | 9 +- .../dev/head/pages/library/library.html | 1 + 10 files changed, 156 insertions(+), 131 deletions(-) create mode 100644 core/templates/dev/head/domain/learner_dashboard/LearnerDashboardActivityIdsObjectFactory.js diff --git a/core/domain/learner_progress_services.py b/core/domain/learner_progress_services.py index 58b31bda5be6..2e04f3b3d91c 100644 --- a/core/domain/learner_progress_services.py +++ b/core/domain/learner_progress_services.py @@ -902,8 +902,8 @@ def get_learner_dashboard_activities(user_id): user_id: str. The id of the learner. Returns: - ActivityIdsInLearnerDashboard. The domain object containing the ids of all activities - in the learner dashboard. + ActivityIdsInLearnerDashboard. The domain object containing the ids of + all activities in the learner dashboard. """ learner_progress_models = ( datastore_services.fetch_multiple_entities_by_ids_and_models( diff --git a/core/templates/dev/head/components/summary_tile/CollectionSummaryTileDirective.js b/core/templates/dev/head/components/summary_tile/CollectionSummaryTileDirective.js index 6d07bc87d7a3..1c76633b189d 100644 --- a/core/templates/dev/head/components/summary_tile/CollectionSummaryTileDirective.js +++ b/core/templates/dev/head/components/summary_tile/CollectionSummaryTileDirective.js @@ -83,16 +83,8 @@ oppia.directive('collectionSummaryTile', [ $scope.canCollectionBeAddedToLearnerPlaylist = function(collectionId) { if ($scope.getLearnerDashboardActivityIds()) { - var incompleteCollectionIds = ( - $scope.getLearnerDashboardActivityIds().incomplete_collection_ids); - var completedCollectionIds = ( - $scope.getLearnerDashboardActivityIds().completed_collection_ids); - var collectionPlaylistIds = ( - $scope.getLearnerDashboardActivityIds().collection_playlist_ids); - - if (incompleteCollectionIds.indexOf(collectionId) !== -1 || - completedCollectionIds.indexOf(collectionId) !== -1 || - collectionPlaylistIds.indexOf(collectionId) !== -1) { + if ($scope.getLearnerDashboardActivityIds( + ).belongsToLearnerDashboardActivities(collectionId)) { return false; } else { return collectionIsActive; @@ -131,14 +123,10 @@ oppia.directive('collectionSummaryTile', [ if (successfullyAdded) { alertsService.addSuccessMessage( 'Successfully added to your \'Play Later\' list.'); - /* eslint-disable max-len */ - $scope.getLearnerDashboardActivityIds().collection_playlist_ids.push( + $scope.getLearnerDashboardActivityIds().addToCollectionLearnerPlaylist( collectionId); - /* eslint-enable max-len */ } }); - $scope.getLearnerDashboardActivityIds().collection_playlist_ids.push( - collectionId); }; $scope.removeFromLearnerPlaylist = function( @@ -181,15 +169,8 @@ oppia.directive('collectionSummaryTile', [ } ] }).result.then(function() { - /* eslint-disable max-len */ - var index = ( - $scope.getLearnerDashboardActivityIds().collection_playlist_ids.indexOf( - collectionId)); - if (index !== -1) { - $scope.getLearnerDashboardActivityIds().collection_playlist_ids.splice( - index, 1); - } - /* eslint-enable max-len */ + $scope.getLearnerDashboardActivityIds().removeFromCollectionLearnerPlaylist( + collectionId); }); }; } diff --git a/core/templates/dev/head/components/summary_tile/ExplorationSummaryTileDirective.js b/core/templates/dev/head/components/summary_tile/ExplorationSummaryTileDirective.js index ea6a525ba3ef..c782755decf8 100644 --- a/core/templates/dev/head/components/summary_tile/ExplorationSummaryTileDirective.js +++ b/core/templates/dev/head/components/summary_tile/ExplorationSummaryTileDirective.js @@ -123,16 +123,8 @@ oppia.directive('explorationSummaryTile', [ $scope.canExplorationBeAddedToLearnerPlaylist = function(explorationId) { if ($scope.getLearnerDashboardActivityIds()) { - var incompleteExplorationIds = ( - $scope.getLearnerDashboardActivityIds().incomplete_exploration_ids); - var completedExplorationIds = ( - $scope.getLearnerDashboardActivityIds().completed_exploration_ids); - var explorationPlaylistIds = ( - $scope.getLearnerDashboardActivityIds().exploration_playlist_ids); - - if (incompleteExplorationIds.indexOf(explorationId) !== -1 || - completedExplorationIds.indexOf(explorationId) !== -1 || - explorationPlaylistIds.indexOf(explorationId) !== -1) { + if ($scope.getLearnerDashboardActivityIds( + ).belongsToLearnerDashboardActivities(explorationId)) { return false; } else { return explorationIsActive; @@ -171,10 +163,8 @@ oppia.directive('explorationSummaryTile', [ if (successfullyAdded) { alertsService.addSuccessMessage( 'Successfully added to your \'Play Later\' list.'); - /* eslint-disable max-len */ - $scope.getLearnerDashboardActivityIds().exploration_playlist_ids.push( + $scope.getLearnerDashboardActivityIds().addToExplorationLearnerPlaylist( explorationId); - /* eslint-enable max-len */ } }); }; @@ -218,15 +208,8 @@ oppia.directive('explorationSummaryTile', [ } ] }).result.then(function() { - /* eslint-disable max-len */ - var index = ( - $scope.getLearnerDashboardActivityIds().exploration_playlist_ids.indexOf( - explorationId)); - if (index !== -1) { - $scope.getLearnerDashboardActivityIds().exploration_playlist_ids.splice( - index, 1); - } - /* eslint-enable max-len */ + $scope.getLearnerDashboardActivityIds().removeFromExplorationLearnerPlaylist( + explorationId); }); }; diff --git a/core/templates/dev/head/components/summary_tile/collection_summary_tile_directive.html b/core/templates/dev/head/components/summary_tile/collection_summary_tile_directive.html index f0ab1431f2ee..9991abfb0165 100644 --- a/core/templates/dev/head/components/summary_tile/collection_summary_tile_directive.html +++ b/core/templates/dev/head/components/summary_tile/collection_summary_tile_directive.html @@ -7,18 +7,18 @@ tooltip="<['I18N_LIBRARY_ADD_TO_LEARNER_PLAYLIST' | translate]>" tooltip-placement="left"> diff --git a/core/templates/dev/head/components/summary_tile/exploration_summary_tile_directive.html b/core/templates/dev/head/components/summary_tile/exploration_summary_tile_directive.html index cf8babbe4cf3..c7793e0d1220 100644 --- a/core/templates/dev/head/components/summary_tile/exploration_summary_tile_directive.html +++ b/core/templates/dev/head/components/summary_tile/exploration_summary_tile_directive.html @@ -7,18 +7,18 @@ tooltip="<['I18N_LIBRARY_ADD_TO_LEARNER_PLAYLIST' | translate]>" tooltip-placement="left"> diff --git a/core/templates/dev/head/domain/learner_dashboard/LearnerDashboardActivityIdsObjectFactory.js b/core/templates/dev/head/domain/learner_dashboard/LearnerDashboardActivityIdsObjectFactory.js new file mode 100644 index 000000000000..a9fdef0ba3ef --- /dev/null +++ b/core/templates/dev/head/domain/learner_dashboard/LearnerDashboardActivityIdsObjectFactory.js @@ -0,0 +1,85 @@ +// Copyright 2015 The Oppia Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS-IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/** + * @fileoverview Factory for creating new frontend instances of learner + dashboard activity ids domain object. + */ + +oppia.factory('LearnerDashboardActivityIdsObjectFactory', [function() { + var LearnerDashboardActivityIds = function( + incompleteExplorationIds, incompleteCollectionIds, + completedExplorationIds, completedCollectionIds, explorationPlaylistIds, + collectionPlaylistIds) { + this.incompleteExplorationIds = incompleteExplorationIds; + this.incompleteCollectionIds = incompleteCollectionIds; + this.completedExplorationIds = completedExplorationIds; + this.completedCollectionIds = completedCollectionIds; + this.explorationPlaylistIds = explorationPlaylistIds; + this.collectionPlaylistIds = collectionPlaylistIds; + }; + + LearnerDashboardActivityIds.prototype.belongsToLearnerDashboardActivities = function( + activityId) { + if (this.incompleteCollectionIds.indexOf(activityId) !== -1 || + this.completedCollectionIds.indexOf(activityId) !== -1 || + this.collectionPlaylistIds.indexOf(activityId) !== -1 || + this.incompleteExplorationIds.indexOf(activityId) !== -1 || + this.completedExplorationIds.indexOf(activityId) !== -1 || + this.explorationPlaylistIds.indexOf(activityId) !== -1) { + return true; + } else { + false; + } + }; + + LearnerDashboardActivityIds.prototype.addToExplorationLearnerPlaylist = function( + explorationId) { + this.explorationPlaylistIds.push(explorationId); + }; + + LearnerDashboardActivityIds.prototype.removeFromExplorationLearnerPlaylist = function( + explorationId) { + var index = this.explorationPlaylistIds.indexOf(explorationId); + if (index !== -1) { + this.explorationPlaylistIds.splice(index, 1); + } + }; + + LearnerDashboardActivityIds.prototype.removeFromCollectionLearnerPlaylist = function( + collectionId) { + var index = this.collectionPlaylistIds.indexOf(collectionId); + if (index !== -1) { + this.collectionPlaylistIds.splice(index, 1); + } + }; + + LearnerDashboardActivityIds.prototype.addToCollectionLearnerPlaylist = function( + collectionId) { + this.collectionPlaylistIds.push(collectionId); + }; + + LearnerDashboardActivityIds.createFromBackendDict = function( + learnerDashboardActivityIdsDict) { + return new LearnerDashboardActivityIds( + learnerDashboardActivityIdsDict.incomplete_exploration_ids, + learnerDashboardActivityIdsDict.incomplete_collection_ids, + learnerDashboardActivityIdsDict.completed_exploration_ids, + learnerDashboardActivityIdsDict.completed_collection_ids, + learnerDashboardActivityIdsDict.exploration_playlist_ids, + learnerDashboardActivityIdsDict.collection_playlist_ids); + }; + + return LearnerDashboardActivityIds; +}]); diff --git a/core/templates/dev/head/pages/learner_dashboard/LearnerDashboard.js b/core/templates/dev/head/pages/learner_dashboard/LearnerDashboard.js index 7051fb955e4e..23b4ab28f5d8 100644 --- a/core/templates/dev/head/pages/learner_dashboard/LearnerDashboard.js +++ b/core/templates/dev/head/pages/learner_dashboard/LearnerDashboard.js @@ -251,57 +251,38 @@ oppia.controller('LearnerDashboard', [ return feedbackThread[$scope.currentFeedbackThreadsSortType]; }; - $scope.explorationPlaylistSortableOptions = { - start: function(e, ui) { - ui.placeholder.height(ui.item.height()); - $scope.$apply(); - }, - update: function(e, ui) { - var insertExpInLearnerPlaylistUrl = ( - UrlInterpolationService.interpolateUrl( - '/learnerplaylistactivityhandler//', { - activityType: constants.ACTIVITY_TYPE_EXPLORATION, - activityId: ( - $scope.explorationPlaylist[ui.item.sortable.index].id) - })); - - $http.post(insertExpInLearnerPlaylistUrl, { - index: ui.item.sortable.dropindex - }); - $scope.$apply(); - }, - stop: function(e, ui) { - $scope.$apply(); - }, - axis: 'y', - 'ui-floating': false + var getPlaylistSortableOptions = function(activityType) { + return { + start: function(e, ui) { + ui.placeholder.height(ui.item.height()); + $scope.$apply(); + }, + update: function(e, ui) { + var insertExpInLearnerPlaylistUrl = ( + UrlInterpolationService.interpolateUrl( + '/learnerplaylistactivityhandler//', { + activityType: activityType, + activityId: ( + $scope.explorationPlaylist[ui.item.sortable.index].id) + })); + + $http.post(insertExpInLearnerPlaylistUrl, { + index: ui.item.sortable.dropindex + }); + $scope.$apply(); + }, + stop: function(e, ui) { + $scope.$apply(); + }, + axis: 'y', + 'ui-floating': false + }; }; - $scope.collectionPlaylistSortableOptions = { - start: function(e, ui) { - ui.placeholder.height(ui.item.height()); - $scope.$apply(); - }, - update: function(e, ui) { - var insertCollectionInLearnerPlaylistUrl = ( - UrlInterpolationService.interpolateUrl( - '/learnerplaylistactivityhandler//', { - activityType: constants.ACTIVITY_TYPE_COLLECTION, - activityId: ( - $scope.collectionPlaylist[ui.item.sortable.index].id) - })); - - $http.post(insertCollectionInLearnerPlaylistUrl, { - index: ui.item.sortable.dropindex - }); - $scope.$apply(); - }, - stop: function(e, ui) { - $scope.$apply(); - }, - axis: 'y', - 'ui-floating': false - }; + $scope.collectionPlaylistSortableOptions = getPlaylistSortableOptions( + constants.ACTIVITY_TYPE_COLLECTION); + $scope.explorationPlaylistSortableOptions = getPlaylistSortableOptions( + constants.ACTIVITY_TYPE_EXPLORATION); $scope.onClickThread = function( threadStatus, explorationId, threadId, explorationTitle) { @@ -435,26 +416,21 @@ oppia.controller('LearnerDashboard', [ activityType = constants.ACTIVITY_TYPE_COLLECTION; } - var removeActivityUrl = ''; + var removeActivityUrlPrefix = ''; if (sectionNameI18nId === LEARNER_DASHBOARD_SECTION_I18N_IDS.PLAYLIST) { - /* eslint-disable max-len */ - removeActivityUrl = ( - UrlInterpolationService.interpolateUrl( - '/learnerplaylistactivityhandler//', { - activityType: activityType, - activityId: activity.id - })); - /* eslint-enable max-len */ + removeActivityUrlPrefix = '/learnerplaylistactivityhandler/'; } else if (sectionNameI18nId === LEARNER_DASHBOARD_SECTION_I18N_IDS.INCOMPLETE) { - removeActivityUrl = UrlInterpolationService.interpolateUrl( - '/learnerincompleteactivityhandler/' + - '/', { + removeActivityUrlPrefix = '/learnerincompleteactivityhandler/'; + } + + removeActivityUrl = ( + UrlInterpolationService.interpolateUrl( + removeActivityUrlPrefix + '/', { activityType: activityType, activityId: activity.id - }); - } + })); $http['delete'](removeActivityUrl); $modalInstance.close(); @@ -482,7 +458,7 @@ oppia.controller('LearnerDashboard', [ } } } else if (sectionNameI18nId === - LEARNER_DASHBOARD_SECTION_I18N_IDS.PLAYLIST){ + LEARNER_DASHBOARD_SECTION_I18N_IDS.PLAYLIST) { if (subsectionName === LEARNER_DASHBOARD_SUBSECTION_I18N_IDS.EXPLORATIONS) { var index = $scope.explorationPlaylist.indexOf(activity); diff --git a/core/templates/dev/head/pages/library/ActivityTilesInfinityGridDirective.js b/core/templates/dev/head/pages/library/ActivityTilesInfinityGridDirective.js index ef9dd9d6ecc6..e31450459c37 100644 --- a/core/templates/dev/head/pages/library/ActivityTilesInfinityGridDirective.js +++ b/core/templates/dev/head/pages/library/ActivityTilesInfinityGridDirective.js @@ -25,13 +25,13 @@ oppia.directive('activityTilesInfinityGrid', [ 'activity_tiles_infinity_grid_directive.html'), controller: [ '$scope', '$rootScope', '$http', 'searchService', 'alertsService', - '$modal', 'LearnerDashboardIdsBackendApiService', function( + 'LearnerDashboardIdsBackendApiService', + 'LearnerDashboardActivityIdsObjectFactory', function( $scope, $rootScope, $http, searchService, alertsService, - $modal, LearnerDashboardIdsBackendApiService) { + LearnerDashboardIdsBackendApiService, + LearnerDashboardActivityIdsObjectFactory) { $scope.endOfPageIsReached = false; $scope.allActivitiesInOrder = []; - var currentlyHoveringOverActivity = false; - var activeActivityId = ''; // Called when the first batch of search results is retrieved from the // server. $scope.$on( @@ -44,15 +44,11 @@ oppia.directive('activityTilesInfinityGrid', [ LearnerDashboardIdsBackendApiService.fetchLearnerDashboardIds().then( function(response) { $scope.learnerDashboardActivityIds = ( - response.data.learner_dashboard_activity_ids); + LearnerDashboardActivityIdsObjectFactory.createFromBackendDict( + response.data.learner_dashboard_activity_ids)); } ); - $scope.setCurrentlyHoveringOverActivity = function(activityId) { - activeActivityId = activityId; - currentlyHoveringOverActivity = !currentlyHoveringOverActivity; - }; - $scope.showMoreActivities = function() { if (!$rootScope.loadingMessage && !$scope.endOfPageIsReached) { $scope.searchResultsAreLoading = true; diff --git a/core/templates/dev/head/pages/library/Library.js b/core/templates/dev/head/pages/library/Library.js index 1cad493a3f76..209442e7eaca 100644 --- a/core/templates/dev/head/pages/library/Library.js +++ b/core/templates/dev/head/pages/library/Library.js @@ -31,12 +31,14 @@ oppia.controller('Library', [ 'i18nIdService', 'urlService', 'ALL_CATEGORIES', 'searchService', 'windowDimensionsService', 'UrlInterpolationService', 'LIBRARY_PAGE_MODES', 'LIBRARY_TILE_WIDTH_PX', 'alertsService', - 'LearnerDashboardIdsBackendApiService', function( + 'LearnerDashboardIdsBackendApiService', + 'LearnerDashboardActivityIdsObjectFactory', function( $scope, $http, $modal, $rootScope, $window, $timeout, i18nIdService, urlService, ALL_CATEGORIES, searchService, windowDimensionsService, UrlInterpolationService, LIBRARY_PAGE_MODES, LIBRARY_TILE_WIDTH_PX, alertsService, - LearnerDashboardIdsBackendApiService) { + LearnerDashboardIdsBackendApiService, + LearnerDashboardActivityIdsObjectFactory) { $rootScope.loadingMessage = 'I18N_LIBRARY_LOADING'; var possibleBannerFilenames = [ 'banner1.svg', 'banner2.svg', 'banner3.svg', 'banner4.svg']; @@ -81,7 +83,8 @@ oppia.controller('Library', [ LearnerDashboardIdsBackendApiService.fetchLearnerDashboardIds().then( function(response) { $scope.learnerDashboardActivityIds = ( - response.data.learner_dashboard_activity_ids); + LearnerDashboardActivityIdsObjectFactory.createFromBackendDict( + response.data.learner_dashboard_activity_ids)); } ); } diff --git a/core/templates/dev/head/pages/library/library.html b/core/templates/dev/head/pages/library/library.html index f816dc80227d..bb7f93983daf 100644 --- a/core/templates/dev/head/pages/library/library.html +++ b/core/templates/dev/head/pages/library/library.html @@ -223,6 +223,7 @@

+ From f5c88823991f90c0424088c2f0059220e603ddc9 Mon Sep 17 00:00:00 2001 From: Arunabh98 Date: Sat, 26 Aug 2017 00:39:04 +0530 Subject: [PATCH 48/65] Add service. --- .../CollectionSummaryTileDirective.js | 93 +++----------- .../ExplorationSummaryTileDirective.js | 94 +++----------- .../LearnerPlaylistService.js | 118 ++++++++++++++++++ .../dev/head/pages/library/Library.js | 4 +- .../dev/head/pages/library/library.html | 1 + 5 files changed, 153 insertions(+), 157 deletions(-) create mode 100644 core/templates/dev/head/domain/learner_dashboard/LearnerPlaylistService.js diff --git a/core/templates/dev/head/components/summary_tile/CollectionSummaryTileDirective.js b/core/templates/dev/head/components/summary_tile/CollectionSummaryTileDirective.js index 1c76633b189d..0010b4a4f01d 100644 --- a/core/templates/dev/head/components/summary_tile/CollectionSummaryTileDirective.js +++ b/core/templates/dev/head/components/summary_tile/CollectionSummaryTileDirective.js @@ -44,10 +44,12 @@ oppia.directive('collectionSummaryTile', [ controller: [ '$scope', '$http', '$modal', 'oppiaDatetimeFormatter', 'COLLECTION_VIEWER_URL', 'COLLECTION_EDITOR_URL', - 'UrlInterpolationService', 'alertsService', function( + 'UrlInterpolationService', 'alertsService', + 'LearnerPlaylistService', function( $scope, $http, $modal, oppiaDatetimeFormatter, COLLECTION_VIEWER_URL, COLLECTION_EDITOR_URL, - UrlInterpolationService, alertsService) { + UrlInterpolationService, alertsService, + LearnerPlaylistService) { $scope.DEFAULT_EMPTY_TITLE = 'Untitled'; $scope.getLastUpdatedDatetime = function() { @@ -93,85 +95,22 @@ oppia.directive('collectionSummaryTile', [ }; $scope.addToLearnerPlaylist = function(collectionId) { - var addCollectionToLearnerPlaylistUrl = ( - UrlInterpolationService.interpolateUrl( - '/learnerplaylistactivityhandler//', { - activityType: constants.ACTIVITY_TYPE_COLLECTION, - collectionId: collectionId - })); - $http.post(addCollectionToLearnerPlaylistUrl, {}) - .then(function(response) { - var successfullyAdded = true; - if (response.data.belongs_to_completed_or_incomplete_list) { - successfullyAdded = false; - alertsService.addInfoMessage( - 'You have already completed or are completing this ' + - 'activity.'); - } - if (response.data.belongs_to_subscribed_activities) { - successfullyAdded = false; - alertsService.addInfoMessage( - 'This is present in your creator dashboard'); - } - if (response.data.playlist_limit_exceeded) { - successfullyAdded = false; - alertsService.addInfoMessage( - 'Your \'Play Later\' list is full! Either you can ' + - 'complete some or you can head to the learner dashboard ' + - 'and remove some.'); - } - if (successfullyAdded) { - alertsService.addSuccessMessage( - 'Successfully added to your \'Play Later\' list.'); - $scope.getLearnerDashboardActivityIds().addToCollectionLearnerPlaylist( - collectionId); - } - }); + var isSuccessfullyAdded = ( + LearnerPlaylistService.addToLearnerPlaylist( + collectionId, constants.ACTIVITY_TYPE_COLLECTION)); + if (isSuccessfullyAdded) { + $scope.getLearnerDashboardActivityIds().addToCollectionLearnerPlaylist( + collectionId); + } }; $scope.removeFromLearnerPlaylist = function( collectionId, collectionTitle) { - $modal.open({ - templateUrl: UrlInterpolationService.getDirectiveTemplateUrl( - '/pages/learner_dashboard/' + - 'remove_activity_from_learner_dashboard_modal_directive.html'), - backdrop: true, - resolve: { - collectionId: function() { - return collectionId; - }, - collectionTitle: function() { - return collectionTitle; - } - }, - controller: [ - '$scope', '$modalInstance', '$http', - 'UrlInterpolationService', function($scope, $modalInstance, - $http, UrlInterpolationService) { - $scope.sectionNameI18nId = ( - 'I18N_LEARNER_DASHBOARD_PLAYLIST_SECTION'); - $scope.collectionTitle = collectionTitle; - var removeFromLearnerPlaylistUrl = ( - UrlInterpolationService.interpolateUrl( - '/learnerplaylistactivityhandler/' + - '/', { - activityType: constants.ACTIVITY_TYPE_COLLECTION, - collectionId: collectionId - })); - $scope.remove = function() { - $http['delete'](removeFromLearnerPlaylistUrl); - $modalInstance.close(); - }; - - $scope.cancel = function() { - $modalInstance.dismiss('cancel'); - }; - } - ] - }).result.then(function() { - $scope.getLearnerDashboardActivityIds().removeFromCollectionLearnerPlaylist( - collectionId); - }); + var isSuccessfullyRemoved = ( + LearnerPlaylistService.removeFromLearnerPlaylist( + collectionId, collectionTitle, + constants.ACTIVITY_TYPE_COLLECTION, + $scope.getLearnerDashboardActivityIds())); }; } ] diff --git a/core/templates/dev/head/components/summary_tile/ExplorationSummaryTileDirective.js b/core/templates/dev/head/components/summary_tile/ExplorationSummaryTileDirective.js index c782755decf8..9c2f5fd21d73 100644 --- a/core/templates/dev/head/components/summary_tile/ExplorationSummaryTileDirective.js +++ b/core/templates/dev/head/components/summary_tile/ExplorationSummaryTileDirective.js @@ -80,12 +80,12 @@ oppia.directive('explorationSummaryTile', [ '$scope', '$http', '$modal', 'oppiaDatetimeFormatter', 'RatingComputationService', 'windowDimensionsService', 'UrlInterpolationService', - 'alertsService', + 'alertsService', 'LearnerPlaylistService', function( $scope, $http, $modal, oppiaDatetimeFormatter, RatingComputationService, windowDimensionsService, UrlInterpolationService, - alertsService) { + alertsService, LearnerPlaylistService) { var contributorsSummary = $scope.getContributorsSummary() || {}; $scope.contributors = Object.keys( contributorsSummary).sort( @@ -133,84 +133,22 @@ oppia.directive('explorationSummaryTile', [ }; $scope.addToLearnerPlaylist = function(explorationId) { - var addExplorationToLearnerPlaylistUrl = ( - UrlInterpolationService.interpolateUrl( - '/learnerplaylistactivityhandler//', { - activityType: constants.ACTIVITY_TYPE_EXPLORATION, - explorationId: explorationId - })); - $http.post(addExplorationToLearnerPlaylistUrl, {}) - .then(function(response) { - var successfullyAdded = true; - if (response.data.belongs_to_completed_or_incomplete_list) { - successfullyAdded = false; - alertsService.addInfoMessage( - 'You have already completed or are completing this ' + - 'activity.'); - } - if (response.data.belongs_to_subscribed_activities) { - successfullyAdded = false; - alertsService.addInfoMessage( - 'This is present in your creator dashboard'); - } - if (response.data.playlist_limit_exceeded) { - successfullyAdded = false; - alertsService.addInfoMessage( - 'Your \'Play Later\' list is full! Either you can ' + - 'complete some or you can head to the learner dashboard ' + - 'and remove some.'); - } - if (successfullyAdded) { - alertsService.addSuccessMessage( - 'Successfully added to your \'Play Later\' list.'); - $scope.getLearnerDashboardActivityIds().addToExplorationLearnerPlaylist( - explorationId); - } - }); + var isSuccessfullyAdded = ( + LearnerPlaylistService.addToLearnerPlaylist( + explorationId, constants.ACTIVITY_TYPE_EXPLORATION)); + if (isSuccessfullyAdded) { + $scope.getLearnerDashboardActivityIds().addToExplorationLearnerPlaylist( + explorationId); + } }; - $scope.removeFromLearnerPlaylist = function(explorationId, explorationTitle) { - $modal.open({ - templateUrl: UrlInterpolationService.getDirectiveTemplateUrl( - '/pages/learner_dashboard/' + - 'remove_activity_from_learner_dashboard_modal_directive.html'), - backdrop: true, - resolve: { - explorationId: function() { - return explorationId; - }, - explorationTitle: function() { - return explorationTitle; - } - }, - controller: [ - '$scope', '$modalInstance', '$http', - 'UrlInterpolationService', function($scope, $modalInstance, - $http, UrlInterpolationService) { - $scope.sectionNameI18nId = ( - 'I18N_LEARNER_DASHBOARD_PLAYLIST_SECTION'); - $scope.explorationTitle = explorationTitle; - var removeFromLearnerPlaylistUrl = ( - UrlInterpolationService.interpolateUrl( - '/learnerplaylistactivityhandler/' + - '/', { - activityType: constants.ACTIVITY_TYPE_EXPLORATION, - explorationId: explorationId - })); - $scope.remove = function() { - $http['delete'](removeFromLearnerPlaylistUrl); - $modalInstance.close(); - }; - - $scope.cancel = function() { - $modalInstance.dismiss('cancel'); - }; - } - ] - }).result.then(function() { - $scope.getLearnerDashboardActivityIds().removeFromExplorationLearnerPlaylist( - explorationId); - }); + $scope.removeFromLearnerPlaylist = function( + explorationId, explorationTitle) { + var isSuccessfullyRemoved = ( + LearnerPlaylistService.removeFromLearnerPlaylist( + explorationId, explorationTitle, + constants.ACTIVITY_TYPE_EXPLORATION, + $scope.getLearnerDashboardActivityIds())); }; $scope.getAverageRating = function() { diff --git a/core/templates/dev/head/domain/learner_dashboard/LearnerPlaylistService.js b/core/templates/dev/head/domain/learner_dashboard/LearnerPlaylistService.js new file mode 100644 index 000000000000..9338feb00926 --- /dev/null +++ b/core/templates/dev/head/domain/learner_dashboard/LearnerPlaylistService.js @@ -0,0 +1,118 @@ +// Copyright 2017 The Oppia Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS-IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/** + * @fileoverview Service related to the learner playlist. + */ + + oppia.factory('LearnerPlaylistService', [ + '$http', '$modal', 'alertsService', 'UrlInterpolationService', + function($http, $modal, alertsService, UrlInterpolationService) { + + var _addToLearnerPlaylist = function(activityId, activityType) { + var successfullyAdded = true; + var addToLearnerPlaylistUrl = ( + UrlInterpolationService.interpolateUrl( + '/learnerplaylistactivityhandler//', { + activityType: activityType, + activityId: activityId + })); + $http.post(addToLearnerPlaylistUrl, {}) + .then(function(response) { + if (response.data.belongs_to_completed_or_incomplete_list) { + successfullyAdded = false; + alertsService.addInfoMessage( + 'You have already completed or are completing this ' + + 'activity.'); + } + if (response.data.belongs_to_subscribed_activities) { + successfullyAdded = false; + alertsService.addInfoMessage( + 'This is present in your creator dashboard'); + } + if (response.data.playlist_limit_exceeded) { + successfullyAdded = false; + alertsService.addInfoMessage( + 'Your \'Play Later\' list is full! Either you can ' + + 'complete some or you can head to the learner dashboard ' + + 'and remove some.'); + } + if (successfullyAdded) { + alertsService.addSuccessMessage( + 'Successfully added to your \'Play Later\' list.'); + } + }); + return successfullyAdded; + }; + + var _removeFromLearnerPlaylist = function(activityId, activityTitle, + activityType, learnerDashboardActivityIds) { + $modal.open({ + templateUrl: UrlInterpolationService.getDirectiveTemplateUrl( + '/pages/learner_dashboard/' + + 'remove_activity_from_learner_dashboard_modal_directive.html'), + backdrop: true, + resolve: { + activityId: function() { + return activityId; + }, + activityTitle: function() { + return activityTitle; + } + }, + controller: [ + '$scope', '$modalInstance', '$http', + 'UrlInterpolationService', function($scope, $modalInstance, + $http, UrlInterpolationService) { + $scope.sectionNameI18nId = ( + 'I18N_LEARNER_DASHBOARD_PLAYLIST_SECTION'); + $scope.activityTitle = activityTitle; + var removeFromLearnerPlaylistUrl = ( + UrlInterpolationService.interpolateUrl( + '/learnerplaylistactivityhandler/' + + '/', { + activityType: activityType, + activityId: activityId + })); + $scope.remove = function() { + $http['delete'](removeFromLearnerPlaylistUrl); + $modalInstance.close(); + }; + + $scope.cancel = function() { + $modalInstance.dismiss('cancel'); + }; + } + ] + }).result.then(function() { + if (activityType === constants.ACTIVITY_TYPE_EXPLORATION) { + learnerDashboardActivityIds.removeFromExplorationLearnerPlaylist( + activityId); + } else if (activityType === constants.ACTIVITY_TYPE_COLLECTION) { + learnerDashboardActivityIds.removeFromCollectionLearnerPlaylist( + activityId); + } + }); + }; + + var _fetchLearnerDashboardData = function() { + return $http.get('/learnerdashboardhandler/data'); + }; + + return { + fetchLearnerDashboardData: _fetchLearnerDashboardData, + addToLearnerPlaylist: _addToLearnerPlaylist, + removeFromLearnerPlaylist: _removeFromLearnerPlaylist + }; +}]); diff --git a/core/templates/dev/head/pages/library/Library.js b/core/templates/dev/head/pages/library/Library.js index 209442e7eaca..303e8108e24e 100644 --- a/core/templates/dev/head/pages/library/Library.js +++ b/core/templates/dev/head/pages/library/Library.js @@ -32,13 +32,13 @@ oppia.controller('Library', [ 'windowDimensionsService', 'UrlInterpolationService', 'LIBRARY_PAGE_MODES', 'LIBRARY_TILE_WIDTH_PX', 'alertsService', 'LearnerDashboardIdsBackendApiService', - 'LearnerDashboardActivityIdsObjectFactory', function( + 'LearnerDashboardActivityIdsObjectFactory', 'LearnerPlaylistService', function( $scope, $http, $modal, $rootScope, $window, $timeout, i18nIdService, urlService, ALL_CATEGORIES, searchService, windowDimensionsService, UrlInterpolationService, LIBRARY_PAGE_MODES, LIBRARY_TILE_WIDTH_PX, alertsService, LearnerDashboardIdsBackendApiService, - LearnerDashboardActivityIdsObjectFactory) { + LearnerDashboardActivityIdsObjectFactory, LearnerPlaylistService) { $rootScope.loadingMessage = 'I18N_LIBRARY_LOADING'; var possibleBannerFilenames = [ 'banner1.svg', 'banner2.svg', 'banner3.svg', 'banner4.svg']; diff --git a/core/templates/dev/head/pages/library/library.html b/core/templates/dev/head/pages/library/library.html index bb7f93983daf..9df3917918f9 100644 --- a/core/templates/dev/head/pages/library/library.html +++ b/core/templates/dev/head/pages/library/library.html @@ -224,6 +224,7 @@

+ From 4c63a1c9831f634a8319b54c709869d44db388c4 Mon Sep 17 00:00:00 2001 From: Arunabh98 Date: Sat, 26 Aug 2017 01:50:40 +0530 Subject: [PATCH 49/65] Fix lint errors. --- .../CollectionSummaryTileDirective.js | 7 +- .../ExplorationSummaryTileDirective.js | 7 +- ...earnerDashboardActivityIdsObjectFactory.js | 69 ++++++++++--------- .../LearnerPlaylistService.js | 5 +- .../dev/head/pages/library/Library.js | 3 +- 5 files changed, 47 insertions(+), 44 deletions(-) diff --git a/core/templates/dev/head/components/summary_tile/CollectionSummaryTileDirective.js b/core/templates/dev/head/components/summary_tile/CollectionSummaryTileDirective.js index 0010b4a4f01d..dcfb2b092ce5 100644 --- a/core/templates/dev/head/components/summary_tile/CollectionSummaryTileDirective.js +++ b/core/templates/dev/head/components/summary_tile/CollectionSummaryTileDirective.js @@ -83,7 +83,8 @@ oppia.directive('collectionSummaryTile', [ collectionIsActive = !collectionIsActive; }; - $scope.canCollectionBeAddedToLearnerPlaylist = function(collectionId) { + $scope.canCollectionBeAddedToLearnerPlaylist = function( + collectionId) { if ($scope.getLearnerDashboardActivityIds()) { if ($scope.getLearnerDashboardActivityIds( ).belongsToLearnerDashboardActivities(collectionId)) { @@ -99,8 +100,8 @@ oppia.directive('collectionSummaryTile', [ LearnerPlaylistService.addToLearnerPlaylist( collectionId, constants.ACTIVITY_TYPE_COLLECTION)); if (isSuccessfullyAdded) { - $scope.getLearnerDashboardActivityIds().addToCollectionLearnerPlaylist( - collectionId); + $scope.getLearnerDashboardActivityIds( + ).addToCollectionLearnerPlaylist(collectionId); } }; diff --git a/core/templates/dev/head/components/summary_tile/ExplorationSummaryTileDirective.js b/core/templates/dev/head/components/summary_tile/ExplorationSummaryTileDirective.js index 9c2f5fd21d73..2fd7303832c5 100644 --- a/core/templates/dev/head/components/summary_tile/ExplorationSummaryTileDirective.js +++ b/core/templates/dev/head/components/summary_tile/ExplorationSummaryTileDirective.js @@ -121,7 +121,8 @@ oppia.directive('explorationSummaryTile', [ explorationIsActive = !explorationIsActive; }; - $scope.canExplorationBeAddedToLearnerPlaylist = function(explorationId) { + $scope.canExplorationBeAddedToLearnerPlaylist = function( + explorationId) { if ($scope.getLearnerDashboardActivityIds()) { if ($scope.getLearnerDashboardActivityIds( ).belongsToLearnerDashboardActivities(explorationId)) { @@ -137,8 +138,8 @@ oppia.directive('explorationSummaryTile', [ LearnerPlaylistService.addToLearnerPlaylist( explorationId, constants.ACTIVITY_TYPE_EXPLORATION)); if (isSuccessfullyAdded) { - $scope.getLearnerDashboardActivityIds().addToExplorationLearnerPlaylist( - explorationId); + $scope.getLearnerDashboardActivityIds( + ).addToExplorationLearnerPlaylist(explorationId); } }; diff --git a/core/templates/dev/head/domain/learner_dashboard/LearnerDashboardActivityIdsObjectFactory.js b/core/templates/dev/head/domain/learner_dashboard/LearnerDashboardActivityIdsObjectFactory.js index a9fdef0ba3ef..ca10589ce3b8 100644 --- a/core/templates/dev/head/domain/learner_dashboard/LearnerDashboardActivityIdsObjectFactory.js +++ b/core/templates/dev/head/domain/learner_dashboard/LearnerDashboardActivityIdsObjectFactory.js @@ -30,45 +30,46 @@ oppia.factory('LearnerDashboardActivityIdsObjectFactory', [function() { this.collectionPlaylistIds = collectionPlaylistIds; }; - LearnerDashboardActivityIds.prototype.belongsToLearnerDashboardActivities = function( + LearnerDashboardActivityIds.prototype.belongsToLearnerDashboardActivities = ( + function( activityId) { - if (this.incompleteCollectionIds.indexOf(activityId) !== -1 || - this.completedCollectionIds.indexOf(activityId) !== -1 || - this.collectionPlaylistIds.indexOf(activityId) !== -1 || - this.incompleteExplorationIds.indexOf(activityId) !== -1 || - this.completedExplorationIds.indexOf(activityId) !== -1 || - this.explorationPlaylistIds.indexOf(activityId) !== -1) { - return true; - } else { - false; - } - }; + if (this.incompleteCollectionIds.indexOf(activityId) !== -1 || + this.completedCollectionIds.indexOf(activityId) !== -1 || + this.collectionPlaylistIds.indexOf(activityId) !== -1 || + this.incompleteExplorationIds.indexOf(activityId) !== -1 || + this.completedExplorationIds.indexOf(activityId) !== -1 || + this.explorationPlaylistIds.indexOf(activityId) !== -1) { + return true; + } else { + false; + } + }); - LearnerDashboardActivityIds.prototype.addToExplorationLearnerPlaylist = function( - explorationId) { - this.explorationPlaylistIds.push(explorationId); - }; + LearnerDashboardActivityIds.prototype.addToExplorationLearnerPlaylist = ( + function(explorationId) { + this.explorationPlaylistIds.push(explorationId); + }); - LearnerDashboardActivityIds.prototype.removeFromExplorationLearnerPlaylist = function( - explorationId) { - var index = this.explorationPlaylistIds.indexOf(explorationId); - if (index !== -1) { - this.explorationPlaylistIds.splice(index, 1); - } - }; + LearnerDashboardActivityIds.prototype.removeFromExplorationLearnerPlaylist = ( + function(explorationId) { + var index = this.explorationPlaylistIds.indexOf(explorationId); + if (index !== -1) { + this.explorationPlaylistIds.splice(index, 1); + } + }); - LearnerDashboardActivityIds.prototype.removeFromCollectionLearnerPlaylist = function( - collectionId) { - var index = this.collectionPlaylistIds.indexOf(collectionId); - if (index !== -1) { - this.collectionPlaylistIds.splice(index, 1); - } - }; + LearnerDashboardActivityIds.prototype.removeFromCollectionLearnerPlaylist = ( + function(collectionId) { + var index = this.collectionPlaylistIds.indexOf(collectionId); + if (index !== -1) { + this.collectionPlaylistIds.splice(index, 1); + } + }); - LearnerDashboardActivityIds.prototype.addToCollectionLearnerPlaylist = function( - collectionId) { - this.collectionPlaylistIds.push(collectionId); - }; + LearnerDashboardActivityIds.prototype.addToCollectionLearnerPlaylist = ( + function(collectionId) { + this.collectionPlaylistIds.push(collectionId); + }); LearnerDashboardActivityIds.createFromBackendDict = function( learnerDashboardActivityIdsDict) { diff --git a/core/templates/dev/head/domain/learner_dashboard/LearnerPlaylistService.js b/core/templates/dev/head/domain/learner_dashboard/LearnerPlaylistService.js index 9338feb00926..19f7081697ce 100644 --- a/core/templates/dev/head/domain/learner_dashboard/LearnerPlaylistService.js +++ b/core/templates/dev/head/domain/learner_dashboard/LearnerPlaylistService.js @@ -19,7 +19,6 @@ oppia.factory('LearnerPlaylistService', [ '$http', '$modal', 'alertsService', 'UrlInterpolationService', function($http, $modal, alertsService, UrlInterpolationService) { - var _addToLearnerPlaylist = function(activityId, activityType) { var successfullyAdded = true; var addToLearnerPlaylistUrl = ( @@ -53,7 +52,7 @@ 'Successfully added to your \'Play Later\' list.'); } }); - return successfullyAdded; + return successfullyAdded; }; var _removeFromLearnerPlaylist = function(activityId, activityTitle, @@ -115,4 +114,4 @@ addToLearnerPlaylist: _addToLearnerPlaylist, removeFromLearnerPlaylist: _removeFromLearnerPlaylist }; -}]); + }]); diff --git a/core/templates/dev/head/pages/library/Library.js b/core/templates/dev/head/pages/library/Library.js index 303e8108e24e..d3b0e58fd71b 100644 --- a/core/templates/dev/head/pages/library/Library.js +++ b/core/templates/dev/head/pages/library/Library.js @@ -32,7 +32,8 @@ oppia.controller('Library', [ 'windowDimensionsService', 'UrlInterpolationService', 'LIBRARY_PAGE_MODES', 'LIBRARY_TILE_WIDTH_PX', 'alertsService', 'LearnerDashboardIdsBackendApiService', - 'LearnerDashboardActivityIdsObjectFactory', 'LearnerPlaylistService', function( + 'LearnerDashboardActivityIdsObjectFactory', 'LearnerPlaylistService', + function( $scope, $http, $modal, $rootScope, $window, $timeout, i18nIdService, urlService, ALL_CATEGORIES, searchService, windowDimensionsService, UrlInterpolationService, LIBRARY_PAGE_MODES, From 2dd128693dde2b08ea1de0289d485af83f124145 Mon Sep 17 00:00:00 2001 From: Arunabh98 Date: Sat, 26 Aug 2017 02:21:15 +0530 Subject: [PATCH 50/65] Fix a bug. --- .../head/domain/learner_dashboard/LearnerPlaylistService.js | 1 + .../dev/head/pages/learner_dashboard/LearnerDashboard.js | 4 +++- .../dev/head/pages/learner_dashboard/learner_dashboard.html | 1 + .../pages/library/LearnerDashboardIdsBackendApiService.js | 4 ++-- core/templates/dev/head/pages/library/Library.js | 2 +- .../pages/library/activity_tiles_infinity_grid_directive.html | 1 + 6 files changed, 9 insertions(+), 4 deletions(-) diff --git a/core/templates/dev/head/domain/learner_dashboard/LearnerPlaylistService.js b/core/templates/dev/head/domain/learner_dashboard/LearnerPlaylistService.js index 19f7081697ce..1eae2a14f82e 100644 --- a/core/templates/dev/head/domain/learner_dashboard/LearnerPlaylistService.js +++ b/core/templates/dev/head/domain/learner_dashboard/LearnerPlaylistService.js @@ -19,6 +19,7 @@ oppia.factory('LearnerPlaylistService', [ '$http', '$modal', 'alertsService', 'UrlInterpolationService', function($http, $modal, alertsService, UrlInterpolationService) { + var _addToLearnerPlaylist = function(activityId, activityType) { var successfullyAdded = true; var addToLearnerPlaylistUrl = ( diff --git a/core/templates/dev/head/pages/learner_dashboard/LearnerDashboard.js b/core/templates/dev/head/pages/learner_dashboard/LearnerDashboard.js index 23b4ab28f5d8..4de114123efa 100644 --- a/core/templates/dev/head/pages/learner_dashboard/LearnerDashboard.js +++ b/core/templates/dev/head/pages/learner_dashboard/LearnerDashboard.js @@ -75,6 +75,7 @@ oppia.controller('LearnerDashboard', [ 'LEARNER_DASHBOARD_SUBSECTION_I18N_IDS', 'threadStatusDisplayService', 'oppiaDatetimeFormatter', 'FEEDBACK_THREADS_SORT_BY_KEYS_AND_I18N_IDS', 'FeedbackThreadSummaryObjectFactory', 'FeedbackMessageSummaryObjectFactory', + 'LearnerPlaylistService', function( $scope, $rootScope, $window, $http, $modal, alertsService, EXPLORATIONS_SORT_BY_KEYS_AND_I18N_IDS, @@ -83,7 +84,8 @@ oppia.controller('LearnerDashboard', [ LEARNER_DASHBOARD_SECTION_I18N_IDS, LEARNER_DASHBOARD_SUBSECTION_I18N_IDS, threadStatusDisplayService, oppiaDatetimeFormatter, FEEDBACK_THREADS_SORT_BY_KEYS_AND_I18N_IDS, - FeedbackThreadSummaryObjectFactory, FeedbackMessageSummaryObjectFactory) { + FeedbackThreadSummaryObjectFactory, FeedbackMessageSummaryObjectFactory, + LearnerPlaylistService) { $scope.EXPLORATIONS_SORT_BY_KEYS_AND_I18N_IDS = ( EXPLORATIONS_SORT_BY_KEYS_AND_I18N_IDS); $scope.SUBSCRIPTION_SORT_BY_KEYS_AND_I18N_IDS = ( diff --git a/core/templates/dev/head/pages/learner_dashboard/learner_dashboard.html b/core/templates/dev/head/pages/learner_dashboard/learner_dashboard.html index 5f87631b3098..4bcf4b200eb6 100644 --- a/core/templates/dev/head/pages/learner_dashboard/learner_dashboard.html +++ b/core/templates/dev/head/pages/learner_dashboard/learner_dashboard.html @@ -778,6 +778,7 @@

{{ super() }} + diff --git a/core/templates/dev/head/pages/library/LearnerDashboardIdsBackendApiService.js b/core/templates/dev/head/pages/library/LearnerDashboardIdsBackendApiService.js index cf1d77890726..290372320d59 100644 --- a/core/templates/dev/head/pages/library/LearnerDashboardIdsBackendApiService.js +++ b/core/templates/dev/head/pages/library/LearnerDashboardIdsBackendApiService.js @@ -13,8 +13,8 @@ // limitations under the License. /** - * @fileoverview get the activity ids that are present in the learner - * dashboard. + * @fileoverview Backend services related to fetching the ids of the + * activities present in the learner dashboard. */ oppia.factory('LearnerDashboardIdsBackendApiService',[ diff --git a/core/templates/dev/head/pages/library/Library.js b/core/templates/dev/head/pages/library/Library.js index d3b0e58fd71b..df7fc75a50e8 100644 --- a/core/templates/dev/head/pages/library/Library.js +++ b/core/templates/dev/head/pages/library/Library.js @@ -80,7 +80,7 @@ oppia.controller('Library', [ $http.get('/libraryindexhandler').success(function(data) { $scope.libraryGroups = data.activity_summary_dicts_by_category; - if (data.user_email) { + if (data.user_id) { LearnerDashboardIdsBackendApiService.fetchLearnerDashboardIds().then( function(response) { $scope.learnerDashboardActivityIds = ( diff --git a/core/templates/dev/head/pages/library/activity_tiles_infinity_grid_directive.html b/core/templates/dev/head/pages/library/activity_tiles_infinity_grid_directive.html index 66cd346c6dcc..9a5087fe7c33 100644 --- a/core/templates/dev/head/pages/library/activity_tiles_infinity_grid_directive.html +++ b/core/templates/dev/head/pages/library/activity_tiles_infinity_grid_directive.html @@ -10,6 +10,7 @@ objective="activity.objective" thumbnail-icon-url="activity.thumbnail_icon_url" thumbnail-bg-color="activity.thumbnail_bg_color" + style="margin-right: 3px;" learner-dashboard-activity-ids="learnerDashboardActivityIds"> Date: Sat, 26 Aug 2017 02:21:53 +0530 Subject: [PATCH 51/65] Fix lint errors. --- .../dev/head/domain/learner_dashboard/LearnerPlaylistService.js | 1 - 1 file changed, 1 deletion(-) diff --git a/core/templates/dev/head/domain/learner_dashboard/LearnerPlaylistService.js b/core/templates/dev/head/domain/learner_dashboard/LearnerPlaylistService.js index 1eae2a14f82e..19f7081697ce 100644 --- a/core/templates/dev/head/domain/learner_dashboard/LearnerPlaylistService.js +++ b/core/templates/dev/head/domain/learner_dashboard/LearnerPlaylistService.js @@ -19,7 +19,6 @@ oppia.factory('LearnerPlaylistService', [ '$http', '$modal', 'alertsService', 'UrlInterpolationService', function($http, $modal, alertsService, UrlInterpolationService) { - var _addToLearnerPlaylist = function(activityId, activityType) { var successfullyAdded = true; var addToLearnerPlaylistUrl = ( From aff0b0c2edc4596e12681e7e4839429e0abcbbcc Mon Sep 17 00:00:00 2001 From: Arunabh98 Date: Sat, 26 Aug 2017 16:35:09 +0530 Subject: [PATCH 52/65] Add directive for icons. --- .../CollectionSummaryTileDirective.js | 39 +------- .../ExplorationSummaryTileDirective.js | 45 ++-------- .../collection_summary_tile_directive.html | 30 ++----- .../exploration_summary_tile_directive.html | 30 ++----- .../LearnerDashboardIconsDirective.js | 88 +++++++++++++++++++ .../learner_dashboard_icons_directive.html | 23 +++++ .../learner_dashboard/LearnerDashboard.js | 4 +- .../learner_dashboard/learner_dashboard.html | 1 + .../ActivityTilesInfinityGridDirective.js | 8 -- .../dev/head/pages/library/Library.js | 10 --- .../pages/library/SearchResultsDirective.js | 1 + ...ctivity_tiles_infinity_grid_directive.html | 8 +- .../dev/head/pages/library/library.html | 10 +-- .../dev/head/pages/profile/profile.html | 2 + 14 files changed, 144 insertions(+), 155 deletions(-) create mode 100644 core/templates/dev/head/domain/learner_dashboard/LearnerDashboardIconsDirective.js create mode 100644 core/templates/dev/head/domain/learner_dashboard/learner_dashboard_icons_directive.html diff --git a/core/templates/dev/head/components/summary_tile/CollectionSummaryTileDirective.js b/core/templates/dev/head/components/summary_tile/CollectionSummaryTileDirective.js index dcfb2b092ce5..80111adb62a3 100644 --- a/core/templates/dev/head/components/summary_tile/CollectionSummaryTileDirective.js +++ b/core/templates/dev/head/components/summary_tile/CollectionSummaryTileDirective.js @@ -35,8 +35,7 @@ oppia.directive('collectionSummaryTile', [ getThumbnailBgColor: '&thumbnailBgColor', isLinkedToEditorPage: '=?isLinkedToEditorPage', getCategory: '&category', - isPlaylistMode: '&playlistMode', - getLearnerDashboardActivityIds: '&learnerDashboardActivityIds', + isPlaylistMode: '&playlistMode' }, templateUrl: UrlInterpolationService.getDirectiveTemplateUrl( '/components/summary_tile/' + @@ -51,6 +50,7 @@ oppia.directive('collectionSummaryTile', [ UrlInterpolationService, alertsService, LearnerPlaylistService) { $scope.DEFAULT_EMPTY_TITLE = 'Untitled'; + $scope.collectionType = constants.ACTIVITY_TYPE_COLLECTION; $scope.getLastUpdatedDatetime = function() { return oppiaDatetimeFormatter.getLocaleAbbreviatedDatetimeString( @@ -77,41 +77,10 @@ oppia.directive('collectionSummaryTile', [ return UrlInterpolationService.getStaticImageUrl(url); }; - var collectionIsActive = false; + $scope.collectionIsActive = false; $scope.toggleCollectionIsActive = function() { - collectionIsActive = !collectionIsActive; - }; - - $scope.canCollectionBeAddedToLearnerPlaylist = function( - collectionId) { - if ($scope.getLearnerDashboardActivityIds()) { - if ($scope.getLearnerDashboardActivityIds( - ).belongsToLearnerDashboardActivities(collectionId)) { - return false; - } else { - return collectionIsActive; - } - } - }; - - $scope.addToLearnerPlaylist = function(collectionId) { - var isSuccessfullyAdded = ( - LearnerPlaylistService.addToLearnerPlaylist( - collectionId, constants.ACTIVITY_TYPE_COLLECTION)); - if (isSuccessfullyAdded) { - $scope.getLearnerDashboardActivityIds( - ).addToCollectionLearnerPlaylist(collectionId); - } - }; - - $scope.removeFromLearnerPlaylist = function( - collectionId, collectionTitle) { - var isSuccessfullyRemoved = ( - LearnerPlaylistService.removeFromLearnerPlaylist( - collectionId, collectionTitle, - constants.ACTIVITY_TYPE_COLLECTION, - $scope.getLearnerDashboardActivityIds())); + $scope.collectionIsActive = !$scope.collectionIsActive; }; } ] diff --git a/core/templates/dev/head/components/summary_tile/ExplorationSummaryTileDirective.js b/core/templates/dev/head/components/summary_tile/ExplorationSummaryTileDirective.js index 2fd7303832c5..b5c21b1d346c 100644 --- a/core/templates/dev/head/components/summary_tile/ExplorationSummaryTileDirective.js +++ b/core/templates/dev/head/components/summary_tile/ExplorationSummaryTileDirective.js @@ -44,8 +44,7 @@ oppia.directive('explorationSummaryTile', [ // if it is not specified, it is treated as 0, which means that the // desktop version of the summary tile is always displayed. mobileCutoffPx: '@mobileCutoffPx', - isPlaylistMode: '&playlistMode', - getLearnerDashboardActivityIds: '&learnerDashboardActivityIds', + isPlaylistMode: '&playlistMode' }, templateUrl: UrlInterpolationService.getDirectiveTemplateUrl( '/components/summary_tile/' + @@ -80,12 +79,13 @@ oppia.directive('explorationSummaryTile', [ '$scope', '$http', '$modal', 'oppiaDatetimeFormatter', 'RatingComputationService', 'windowDimensionsService', 'UrlInterpolationService', - 'alertsService', 'LearnerPlaylistService', + 'alertsService', function( $scope, $http, $modal, oppiaDatetimeFormatter, RatingComputationService, windowDimensionsService, UrlInterpolationService, - alertsService, LearnerPlaylistService) { + alertsService) { + $scope.explorationType = constants.ACTIVITY_TYPE_EXPLORATION; var contributorsSummary = $scope.getContributorsSummary() || {}; $scope.contributors = Object.keys( contributorsSummary).sort( @@ -115,41 +115,10 @@ oppia.directive('explorationSummaryTile', [ } $scope.MAX_AVATARS_TO_DISPLAY = 5; - var explorationIsActive = false; + $scope.explorationIsActive = false; - $scope.toggleExplorationIsActive = function(explorationId) { - explorationIsActive = !explorationIsActive; - }; - - $scope.canExplorationBeAddedToLearnerPlaylist = function( - explorationId) { - if ($scope.getLearnerDashboardActivityIds()) { - if ($scope.getLearnerDashboardActivityIds( - ).belongsToLearnerDashboardActivities(explorationId)) { - return false; - } else { - return explorationIsActive; - } - } - }; - - $scope.addToLearnerPlaylist = function(explorationId) { - var isSuccessfullyAdded = ( - LearnerPlaylistService.addToLearnerPlaylist( - explorationId, constants.ACTIVITY_TYPE_EXPLORATION)); - if (isSuccessfullyAdded) { - $scope.getLearnerDashboardActivityIds( - ).addToExplorationLearnerPlaylist(explorationId); - } - }; - - $scope.removeFromLearnerPlaylist = function( - explorationId, explorationTitle) { - var isSuccessfullyRemoved = ( - LearnerPlaylistService.removeFromLearnerPlaylist( - explorationId, explorationTitle, - constants.ACTIVITY_TYPE_EXPLORATION, - $scope.getLearnerDashboardActivityIds())); + $scope.toggleExplorationIsActive = function() { + $scope.explorationIsActive = !$scope.explorationIsActive; }; $scope.getAverageRating = function() { diff --git a/core/templates/dev/head/components/summary_tile/collection_summary_tile_directive.html b/core/templates/dev/head/components/summary_tile/collection_summary_tile_directive.html index 9991abfb0165..cec057410919 100644 --- a/core/templates/dev/head/components/summary_tile/collection_summary_tile_directive.html +++ b/core/templates/dev/head/components/summary_tile/collection_summary_tile_directive.html @@ -1,28 +1,8 @@ - - - - - - + + - - - - - + + diff --git a/core/templates/dev/head/domain/learner_dashboard/LearnerDashboardIconsDirective.js b/core/templates/dev/head/domain/learner_dashboard/LearnerDashboardIconsDirective.js new file mode 100644 index 000000000000..e433ea215712 --- /dev/null +++ b/core/templates/dev/head/domain/learner_dashboard/LearnerDashboardIconsDirective.js @@ -0,0 +1,88 @@ +// Copyright 2017 The Oppia Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS-IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/** + * @fileoverview Directive for showing learner dashboard icons. + */ + +oppia.directive('learnerDashboardIcons', [ + 'UrlInterpolationService', function(UrlInterpolationService) { + return { + restrict: 'E', + scope: { + getActivityType: '&activityType', + getActivityId: '&activityId', + getActivityTitle: '&activityTitle', + activityActive: '=activityActive' + }, + templateUrl: UrlInterpolationService.getDirectiveTemplateUrl( + '/domain/learner_dashboard/' + + 'learner_dashboard_icons_directive.html'), + controller: [ + '$scope', 'LearnerDashboardIdsBackendApiService', + 'LearnerDashboardActivityIdsObjectFactory', + 'LearnerPlaylistService', + function($scope, LearnerDashboardIdsBackendApiService, + LearnerDashboardActivityIdsObjectFactory, + LearnerPlaylistService) { + $scope.activityIsActive = true; + + $scope.$watch('activityActive', function(value) { + $scope.activityIsActive = !$scope.activityIsActive; + }); + + LearnerDashboardIdsBackendApiService.fetchLearnerDashboardIds().then( + function(response) { + $scope.learnerDashboardActivityIds = ( + LearnerDashboardActivityIdsObjectFactory.createFromBackendDict( + response.data.learner_dashboard_activity_ids)); + } + ); + + $scope.toggleActivityIsActive = function(activityId) { + $scope.activityIsActive = !$scope.activityIsActive; + }; + + $scope.canActivityBeAddedToLearnerPlaylist = function( + activityId) { + if ($scope.learnerDashboardActivityIds) { + if ($scope.learnerDashboardActivityIds.belongsToLearnerDashboardActivities(activityId)) { + return false; + } else { + return $scope.activityIsActive; + } + } + }; + + $scope.addToLearnerPlaylist = function(activityId, activityType) { + var isSuccessfullyAdded = ( + LearnerPlaylistService.addToLearnerPlaylist( + activityId, activityType)); + if (isSuccessfullyAdded) { + $scope.learnerDashboardActivityIds.addToExplorationLearnerPlaylist(activityId); + } + }; + + $scope.removeFromLearnerPlaylist = function( + activityId, activityTitle, activityType) { + var isSuccessfullyRemoved = ( + LearnerPlaylistService.removeFromLearnerPlaylist( + activityId, activityTitle, + activityType, + $scope.learnerDashboardActivityIds)); + }; + } + ] + }; + }]); diff --git a/core/templates/dev/head/domain/learner_dashboard/learner_dashboard_icons_directive.html b/core/templates/dev/head/domain/learner_dashboard/learner_dashboard_icons_directive.html new file mode 100644 index 000000000000..fce4f723f739 --- /dev/null +++ b/core/templates/dev/head/domain/learner_dashboard/learner_dashboard_icons_directive.html @@ -0,0 +1,23 @@ + + + + \ No newline at end of file diff --git a/core/templates/dev/head/pages/learner_dashboard/LearnerDashboard.js b/core/templates/dev/head/pages/learner_dashboard/LearnerDashboard.js index 4de114123efa..23b4ab28f5d8 100644 --- a/core/templates/dev/head/pages/learner_dashboard/LearnerDashboard.js +++ b/core/templates/dev/head/pages/learner_dashboard/LearnerDashboard.js @@ -75,7 +75,6 @@ oppia.controller('LearnerDashboard', [ 'LEARNER_DASHBOARD_SUBSECTION_I18N_IDS', 'threadStatusDisplayService', 'oppiaDatetimeFormatter', 'FEEDBACK_THREADS_SORT_BY_KEYS_AND_I18N_IDS', 'FeedbackThreadSummaryObjectFactory', 'FeedbackMessageSummaryObjectFactory', - 'LearnerPlaylistService', function( $scope, $rootScope, $window, $http, $modal, alertsService, EXPLORATIONS_SORT_BY_KEYS_AND_I18N_IDS, @@ -84,8 +83,7 @@ oppia.controller('LearnerDashboard', [ LEARNER_DASHBOARD_SECTION_I18N_IDS, LEARNER_DASHBOARD_SUBSECTION_I18N_IDS, threadStatusDisplayService, oppiaDatetimeFormatter, FEEDBACK_THREADS_SORT_BY_KEYS_AND_I18N_IDS, - FeedbackThreadSummaryObjectFactory, FeedbackMessageSummaryObjectFactory, - LearnerPlaylistService) { + FeedbackThreadSummaryObjectFactory, FeedbackMessageSummaryObjectFactory) { $scope.EXPLORATIONS_SORT_BY_KEYS_AND_I18N_IDS = ( EXPLORATIONS_SORT_BY_KEYS_AND_I18N_IDS); $scope.SUBSCRIPTION_SORT_BY_KEYS_AND_I18N_IDS = ( diff --git a/core/templates/dev/head/pages/learner_dashboard/learner_dashboard.html b/core/templates/dev/head/pages/learner_dashboard/learner_dashboard.html index 4bcf4b200eb6..09b06e59291d 100644 --- a/core/templates/dev/head/pages/learner_dashboard/learner_dashboard.html +++ b/core/templates/dev/head/pages/learner_dashboard/learner_dashboard.html @@ -779,6 +779,7 @@

+ diff --git a/core/templates/dev/head/pages/library/ActivityTilesInfinityGridDirective.js b/core/templates/dev/head/pages/library/ActivityTilesInfinityGridDirective.js index e31450459c37..776da27b23c6 100644 --- a/core/templates/dev/head/pages/library/ActivityTilesInfinityGridDirective.js +++ b/core/templates/dev/head/pages/library/ActivityTilesInfinityGridDirective.js @@ -41,14 +41,6 @@ oppia.directive('activityTilesInfinityGrid', [ } ); - LearnerDashboardIdsBackendApiService.fetchLearnerDashboardIds().then( - function(response) { - $scope.learnerDashboardActivityIds = ( - LearnerDashboardActivityIdsObjectFactory.createFromBackendDict( - response.data.learner_dashboard_activity_ids)); - } - ); - $scope.showMoreActivities = function() { if (!$rootScope.loadingMessage && !$scope.endOfPageIsReached) { $scope.searchResultsAreLoading = true; diff --git a/core/templates/dev/head/pages/library/Library.js b/core/templates/dev/head/pages/library/Library.js index df7fc75a50e8..a0d9bd78dbdc 100644 --- a/core/templates/dev/head/pages/library/Library.js +++ b/core/templates/dev/head/pages/library/Library.js @@ -80,16 +80,6 @@ oppia.controller('Library', [ $http.get('/libraryindexhandler').success(function(data) { $scope.libraryGroups = data.activity_summary_dicts_by_category; - if (data.user_id) { - LearnerDashboardIdsBackendApiService.fetchLearnerDashboardIds().then( - function(response) { - $scope.learnerDashboardActivityIds = ( - LearnerDashboardActivityIdsObjectFactory.createFromBackendDict( - response.data.learner_dashboard_activity_ids)); - } - ); - } - $rootScope.$broadcast( 'preferredLanguageCodesLoaded', data.preferred_language_codes); diff --git a/core/templates/dev/head/pages/library/SearchResultsDirective.js b/core/templates/dev/head/pages/library/SearchResultsDirective.js index f85cf5afab69..3404a05babef 100644 --- a/core/templates/dev/head/pages/library/SearchResultsDirective.js +++ b/core/templates/dev/head/pages/library/SearchResultsDirective.js @@ -27,6 +27,7 @@ oppia.directive('searchResults', [ $rootScope.loadingMessage = 'Loading'; $scope.someResultsExist = true; $scope.userIsLoggedIn = GLOBALS.userIsLoggedIn; + // Called when the first batch of search results is retrieved from the // server. $scope.$on( diff --git a/core/templates/dev/head/pages/library/activity_tiles_infinity_grid_directive.html b/core/templates/dev/head/pages/library/activity_tiles_infinity_grid_directive.html index 9a5087fe7c33..c845859b4cac 100644 --- a/core/templates/dev/head/pages/library/activity_tiles_infinity_grid_directive.html +++ b/core/templates/dev/head/pages/library/activity_tiles_infinity_grid_directive.html @@ -1,7 +1,7 @@
-
+
+ style="margin-right: 3px;"> + class="protractor-test-exp-summary-tile">
diff --git a/core/templates/dev/head/pages/library/library.html b/core/templates/dev/head/pages/library/library.html index 9df3917918f9..b516f16f1334 100644 --- a/core/templates/dev/head/pages/library/library.html +++ b/core/templates/dev/head/pages/library/library.html @@ -116,8 +116,7 @@

diff --git a/core/templates/dev/head/css/oppia.css b/core/templates/dev/head/css/oppia.css index 7db0f6d59eea..cd56385184b0 100644 --- a/core/templates/dev/head/css/oppia.css +++ b/core/templates/dev/head/css/oppia.css @@ -4107,7 +4107,7 @@ md-card.preview-conversation-skin-supplemental-card { .oppia-activity-summary-tile-mobile .exploration-summary-avatars { padding-bottom: 4px; padding-right: 5px; - left: 169px; + left: 140px; position: absolute; top: 3px; width: 31px; diff --git a/core/templates/dev/head/pages/profile/profile.html b/core/templates/dev/head/pages/profile/profile.html index 49d1543a6573..adb3c5806014 100644 --- a/core/templates/dev/head/pages/profile/profile.html +++ b/core/templates/dev/head/pages/profile/profile.html @@ -160,8 +160,6 @@

- - From 2f0fcfcaf19f15a7634869ca8a3c20beb789a62a Mon Sep 17 00:00:00 2001 From: Arunabh98 Date: Sat, 26 Aug 2017 17:20:07 +0530 Subject: [PATCH 56/65] Remove unnecessary code 2. --- .../pages/library/ActivityTilesInfinityGridDirective.js | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/core/templates/dev/head/pages/library/ActivityTilesInfinityGridDirective.js b/core/templates/dev/head/pages/library/ActivityTilesInfinityGridDirective.js index 776da27b23c6..748acc0ab19a 100644 --- a/core/templates/dev/head/pages/library/ActivityTilesInfinityGridDirective.js +++ b/core/templates/dev/head/pages/library/ActivityTilesInfinityGridDirective.js @@ -24,12 +24,8 @@ oppia.directive('activityTilesInfinityGrid', [ '/pages/library/' + 'activity_tiles_infinity_grid_directive.html'), controller: [ - '$scope', '$rootScope', '$http', 'searchService', 'alertsService', - 'LearnerDashboardIdsBackendApiService', - 'LearnerDashboardActivityIdsObjectFactory', function( - $scope, $rootScope, $http, searchService, alertsService, - LearnerDashboardIdsBackendApiService, - LearnerDashboardActivityIdsObjectFactory) { + '$scope', '$rootScope', 'searchService', + function($scope, $rootScope, searchService) { $scope.endOfPageIsReached = false; $scope.allActivitiesInOrder = []; // Called when the first batch of search results is retrieved from the From 43d193e145621dc0051556584779ec1e9970015a Mon Sep 17 00:00:00 2001 From: Arunabh98 Date: Sat, 26 Aug 2017 21:35:48 +0530 Subject: [PATCH 57/65] Address review comments 3. --- core/domain/learner_progress_services.py | 24 +++++++++---------- .../CollectionSummaryTileDirective.js | 2 +- .../ExplorationSummaryTileDirective.js | 3 ++- .../collection_summary_tile_directive.html | 2 +- .../exploration_summary_tile_directive.html | 2 +- ...earnerDashboardActivityIdsObjectFactory.js | 15 ++++++------ .../LearnerDashboardIconsDirective.js | 22 ++++++++++------- .../LearnerDashboardIdsBackendApiService.js | 0 .../LearnerPlaylistService.js | 5 ---- .../learner_dashboard/LearnerDashboard.js | 15 ++++++++++-- .../learner_dashboard/learner_dashboard.html | 4 ---- .../dev/head/pages/library/library.html | 2 +- 12 files changed, 51 insertions(+), 45 deletions(-) rename core/templates/dev/head/{pages/library => domain/learner_dashboard}/LearnerDashboardIdsBackendApiService.js (100%) diff --git a/core/domain/learner_progress_services.py b/core/domain/learner_progress_services.py index 2e04f3b3d91c..7f89be74eb58 100644 --- a/core/domain/learner_progress_services.py +++ b/core/domain/learner_progress_services.py @@ -326,12 +326,12 @@ def add_collection_to_learner_playlist( end. Returns: - bool. Indicates whether the collection already exists in either of the - "completed collections" or "incomplete collections" lists. - bool. Indicates whether the playlist limit of the user has been - exceeded. - bool. Indicates whether the collection belongs to the created or edited - collections of the user. + (bool, bool, bool). The first boolean indicates whether the collection + already exists in either of the "completed collections" or + "incomplete collections" lists, the second boolean indicates + whether the playlist limit of the user has been + exceeded, and the third boolean indicates whether the collection + belongs to the created or edited collections of the user. """ completed_collection_ids = get_all_completed_collection_ids(user_id) incomplete_collection_ids = get_all_incomplete_collection_ids(user_id) @@ -370,12 +370,12 @@ def add_exp_to_learner_playlist( end. Returns: - bool. Indicates whether the exploration belongs to the completed or - incomplete list of explorations. - bool. Indicates whether the playlist limit of the user has been - exceeded. - bool. Indicates whether the exploration belongs to the created or edited - explorations of the user. + (bool, bool, bool). The first boolean indicates whether the exploration + already exists in either of the "completed explorations" or + "incomplete explorations" lists, the second boolean indicates + whether the playlist limit of the user has been + exceeded, and the third boolean indicates whether the exploration + belongs to the created or edited explorations of the user. """ completed_exploration_ids = get_all_completed_exp_ids(user_id) incomplete_exploration_ids = get_all_incomplete_exp_ids(user_id) diff --git a/core/templates/dev/head/components/summary_tile/CollectionSummaryTileDirective.js b/core/templates/dev/head/components/summary_tile/CollectionSummaryTileDirective.js index 52073ea2f1d8..285441a018c1 100644 --- a/core/templates/dev/head/components/summary_tile/CollectionSummaryTileDirective.js +++ b/core/templates/dev/head/components/summary_tile/CollectionSummaryTileDirective.js @@ -46,7 +46,7 @@ oppia.directive('collectionSummaryTile', [ oppiaDatetimeFormatter, COLLECTION_VIEWER_URL, COLLECTION_EDITOR_URL) { $scope.DEFAULT_EMPTY_TITLE = 'Untitled'; - $scope.collectionType = constants.ACTIVITY_TYPE_COLLECTION; + $scope.ACTIVITY_TYPE_COLLECTION = constants.ACTIVITY_TYPE_COLLECTION; $scope.getLastUpdatedDatetime = function() { return oppiaDatetimeFormatter.getLocaleAbbreviatedDatetimeString( diff --git a/core/templates/dev/head/components/summary_tile/ExplorationSummaryTileDirective.js b/core/templates/dev/head/components/summary_tile/ExplorationSummaryTileDirective.js index 4062c0a7b47e..814277e145ec 100644 --- a/core/templates/dev/head/components/summary_tile/ExplorationSummaryTileDirective.js +++ b/core/templates/dev/head/components/summary_tile/ExplorationSummaryTileDirective.js @@ -83,7 +83,8 @@ oppia.directive('explorationSummaryTile', [ $scope, $http, oppiaDatetimeFormatter, RatingComputationService, windowDimensionsService) { - $scope.explorationType = constants.ACTIVITY_TYPE_EXPLORATION; + $scope.ACTIVITY_TYPE_EXPLORATION = ( + constants.ACTIVITY_TYPE_EXPLORATION); var contributorsSummary = $scope.getContributorsSummary() || {}; $scope.contributors = Object.keys( contributorsSummary).sort( diff --git a/core/templates/dev/head/components/summary_tile/collection_summary_tile_directive.html b/core/templates/dev/head/components/summary_tile/collection_summary_tile_directive.html index cec057410919..4d611541fe53 100644 --- a/core/templates/dev/head/components/summary_tile/collection_summary_tile_directive.html +++ b/core/templates/dev/head/components/summary_tile/collection_summary_tile_directive.html @@ -1,4 +1,4 @@ - diff --git a/core/templates/dev/head/components/summary_tile/exploration_summary_tile_directive.html b/core/templates/dev/head/components/summary_tile/exploration_summary_tile_directive.html index 862fcd27e0f5..bab90dc292e4 100644 --- a/core/templates/dev/head/components/summary_tile/exploration_summary_tile_directive.html +++ b/core/templates/dev/head/components/summary_tile/exploration_summary_tile_directive.html @@ -1,4 +1,4 @@ - diff --git a/core/templates/dev/head/domain/learner_dashboard/LearnerDashboardActivityIdsObjectFactory.js b/core/templates/dev/head/domain/learner_dashboard/LearnerDashboardActivityIdsObjectFactory.js index ca10589ce3b8..25f9c14e7cb5 100644 --- a/core/templates/dev/head/domain/learner_dashboard/LearnerDashboardActivityIdsObjectFactory.js +++ b/core/templates/dev/head/domain/learner_dashboard/LearnerDashboardActivityIdsObjectFactory.js @@ -30,9 +30,8 @@ oppia.factory('LearnerDashboardActivityIdsObjectFactory', [function() { this.collectionPlaylistIds = collectionPlaylistIds; }; - LearnerDashboardActivityIds.prototype.belongsToLearnerDashboardActivities = ( - function( - activityId) { + LearnerDashboardActivityIds.prototype.includesActivity = ( + function(activityId) { if (this.incompleteCollectionIds.indexOf(activityId) !== -1 || this.completedCollectionIds.indexOf(activityId) !== -1 || this.collectionPlaylistIds.indexOf(activityId) !== -1 || @@ -58,6 +57,11 @@ oppia.factory('LearnerDashboardActivityIdsObjectFactory', [function() { } }); + LearnerDashboardActivityIds.prototype.addToCollectionLearnerPlaylist = ( + function(collectionId) { + this.collectionPlaylistIds.push(collectionId); + }); + LearnerDashboardActivityIds.prototype.removeFromCollectionLearnerPlaylist = ( function(collectionId) { var index = this.collectionPlaylistIds.indexOf(collectionId); @@ -66,11 +70,6 @@ oppia.factory('LearnerDashboardActivityIdsObjectFactory', [function() { } }); - LearnerDashboardActivityIds.prototype.addToCollectionLearnerPlaylist = ( - function(collectionId) { - this.collectionPlaylistIds.push(collectionId); - }); - LearnerDashboardActivityIds.createFromBackendDict = function( learnerDashboardActivityIdsDict) { return new LearnerDashboardActivityIds( diff --git a/core/templates/dev/head/domain/learner_dashboard/LearnerDashboardIconsDirective.js b/core/templates/dev/head/domain/learner_dashboard/LearnerDashboardIconsDirective.js index a317637ebd48..c988267c21f5 100644 --- a/core/templates/dev/head/domain/learner_dashboard/LearnerDashboardIconsDirective.js +++ b/core/templates/dev/head/domain/learner_dashboard/LearnerDashboardIconsDirective.js @@ -54,13 +54,10 @@ oppia.directive('learnerDashboardIcons', [ $scope.activityIsActive = !$scope.activityIsActive; }; - $scope.canActivityBeAddedToLearnerPlaylist = function( - activityId) { + $scope.canActivityBeAddedToLearnerPlaylist = function(activityId) { if ($scope.learnerDashboardActivityIds) { - /* eslint-disable max-len */ - if ($scope.learnerDashboardActivityIds.belongsToLearnerDashboardActivities( + if ($scope.learnerDashboardActivityIds.includesActivity( activityId)) { - /* eslint-enable max-len */ return false; } else { return $scope.activityIsActive; @@ -73,10 +70,17 @@ oppia.directive('learnerDashboardIcons', [ LearnerPlaylistService.addToLearnerPlaylist( activityId, activityType)); if (isSuccessfullyAdded) { - /* eslint-disable max-len */ - $scope.learnerDashboardActivityIds.addToExplorationLearnerPlaylist( - activityId); - /* eslint-enable max-len */ + if (activityType === constants.ACTIVITY_TYPE_EXPLORATION) { + /* eslint-disable max-len */ + $scope.learnerDashboardActivityIds.addToExplorationLearnerPlaylist( + activityId); + /* eslint-enable max-len */ + } else if (activityType === constants.ACTIVITY_TYPE_COLLECTION) { + /* eslint-disable max-len */ + $scope.learnerDashboardActivityIds.addToCollectionLearnerPlaylist( + activityId); + /* eslint-enable max-len */ + } } }; diff --git a/core/templates/dev/head/pages/library/LearnerDashboardIdsBackendApiService.js b/core/templates/dev/head/domain/learner_dashboard/LearnerDashboardIdsBackendApiService.js similarity index 100% rename from core/templates/dev/head/pages/library/LearnerDashboardIdsBackendApiService.js rename to core/templates/dev/head/domain/learner_dashboard/LearnerDashboardIdsBackendApiService.js diff --git a/core/templates/dev/head/domain/learner_dashboard/LearnerPlaylistService.js b/core/templates/dev/head/domain/learner_dashboard/LearnerPlaylistService.js index 19f7081697ce..ebbcf578909e 100644 --- a/core/templates/dev/head/domain/learner_dashboard/LearnerPlaylistService.js +++ b/core/templates/dev/head/domain/learner_dashboard/LearnerPlaylistService.js @@ -105,12 +105,7 @@ }); }; - var _fetchLearnerDashboardData = function() { - return $http.get('/learnerdashboardhandler/data'); - }; - return { - fetchLearnerDashboardData: _fetchLearnerDashboardData, addToLearnerPlaylist: _addToLearnerPlaylist, removeFromLearnerPlaylist: _removeFromLearnerPlaylist }; diff --git a/core/templates/dev/head/pages/learner_dashboard/LearnerDashboard.js b/core/templates/dev/head/pages/learner_dashboard/LearnerDashboard.js index 23b4ab28f5d8..2bc867682af1 100644 --- a/core/templates/dev/head/pages/learner_dashboard/LearnerDashboard.js +++ b/core/templates/dev/head/pages/learner_dashboard/LearnerDashboard.js @@ -252,11 +252,23 @@ oppia.controller('LearnerDashboard', [ }; var getPlaylistSortableOptions = function(activityType) { + var windowScrollTop = ''; + var startSort = false; return { + 'ui-floating': 'auto', start: function(e, ui) { + if(startSort){ + windowScrollTop = $(window).scrollTop(); + } + startSort = true; ui.placeholder.height(ui.item.height()); $scope.$apply(); }, + sort: function (e, ui) { + /* eslint-disable quote-props */ + ui.helper.css({'top': ui.position.top + windowScrollTop + 'px'}); + /* eslint-enable quote-props */ + }, update: function(e, ui) { var insertExpInLearnerPlaylistUrl = ( UrlInterpolationService.interpolateUrl( @@ -274,8 +286,7 @@ oppia.controller('LearnerDashboard', [ stop: function(e, ui) { $scope.$apply(); }, - axis: 'y', - 'ui-floating': false + axis: 'y' }; }; diff --git a/core/templates/dev/head/pages/learner_dashboard/learner_dashboard.html b/core/templates/dev/head/pages/learner_dashboard/learner_dashboard.html index 09b06e59291d..0ecef717d4ad 100644 --- a/core/templates/dev/head/pages/learner_dashboard/learner_dashboard.html +++ b/core/templates/dev/head/pages/learner_dashboard/learner_dashboard.html @@ -544,8 +544,6 @@

<[subscriptionsList.length]>

- -

{{ super() }} - - diff --git a/core/templates/dev/head/pages/library/library.html b/core/templates/dev/head/pages/library/library.html index b516f16f1334..fb6585ba7de7 100644 --- a/core/templates/dev/head/pages/library/library.html +++ b/core/templates/dev/head/pages/library/library.html @@ -219,7 +219,7 @@

- + From 5523dbe665221678bfb4a60f6f5baea00b562983 Mon Sep 17 00:00:00 2001 From: Arunabh98 Date: Sun, 27 Aug 2017 10:13:22 +0530 Subject: [PATCH 58/65] Fix e2e tests. --- .../CollectionSummaryTileDirective.js | 3 +- .../ExplorationSummaryTileDirective.js | 3 +- .../collection_summary_tile_directive.html | 3 +- .../exploration_summary_tile_directive.html | 3 +- .../ActivityTilesInfinityGridDirective.js | 1 + .../dev/head/pages/library/Library.js | 1 + ...ctivity_tiles_infinity_grid_directive.html | 2 + .../dev/head/pages/library/library.html | 6 +- core/tests/protractor.conf.js | 95 ++++++++++--------- 9 files changed, 64 insertions(+), 53 deletions(-) diff --git a/core/templates/dev/head/components/summary_tile/CollectionSummaryTileDirective.js b/core/templates/dev/head/components/summary_tile/CollectionSummaryTileDirective.js index 285441a018c1..63cc4349319b 100644 --- a/core/templates/dev/head/components/summary_tile/CollectionSummaryTileDirective.js +++ b/core/templates/dev/head/components/summary_tile/CollectionSummaryTileDirective.js @@ -35,7 +35,8 @@ oppia.directive('collectionSummaryTile', [ getThumbnailBgColor: '&thumbnailBgColor', isLinkedToEditorPage: '=?isLinkedToEditorPage', getCategory: '&category', - isPlaylistMode: '&playlistMode' + isPlaylistMode: '&playlistMode', + showLearnerDashboardIcons: '&showLearnerDashboardIcons' }, templateUrl: UrlInterpolationService.getDirectiveTemplateUrl( '/components/summary_tile/' + diff --git a/core/templates/dev/head/components/summary_tile/ExplorationSummaryTileDirective.js b/core/templates/dev/head/components/summary_tile/ExplorationSummaryTileDirective.js index 814277e145ec..21cc4b22d2e1 100644 --- a/core/templates/dev/head/components/summary_tile/ExplorationSummaryTileDirective.js +++ b/core/templates/dev/head/components/summary_tile/ExplorationSummaryTileDirective.js @@ -44,7 +44,8 @@ oppia.directive('explorationSummaryTile', [ // if it is not specified, it is treated as 0, which means that the // desktop version of the summary tile is always displayed. mobileCutoffPx: '@mobileCutoffPx', - isPlaylistMode: '&playlistMode' + isPlaylistMode: '&playlistMode', + showLearnerDashboardIcons: '&showLearnerDashboardIcons' }, templateUrl: UrlInterpolationService.getDirectiveTemplateUrl( '/components/summary_tile/' + diff --git a/core/templates/dev/head/components/summary_tile/collection_summary_tile_directive.html b/core/templates/dev/head/components/summary_tile/collection_summary_tile_directive.html index 4d611541fe53..3b65c54cf9e8 100644 --- a/core/templates/dev/head/components/summary_tile/collection_summary_tile_directive.html +++ b/core/templates/dev/head/components/summary_tile/collection_summary_tile_directive.html @@ -1,4 +1,5 @@ - diff --git a/core/templates/dev/head/components/summary_tile/exploration_summary_tile_directive.html b/core/templates/dev/head/components/summary_tile/exploration_summary_tile_directive.html index bab90dc292e4..1716f087094e 100644 --- a/core/templates/dev/head/components/summary_tile/exploration_summary_tile_directive.html +++ b/core/templates/dev/head/components/summary_tile/exploration_summary_tile_directive.html @@ -1,4 +1,5 @@ - diff --git a/core/templates/dev/head/pages/library/ActivityTilesInfinityGridDirective.js b/core/templates/dev/head/pages/library/ActivityTilesInfinityGridDirective.js index 748acc0ab19a..3945954f0695 100644 --- a/core/templates/dev/head/pages/library/ActivityTilesInfinityGridDirective.js +++ b/core/templates/dev/head/pages/library/ActivityTilesInfinityGridDirective.js @@ -28,6 +28,7 @@ oppia.directive('activityTilesInfinityGrid', [ function($scope, $rootScope, searchService) { $scope.endOfPageIsReached = false; $scope.allActivitiesInOrder = []; + $scope.userIsLoggedIn = GLOBALS.userIsLoggedIn; // Called when the first batch of search results is retrieved from the // server. $scope.$on( diff --git a/core/templates/dev/head/pages/library/Library.js b/core/templates/dev/head/pages/library/Library.js index a0d9bd78dbdc..3ec0c5d3f182 100644 --- a/core/templates/dev/head/pages/library/Library.js +++ b/core/templates/dev/head/pages/library/Library.js @@ -41,6 +41,7 @@ oppia.controller('Library', [ LearnerDashboardIdsBackendApiService, LearnerDashboardActivityIdsObjectFactory, LearnerPlaylistService) { $rootScope.loadingMessage = 'I18N_LIBRARY_LOADING'; + $scope.userIsLoggedIn = GLOBALS.userIsLoggedIn; var possibleBannerFilenames = [ 'banner1.svg', 'banner2.svg', 'banner3.svg', 'banner4.svg']; $scope.bannerImageFilename = possibleBannerFilenames[ diff --git a/core/templates/dev/head/pages/library/activity_tiles_infinity_grid_directive.html b/core/templates/dev/head/pages/library/activity_tiles_infinity_grid_directive.html index c845859b4cac..92594c54dd1e 100644 --- a/core/templates/dev/head/pages/library/activity_tiles_infinity_grid_directive.html +++ b/core/templates/dev/head/pages/library/activity_tiles_infinity_grid_directive.html @@ -10,6 +10,7 @@ objective="activity.objective" thumbnail-icon-url="activity.thumbnail_icon_url" thumbnail-bg-color="activity.thumbnail_bg_color" + show-learner-dashboard-icons="userIsLoggedIn" style="margin-right: 3px;">

diff --git a/core/templates/dev/head/pages/library/library.html b/core/templates/dev/head/pages/library/library.html index fb6585ba7de7..443063356dfb 100644 --- a/core/templates/dev/head/pages/library/library.html +++ b/core/templates/dev/head/pages/library/library.html @@ -125,7 +125,8 @@

+ thumbnail-bg-color="tile.thumbnail_bg_color" + show-learner-dashboard-icons="userIsLoggedIn"> + class="protractor-test-exp-summary-tile" + show-learner-dashboard-icons="userIsLoggedIn">

diff --git a/core/tests/protractor.conf.js b/core/tests/protractor.conf.js index c7a5c53959ac..ca8b2fa4d113 100755 --- a/core/tests/protractor.conf.js +++ b/core/tests/protractor.conf.js @@ -57,56 +57,57 @@ exports.config = { // with --suite=smoke, only the patterns matched by that suite will run. suites: { full: [ - 'protractor/*.js' - ], - - mainEditor: [ - 'protractor/editorAndPlayer.js', - 'protractor/stateEditor.js', - 'protractor/explorationFeedback.js' - ], - - editorFeatures: [ - 'protractor/gadgetEditor.js', - 'protractor/historyTab.js', - 'protractor/parameters.js' - ], - - extensions: [ - 'protractor/richTextComponents.js', - 'protractor/interactions.js' - ], - - library: [ - 'protractor/explorationRating.js', - 'protractor/privileges.js', + // 'protractor/*.js' 'protractor/libraryPagesTour.js', - 'protractor/publicationAndLibrary.js' - ], - - learnerDashboard: [ - 'protractor/learnerDashboard.js', - ], - - users: [ - 'protractor/userManagement.js', - 'protractor/loginFlow.js', - 'protractor/subscriptions.js', - 'protractor/preferences.js' - ], - - misc: [ - 'protractor/suggestions.js', - 'protractor/cacheSlugs.js', - 'protractor/staticPagesTour.js', - 'protractor/collections.js', - 'protractor/accessibility.js', - 'protractor/i18n.js' ], - embedding: [ - 'protractor/embedding.js' - ] + // mainEditor: [ + // 'protractor/editorAndPlayer.js', + // 'protractor/stateEditor.js', + // 'protractor/explorationFeedback.js' + // ], + + // editorFeatures: [ + // 'protractor/gadgetEditor.js', + // 'protractor/historyTab.js', + // 'protractor/parameters.js' + // ], + + // extensions: [ + // 'protractor/richTextComponents.js', + // 'protractor/interactions.js' + // ], + + // library: [ + // 'protractor/explorationRating.js', + // 'protractor/privileges.js', + // 'protractor/libraryPagesTour.js', + // 'protractor/publicationAndLibrary.js' + // ], + + // learnerDashboard: [ + // 'protractor/learnerDashboard.js', + // ], + + // users: [ + // 'protractor/userManagement.js', + // 'protractor/loginFlow.js', + // 'protractor/subscriptions.js', + // 'protractor/preferences.js' + // ], + + // misc: [ + // 'protractor/suggestions.js', + // 'protractor/cacheSlugs.js', + // 'protractor/staticPagesTour.js', + // 'protractor/collections.js', + // 'protractor/accessibility.js', + // 'protractor/i18n.js' + // ], + + // embedding: [ + // 'protractor/embedding.js' + // ] }, // ----- Capabilities to be passed to the webdriver instance ---- From a4b64b82e4d4a71583df324a8a53db02ba075847 Mon Sep 17 00:00:00 2001 From: Arunabh98 Date: Sun, 27 Aug 2017 10:16:22 +0530 Subject: [PATCH 59/65] Remve unintended changes. --- core/tests/protractor.conf.js | 95 +++++++++++++++++------------------ 1 file changed, 47 insertions(+), 48 deletions(-) diff --git a/core/tests/protractor.conf.js b/core/tests/protractor.conf.js index ca8b2fa4d113..c7a5c53959ac 100755 --- a/core/tests/protractor.conf.js +++ b/core/tests/protractor.conf.js @@ -57,57 +57,56 @@ exports.config = { // with --suite=smoke, only the patterns matched by that suite will run. suites: { full: [ - // 'protractor/*.js' + 'protractor/*.js' + ], + + mainEditor: [ + 'protractor/editorAndPlayer.js', + 'protractor/stateEditor.js', + 'protractor/explorationFeedback.js' + ], + + editorFeatures: [ + 'protractor/gadgetEditor.js', + 'protractor/historyTab.js', + 'protractor/parameters.js' + ], + + extensions: [ + 'protractor/richTextComponents.js', + 'protractor/interactions.js' + ], + + library: [ + 'protractor/explorationRating.js', + 'protractor/privileges.js', 'protractor/libraryPagesTour.js', + 'protractor/publicationAndLibrary.js' + ], + + learnerDashboard: [ + 'protractor/learnerDashboard.js', + ], + + users: [ + 'protractor/userManagement.js', + 'protractor/loginFlow.js', + 'protractor/subscriptions.js', + 'protractor/preferences.js' + ], + + misc: [ + 'protractor/suggestions.js', + 'protractor/cacheSlugs.js', + 'protractor/staticPagesTour.js', + 'protractor/collections.js', + 'protractor/accessibility.js', + 'protractor/i18n.js' ], - // mainEditor: [ - // 'protractor/editorAndPlayer.js', - // 'protractor/stateEditor.js', - // 'protractor/explorationFeedback.js' - // ], - - // editorFeatures: [ - // 'protractor/gadgetEditor.js', - // 'protractor/historyTab.js', - // 'protractor/parameters.js' - // ], - - // extensions: [ - // 'protractor/richTextComponents.js', - // 'protractor/interactions.js' - // ], - - // library: [ - // 'protractor/explorationRating.js', - // 'protractor/privileges.js', - // 'protractor/libraryPagesTour.js', - // 'protractor/publicationAndLibrary.js' - // ], - - // learnerDashboard: [ - // 'protractor/learnerDashboard.js', - // ], - - // users: [ - // 'protractor/userManagement.js', - // 'protractor/loginFlow.js', - // 'protractor/subscriptions.js', - // 'protractor/preferences.js' - // ], - - // misc: [ - // 'protractor/suggestions.js', - // 'protractor/cacheSlugs.js', - // 'protractor/staticPagesTour.js', - // 'protractor/collections.js', - // 'protractor/accessibility.js', - // 'protractor/i18n.js' - // ], - - // embedding: [ - // 'protractor/embedding.js' - // ] + embedding: [ + 'protractor/embedding.js' + ] }, // ----- Capabilities to be passed to the webdriver instance ---- From fec579a91e1cf81d22504ec6769b67aae19fcf37 Mon Sep 17 00:00:00 2001 From: Arunabh98 Date: Sun, 27 Aug 2017 14:06:19 +0530 Subject: [PATCH 60/65] Address review comments 4. --- .../components/summary_tile/CollectionSummaryTileDirective.js | 3 ++- .../summary_tile/ExplorationSummaryTileDirective.js | 3 ++- .../summary_tile/collection_summary_tile_directive.html | 2 +- .../summary_tile/exploration_summary_tile_directive.html | 2 +- .../head/pages/library/ActivityTilesInfinityGridDirective.js | 1 - core/templates/dev/head/pages/library/Library.js | 1 - .../pages/library/activity_tiles_infinity_grid_directive.html | 4 ++-- core/templates/dev/head/pages/library/library.html | 4 ++-- 8 files changed, 10 insertions(+), 10 deletions(-) diff --git a/core/templates/dev/head/components/summary_tile/CollectionSummaryTileDirective.js b/core/templates/dev/head/components/summary_tile/CollectionSummaryTileDirective.js index 63cc4349319b..ecfc3a85a1e1 100644 --- a/core/templates/dev/head/components/summary_tile/CollectionSummaryTileDirective.js +++ b/core/templates/dev/head/components/summary_tile/CollectionSummaryTileDirective.js @@ -36,7 +36,7 @@ oppia.directive('collectionSummaryTile', [ isLinkedToEditorPage: '=?isLinkedToEditorPage', getCategory: '&category', isPlaylistMode: '&playlistMode', - showLearnerDashboardIcons: '&showLearnerDashboardIcons' + showLearnerDashboardIconsIfPossible: '&showLearnerDashboardIconsIfPossible' }, templateUrl: UrlInterpolationService.getDirectiveTemplateUrl( '/components/summary_tile/' + @@ -46,6 +46,7 @@ oppia.directive('collectionSummaryTile', [ 'COLLECTION_VIEWER_URL', 'COLLECTION_EDITOR_URL', function($scope, oppiaDatetimeFormatter, COLLECTION_VIEWER_URL, COLLECTION_EDITOR_URL) { + $scope.userIsLoggedIn = GLOBALS.userIsLoggedIn; $scope.DEFAULT_EMPTY_TITLE = 'Untitled'; $scope.ACTIVITY_TYPE_COLLECTION = constants.ACTIVITY_TYPE_COLLECTION; diff --git a/core/templates/dev/head/components/summary_tile/ExplorationSummaryTileDirective.js b/core/templates/dev/head/components/summary_tile/ExplorationSummaryTileDirective.js index 21cc4b22d2e1..48e46e0ffab5 100644 --- a/core/templates/dev/head/components/summary_tile/ExplorationSummaryTileDirective.js +++ b/core/templates/dev/head/components/summary_tile/ExplorationSummaryTileDirective.js @@ -45,7 +45,7 @@ oppia.directive('explorationSummaryTile', [ // desktop version of the summary tile is always displayed. mobileCutoffPx: '@mobileCutoffPx', isPlaylistMode: '&playlistMode', - showLearnerDashboardIcons: '&showLearnerDashboardIcons' + showLearnerDashboardIconsIfPossible: '&showLearnerDashboardIconsIfPossible' }, templateUrl: UrlInterpolationService.getDirectiveTemplateUrl( '/components/summary_tile/' + @@ -84,6 +84,7 @@ oppia.directive('explorationSummaryTile', [ $scope, $http, oppiaDatetimeFormatter, RatingComputationService, windowDimensionsService) { + $scope.userIsLoggedIn = GLOBALS.userIsLoggedIn; $scope.ACTIVITY_TYPE_EXPLORATION = ( constants.ACTIVITY_TYPE_EXPLORATION); var contributorsSummary = $scope.getContributorsSummary() || {}; diff --git a/core/templates/dev/head/components/summary_tile/collection_summary_tile_directive.html b/core/templates/dev/head/components/summary_tile/collection_summary_tile_directive.html index 3b65c54cf9e8..e48ed4016bf0 100644 --- a/core/templates/dev/head/components/summary_tile/collection_summary_tile_directive.html +++ b/core/templates/dev/head/components/summary_tile/collection_summary_tile_directive.html @@ -1,4 +1,4 @@ - diff --git a/core/templates/dev/head/pages/library/library.html b/core/templates/dev/head/pages/library/library.html index 443063356dfb..11aea2c6e838 100644 --- a/core/templates/dev/head/pages/library/library.html +++ b/core/templates/dev/head/pages/library/library.html @@ -126,7 +126,7 @@

+ show-learner-dashboard-icons-if-possible="true"> + show-learner-dashboard-icons-if-possible="true"> From e0d7e7d9b93eed8b68530d58b2e5e600c1ad3a22 Mon Sep 17 00:00:00 2001 From: Arunabh98 Date: Sun, 27 Aug 2017 14:10:36 +0530 Subject: [PATCH 61/65] Fix lint errors. --- .../components/summary_tile/ExplorationSummaryTileDirective.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/core/templates/dev/head/components/summary_tile/ExplorationSummaryTileDirective.js b/core/templates/dev/head/components/summary_tile/ExplorationSummaryTileDirective.js index 48e46e0ffab5..deb3e101056b 100644 --- a/core/templates/dev/head/components/summary_tile/ExplorationSummaryTileDirective.js +++ b/core/templates/dev/head/components/summary_tile/ExplorationSummaryTileDirective.js @@ -45,7 +45,8 @@ oppia.directive('explorationSummaryTile', [ // desktop version of the summary tile is always displayed. mobileCutoffPx: '@mobileCutoffPx', isPlaylistMode: '&playlistMode', - showLearnerDashboardIconsIfPossible: '&showLearnerDashboardIconsIfPossible' + showLearnerDashboardIconsIfPossible: ( + '&showLearnerDashboardIconsIfPossible') }, templateUrl: UrlInterpolationService.getDirectiveTemplateUrl( '/components/summary_tile/' + From c53fc5b8f71ac85cf0b6f52dce33d61d7f80aec7 Mon Sep 17 00:00:00 2001 From: Arunabh98 Date: Sun, 27 Aug 2017 14:11:16 +0530 Subject: [PATCH 62/65] Fix more lint errors. --- .../components/summary_tile/CollectionSummaryTileDirective.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/core/templates/dev/head/components/summary_tile/CollectionSummaryTileDirective.js b/core/templates/dev/head/components/summary_tile/CollectionSummaryTileDirective.js index ecfc3a85a1e1..4c8a0f8674ea 100644 --- a/core/templates/dev/head/components/summary_tile/CollectionSummaryTileDirective.js +++ b/core/templates/dev/head/components/summary_tile/CollectionSummaryTileDirective.js @@ -36,7 +36,8 @@ oppia.directive('collectionSummaryTile', [ isLinkedToEditorPage: '=?isLinkedToEditorPage', getCategory: '&category', isPlaylistMode: '&playlistMode', - showLearnerDashboardIconsIfPossible: '&showLearnerDashboardIconsIfPossible' + showLearnerDashboardIconsIfPossible: ( + '&showLearnerDashboardIconsIfPossible') }, templateUrl: UrlInterpolationService.getDirectiveTemplateUrl( '/components/summary_tile/' + From 921c5866c418fb3d590a31fcff7e9ae0d391f56d Mon Sep 17 00:00:00 2001 From: Arunabh98 Date: Sun, 27 Aug 2017 15:23:53 +0530 Subject: [PATCH 63/65] Changed another translation file to account for the new keys. --- assets/i18n/it.json | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/assets/i18n/it.json b/assets/i18n/it.json index 0a2b91f42662..e4e0929bdcbb 100644 --- a/assets/i18n/it.json +++ b/assets/i18n/it.json @@ -140,14 +140,10 @@ "I18N_LANGUAGE_FOOTER_VIEW_IN": "Vedi Oppia in:", "I18N_LEARNER_DASHBOARD_COMPLETED_SECTION": "Completato", "I18N_LEARNER_DASHBOARD_COMPLETED_TO_INCOMPLETE_COLLECTIONS": "<[numberMoved]> delle collezioni che hai completato sono state spostate nella sezione 'in avanzamento' perchè nuove esplorazioni sono state aggiunte!", - "I18N_LEARNER_DASHBOARD_DELETED_COMPLETED_COLLECTION": "<[numberDeleted]> delle collezioni che hai completato sono state recentemente cancellate. Ci scusiamo per il disagio.", - "I18N_LEARNER_DASHBOARD_DELETED_COMPLETED_COLLECTIONS": "<[numberDeleted]> delle collezioni che hai completato sono state recentemente cancellate. Ci scusiamo per il disagio", - "I18N_LEARNER_DASHBOARD_DELETED_COMPLETED_EXPLORATION": "<[numberDeleted]> delle esplorazioni che hai completato sono state recentemente cancellate. Ci scusiamo per il disagio", - "I18N_LEARNER_DASHBOARD_DELETED_COMPLETED_EXPLORATIONS": "<[numberDeleted]> delle esplorazioni che hai completato sono state recentemente cancellate. Ci scusiamo per il disagio", - "I18N_LEARNER_DASHBOARD_DELETED_INCOMPLETE_COLLECTION": "<[numberDeleted]> delle collezioni in avanzamento sono state recentemente cancellate. Ci scusiamo per il disagio", - "I18N_LEARNER_DASHBOARD_DELETED_INCOMPLETE_COLLECTIONS": "<[numberDeleted]> delle collezioni in avanzamento sono state recentemente cancellate. Ci scusiamo per il disagio", - "I18N_LEARNER_DASHBOARD_DELETED_INCOMPLETE_EXPLORATION": "<[numberDeleted]> delle esplorazioni in avanzamento sono state recentemente cancellate. Ci scusiamo per il disagio", - "I18N_LEARNER_DASHBOARD_DELETED_INCOMPLETE_EXPLORATIONS": " <[numberDeleted]> delle esplorazioni in avanzamento sono state recentemente cancellate. Ci scusiamo per il disagio", + "I18N_LEARNER_DASHBOARD_DELETED_COMPLETED_COLLECTIONS": "{numberDeleted, plural, one{1 delle collezioni che hai completato sono state recentemente cancellate. Ci scusiamo per il disagio} other{# delle collezioni che hai completato sono state recentemente cancellate. Ci scusiamo per il disagio}}", + "I18N_LEARNER_DASHBOARD_DELETED_COMPLETED_EXPLORATIONS": "{numberDeleted, plural, one{1 delle esplorazioni che hai completato sono state recentemente cancellate. Ci scusiamo per il disagio} other{# delle esplorazioni che hai completato sono state recentemente cancellate. Ci scusiamo per il disagio}}", + "I18N_LEARNER_DASHBOARD_DELETED_INCOMPLETE_COLLECTIONS": "{numberDeleted, plural, one{1 delle collezioni in avanzamento sono state recentemente cancellate. Ci scusiamo per il disagio} other{# delle collezioni in avanzamento sono state recentemente cancellate. Ci scusiamo per il disagio}}", + "I18N_LEARNER_DASHBOARD_DELETED_INCOMPLETE_EXPLORATIONS": "{numberDeleted, plural, one{1 delle esplorazioni in avanzamento sono state recentemente cancellate. Ci scusiamo per il disagio} other{# delle esplorazioni in avanzamento sono state recentemente cancellate. Ci scusiamo per il disagio}}", "I18N_LEARNER_DASHBOARD_EMPTY_COMPLETED_COLLECTIONS": "Sembra che tu non abbia ancora completato alcuna collezione. Torna alla libreria per iniziare una nuova entusiasmante collezione!", "I18N_LEARNER_DASHBOARD_EMPTY_COMPLETED_EXPLORATIONS": "Sembra che tu non abbia ancora completato alcuna esplorazione. Torna alla libreria per iniziare una nuova entusiasmante esplorazione!", "I18N_LEARNER_DASHBOARD_EMPTY_FEEDBACK_THREADS": "Sembra che tu non abbia ancora inserito alcun feedback attivo. I tuoi feedback ci aiutano a migliorare la qualità delle nostre lezioni. Torna alla libreria per imparare qualcosa di entusiasmante e invia i tuoi preziosi feedback!", From 129952332e5165d63a47614f16c0c689ad184ab7 Mon Sep 17 00:00:00 2001 From: Arunabh98 Date: Mon, 28 Aug 2017 05:07:23 +0530 Subject: [PATCH 64/65] Address review comments 4 --- core/domain/learner_progress_services.py | 13 +- .../CollectionSummaryTileDirective.js | 13 +- .../ExplorationSummaryTileDirective.js | 7 +- .../collection_summary_tile_directive.html | 14 +- .../exploration_summary_tile_directive.html | 12 +- ...FeedbackMessageSummaryObjectFactorySpec.js | 2 +- ...earnerDashboardActivityIdsObjectFactory.js | 56 ++++++- ...erDashboardActivityIdsObjectFactorySpec.js | 138 ++++++++++++++++++ .../LearnerDashboardIconsDirective.js | 72 +++++++-- .../LearnerPlaylistService.js | 9 +- .../learner_dashboard_icons_directive.html | 8 +- .../learner_dashboard/LearnerDashboard.js | 20 +-- .../learner_dashboard/learner_dashboard.html | 30 ++-- 13 files changed, 317 insertions(+), 77 deletions(-) create mode 100644 core/templates/dev/head/domain/learner_dashboard/LearnerDashboardActivityIdsObjectFactorySpec.js diff --git a/core/domain/learner_progress_services.py b/core/domain/learner_progress_services.py index 7f89be74eb58..6cc268c1fbb4 100644 --- a/core/domain/learner_progress_services.py +++ b/core/domain/learner_progress_services.py @@ -960,10 +960,10 @@ def get_activity_progress(user_id): user_id: str. The id of the learner. Returns: - LearnerProgress. The learner progress domain object corresponding to the - particular learner. - dict. The numbers of the activities that are no longer present. It - contains four keys: + (LearnerProgress, dict, list(str)). The first return value is the + learner progress domain object corresponding to the particular + learner. The second return value is the numbers of the activities + that are no longer present. It contains four keys: - incomplete_explorations: int. The number of incomplete explorations no longer present. - incomplete_collections: int. The number of incomplete collections @@ -972,9 +972,8 @@ def get_activity_progress(user_id): no longer present. - completed_collections: int. The number of completed collections no longer present. - list(str). The titles of the collections to which new explorations have - been added. - + The third return valus is the titles of the collections to which new + explorations have been added. """ activity_ids_in_learner_dashboard = ( get_learner_dashboard_activities(user_id)) diff --git a/core/templates/dev/head/components/summary_tile/CollectionSummaryTileDirective.js b/core/templates/dev/head/components/summary_tile/CollectionSummaryTileDirective.js index 4c8a0f8674ea..c2137bb694f0 100644 --- a/core/templates/dev/head/components/summary_tile/CollectionSummaryTileDirective.js +++ b/core/templates/dev/head/components/summary_tile/CollectionSummaryTileDirective.js @@ -35,7 +35,7 @@ oppia.directive('collectionSummaryTile', [ getThumbnailBgColor: '&thumbnailBgColor', isLinkedToEditorPage: '=?isLinkedToEditorPage', getCategory: '&category', - isPlaylistMode: '&playlistMode', + isPlaylistTile: '&playlistTile', showLearnerDashboardIconsIfPossible: ( '&showLearnerDashboardIconsIfPossible') }, @@ -44,9 +44,9 @@ oppia.directive('collectionSummaryTile', [ 'collection_summary_tile_directive.html'), controller: [ '$scope', 'oppiaDatetimeFormatter', - 'COLLECTION_VIEWER_URL', 'COLLECTION_EDITOR_URL', function($scope, - oppiaDatetimeFormatter, COLLECTION_VIEWER_URL, - COLLECTION_EDITOR_URL) { + 'COLLECTION_VIEWER_URL', 'COLLECTION_EDITOR_URL', function( + $scope, oppiaDatetimeFormatter, + COLLECTION_VIEWER_URL, COLLECTION_EDITOR_URL) { $scope.userIsLoggedIn = GLOBALS.userIsLoggedIn; $scope.DEFAULT_EMPTY_TITLE = 'Untitled'; $scope.ACTIVITY_TYPE_COLLECTION = constants.ACTIVITY_TYPE_COLLECTION; @@ -76,9 +76,8 @@ oppia.directive('collectionSummaryTile', [ return UrlInterpolationService.getStaticImageUrl(url); }; - $scope.collectionIsActive = false; - $scope.toggleCollectionIsActive = function() { - $scope.collectionIsActive = !$scope.collectionIsActive; + $scope.setHoverState = function(hoverState) { + $scope.collectionIsCurrentlyHoveredOver = hoverState; }; } ] diff --git a/core/templates/dev/head/components/summary_tile/ExplorationSummaryTileDirective.js b/core/templates/dev/head/components/summary_tile/ExplorationSummaryTileDirective.js index deb3e101056b..c788c5525496 100644 --- a/core/templates/dev/head/components/summary_tile/ExplorationSummaryTileDirective.js +++ b/core/templates/dev/head/components/summary_tile/ExplorationSummaryTileDirective.js @@ -44,7 +44,7 @@ oppia.directive('explorationSummaryTile', [ // if it is not specified, it is treated as 0, which means that the // desktop version of the summary tile is always displayed. mobileCutoffPx: '@mobileCutoffPx', - isPlaylistMode: '&playlistMode', + isPlaylistTile: '&playlistTile', showLearnerDashboardIconsIfPossible: ( '&showLearnerDashboardIconsIfPossible') }, @@ -118,9 +118,8 @@ oppia.directive('explorationSummaryTile', [ $scope.MAX_AVATARS_TO_DISPLAY = 5; - $scope.explorationIsActive = false; - $scope.toggleExplorationIsActive = function() { - $scope.explorationIsActive = !$scope.explorationIsActive; + $scope.setHoverState = function(hoverState) { + $scope.explorationIsCurrentlyHoveredOver = hoverState; }; $scope.getAverageRating = function() { diff --git a/core/templates/dev/head/components/summary_tile/collection_summary_tile_directive.html b/core/templates/dev/head/components/summary_tile/collection_summary_tile_directive.html index e48ed4016bf0..1368512eb813 100644 --- a/core/templates/dev/head/components/summary_tile/collection_summary_tile_directive.html +++ b/core/templates/dev/head/components/summary_tile/collection_summary_tile_directive.html @@ -2,20 +2,20 @@ activity-type="ACTIVITY_TYPE_COLLECTION" activity-id="getCollectionId()" activity-title="getCollectionTitle()" - activity-active="collectionIsActive"> + activity-active="collectionIsCurrentlyHoveredOver">
- <[getCategory()]> -

<[getCollectionTitle() || DEFAULT_EMPTY_TITLE]>

+ <[getCategory()]> +

<[getCollectionTitle() || DEFAULT_EMPTY_TITLE]>

-
+
<[getObjective() | truncateAndCapitalize: 95]> No objective specified. @@ -34,7 +34,7 @@

-
+
diff --git a/core/templates/dev/head/components/summary_tile/exploration_summary_tile_directive.html b/core/templates/dev/head/components/summary_tile/exploration_summary_tile_directive.html index 268bb89cc338..1834851c45e9 100644 --- a/core/templates/dev/head/components/summary_tile/exploration_summary_tile_directive.html +++ b/core/templates/dev/head/components/summary_tile/exploration_summary_tile_directive.html @@ -2,15 +2,15 @@ activity-type="ACTIVITY_TYPE_EXPLORATION" activity-id="getExplorationId()" activity-title="getExplorationTitle()" - activity-active="explorationIsActive"> + activity-active="explorationIsCurrentlyHoveredOver"> -
- <[getCategory()]> -

+ <[getCategory()]> +

<[getExplorationTitle()|truncate:40]> <[getExplorationTitle()|truncate:40]>

@@ -27,7 +27,7 @@

+
<[getObjective() | truncateAndCapitalize: 95]> diff --git a/core/templates/dev/head/domain/feedback_message/FeedbackMessageSummaryObjectFactorySpec.js b/core/templates/dev/head/domain/feedback_message/FeedbackMessageSummaryObjectFactorySpec.js index 131f6e13e411..5bc71a952729 100644 --- a/core/templates/dev/head/domain/feedback_message/FeedbackMessageSummaryObjectFactorySpec.js +++ b/core/templates/dev/head/domain/feedback_message/FeedbackMessageSummaryObjectFactorySpec.js @@ -49,7 +49,7 @@ describe('Feedback message object factory', function() { created_on: 1000 }; - feedbackMessageSummary = ( + var feedbackMessageSummary = ( FeedbackMessageSummaryObjectFactory.createFromBackendDict( messageSummary)); diff --git a/core/templates/dev/head/domain/learner_dashboard/LearnerDashboardActivityIdsObjectFactory.js b/core/templates/dev/head/domain/learner_dashboard/LearnerDashboardActivityIdsObjectFactory.js index 25f9c14e7cb5..a5c1a9a776f6 100644 --- a/core/templates/dev/head/domain/learner_dashboard/LearnerDashboardActivityIdsObjectFactory.js +++ b/core/templates/dev/head/domain/learner_dashboard/LearnerDashboardActivityIdsObjectFactory.js @@ -40,7 +40,61 @@ oppia.factory('LearnerDashboardActivityIdsObjectFactory', [function() { this.explorationPlaylistIds.indexOf(activityId) !== -1) { return true; } else { - false; + return false; + } + }); + + LearnerDashboardActivityIds.prototype.belongsToExplorationPlaylist = ( + function(explorationId) { + if (this.explorationPlaylistIds.indexOf(explorationId) !== -1) { + return true; + } else { + return false; + } + }); + + LearnerDashboardActivityIds.prototype.belongsToCollectionPlaylist = ( + function(collectionId) { + if (this.collectionPlaylistIds.indexOf(collectionId) !== -1) { + return true; + } else { + return false; + } + }); + + LearnerDashboardActivityIds.prototype.belongsToCompletedExplorations = ( + function(explorationId) { + if (this.completedExplorationIds.indexOf(explorationId) !== -1) { + return true; + } else { + return false; + } + }); + + LearnerDashboardActivityIds.prototype.belongsToCompletedCollections = ( + function(collectionId) { + if (this.completedCollectionIds.indexOf(collectionId) !== -1) { + return true; + } else { + return false; + } + }); + + LearnerDashboardActivityIds.prototype.belongsToIncompleteExplorations = ( + function(explorationId) { + if (this.incompleteExplorationIds.indexOf(explorationId) !== -1) { + return true; + } else { + return false; + } + }); + + LearnerDashboardActivityIds.prototype.belongsToIncompleteCollections = ( + function(collectionId) { + if (this.incompleteCollectionIds.indexOf(collectionId) !== -1) { + return true; + } else { + return false; } }); diff --git a/core/templates/dev/head/domain/learner_dashboard/LearnerDashboardActivityIdsObjectFactorySpec.js b/core/templates/dev/head/domain/learner_dashboard/LearnerDashboardActivityIdsObjectFactorySpec.js new file mode 100644 index 000000000000..118ee7139e84 --- /dev/null +++ b/core/templates/dev/head/domain/learner_dashboard/LearnerDashboardActivityIdsObjectFactorySpec.js @@ -0,0 +1,138 @@ +// Copyright 2016 The Oppia Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS-IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/** + * @fileoverview Tests for LearnerDashboardActivityIdsObjectFactory. + */ + +describe('Learner dashboard activity ids object factory', function() { + var LearnerDashboardActivityIdsObjectFactory = null; + + beforeEach(module('oppia')); + + beforeEach(inject(function($injector) { + LearnerDashboardActivityIdsObjectFactory = $injector.get( + 'LearnerDashboardActivityIdsObjectFactory'); + })); + + var learnerDashboardActivityIdsDict = { + incomplete_exploration_ids: ['0', '1'], + incomplete_collection_ids: ['2', '3'], + completed_exploration_ids: ['4', '5'], + completed_collection_ids: ['6', '7'], + exploration_playlist_ids: ['8', '9'], + collection_playlist_ids: ['10', '11'] + }; + + it('should check if activity id is present among learner dashboard ' + + ' activity ids', function() { + var learnerDashboardActivityIds = ( + LearnerDashboardActivityIdsObjectFactory.createFromBackendDict( + learnerDashboardActivityIdsDict)); + + expect(learnerDashboardActivityIds.includesActivity('0')).toEqual(true); + expect(learnerDashboardActivityIds.includesActivity('1')).toEqual(true); + expect(learnerDashboardActivityIds.includesActivity('8')).toEqual(true); + + expect(learnerDashboardActivityIds.includesActivity('12')).toEqual(false); + expect(learnerDashboardActivityIds.includesActivity('13')).toEqual(false); + expect(learnerDashboardActivityIds.includesActivity('14')).toEqual(false); + }); + + + it('should add exploration to learner playlist', function() { + var learnerDashboardActivityIds = ( + LearnerDashboardActivityIdsObjectFactory.createFromBackendDict( + learnerDashboardActivityIdsDict)); + + learnerDashboardActivityIds.addToExplorationLearnerPlaylist('12'); + expect(learnerDashboardActivityIds.explorationPlaylistIds).toEqual( + ['8', '9', '12']); + + learnerDashboardActivityIds.addToExplorationLearnerPlaylist('13'); + expect(learnerDashboardActivityIds.explorationPlaylistIds).toEqual( + ['8', '9', '12', '13']); + }); + + it('should add collection to learner playlist', function() { + var learnerDashboardActivityIds = ( + LearnerDashboardActivityIdsObjectFactory.createFromBackendDict( + learnerDashboardActivityIdsDict)); + + learnerDashboardActivityIds.addToCollectionLearnerPlaylist('12'); + expect(learnerDashboardActivityIds.collectionPlaylistIds).toEqual( + ['10', '11', '12']); + + learnerDashboardActivityIds.addToCollectionLearnerPlaylist('13'); + expect(learnerDashboardActivityIds.collectionPlaylistIds).toEqual( + ['10', '11', '12', '13']); + }); + + it('should remove exploration from learner playlist', function() { + var learnerDashboardActivityIds = ( + LearnerDashboardActivityIdsObjectFactory.createFromBackendDict( + learnerDashboardActivityIdsDict)); + + learnerDashboardActivityIds.removeFromExplorationLearnerPlaylist('9'); + expect(learnerDashboardActivityIds.explorationPlaylistIds).toEqual( + ['8', '12', '13']); + + learnerDashboardActivityIds.removeFromExplorationLearnerPlaylist('8'); + expect(learnerDashboardActivityIds.explorationPlaylistIds).toEqual( + ['12', '13']); + }); + + it('should remove collection from learner playlist', function() { + var learnerDashboardActivityIds = ( + LearnerDashboardActivityIdsObjectFactory.createFromBackendDict( + learnerDashboardActivityIdsDict)); + + learnerDashboardActivityIds.removeFromCollectionLearnerPlaylist('11'); + expect(learnerDashboardActivityIds.collectionPlaylistIds).toEqual( + ['10', '12', '13']); + + learnerDashboardActivityIds.removeFromCollectionLearnerPlaylist('10'); + expect(learnerDashboardActivityIds.collectionPlaylistIds).toEqual( + ['12', '13']); + }); + + it('should fetch the learner dashboard activity ids domain object from the ' + + ' backend summary dict', function() { + var learnerDashboardActivityIdsDict = { + incomplete_exploration_ids: ['0', '1'], + incomplete_collection_ids: ['2', '3'], + completed_exploration_ids: ['4', '5'], + completed_collection_ids: ['6', '7'], + exploration_playlist_ids: ['8', '9'], + collection_playlist_ids: ['10', '11'] + }; + + var learnerDashboardActivityIds = ( + LearnerDashboardActivityIdsObjectFactory.createFromBackendDict( + learnerDashboardActivityIdsDict)); + + expect(learnerDashboardActivityIds.incompleteExplorationIds).toEqual( + ['0', '1']); + expect(learnerDashboardActivityIds.incompleteCollectionIds).toEqual( + ['2', '3']); + expect(learnerDashboardActivityIds.completedExplorationIds).toEqual( + ['4', '5']); + expect(learnerDashboardActivityIds.completedCollectionIds).toEqual( + ['6', '7']); + expect(learnerDashboardActivityIds.explorationPlaylistIds).toEqual( + ['8', '9']); + expect(learnerDashboardActivityIds.collectionPlaylistIds).toEqual( + ['10', '11']); + }); +}); diff --git a/core/templates/dev/head/domain/learner_dashboard/LearnerDashboardIconsDirective.js b/core/templates/dev/head/domain/learner_dashboard/LearnerDashboardIconsDirective.js index c988267c21f5..cdb0a02d9ced 100644 --- a/core/templates/dev/head/domain/learner_dashboard/LearnerDashboardIconsDirective.js +++ b/core/templates/dev/head/domain/learner_dashboard/LearnerDashboardIconsDirective.js @@ -33,13 +33,15 @@ oppia.directive('learnerDashboardIcons', [ '$scope', 'LearnerDashboardIdsBackendApiService', 'LearnerDashboardActivityIdsObjectFactory', 'LearnerPlaylistService', - function($scope, LearnerDashboardIdsBackendApiService, - LearnerDashboardActivityIdsObjectFactory, - LearnerPlaylistService) { - $scope.activityIsActive = true; + function( + $scope, LearnerDashboardIdsBackendApiService, + LearnerDashboardActivityIdsObjectFactory, + LearnerPlaylistService) { + $scope.activityIsCurrentlyHoveredOver = true; $scope.$watch('activityActive', function(value) { - $scope.activityIsActive = !$scope.activityIsActive; + $scope.activityIsCurrentlyHoveredOver = ( + !$scope.activityIsCurrentlyHoveredOver); }); LearnerDashboardIdsBackendApiService.fetchLearnerDashboardIds().then( @@ -50,8 +52,8 @@ oppia.directive('learnerDashboardIcons', [ } ); - $scope.toggleActivityIsActive = function(activityId) { - $scope.activityIsActive = !$scope.activityIsActive; + $scope.setHoverState = function(hoverState) { + $scope.activityIsCurrentlyHoveredOver = hoverState; }; $scope.canActivityBeAddedToLearnerPlaylist = function(activityId) { @@ -60,11 +62,62 @@ oppia.directive('learnerDashboardIcons', [ activityId)) { return false; } else { - return $scope.activityIsActive; + return $scope.activityIsCurrentlyHoveredOver; } } }; + $scope.belongsToLearnerPlaylist = function() { + var activityType = $scope.getActivityType(); + if ($scope.learnerDashboardActivityIds) { + /* eslint-disable max-len */ + if (activityType === constants.ACTIVITY_TYPE_EXPLORATION) { + return ( + $scope.learnerDashboardActivityIds.belongsToExplorationPlaylist( + $scope.getActivityId())); + } else if (activityType === constants.ACTIVITY_TYPE_COLLECTION) { + return ( + $scope.learnerDashboardActivityIds.belongsToCollectionPlaylist( + $scope.getActivityId())); + } + /* eslint-enable max-len */ + } + }; + + $scope.belongsToCompletedActivities = function() { + var activityType = $scope.getActivityType(); + if ($scope.learnerDashboardActivityIds) { + /* eslint-disable max-len */ + if (activityType === constants.ACTIVITY_TYPE_EXPLORATION) { + return ( + $scope.learnerDashboardActivityIds.belongsToCompletedExplorations( + $scope.getActivityId())); + } else if (activityType === constants.ACTIVITY_TYPE_COLLECTION) { + return ( + $scope.learnerDashboardActivityIds.belongsToCompletedCollections( + $scope.getActivityId())); + } + /* eslint-enable max-len */ + } + }; + + $scope.belongsToIncompleteActivities = function() { + var activityType = $scope.getActivityType(); + if ($scope.learnerDashboardActivityIds) { + /* eslint-disable max-len */ + if (activityType === constants.ACTIVITY_TYPE_EXPLORATION) { + return ( + $scope.learnerDashboardActivityIds.belongsToIncompleteExplorations( + $scope.getActivityId())); + } else if (activityType === constants.ACTIVITY_TYPE_COLLECTION) { + return ( + $scope.learnerDashboardActivityIds.belongsToIncompleteCollections( + $scope.getActivityId())); + } + /* eslint-enable max-len */ + } + }; + $scope.addToLearnerPlaylist = function(activityId, activityType) { var isSuccessfullyAdded = ( LearnerPlaylistService.addToLearnerPlaylist( @@ -88,8 +141,7 @@ oppia.directive('learnerDashboardIcons', [ activityId, activityTitle, activityType) { var isSuccessfullyRemoved = ( LearnerPlaylistService.removeFromLearnerPlaylist( - activityId, activityTitle, - activityType, + activityId, activityTitle, activityType, $scope.learnerDashboardActivityIds)); }; } diff --git a/core/templates/dev/head/domain/learner_dashboard/LearnerPlaylistService.js b/core/templates/dev/head/domain/learner_dashboard/LearnerPlaylistService.js index ebbcf578909e..450f1208d8b8 100644 --- a/core/templates/dev/head/domain/learner_dashboard/LearnerPlaylistService.js +++ b/core/templates/dev/head/domain/learner_dashboard/LearnerPlaylistService.js @@ -55,8 +55,8 @@ return successfullyAdded; }; - var _removeFromLearnerPlaylist = function(activityId, activityTitle, - activityType, learnerDashboardActivityIds) { + var _removeFromLearnerPlaylist = function( + activityId, activityTitle, activityType, learnerDashboardActivityIds) { $modal.open({ templateUrl: UrlInterpolationService.getDirectiveTemplateUrl( '/pages/learner_dashboard/' + @@ -71,9 +71,8 @@ } }, controller: [ - '$scope', '$modalInstance', '$http', - 'UrlInterpolationService', function($scope, $modalInstance, - $http, UrlInterpolationService) { + '$scope', '$modalInstance', '$http', 'UrlInterpolationService', + function($scope, $modalInstance, $http, UrlInterpolationService) { $scope.sectionNameI18nId = ( 'I18N_LEARNER_DASHBOARD_PLAYLIST_SECTION'); $scope.activityTitle = activityTitle; diff --git a/core/templates/dev/head/domain/learner_dashboard/learner_dashboard_icons_directive.html b/core/templates/dev/head/domain/learner_dashboard/learner_dashboard_icons_directive.html index d428ccca5e2a..d7c0f0ffcc95 100644 --- a/core/templates/dev/head/domain/learner_dashboard/learner_dashboard_icons_directive.html +++ b/core/templates/dev/head/domain/learner_dashboard/learner_dashboard_icons_directive.html @@ -1,23 +1,23 @@ diff --git a/core/templates/dev/head/pages/learner_dashboard/LearnerDashboard.js b/core/templates/dev/head/pages/learner_dashboard/LearnerDashboard.js index 2bc867682af1..8334524ac5e5 100644 --- a/core/templates/dev/head/pages/learner_dashboard/LearnerDashboard.js +++ b/core/templates/dev/head/pages/learner_dashboard/LearnerDashboard.js @@ -252,21 +252,18 @@ oppia.controller('LearnerDashboard', [ }; var getPlaylistSortableOptions = function(activityType) { - var windowScrollTop = ''; - var startSort = false; return { 'ui-floating': 'auto', start: function(e, ui) { - if(startSort){ - windowScrollTop = $(window).scrollTop(); - } - startSort = true; ui.placeholder.height(ui.item.height()); $scope.$apply(); }, sort: function (e, ui) { /* eslint-disable quote-props */ - ui.helper.css({'top': ui.position.top + windowScrollTop + 'px'}); + // Reset the position of the window on scrolling. This keeps the mouse + // position and elements in sync. + ui.helper.css( + {'top': ui.position.top + $(window).scrollTop() + 'px'}); /* eslint-enable quote-props */ }, update: function(e, ui) { @@ -412,8 +409,9 @@ oppia.controller('LearnerDashboard', [ }, controller: [ '$scope', '$modalInstance', '$http', 'sectionNameI18nId', - 'subsectionName', function($scope, $modalInstance, $http, - sectionNameI18nId, subsectionName) { + 'subsectionName', function( + $scope, $modalInstance, $http, sectionNameI18nId, + subsectionName) { $scope.sectionNameI18nId = sectionNameI18nId; $scope.subsectionName = subsectionName; $scope.activityTitle = activity.title; @@ -425,6 +423,8 @@ oppia.controller('LearnerDashboard', [ } else if (subsectionName === LEARNER_DASHBOARD_SUBSECTION_I18N_IDS.COLLECTIONS) { activityType = constants.ACTIVITY_TYPE_COLLECTION; + } else { + throw new Error('Subsection name is not valid.'); } var removeActivityUrlPrefix = ''; @@ -434,6 +434,8 @@ oppia.controller('LearnerDashboard', [ } else if (sectionNameI18nId === LEARNER_DASHBOARD_SECTION_I18N_IDS.INCOMPLETE) { removeActivityUrlPrefix = '/learnerincompleteactivityhandler/'; + } else { + throw new Error('Section name is not valid.'); } removeActivityUrl = ( diff --git a/core/templates/dev/head/pages/learner_dashboard/learner_dashboard.html b/core/templates/dev/head/pages/learner_dashboard/learner_dashboard.html index 5df34a45b8e7..f4378ba43bfd 100644 --- a/core/templates/dev/head/pages/learner_dashboard/learner_dashboard.html +++ b/core/templates/dev/head/pages/learner_dashboard/learner_dashboard.html @@ -359,19 +359,18 @@

<[subscriptionsList.length]>

ng-click="openRemoveActivityModal(activeSection, activeSubsection, tile)" tooltip="Remove" tooltip-placement="top"> - +
@@ -470,8 +469,7 @@

<[subscriptionsList.length]>

ng-click="openRemoveActivityModal(activeSection, activeSubsection, tile)" tooltip="Remove" tooltip-placement="top"> - <[subscriptionsList.length]>

category="tile.category" thumbnail-icon-url="tile.thumbnail_icon_url" thumbnail-bg-color="tile.thumbnail_bg_color" - playlist-mode="true"> + playlist-tile="true"> From ae86749979474e0b95bb54122e2335e7155a8921 Mon Sep 17 00:00:00 2001 From: Arunabh98 Date: Mon, 28 Aug 2017 08:26:55 +0530 Subject: [PATCH 65/65] Address review comments 5. --- core/domain/learner_progress_services.py | 2 +- .../summary_tile/CollectionSummaryTileDirective.js | 2 +- .../summary_tile/ExplorationSummaryTileDirective.js | 2 +- core/templates/dev/head/css/oppia.css | 4 ++-- .../learner_dashboard/LearnerDashboardIconsDirective.js | 9 ++++----- .../dev/head/pages/learner_dashboard/LearnerDashboard.js | 4 ++-- .../head/pages/learner_dashboard/learner_dashboard.html | 4 ++-- 7 files changed, 13 insertions(+), 14 deletions(-) diff --git a/core/domain/learner_progress_services.py b/core/domain/learner_progress_services.py index 6cc268c1fbb4..4627096342d0 100644 --- a/core/domain/learner_progress_services.py +++ b/core/domain/learner_progress_services.py @@ -972,7 +972,7 @@ def get_activity_progress(user_id): no longer present. - completed_collections: int. The number of completed collections no longer present. - The third return valus is the titles of the collections to which new + The third return value is the titles of the collections to which new explorations have been added. """ activity_ids_in_learner_dashboard = ( diff --git a/core/templates/dev/head/components/summary_tile/CollectionSummaryTileDirective.js b/core/templates/dev/head/components/summary_tile/CollectionSummaryTileDirective.js index c2137bb694f0..7b0554b9fa5a 100644 --- a/core/templates/dev/head/components/summary_tile/CollectionSummaryTileDirective.js +++ b/core/templates/dev/head/components/summary_tile/CollectionSummaryTileDirective.js @@ -35,7 +35,7 @@ oppia.directive('collectionSummaryTile', [ getThumbnailBgColor: '&thumbnailBgColor', isLinkedToEditorPage: '=?isLinkedToEditorPage', getCategory: '&category', - isPlaylistTile: '&playlistTile', + isPlaylistTile: '&isPlaylistTile', showLearnerDashboardIconsIfPossible: ( '&showLearnerDashboardIconsIfPossible') }, diff --git a/core/templates/dev/head/components/summary_tile/ExplorationSummaryTileDirective.js b/core/templates/dev/head/components/summary_tile/ExplorationSummaryTileDirective.js index c788c5525496..881b29694512 100644 --- a/core/templates/dev/head/components/summary_tile/ExplorationSummaryTileDirective.js +++ b/core/templates/dev/head/components/summary_tile/ExplorationSummaryTileDirective.js @@ -44,7 +44,7 @@ oppia.directive('explorationSummaryTile', [ // if it is not specified, it is treated as 0, which means that the // desktop version of the summary tile is always displayed. mobileCutoffPx: '@mobileCutoffPx', - isPlaylistTile: '&playlistTile', + isPlaylistTile: '&isPlaylistTile', showLearnerDashboardIconsIfPossible: ( '&showLearnerDashboardIconsIfPossible') }, diff --git a/core/templates/dev/head/css/oppia.css b/core/templates/dev/head/css/oppia.css index c2e593655924..e47068386586 100644 --- a/core/templates/dev/head/css/oppia.css +++ b/core/templates/dev/head/css/oppia.css @@ -3898,13 +3898,13 @@ md-card.preview-conversation-skin-supplemental-card { text-align: center; } -@media(max-width: 895px) { +@media (min-width: 744px) and (max-width: 895px) { .oppia-activity-summary-tile.oppia-activity-playlist-tile .summary-section { width: 55%; } } -@media(max-width: 743px) { +@media (min-width: 630px) and (max-width: 743px) { .oppia-activity-summary-tile.oppia-activity-playlist-tile .thumbnail-image { width: 45px; } diff --git a/core/templates/dev/head/domain/learner_dashboard/LearnerDashboardIconsDirective.js b/core/templates/dev/head/domain/learner_dashboard/LearnerDashboardIconsDirective.js index cdb0a02d9ced..4ea1ebb78d9b 100644 --- a/core/templates/dev/head/domain/learner_dashboard/LearnerDashboardIconsDirective.js +++ b/core/templates/dev/head/domain/learner_dashboard/LearnerDashboardIconsDirective.js @@ -34,14 +34,13 @@ oppia.directive('learnerDashboardIcons', [ 'LearnerDashboardActivityIdsObjectFactory', 'LearnerPlaylistService', function( - $scope, LearnerDashboardIdsBackendApiService, - LearnerDashboardActivityIdsObjectFactory, - LearnerPlaylistService) { + $scope, LearnerDashboardIdsBackendApiService, + LearnerDashboardActivityIdsObjectFactory, + LearnerPlaylistService) { $scope.activityIsCurrentlyHoveredOver = true; $scope.$watch('activityActive', function(value) { - $scope.activityIsCurrentlyHoveredOver = ( - !$scope.activityIsCurrentlyHoveredOver); + $scope.activityIsCurrentlyHoveredOver = $scope.activityActive; }); LearnerDashboardIdsBackendApiService.fetchLearnerDashboardIds().then( diff --git a/core/templates/dev/head/pages/learner_dashboard/LearnerDashboard.js b/core/templates/dev/head/pages/learner_dashboard/LearnerDashboard.js index 8334524ac5e5..706ca0e4ef20 100644 --- a/core/templates/dev/head/pages/learner_dashboard/LearnerDashboard.js +++ b/core/templates/dev/head/pages/learner_dashboard/LearnerDashboard.js @@ -410,8 +410,8 @@ oppia.controller('LearnerDashboard', [ controller: [ '$scope', '$modalInstance', '$http', 'sectionNameI18nId', 'subsectionName', function( - $scope, $modalInstance, $http, sectionNameI18nId, - subsectionName) { + $scope, $modalInstance, $http, sectionNameI18nId, + subsectionName) { $scope.sectionNameI18nId = sectionNameI18nId; $scope.subsectionName = subsectionName; $scope.activityTitle = activity.title; diff --git a/core/templates/dev/head/pages/learner_dashboard/learner_dashboard.html b/core/templates/dev/head/pages/learner_dashboard/learner_dashboard.html index f4378ba43bfd..cc52781f9e96 100644 --- a/core/templates/dev/head/pages/learner_dashboard/learner_dashboard.html +++ b/core/templates/dev/head/pages/learner_dashboard/learner_dashboard.html @@ -370,7 +370,7 @@

<[subscriptionsList.length]>

thumbnail-icon-url="tile.thumbnail_icon_url" thumbnail-bg-color="tile.thumbnail_bg_color" class="protractor-test-exp-summary-tile" - playlist-tile="true"> + is-playlist-tile="true"> @@ -478,7 +478,7 @@

<[subscriptionsList.length]>

category="tile.category" thumbnail-icon-url="tile.thumbnail_icon_url" thumbnail-bg-color="tile.thumbnail_bg_color" - playlist-tile="true"> + is-playlist-tile="true">