def get(self, exploration_id): """Populates the data on the individual exploration page.""" # TODO(sll): Maybe this should send a complete state machine to the # frontend, and all interaction would happen client-side? exploration = Exploration.get(exploration_id) init_state = exploration.init_state.get() params = self.get_params(init_state) init_html, init_widgets = parse_content_into_html( init_state.content, 0, params) interactive_widget_html = InteractiveWidget.get_raw_code( init_state.widget.widget_id, params=utils.parse_dict_with_params( init_state.widget.params, params) ) self.values.update({ 'block_number': 0, 'interactive_widget_html': interactive_widget_html, 'interactive_params': init_state.widget.params, 'oppia_html': init_html, 'params': params, 'state_id': init_state.id, 'title': exploration.title, 'widgets': init_widgets, }) if init_state.widget.widget_id in DEFAULT_ANSWERS: self.values['default_answer'] = ( DEFAULT_ANSWERS[init_state.widget.widget_id]) self.response.write(json.dumps(self.values)) EventHandler.record_exploration_visited(exploration_id) EventHandler.record_state_hit(exploration_id, init_state.id)
def post(self, user): """Handles POST requests.""" payload = json.loads(self.request.get('payload')) title = payload.get('title') category = payload.get('category') if not title: raise self.InvalidInputException('No title supplied.') if not category: raise self.InvalidInputException('No category chosen.') yaml = self.request.get('yaml') if yaml and feconf.ALLOW_YAML_FILE_UPLOAD: exploration = Exploration.create_from_yaml( yaml_file=yaml, user=user, title=title, category=category) else: exploration = Exploration.create( user, title=title, category=category) self.response.write(json.dumps({ 'explorationId': exploration.id, }))
def reload_demos(): """Reload the default widgets, then reload the default explorations.""" Widget.delete_all_widgets() InteractiveWidget.load_default_widgets() NonInteractiveWidget.load_default_widgets() Exploration.delete_demo_explorations() Exploration.load_demo_explorations()
def test_editor(self, exploration_id, state_id=None, **kwargs): """Gets the user and exploration id if the user can edit it. Args: self: the handler instance exploration_id: the exploration id state_id: the state id, if it exists **kwargs: any other arguments passed to the handler Returns: The user and exploration instance, if the user is authorized to edit this exploration. Also, the state instance, if one is supplied. Raises: self.NotLoggedInException: if there is no current user. self.UnauthorizedUserException: if the user exists but does not have the right credentials. """ user = users.get_current_user() if not user: self.redirect(users.create_login_url(self.request.uri)) return exploration = Exploration.get(exploration_id) if not exploration.is_editable_by(user): raise self.UnauthorizedUserException( '%s does not have the credentials to edit this exploration.', user) if not state_id: return handler(self, user, exploration, **kwargs) state = State.get(state_id, exploration) return handler(self, user, exploration, state, **kwargs)
def get(self): """Handles GET requests.""" if not Exploration.get('0', strict=False): admin.reload_demos() self.values.update({ 'gallery_login_url': users.create_login_url('/gallery'), }) self.render_template('index.html')
def get(self): """Handles GET requests.""" explorations = Exploration.query().filter( Exploration.is_public == True).fetch(100) # Don't use the first exploration; users will have seen that already # on the main page. selected_exploration = utils.get_random_choice(explorations[1:]) self.redirect('/learn/%s' % selected_exploration.id)
def post(self, user): """Handles POST requests.""" payload = json.loads(self.request.get('payload')) exploration_id = payload.get('exploration_id') forked_exploration = Exploration.get(exploration_id) if not forked_exploration.is_demo_exploration(): raise self.InvalidInputException('Exploration cannot be forked.') # Get the demo exploration as a YAML file, so that new states can be # created. yaml = forked_exploration.as_yaml() title = 'Copy of %s' % forked_exploration.title category = forked_exploration.category exploration = Exploration.create_from_yaml( yaml_file=yaml, user=user, title=title, category=category) self.response.write(json.dumps({ 'explorationId': exploration.id, }))
def get(self): """Handles GET requests.""" user = users.get_current_user() used_keys = [] categories = {} explorations = Exploration.get_viewable_explorations(user) for exploration in explorations: category_name = exploration.category can_edit = user and exploration.is_editable_by(user) used_keys.append(exploration.key) data = exploration.to_dict( exclude=['states', 'init_state']) data.update({'id': exploration.id}) data['editors'] = [editor.nickname() for editor in exploration.editors] if not categories.get(category_name): categories[category_name] = [] categories[category_name].append({ 'data': data, 'can_edit': can_edit, 'can_fork': user and exploration.is_demo_exploration(), 'is_owner': (user and exploration.editors and user == exploration.editors[0]), }) self.values.update({ 'categories': categories, }) self.response.write(json.dumps(self.values))
def post(self, exploration_id, state_id): """Handles feedback interactions with readers.""" values = {'error': []} exploration = Exploration.get(exploration_id) state = State.get(state_id, exploration) old_state = state payload = json.loads(self.request.get('payload')) # The 0-based index of the last content block already on the page. block_number = payload.get('block_number') params = self.get_params(state, payload.get('params')) # The reader's answer. answer = payload.get('answer') # Add the reader's answer to the parameter list. This must happen before # the interactive widget is constructed. params['answer'] = answer interactive_widget_properties = ( InteractiveWidget.get_with_params( state.widget.widget_id)['actions']['submit']) dest_id, feedback, rule, recorded_answer = state.transition( answer, params, interactive_widget_properties) if recorded_answer: EventHandler.record_rule_hit( exploration_id, state_id, rule, recorded_answer) # Add this answer to the state's 'unresolved answers' list. if recorded_answer not in old_state.unresolved_answers: old_state.unresolved_answers[recorded_answer] = 0 old_state.unresolved_answers[recorded_answer] += 1 # TODO(sll): Make this async? old_state.put() assert dest_id html_output, widget_output = '', [] # TODO(sll): The following is a special-case for multiple choice input, # in which the choice text must be displayed instead of the choice # number. We might need to find a way to do this more generically. if state.widget.widget_id == 'MultipleChoiceInput': answer = state.widget.params['choices'][int(answer)] # Append reader's answer. values['reader_html'] = feconf.JINJA_ENV.get_template( 'reader_response.html').render({'response': answer}) if dest_id == feconf.END_DEST: # This leads to a FINISHED state. if feedback: html_output, widget_output = self.append_feedback( feedback, html_output, widget_output, block_number, params) EventHandler.record_exploration_completed(exploration_id) else: state = State.get(dest_id, exploration) EventHandler.record_state_hit(exploration_id, state_id) if feedback: html_output, widget_output = self.append_feedback( feedback, html_output, widget_output, block_number, params) # Append text for the new state only if the new and old states # differ. if old_state.id != state.id: state_html, state_widgets = parse_content_into_html( state.content, block_number, params) # Separate text for the new state and feedback for the old state # by an additional line. if state_html and feedback: html_output += '<br>' html_output += state_html widget_output.append(state_widgets) if state.widget.widget_id in DEFAULT_ANSWERS: values['default_answer'] = DEFAULT_ANSWERS[state.widget.widget_id] values['exploration_id'] = exploration.id values['state_id'] = state.id values['oppia_html'] = html_output values['widgets'] = widget_output values['block_number'] = block_number + 1 values['params'] = params if dest_id != feconf.END_DEST: values['finished'] = False if state.widget.sticky and ( state.widget.widget_id == old_state.widget.widget_id): values['interactive_widget_html'] = '' values['sticky_interactive_widget'] = True else: values['interactive_widget_html'] = ( InteractiveWidget.get_raw_code( state.widget.widget_id, params=utils.parse_dict_with_params( state.widget.params, params) ) ) else: values['finished'] = True values['interactive_widget_html'] = '' self.response.write(json.dumps(values))
def get(self, exploration_id): """Handles GET requests.""" self.values.update({ 'js': utils.get_js_controllers(['readerExploration']), 'nav_mode': READER_MODE, }) Exploration.get(exploration_id) # The following allows embedding of Oppia explorations in other pages. if self.request.get('iframed') == 'true': self.values['iframed'] = True self.render_template('reader/reader_exploration.html')