From 058e3a06d8726171f53f0533a081d75f8ec5cd34 Mon Sep 17 00:00:00 2001 From: Akshay Anand Date: Sat, 15 Sep 2018 14:20:33 +0530 Subject: [PATCH] UI modifications for the new editors and dashboard (#5601) * Made UI changes to skill and topic editors * made review and more ui changes * Fixed backend tests * Made more ui changes * lint fix * More ui changes * final ui changes * Made UI changes * made review changes * disabled flag * made code review changes * disabled flag * made review changes --- assets/i18n/en.json | 1 + assets/i18n/qqq.json | 1 + core/controllers/base.py | 2 + core/controllers/library_test.py | 1 + core/controllers/topic_editor.py | 6 +- core/controllers/topic_editor_test.py | 5 +- .../topics_and_skills_dashboard.py | 20 +++--- .../topics_and_skills_dashboard_test.py | 10 ++- core/domain/topic_services.py | 24 +++++-- core/domain/topic_services_test.py | 11 +++ .../head/components/SkillCreationService.js | 5 +- .../components/SummaryListHeaderDirective.js | 1 + .../summary_list_header_directive.html | 7 +- .../TopNavigationBarDirective.js | 1 + .../top_navigation_bar_directive.html | 6 ++ core/templates/dev/head/pages/base.html | 1 + .../SkillEditorNavbarBreadcrumbDirective.js | 40 +++++++++++ .../SkillEditorNavbarDirective.js | 2 + .../SkillDescriptionEditorDirective.js | 16 ++--- .../add_misconception_modal_directive.html | 5 +- .../misconception_editor_directive.html | 5 +- .../skill_concept_card_editor_directive.html | 54 ++++++++------- .../skill_description_editor_directive.html | 50 +++++++------- .../skill_editor_main_tab_directive.html | 2 +- ...skill_misconceptions_editor_directive.html | 29 ++++---- .../head/pages/skill_editor/skill_editor.html | 4 +- ...ll_editor_navbar_breadcrumb_directive.html | 6 ++ .../skill_editor_navbar_directive.html | 62 ++++++++--------- .../main_editor/TopicEditorTabDirective.js | 17 +---- .../topic_editor_tab_directive.html | 32 ++++----- .../SubtopicsListTabDirective.js | 42 +++++++++--- .../new_subtopic_title_modal_directive.html | 16 ++--- .../subtopic_editor_modal_directive.html | 59 ++++++++-------- .../subtopics_list_tab_directive.html | 42 +++++++++--- ...ic_editor_navbar_breadcrumb_directive.html | 2 +- .../topic_editor_navbar_directive.html | 68 ++++++++++--------- .../SelectTopicsDirective.js | 46 +++++++++++++ .../SkillsListDirective.js | 9 +++ .../TopicsAndSkillsDashboard.js | 45 ++++++++++-- ...TopicsAndSkillsDashboardNavbarDirective.js | 8 ++- .../TopicsListDirective.js | 4 -- ...assign_skill_to_topic_modal_directive.html | 17 +---- .../create_new_skill_modal_directive.html | 4 +- .../new_topic_name_editor_directive.html | 8 +-- .../select_topics_directive.html | 10 +++ .../skills_list_directive.html | 47 ++++++++++--- .../topics_and_skills_dashboard.html | 31 +++++++-- .../topics_list_directive.html | 49 +++++++++---- .../head/services/contextual/UrlService.js | 6 +- 49 files changed, 617 insertions(+), 322 deletions(-) create mode 100644 core/templates/dev/head/pages/skill_editor/SkillEditorNavbarBreadcrumbDirective.js create mode 100644 core/templates/dev/head/pages/skill_editor/skill_editor_navbar_breadcrumb_directive.html create mode 100644 core/templates/dev/head/pages/topics_and_skills_dashboard/SelectTopicsDirective.js create mode 100644 core/templates/dev/head/pages/topics_and_skills_dashboard/select_topics_directive.html diff --git a/assets/i18n/en.json b/assets/i18n/en.json index 47438e514864..f28503c22ac1 100644 --- a/assets/i18n/en.json +++ b/assets/i18n/en.json @@ -525,6 +525,7 @@ "I18N_TOPNAV_SIGN_IN": "Sign in", "I18N_TOPNAV_SIGN_IN_WITH_GOOGLE": "Sign in with Google", "I18N_TOPNAV_TEACH_WITH_OPPIA": "Teach with Oppia", + "I18N_TOPNAV_TOPICS_AND_SKILLS_DASHBOARD": "Topics and Skills Dashboard", "I18N_TOTAL_SUBSCRIBERS_TEXT": "You have a total of <[totalSubscribers]> subscribers.", "I18N_UNSUBSCRIBE_BUTTON_TEXT": "Unsubscribe", "I18N_WORKED_EXAMPLE": "Worked Example" diff --git a/assets/i18n/qqq.json b/assets/i18n/qqq.json index fc38c1442cd8..c33899659eeb 100644 --- a/assets/i18n/qqq.json +++ b/assets/i18n/qqq.json @@ -525,6 +525,7 @@ "I18N_TOPNAV_SIGN_IN": "Text displayed in the top right corner of the page. - When clicked, the user is redirected to the sign in page where he can access his account.\n{{Identical|Sign in}}", "I18N_TOPNAV_SIGN_IN_WITH_GOOGLE": "Text displayed inside the Sign In dropdown. - When clicked, the user is signed in with Google Oauth - The text in the button needs to be less than 25 characters long", "I18N_TOPNAV_TEACH_WITH_OPPIA": "Text displayed inside drop-down menu - The list is shown after the user hovers over the I18N_TOPNAV_ABOUT button. When the option is clicked, the teach with oppia page is loaded which contains information specific for teachers who would like to create explorations.", + "I18N_TOPNAV_TOPICS_AND_SKILLS_DASHBOARD": "Text displayed in the dropdown on the navbar for reaching the topics and skills dashboard.", "I18N_TOTAL_SUBSCRIBERS_TEXT": "Text displayed under the subscribers tab in creator dashboard. Tells the creator the total number of subscribers he/she has.", "I18N_UNSUBSCRIBE_BUTTON_TEXT": "The text that appears on the unsubscribe button, which allows users to unsubscribe from creators.\n{{Identical|Unsubscribe}}", "I18N_WORKED_EXAMPLE": "The text that is displayed on the button to view another worked example when a skill concept card is displayed in the exploration player." diff --git a/core/controllers/base.py b/core/controllers/base.py index da67f2de905f..3e18fd6fa08d 100755 --- a/core/controllers/base.py +++ b/core/controllers/base.py @@ -201,6 +201,8 @@ def __init__(self, request, response): # pylint: disable=super-init-not-called self.values['is_moderator'] = user_services.is_at_least_moderator( self.user_id) self.values['is_admin'] = user_services.is_admin(self.user_id) + self.values['is_topic_manager'] = ( + user_services.is_topic_manager(self.user_id)) self.values['is_super_admin'] = self.is_super_admin if self.request.get('payload'): diff --git a/core/controllers/library_test.py b/core/controllers/library_test.py index 51188170c348..395afd0e7c5c 100644 --- a/core/controllers/library_test.py +++ b/core/controllers/library_test.py @@ -55,6 +55,7 @@ def test_library_handler_demo_exploration(self): self.assertEqual({ 'iframed': False, 'is_admin': False, + 'is_topic_manager': False, 'is_moderator': False, 'is_super_admin': False, 'activity_list': [], diff --git a/core/controllers/topic_editor.py b/core/controllers/topic_editor.py index 9433f94d8053..27cc213d871c 100644 --- a/core/controllers/topic_editor.py +++ b/core/controllers/topic_editor.py @@ -42,7 +42,7 @@ class TopicEditorStoryHandler(base.BaseHandler): display in topic editor page. """ - @acl_decorators.can_edit_topic + @acl_decorators.can_view_any_topic_editor def get(self, topic_id): """Handles GET requests.""" @@ -97,7 +97,7 @@ class TopicEditorQuestionHandler(base.BaseHandler): summaries for display in topic editor page. """ - @acl_decorators.can_edit_topic + @acl_decorators.can_view_any_topic_editor def get(self, topic_id): """Handles GET requests.""" if not feconf.ENABLE_NEW_STRUCTURES: @@ -191,7 +191,7 @@ def _require_valid_version( 'which is too old. Please reload the page and try again.' % (subtopic_page_version, version_from_payload)) - @acl_decorators.can_edit_subtopic_page + @acl_decorators.can_view_any_topic_editor def get(self, topic_id, subtopic_id): """Handles GET requests.""" diff --git a/core/controllers/topic_editor_test.py b/core/controllers/topic_editor_test.py index c7b991c55a24..4b6b923b2f0a 100644 --- a/core/controllers/topic_editor_test.py +++ b/core/controllers/topic_editor_test.py @@ -118,9 +118,8 @@ def test_get(self): self.login(self.TOPIC_MANAGER_EMAIL) response = self.testapp.get( '%s/%s?cursor=' % ( - feconf.TOPIC_EDITOR_QUESTION_URL, self.topic_id - ), expect_errors=True) - self.assertEqual(response.status_int, 401) + feconf.TOPIC_EDITOR_QUESTION_URL, self.topic_id)) + self.assertEqual(response.status_int, 200) self.logout() topic_services.assign_role( diff --git a/core/controllers/topics_and_skills_dashboard.py b/core/controllers/topics_and_skills_dashboard.py index 75e1b511e2b1..484adffbf0f1 100644 --- a/core/controllers/topics_and_skills_dashboard.py +++ b/core/controllers/topics_and_skills_dashboard.py @@ -146,26 +146,24 @@ class NewSkillHandler(base.BaseHandler): def post(self): if not feconf.ENABLE_NEW_STRUCTURES: raise self.PageNotFoundException - topic_id = self.payload.get('topic_id') - - if topic_id is not None: - topic = topic_services.get_topic_by_id(topic_id, strict=False) - if topic is None: - raise self.InvalidInputException description = self.payload.get('description') + linked_topic_ids = self.payload.get('linked_topic_ids') + new_skill_id = skill_services.get_new_skill_id() + if linked_topic_ids is not None: + topics = topic_services.get_topics_by_ids(linked_topic_ids) + for topic in topics: + if topic is None: + raise self.InvalidInputException + topic_services.add_uncategorized_skill( + self.user_id, topic.id, new_skill_id) skill_domain.Skill.require_valid_description(description) - new_skill_id = skill_services.get_new_skill_id() skill = skill_domain.Skill.create_default_skill( new_skill_id, description) skill_services.save_new_skill(self.user_id, skill) - if topic_id is not None: - topic_services.add_uncategorized_skill( - self.user_id, topic_id, new_skill_id) - self.render_json({ 'skillId': new_skill_id }) diff --git a/core/controllers/topics_and_skills_dashboard_test.py b/core/controllers/topics_and_skills_dashboard_test.py index a7770a39fe02..a6e585fe7f29 100644 --- a/core/controllers/topics_and_skills_dashboard_test.py +++ b/core/controllers/topics_and_skills_dashboard_test.py @@ -169,7 +169,10 @@ def test_skill_creation_in_invalid_topic(self): json_response = self.post_json( '%s' % feconf.NEW_SKILL_URL, - {'description': 'Skill Description', 'topic_id': 'topic'}, + { + 'description': 'Skill Description', + 'linked_topic_ids': ['topic'] + }, csrf_token=csrf_token, expect_errors=True, expected_status_int=400) self.assertEqual(json_response['status_code'], 400) @@ -184,7 +187,10 @@ def test_skill_creation_in_valid_topic(self): json_response = self.post_json( '%s' % feconf.NEW_SKILL_URL, - {'description': 'Skill Description', 'topic_id': self.topic_id}, + { + 'description': 'Skill Description', + 'linked_topic_ids': [self.topic_id] + }, csrf_token=csrf_token) skill_id = json_response['skillId'] self.assertEqual(len(skill_id), 12) diff --git a/core/domain/topic_services.py b/core/domain/topic_services.py index dbf609600b5a..99a77bf3f03c 100644 --- a/core/domain/topic_services.py +++ b/core/domain/topic_services.py @@ -201,6 +201,23 @@ def get_topic_by_id(topic_id, strict=True, version=None): return None +def get_topics_by_ids(topic_ids): + """Returns a list of topics matching the IDs provided. + + Args: + topic_ids: list(str). List of IDs to get topics for. + + Returns: + list(Topic|None). The list of topics corresponding to given ids + (with None in place of topic ids corresponding to deleted topics). + """ + all_topic_models = topic_models.TopicModel.get_multi(topic_ids) + topics = [ + get_topic_from_model(topic_model) if topic_model is not None else None + for topic_model in all_topic_models] + return topics + + def get_topic_by_name(topic_name): """Returns a domain object representing a topic. @@ -625,6 +642,9 @@ def delete_topic(committer_id, topic_id, force_deletion=False): committer_id, feconf.COMMIT_MESSAGE_TOPIC_DELETED, force_deletion=force_deletion) + # Delete the summary of the topic (regardless of whether + # force_deletion is True or not). + delete_topic_summary(topic_id) topic_model = topic_models.TopicModel.get(topic_id) for subtopic in topic_model.subtopics: subtopic_page_services.delete_subtopic_page( @@ -638,10 +658,6 @@ def delete_topic(committer_id, topic_id, force_deletion=False): topic_memcache_key = _get_topic_memcache_key(topic_id) memcache_services.delete(topic_memcache_key) - # Delete the summary of the topic (regardless of whether - # force_deletion is True or not). - delete_topic_summary(topic_id) - def delete_topic_summary(topic_id): """Delete a topic summary model. diff --git a/core/domain/topic_services_test.py b/core/domain/topic_services_test.py index 140aa5c1872e..9bb5d1cc32e8 100644 --- a/core/domain/topic_services_test.py +++ b/core/domain/topic_services_test.py @@ -119,6 +119,17 @@ def test_get_topic_by_id(self): topic = topic_services.get_topic_by_id(self.TOPIC_ID) self.assertEqual(topic.to_dict(), expected_topic) + def test_get_topics_by_id(self): + expected_topic = self.topic.to_dict() + topics = topic_services.get_topics_by_ids([self.TOPIC_ID]) + self.assertEqual(topics[0].to_dict(), expected_topic) + self.assertEqual(len(topics), 1) + + topics = topic_services.get_topics_by_ids([self.TOPIC_ID, 'topic']) + self.assertEqual(topics[0].to_dict(), expected_topic) + self.assertIsNone(topics[1]) + self.assertEqual(len(topics), 2) + def test_commit_log_entry(self): topic_commit_log_entry = ( topic_models.TopicCommitLogEntryModel.get_commit(self.TOPIC_ID, 1) diff --git a/core/templates/dev/head/components/SkillCreationService.js b/core/templates/dev/head/components/SkillCreationService.js index b51452cb8bc5..a8f1a876ce87 100644 --- a/core/templates/dev/head/components/SkillCreationService.js +++ b/core/templates/dev/head/components/SkillCreationService.js @@ -27,7 +27,7 @@ oppia.factory('SkillCreationService', [ var skillCreationInProgress = false; return { - createNewSkill: function(description) { + createNewSkill: function(description, linkedTopicIds) { if (skillCreationInProgress) { return; } @@ -35,7 +35,8 @@ oppia.factory('SkillCreationService', [ AlertsService.clearWarnings(); $rootScope.loadingMessage = 'Creating skill'; $http.post('/skill_editor_handler/create_new', { - description: description + description: description, + linked_topic_ids: linkedTopicIds }).then(function(response) { $timeout(function() { $window.location = UrlInterpolationService.interpolateUrl( diff --git a/core/templates/dev/head/components/SummaryListHeaderDirective.js b/core/templates/dev/head/components/SummaryListHeaderDirective.js index 0faf5bd7b744..dae4a49bdd15 100644 --- a/core/templates/dev/head/components/SummaryListHeaderDirective.js +++ b/core/templates/dev/head/components/SummaryListHeaderDirective.js @@ -21,6 +21,7 @@ oppia.directive('summaryListHeader', [ return { restrict: 'E', scope: { + isSortingDisabled: '&disableSorting', getIndex: '&index', getSummary: '&summary', getShortSummary: '&shortSummary', diff --git a/core/templates/dev/head/components/summary_list_header_directive.html b/core/templates/dev/head/components/summary_list_header_directive.html index a97e8063f688..4df0d0e57941 100644 --- a/core/templates/dev/head/components/summary_list_header_directive.html +++ b/core/templates/dev/head/components/summary_list_header_directive.html @@ -14,10 +14,13 @@ summary-list-header .oppia-example-header-block { overflow: hidden; - padding-left: 24px; white-space: nowrap; } + summary-list-header .left-padding { + padding-left: 24px; + } + summary-list-header .oppia-example-header { float: left; overflow: hidden; @@ -34,7 +37,7 @@ } } -
+
<[getShortSummary()]> diff --git a/core/templates/dev/head/components/top_navigation_bar/TopNavigationBarDirective.js b/core/templates/dev/head/components/top_navigation_bar/TopNavigationBarDirective.js index e37689bd6416..46e973814a08 100644 --- a/core/templates/dev/head/components/top_navigation_bar/TopNavigationBarDirective.js +++ b/core/templates/dev/head/components/top_navigation_bar/TopNavigationBarDirective.js @@ -52,6 +52,7 @@ oppia.directive('topNavigationBar', [ $scope.profilePictureDataUrl = dataUrl; }); $scope.isAdmin = GLOBALS.isAdmin; + $scope.isTopicManager = GLOBALS.isTopicManager; $scope.isModerator = GLOBALS.isModerator; $scope.isSuperAdmin = GLOBALS.isSuperAdmin; $scope.logoutUrl = GLOBALS.logoutUrl; diff --git a/core/templates/dev/head/components/top_navigation_bar/top_navigation_bar_directive.html b/core/templates/dev/head/components/top_navigation_bar/top_navigation_bar_directive.html index 27aeee044883..58c44b16cffd 100644 --- a/core/templates/dev/head/components/top_navigation_bar/top_navigation_bar_directive.html +++ b/core/templates/dev/head/components/top_navigation_bar/top_navigation_bar_directive.html @@ -123,6 +123,12 @@ +
  • + + + +
  • diff --git a/core/templates/dev/head/pages/base.html b/core/templates/dev/head/pages/base.html index 92c2616e9192..02589f78bddd 100755 --- a/core/templates/dev/head/pages/base.html +++ b/core/templates/dev/head/pages/base.html @@ -91,6 +91,7 @@ SITE_FEEDBACK_FORM_URL: JSON.parse('{{SITE_FEEDBACK_FORM_URL|js_string}}'), iframed: JSON.parse('{{iframed|js_string}}'), isAdmin: JSON.parse('{{is_admin|js_string}}'), + isTopicManager: JSON.parse('{{is_topic_manager|js_string}}'), isModerator: JSON.parse('{{is_moderator|js_string}}'), isSuperAdmin: JSON.parse('{{is_super_admin|js_string}}'), loginUrl: JSON.parse('{{login_url|js_string}}'), diff --git a/core/templates/dev/head/pages/skill_editor/SkillEditorNavbarBreadcrumbDirective.js b/core/templates/dev/head/pages/skill_editor/SkillEditorNavbarBreadcrumbDirective.js new file mode 100644 index 000000000000..7fd9f3558dbf --- /dev/null +++ b/core/templates/dev/head/pages/skill_editor/SkillEditorNavbarBreadcrumbDirective.js @@ -0,0 +1,40 @@ +// 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 Controller for the navbar breadcrumb of the skill editor. + */ +oppia.directive('skillEditorNavbarBreadcrumb', [ + 'UrlInterpolationService', function(UrlInterpolationService) { + return { + restrict: 'E', + scope: {}, + templateUrl: UrlInterpolationService.getDirectiveTemplateUrl( + '/pages/skill_editor/skill_editor_navbar_breadcrumb_directive.html'), + controller: [ + '$scope', 'SkillEditorStateService', + function($scope, SkillEditorStateService) { + var skill = SkillEditorStateService.getSkill(); + $scope.getTruncatedDescription = function() { + var truncatedDescription = skill.getDescription().substr(0, 40); + if (skill.getDescription().length > 40) { + truncatedDescription += '...'; + } + return truncatedDescription; + }; + } + ] + }; + } +]); diff --git a/core/templates/dev/head/pages/skill_editor/SkillEditorNavbarDirective.js b/core/templates/dev/head/pages/skill_editor/SkillEditorNavbarDirective.js index 866424f2be03..1e6d9b6505a0 100644 --- a/core/templates/dev/head/pages/skill_editor/SkillEditorNavbarDirective.js +++ b/core/templates/dev/head/pages/skill_editor/SkillEditorNavbarDirective.js @@ -79,6 +79,7 @@ oppia.directive('skillEditorNavbar', [ $scope.skillRights.setPublic(); SkillEditorStateService.setSkillRights( $scope.skillRights); + AlertsService.addSuccessMessage('Skill Published.'); }); }; @@ -103,6 +104,7 @@ oppia.directive('skillEditorNavbar', [ modalInstance.result.then(function(commitMessage) { SkillEditorStateService.saveSkill(commitMessage); + AlertsService.addSuccessMessage('Changes Saved.'); }); }; diff --git a/core/templates/dev/head/pages/skill_editor/editor_tab/SkillDescriptionEditorDirective.js b/core/templates/dev/head/pages/skill_editor/editor_tab/SkillDescriptionEditorDirective.js index 2e9ba4f0f8cd..b51c24dbc208 100644 --- a/core/templates/dev/head/pages/skill_editor/editor_tab/SkillDescriptionEditorDirective.js +++ b/core/templates/dev/head/pages/skill_editor/editor_tab/SkillDescriptionEditorDirective.js @@ -32,25 +32,17 @@ oppia.directive('skillDescriptionEditor', [ '$scope', function($scope) { $scope.skill = SkillEditorStateService.getSkill(); + $scope.tmpSkillDescription = $scope.skill.getDescription(); $scope.skillRights = SkillEditorStateService.getSkillRights(); - $scope.skillDescriptionEditorIsShown = false; - - $scope.openSkillDescriptionEditor = function() { - if ($scope.canEditSkillDescription()) { - $scope.skillDescriptionEditorIsShown = true; - $scope.tmpSkillDescription = $scope.skill.getDescription(); - } - }; - - $scope.closeSkillDescriptionEditor = function() { - $scope.skillDescriptionEditorIsShown = false; - }; $scope.canEditSkillDescription = function() { return $scope.skillRights.canEditSkillDescription(); }; $scope.saveSkillDescription = function(newSkillDescription) { + if (newSkillDescription === $scope.skill.getDescription()) { + return; + } if (SkillObjectFactory.hasValidDescription( newSkillDescription)) { $scope.skillDescriptionEditorIsShown = false; diff --git a/core/templates/dev/head/pages/skill_editor/editor_tab/add_misconception_modal_directive.html b/core/templates/dev/head/pages/skill_editor/editor_tab/add_misconception_modal_directive.html index c9755113a056..fc0fd0b36a90 100644 --- a/core/templates/dev/head/pages/skill_editor/editor_tab/add_misconception_modal_directive.html +++ b/core/templates/dev/head/pages/skill_editor/editor_tab/add_misconception_modal_directive.html @@ -22,7 +22,10 @@

    Add Misconception

    Use a name that will be easy for question creators to understand.
  • - + + + Please use at most 30 characters. +
    diff --git a/core/templates/dev/head/pages/skill_editor/editor_tab/misconception_editor_directive.html b/core/templates/dev/head/pages/skill_editor/editor_tab/misconception_editor_directive.html index dfcdd11cfda2..f921c59aa9fd 100644 --- a/core/templates/dev/head/pages/skill_editor/editor_tab/misconception_editor_directive.html +++ b/core/templates/dev/head/pages/skill_editor/editor_tab/misconception_editor_directive.html @@ -31,7 +31,10 @@
    Misconception Name - + + + Please use at most 30 characters. +
    diff --git a/core/templates/dev/head/pages/skill_editor/editor_tab/skill_concept_card_editor_directive.html b/core/templates/dev/head/pages/skill_editor/editor_tab/skill_concept_card_editor_directive.html index 6a925112edba..bcd039aa33cf 100644 --- a/core/templates/dev/head/pages/skill_editor/editor_tab/skill_concept_card_editor_directive.html +++ b/core/templates/dev/head/pages/skill_editor/editor_tab/skill_concept_card_editor_directive.html @@ -1,15 +1,11 @@
    - Concept Card - + Review Material
    - This will be displayed to learners if they are having trouble with this particular skill during a practice test. - Give them a refresher by providing a review of the skill along with some worked examples. + This gives the learner a brief overview of how to perform the skill.
    - - Review Material -
    +
    +
    +
    +
    - Worked Examples -
    + +
    +
    +
    + Worked Examples +
    + These will be displayed one-by-one to the learner, in order, if they ask for them. +
    +
    +
    - - -
    - -
    -
    +
    diff --git a/core/templates/dev/head/pages/skill_editor/editor_tab/skill_description_editor_directive.html b/core/templates/dev/head/pages/skill_editor/editor_tab/skill_description_editor_directive.html index 31f68eb62187..fe9d6fecf885 100644 --- a/core/templates/dev/head/pages/skill_editor/editor_tab/skill_description_editor_directive.html +++ b/core/templates/dev/head/pages/skill_editor/editor_tab/skill_description_editor_directive.html @@ -1,30 +1,26 @@ -
    - - - <[skill.getDescription()]> -  - - - -
    - - - -
    -
    -
    -
    + +
    +
    + Skill Description +
    + This is the name of the skill as visible to learners and other creators. +
    +

    + + + Please use at most 40 characters. + +

    +
    +
    +
    diff --git a/core/templates/dev/head/pages/skill_editor/editor_tab/skill_editor_main_tab_directive.html b/core/templates/dev/head/pages/skill_editor/editor_tab/skill_editor_main_tab_directive.html index 5480b65e341e..69873859a35d 100644 --- a/core/templates/dev/head/pages/skill_editor/editor_tab/skill_editor_main_tab_directive.html +++ b/core/templates/dev/head/pages/skill_editor/editor_tab/skill_editor_main_tab_directive.html @@ -1,4 +1,4 @@ -
    +
    diff --git a/core/templates/dev/head/pages/skill_editor/editor_tab/skill_misconceptions_editor_directive.html b/core/templates/dev/head/pages/skill_editor/editor_tab/skill_misconceptions_editor_directive.html index d477e15db900..56d2c20c2f74 100644 --- a/core/templates/dev/head/pages/skill_editor/editor_tab/skill_misconceptions_editor_directive.html +++ b/core/templates/dev/head/pages/skill_editor/editor_tab/skill_misconceptions_editor_directive.html @@ -2,25 +2,26 @@
    Misconceptions -
    +
    - These are used to assist creators in writing answer groups of questions that test this skill. Question creators may tag each answer group with a misconception to better ensure that all misconceptions are addressed for the skill being tested. + These misconceptions represent common mistakes that are made by students when trying to apply this skill.
    -
    + diff --git a/core/templates/dev/head/pages/skill_editor/skill_editor.html b/core/templates/dev/head/pages/skill_editor/skill_editor.html index 3c697af181cf..c28afdfa639f 100644 --- a/core/templates/dev/head/pages/skill_editor/skill_editor.html +++ b/core/templates/dev/head/pages/skill_editor/skill_editor.html @@ -6,7 +6,8 @@ {% block navbar_breadcrumb %} - + + {% endblock navbar_breadcrumb %} {% block local_top_nav_options %} @@ -35,6 +36,7 @@ + diff --git a/core/templates/dev/head/pages/skill_editor/skill_editor_navbar_breadcrumb_directive.html b/core/templates/dev/head/pages/skill_editor/skill_editor_navbar_breadcrumb_directive.html new file mode 100644 index 000000000000..8130382da8c7 --- /dev/null +++ b/core/templates/dev/head/pages/skill_editor/skill_editor_navbar_breadcrumb_directive.html @@ -0,0 +1,6 @@ + diff --git a/core/templates/dev/head/pages/skill_editor/skill_editor_navbar_directive.html b/core/templates/dev/head/pages/skill_editor/skill_editor_navbar_directive.html index e2f2285db971..77dc775f249f 100644 --- a/core/templates/dev/head/pages/skill_editor/skill_editor_navbar_directive.html +++ b/core/templates/dev/head/pages/skill_editor/skill_editor_navbar_directive.html @@ -1,24 +1,17 @@
    diff --git a/core/templates/dev/head/pages/topic_editor/main_editor/TopicEditorTabDirective.js b/core/templates/dev/head/pages/topic_editor/main_editor/TopicEditorTabDirective.js index 6d631c73763d..1443bdbbf763 100644 --- a/core/templates/dev/head/pages/topic_editor/main_editor/TopicEditorTabDirective.js +++ b/core/templates/dev/head/pages/topic_editor/main_editor/TopicEditorTabDirective.js @@ -75,23 +75,10 @@ oppia.directive('topicMainEditor', [ $scope.topicDescriptionChanged = true; }; - $scope.openTopicNameEditor = function() { - if (!$scope.topicRights.canEditName()) { - return; - } - $scope.topicNameEditorIsShown = true; - $scope.editableName = $scope.topic.getName(); - }; - - $scope.closeTopicNameEditor = function() { - if (!$scope.topicRights.canEditName()) { + $scope.updateTopicName = function(newName) { + if (newName === $scope.topic.getName()) { return; } - $scope.topicNameEditorIsShown = false; - $scope.editableName = $scope.topic.getName(); - }; - - $scope.updateTopicName = function(newName) { TopicUpdateService.setTopicName($scope.topic, newName); $scope.topicNameEditorIsShown = false; }; diff --git a/core/templates/dev/head/pages/topic_editor/main_editor/topic_editor_tab_directive.html b/core/templates/dev/head/pages/topic_editor/main_editor/topic_editor_tab_directive.html index 876e115c7599..debf0278bad9 100644 --- a/core/templates/dev/head/pages/topic_editor/main_editor/topic_editor_tab_directive.html +++ b/core/templates/dev/head/pages/topic_editor/main_editor/topic_editor_tab_directive.html @@ -1,19 +1,13 @@
    - - <[topic.getName()]> -  - - - -
    - - - -
    + + + + Please use at most 20 characters for the topic name.
    @@ -21,10 +15,14 @@ + + Please use at most 120 characters for the topic description. + What does this topic contain? @@ -51,8 +49,8 @@

    diff --git a/core/templates/dev/head/pages/topic_editor/subtopics_editor/SubtopicsListTabDirective.js b/core/templates/dev/head/pages/topic_editor/subtopics_editor/SubtopicsListTabDirective.js index 890c7724d0a1..a111b2857946 100644 --- a/core/templates/dev/head/pages/topic_editor/subtopics_editor/SubtopicsListTabDirective.js +++ b/core/templates/dev/head/pages/topic_editor/subtopics_editor/SubtopicsListTabDirective.js @@ -38,6 +38,11 @@ oppia.directive('subtopicsListTab', [ var _initEditor = function() { $scope.topic = TopicEditorStateService.getTopic(); $scope.subtopics = $scope.topic.getSubtopics(); + $scope.subtopicTitles = []; + $scope.subtopics.forEach( + function(subtopic) { + return $scope.subtopicTitles.push(subtopic.getTitle()); + }); $scope.subtopicEditorIsShown = false; $scope.uncategorizedSkillSummaries = $scope.topic.getUncategorizedSkillSummaries(); @@ -47,6 +52,7 @@ oppia.directive('subtopicsListTab', [ var editableTitle = subtopic.getTitle(); TopicEditorStateService.loadSubtopicPage( $scope.topic.getId(), subtopic.getId()); + var subtopicTitles = $scope.subtopicTitles; var modalInstance = $uibModal.open({ templateUrl: UrlInterpolationService.getDirectiveTemplateUrl( '/pages/topic_editor/subtopics_editor/' + @@ -56,10 +62,12 @@ oppia.directive('subtopicsListTab', [ '$scope', '$uibModalInstance', function($scope, $uibModalInstance) { $scope.subtopicId = subtopic.getId(); + $scope.subtopicTitles = subtopicTitles; $scope.editableTitle = editableTitle; $scope.subtopicPage = TopicEditorStateService.getSubtopicPage(); $scope.htmlData = $scope.subtopicPage.getHtmlData(); + $scope.errorMsg = null; $scope.$on(EVENT_SUBTOPIC_PAGE_LOADED, function() { $scope.subtopicPage = TopicEditorStateService.getSubtopicPage(); @@ -73,8 +81,19 @@ oppia.directive('subtopicsListTab', [ }; $scope.updateSubtopicTitle = function(title) { + if (title === subtopic.getTitle()) { + return; + } + if ($scope.subtopicTitles.indexOf(title) !== -1) { + $scope.errorMsg = + 'A subtopic with this title already exists'; + return; + } $scope.editableTitle = title; - $scope.closeSubtopicTitleEditor(); + }; + + $scope.resetErrorMsg = function() { + $scope.errorMsg = null; }; $scope.updateHtmlData = function(htmlData) { @@ -82,17 +101,8 @@ oppia.directive('subtopicsListTab', [ $scope.openPreviewSubtopicPage(htmlData); }; - $scope.openSubtopicTitleEditor = function() { - $scope.subtopicTitleEditorIsShown = true; - }; - - $scope.closeSubtopicTitleEditor = function() { - $scope.subtopicTitleEditorIsShown = false; - }; - $scope.openPreviewSubtopicPage = function(htmlData) { $scope.subtopicEditorIsShown = false; - $scope.htmlData = htmlData; }; $scope.closePreviewSubtopicPage = function(previewHtmlData) { @@ -184,6 +194,7 @@ oppia.directive('subtopicsListTab', [ }; $scope.createSubtopic = function() { + var subtopicTitles = $scope.subtopicTitles; var modalInstance = $uibModal.open({ templateUrl: UrlInterpolationService.getDirectiveTemplateUrl( '/pages/topic_editor/subtopics_editor/' + @@ -193,10 +204,21 @@ oppia.directive('subtopicsListTab', [ '$scope', '$uibModalInstance', function($scope, $uibModalInstance) { $scope.subtopicTitle = ''; + $scope.subtopicTitles = subtopicTitles; + $scope.errorMsg = null; + + $scope.resetErrorMsg = function() { + $scope.errorMsg = null; + }; $scope.isSubtopicTitleEmpty = function(subtopicTitle) { return (subtopicTitle === ''); }; $scope.save = function(title) { + if ($scope.subtopicTitles.indexOf(title) !== -1) { + $scope.errorMsg = + 'A subtopic with this title already exists'; + return; + } $uibModalInstance.close(title); }; $scope.cancel = function() { diff --git a/core/templates/dev/head/pages/topic_editor/subtopics_editor/new_subtopic_title_modal_directive.html b/core/templates/dev/head/pages/topic_editor/subtopics_editor/new_subtopic_title_modal_directive.html index 19f3d89ab624..5ed513461772 100644 --- a/core/templates/dev/head/pages/topic_editor/subtopics_editor/new_subtopic_title_modal_directive.html +++ b/core/templates/dev/head/pages/topic_editor/subtopics_editor/new_subtopic_title_modal_directive.html @@ -3,16 +3,16 @@

    Enter Subtopic Title

    - - - diff --git a/core/templates/dev/head/pages/topics_and_skills_dashboard/create_new_skill_modal_directive.html b/core/templates/dev/head/pages/topics_and_skills_dashboard/create_new_skill_modal_directive.html index d19dd95fc0cc..df21fa8a78ee 100644 --- a/core/templates/dev/head/pages/topics_and_skills_dashboard/create_new_skill_modal_directive.html +++ b/core/templates/dev/head/pages/topics_and_skills_dashboard/create_new_skill_modal_directive.html @@ -3,10 +3,10 @@

    Create New Skill