Repository: oppia/oppia

Issue:
Split up the admin controller
The admin page is going to be the first de-facto example of how to split up a large controller into multiple directives and services. This will be used as a guide for other parts of the frontend refactoring project. The overall process used as part of this refactor is:
1. Minimize the HTML in the controller by reusing existing Jinja templates and directives as makes sense (this should only affect admin.html and not require any significant refactoring)
2. Extract major parts of the controller into isolated directives (and move dependent JS from the controller JS file to directive JS files)
3. Additional steps may need to be done to further split directives that are too large once they are pulled out of the controller
4. Functionality already implemented in the controller/directive JS files should be replaced with calls to existing services (possibly moving those services to the domain folder if they are in other pages/ directories)
5. Common functionality in the directive and controller JS files should be split into non-UI services
   Tests should be added for these services
6. If these services need to be used by other pages, they should be moved to domain/{directory}
7. Finally, if domain objects are needed they should be added to domain/{directory} and the services should be updated to use them

The admin page doesn't require all of the above steps, which means the collection editor and simple exploration editor will need to be used as examples for how some of other steps look (like creating domain object factories).



Discussion:

Resolving patch:
diff --git a/core/controllers/admin.py b/core/controllers/admin.py
--- a/core/controllers/admin.py
+++ b/core/controllers/admin.py
@@ -130,20 +130,10 @@ def post(self):
         try:
             if self.payload.get('action') == 'reload_exploration':
                 exploration_id = self.payload.get('exploration_id')
-                logging.info(
-                    '[ADMIN] %s reloaded exploration %s' %
-                    (self.user_id, exploration_id))
-                exp_services.load_demo(unicode(exploration_id))
-                rights_manager.release_ownership_of_exploration(
-                    feconf.SYSTEM_COMMITTER_ID, unicode(exploration_id))
+                self._reload_exploration(exploration_id)
             elif self.payload.get('action') == 'reload_collection':
                 collection_id = self.payload.get('collection_id')
-                logging.info(
-                    '[ADMIN] %s reloaded collection %s' %
-                    (self.user_id, collection_id))
-                collection_services.load_demo(unicode(collection_id))
-                rights_manager.release_ownership_of_collection(
-                    feconf.SYSTEM_COMMITTER_ID, unicode(collection_id))
+                self._reload_collection(collection_id)
             elif self.payload.get('action') == 'clear_search_index':
                 exp_services.clear_search_index()
             elif self.payload.get('action') == 'save_config_properties':
@@ -192,6 +182,28 @@ def post(self):
             self.render_json({'error': unicode(e)})
             raise
 
+    def _reload_exploration(self, exploration_id):
+        if feconf.DEV_MODE:
+            logging.info(
+                '[ADMIN] %s reloaded exploration %s' %
+                (self.user_id, exploration_id))
+            exp_services.load_demo(unicode(exploration_id))
+            rights_manager.release_ownership_of_exploration(
+                feconf.SYSTEM_COMMITTER_ID, unicode(exploration_id))
+        else:
+            raise Exception('Cannot reload an exploration in production.')
+
+    def _reload_collection(self, collection_id):
+        if feconf.DEV_MODE:
+            logging.info(
+                '[ADMIN] %s reloaded collection %s' %
+                (self.user_id, collection_id))
+            collection_services.load_demo(unicode(collection_id))
+            rights_manager.release_ownership_of_collection(
+                feconf.SYSTEM_COMMITTER_ID, unicode(collection_id))
+        else:
+            raise Exception('Cannot reload a collection in production.')
+
 
 class AdminJobOutput(base.BaseHandler):
     """Retrieves job output to show on the admin page."""


Test patch: