def get_add_custom_tag(self): """Return the page for the popup used to add a custom HTML tag.""" tag_name = self.request.get('tag_name') tag_bindings = tags.get_tag_bindings() select_data = [] for name in tag_bindings.keys(): clazz = tag_bindings[name] select_data.append((name, '%s: %s' % ( clazz.vendor(), clazz.name()))) select_data = sorted(select_data, key=lambda pair: pair[1]) if tag_name: tag_class = tag_bindings[tag_name] else: tag_class = tag_bindings[select_data[0][0]] tag_schema = tag_class().get_schema(self) schema = schema_fields.FieldRegistry('Add a Component') type_select = schema.add_sub_registry('type', 'Component Type') type_select.add_property(schema_fields.SchemaField( 'tag', 'Name', 'string', select_data=select_data)) schema.add_sub_registry('attributes', registry=tag_schema) template_values = {} template_values['form_html'] = ObjectEditor.get_html_for( self, schema.get_json_schema(), schema.get_schema_dict(), None, None, None, required_modules=tag_class.required_modules(), extra_js_files=['add_custom_tag.js']) self.response.out.write( self.get_template('popup.html', []).render(template_values))
def _render_custom_tags(self): tag_content = safe_dom.NodeList() tag_content.append( safe_dom.Element('h3').add_text('Custom Tags')) ol = safe_dom.Element('ol') tag_content.append(ol) tag_bindings = tags.get_tag_bindings() for name in sorted(tag_bindings.keys()): clazz = tag_bindings.get(name) tag = clazz() vendor = tag.vendor() ol.add_child(safe_dom.Element('li').add_text( '%s: %s: %s' % (name, tag.__class__.__name__, vendor))) return tag_content
def get(self): css = [] for tag_name, tag_class in tags.get_tag_bindings().items(): css.append( '.yui-toolbar-%(tag_name)s > .yui-toolbar-icon {' ' background: url(%(icon_url)s) !important;' ' background-size: 100%% !important;' ' left: 5px;' '}' % { 'tag_name': tag_name, 'icon_url': tag_class().get_icon_url()}) # Ensure this resource is cacheable. sites.set_static_resource_cache_control(self) self.response.headers['Content-Type'] = 'text/css' self.response.out.write('\n'.join(css))
def get_edit_custom_tag(self): """Return the the page used to edit a custom HTML tag in a popup.""" tag_name = self.request.get('tag_name') tag_bindings = tags.get_tag_bindings() tag_class = tag_bindings[tag_name] schema = tag_class().get_schema(self) if schema.has_subregistries(): raise NotImplementedError() template_values = {} template_values['form_html'] = ObjectEditor.get_html_for( self, schema.get_json_schema(), schema.get_schema_dict(), None, None, None) self.response.out.write( self.get_template('popup.html', []).render(template_values))
def get_add_custom_tag(self): """Return the page for the popup used to add a custom HTML tag.""" tag_name = self.request.get('tag_name') excluded_tags = self.request.get_all('excluded_tags') tag_bindings = tags.get_tag_bindings() select_data = [] for name in tag_bindings.keys(): if name not in excluded_tags: clazz = tag_bindings[name] select_data.append( (name, '%s: %s' % (clazz.vendor(), clazz.name()))) select_data = sorted(select_data, key=lambda pair: pair[1]) if tag_name: tag_class = tag_bindings[tag_name] else: tag_class = tag_bindings[select_data[0][0]] tag = tag_class() tag_schema = tag.get_schema(self) tag_schema = self._validate_schema(tag, tag_schema) schema = schema_fields.FieldRegistry('Add a Component') type_select = schema.add_sub_registry('type', 'Component Type') type_select.add_property( schema_fields.SchemaField('tag', 'Name', 'string', select_data=select_data)) schema.add_sub_registry('attributes', registry=tag_schema) template_values = {} template_values['form_html'] = ObjectEditor.get_html_for( self, schema.get_json_schema(), schema.get_schema_dict(), None, None, None, required_modules=tag_class.required_modules(), extra_js_files=['add_custom_tag.js'] + tag_class.extra_js_files(), extra_css_files=tag_class.extra_css_files(), additional_dirs=tag_class.additional_dirs()) self.response.out.write( self.get_template('popup.html', []).render(template_values))
def get_edit_custom_tag(self): """Return the the page used to edit a custom HTML tag in a popup.""" tag_name = self.request.get('tag_name') tag_bindings = tags.get_tag_bindings() tag_class = tag_bindings[tag_name] tag = tag_class() schema = tag.get_schema(self) schema = self._validate_schema(tag, schema) template_values = {} template_values['form_html'] = ObjectEditor.get_html_for( self, schema.get_json_schema(), schema.get_schema_dict(), None, None, None, required_modules=tag_class.required_modules(), extra_js_files=tag_class.extra_js_files(), extra_css_files=tag_class.extra_css_files(), additional_dirs=tag_class.additional_dirs()) self.response.out.write( self.get_template('popup.html', []).render(template_values))
def get_html_for( cls, handler, schema_json, annotations, object_key, rest_url, exit_url, additional_dirs=None, auto_return=False, delete_url=None, delete_message=None, delete_method='post', delete_button_caption='Delete', display_types=None, exit_button_caption='Close', extra_args=None, extra_css_files=None, extra_js_files=None, extra_required_modules=None, read_only=False, required_modules=None, save_button_caption='Save', save_method='put'): """Creates an HTML code needed to embed and operate this form. This method creates an HTML, JS and CSS required to embed JSON schema-based object editor into a view. Args: handler: a BaseHandler class, which will host this HTML, JS and CSS schema_json: a text of JSON schema for the object being edited annotations: schema annotations dictionary object_key: a key of an object being edited rest_url: a REST endpoint for object GET/PUT operation exit_url: a URL to go to after the editor form is dismissed auto_return: whether to return to the exit_url on successful save additional_dirs: list of extra directories to look for Jinja template files, e.g., JS or CSS files included by modules. delete_url: optional URL for delete operation delete_message: string. Optional custom delete confirmation message delete_method: optional HTTP method for delete operation delete_button_caption: string. A caption for the 'Delete' button display_types: list of strings. All schema field types exit_button_caption: a caption for the 'Close' button extra_args: extra request params passed back in GET and POST extra_css_files: list of extra CSS files to be included extra_js_files: list of extra JS files to be included extra_required_modules: list of strings. inputex modules not covered by display_types read_only: optional flag; if set, removes Save and Delete operations required_modules: list of inputex modules required for this editor save_button_caption: a caption for the 'Save' button save_method: how the data should be saved to the server (put|upload) Returns: The HTML, JS and CSS text that will instantiate an object editor. """ if required_modules: if not set(required_modules).issubset(set(ALL_MODULES)): difference = set(required_modules).difference(set(ALL_MODULES)) raise ValueError( "Unsupported inputEx modules were required: {}".format( difference)) elif display_types: required_modules = list(set( TYPES_TO_MODULES[type_name] for type_name in display_types)) else: required_modules = ALL_MODULES if extra_required_modules: required_modules += extra_required_modules if not delete_message: kind = transforms.loads(schema_json).get('description') if not kind: kind = 'content' delete_message = 'Are you sure you want to delete this %s?' % kind # construct parameters get_url = rest_url get_args = {'key': object_key} post_url = rest_url post_args = {'key': object_key} if extra_args: get_args.update(extra_args) post_args.update(extra_args) if read_only: post_url = '' post_args = '' rte_tag_data = [] for tag, tag_class in tags.get_tag_bindings().items(): rte_tag_data.append({ 'name': tag, 'vendor': tag_class.vendor(), 'label': tag_class.name(), 'iconUrl': tag_class().get_icon_url()}) editor_prefs = { 'xsrf_token': crypto.XsrfTokenManager.create_xsrf_token( EditorPrefsRestHandler.XSRF_TOKEN), 'location': rest_url, 'key': object_key, 'prefs': {} } user = users.get_current_user() if user is not None: key_name = EditorPrefsDao.create_key_name( user.user_id(), rest_url, object_key) editor_prefs_dto = EditorPrefsDao.load(key_name) if editor_prefs_dto: editor_prefs['prefs'] = editor_prefs_dto.dict extra_script_tag_urls = [] for callback in cls.EXTRA_SCRIPT_TAG_URLS: for url in callback(): extra_script_tag_urls.append(url) template_values = { 'enabled': custom_module.enabled, 'schema': schema_json, 'get_url': '%s?%s' % (get_url, urllib.urlencode(get_args, True)), 'save_url': post_url, 'save_args': transforms.dumps(post_args), 'exit_button_caption': exit_button_caption, 'exit_url': exit_url or '', 'required_modules': COMMON_REQUIRED_MODULES + required_modules, 'extra_css_files': extra_css_files or [], 'extra_js_files': extra_js_files or [], 'schema_annotations': [ (item[0], transforms.dumps(item[1])) for item in annotations], 'save_method': save_method, 'auto_return': auto_return, 'delete_button_caption': delete_button_caption, 'save_button_caption': save_button_caption, 'rte_tag_data': transforms.dumps(rte_tag_data), 'delete_message': delete_message, 'preview_xsrf_token': crypto.XsrfTokenManager.create_xsrf_token( PreviewHandler.XSRF_TOKEN), 'editor_prefs': transforms.dumps(editor_prefs), 'extra_script_tag_urls': extra_script_tag_urls } if delete_url and not read_only: template_values['delete_url'] = delete_url if delete_method: template_values['delete_method'] = delete_method if appengine_config.BUNDLE_LIB_FILES: template_values['bundle_lib_files'] = True return jinja2.utils.Markup(handler.get_template('oeditor.html', ( [TEMPLATES_DIR] + (additional_dirs or []) )).render(template_values))
def get_deployment(self): """Shows server environment and deployment information page.""" template_values = {} template_values['page_title'] = self.format_title('Deployment') template_values['page_description'] = messages.DEPLOYMENT_DESCRIPTION # modules module_content = safe_dom.NodeList() module_content.append( safe_dom.Element('h3').add_text('Custom Modules')) ol = safe_dom.Element('ol') module_content.append(ol) for name in sorted(custom_modules.Registry.registered_modules.keys()): enabled_text = '' if name not in custom_modules.Registry.enabled_module_names: enabled_text = ' (disabled)' li = safe_dom.Element('li').add_text('%s%s' % (name, enabled_text)) ol.add_child(li) amodule = custom_modules.Registry.registered_modules.get(name) self._make_routes_dom( li, amodule.global_routes, 'Global Routes') self._make_routes_dom( li, amodule.namespaced_routes, 'Namespaced Routes') # Custom tags. tag_content = safe_dom.NodeList() tag_content.append( safe_dom.Element('h3').add_text('Custom Tags')) ol = safe_dom.Element('ol') tag_content.append(ol) tag_bindings = tags.get_tag_bindings() for name in sorted(tag_bindings.keys()): clazz = tag_bindings.get(name) tag = clazz() vendor = tag.vendor() ol.add_child(safe_dom.Element('li').add_text( '%s: %s: %s' % (name, tag.__class__.__name__, vendor))) # Yaml file content. yaml_content = safe_dom.NodeList() yaml_content.append( safe_dom.Element('h3').add_text('Contents of ').add_child( safe_dom.Element('code').add_text('app.yaml'))) ol = safe_dom.Element('ol') yaml_content.append(ol) yaml_lines = open(os.path.join(os.path.dirname( __file__), '../../app.yaml'), 'r').readlines() for line in yaml_lines: ol.add_child(safe_dom.Element('li').add_text(line)) # Application identity. app_id = app.get_application_id() app_dict = {} app_dict['application_id'] = escape(app_id) app_dict['default_ver_hostname'] = escape( app.get_default_version_hostname()) template_values['main_content'] = safe_dom.NodeList().append( self.render_dict(app_dict, 'About the Application') ).append( module_content ).append( tag_content ).append( yaml_content ).append( self.render_dict(os.environ, 'Server Environment Variables')) self.render_page(template_values)
def get_deployment(self): """Shows server environment and deployment information page.""" template_values = {} template_values['page_title'] = self.format_title('Deployment') template_values['page_description'] = messages.DEPLOYMENT_DESCRIPTION # modules module_content = safe_dom.NodeList() module_content.append(safe_dom.Element('h3').add_text('Modules')) ol = safe_dom.Element('ol') module_content.append(ol) for name in sorted(custom_modules.Registry.registered_modules.keys()): enabled_text = '' if name not in custom_modules.Registry.enabled_module_names: enabled_text = ' (disabled)' li = safe_dom.Element('li').add_text('%s%s' % (name, enabled_text)) ol.add_child(li) amodule = custom_modules.Registry.registered_modules.get(name) self._make_routes_dom(li, amodule.global_routes, 'Global Routes') self._make_routes_dom(li, amodule.namespaced_routes, 'Namespaced Routes') # Custom tags. tag_content = safe_dom.NodeList() tag_content.append(safe_dom.Element('h3').add_text('Custom Tags')) ol = safe_dom.Element('ol') tag_content.append(ol) tag_bindings = tags.get_tag_bindings() for name in sorted(tag_bindings.keys()): clazz = tag_bindings.get(name) tag = clazz() vendor = tag.vendor() ol.add_child( safe_dom.Element('li').add_text( '%s: %s: %s' % (name, tag.__class__.__name__, vendor))) # Yaml file content. yaml_content = safe_dom.NodeList() yaml_content.append( safe_dom.Element('h3').add_text('Contents of ').add_child( safe_dom.Element('code').add_text('app.yaml'))) ol = safe_dom.Element('ol') yaml_content.append(ol) yaml_lines = open( os.path.join(os.path.dirname(__file__), '../../app.yaml'), 'r').readlines() for line in yaml_lines: ol.add_child(safe_dom.Element('li').add_text(line)) # Describe DB entity types entity_content = safe_dom.NodeList() entity_content.append( safe_dom.Element('h3').add_text('Database Entities')) entity_content.append(self._describe_db_types()) entity_content.append(safe_dom.Element('p')) # Application identity and users service information. app_id = app.get_application_id() app_dict = {} app_dict['application_id'] = escape(app_id) app_dict['default_ver_hostname'] = escape( app.get_default_version_hostname()) app_dict['users_service_name'] = escape( users.UsersServiceManager.get().get_service_name()) # sys.path information. sys_path_content = safe_dom.NodeList() sys_path_content.append(safe_dom.Element('h3').add_text('sys.path')) ol = safe_dom.Element('ol') sys_path_content.append(ol) for path in sys.path: ol.add_child(safe_dom.Element('li').add_text(path)) template_values['main_content'] = safe_dom.NodeList().append( self.render_dict(app_dict, 'About the Application') ).append(module_content).append(entity_content).append( tag_content).append(yaml_content).append( self.render_dict( os.environ, 'Server Environment Variables')).append(sys_path_content) self.render_page(template_values)
def get_html_for(cls, handler, schema_json, annotations, object_key, rest_url, exit_url, extra_args=None, save_method='put', delete_url=None, delete_message=None, delete_method='post', auto_return=False, read_only=False, required_modules=None, extra_css_files=None, extra_js_files=None, additional_dirs=None, delete_button_caption='Delete', save_button_caption='Save', exit_button_caption='Close'): """Creates an HTML code needed to embed and operate this form. This method creates an HTML, JS and CSS required to embed JSON schema-based object editor into a view. Args: handler: a BaseHandler class, which will host this HTML, JS and CSS schema_json: a text of JSON schema for the object being edited annotations: schema annotations dictionary object_key: a key of an object being edited rest_url: a REST endpoint for object GET/PUT operation exit_url: a URL to go to after the editor form is dismissed extra_args: extra request params passed back in GET and POST save_method: how the data should be saved to the server (put|upload) delete_url: optional URL for delete operation delete_message: string. Optional custom delete confirmation message delete_method: optional HTTP method for delete operation auto_return: whether to return to the exit_url on successful save read_only: optional flag; if set, removes Save and Delete operations required_modules: list of inputex modules required for this editor extra_css_files: list of extra CSS files to be included extra_js_files: list of extra JS files to be included additional_dirs: list of extra directories to look for Jinja template files, e.g., JS or CSS files included by modules. delete_button_caption: string. A caption for the 'Delete' button save_button_caption: a caption for the 'Save' button exit_button_caption: a caption for the 'Close' button Returns: The HTML, JS and CSS text that will instantiate an object editor. """ required_modules = required_modules or ALL_MODULES if not delete_message: kind = transforms.loads(schema_json).get('description') if not kind: kind = 'Generic Object' delete_message = 'Are you sure you want to delete this %s?' % kind # construct parameters get_url = rest_url get_args = {'key': object_key} post_url = rest_url post_args = {'key': object_key} if extra_args: get_args.update(extra_args) post_args.update(extra_args) if read_only: post_url = '' post_args = '' custom_rte_tag_icons = [] for tag, tag_class in tags.get_tag_bindings().items(): custom_rte_tag_icons.append({ 'name': tag, 'iconUrl': tag_class().get_icon_url() }) extra_script_tag_urls = [] for callback in cls.EXTRA_SCRIPT_TAG_URLS: for url in callback(): extra_script_tag_urls.append(url) template_values = { 'enabled': custom_module.enabled, 'schema': schema_json, 'get_url': '%s?%s' % (get_url, urllib.urlencode(get_args, True)), 'save_url': post_url, 'save_args': transforms.dumps(post_args), 'exit_button_caption': exit_button_caption, 'exit_url': exit_url, 'required_modules': COMMON_REQUIRED_MODULES + required_modules, 'extra_css_files': extra_css_files or [], 'extra_js_files': extra_js_files or [], 'schema_annotations': [(item[0], transforms.dumps(item[1])) for item in annotations], 'save_method': save_method, 'auto_return': auto_return, 'delete_button_caption': delete_button_caption, 'save_button_caption': save_button_caption, 'custom_rte_tag_icons': transforms.dumps(custom_rte_tag_icons), 'delete_message': delete_message, 'can_highlight_code': CAN_HIGHLIGHT_CODE.value, 'extra_script_tag_urls': extra_script_tag_urls, } if delete_url and not read_only: template_values['delete_url'] = delete_url if delete_method: template_values['delete_method'] = delete_method if appengine_config.BUNDLE_LIB_FILES: template_values['bundle_lib_files'] = True return jinja2.utils.Markup( handler.get_template( 'oeditor.html', ([os.path.dirname(__file__)] + (additional_dirs or []))).render(template_values))
def get_html_for( cls, handler, schema_json, annotations, object_key, rest_url, exit_url, extra_args=None, save_method='put', delete_url=None, delete_message=None, delete_method='post', auto_return=False, read_only=False, required_modules=None, extra_css_files=None, extra_js_files=None, delete_button_caption='Delete', save_button_caption='Save', exit_button_caption='Close'): """Creates an HTML code needed to embed and operate this form. This method creates an HTML, JS and CSS required to embed JSON schema-based object editor into a view. Args: handler: a BaseHandler class, which will host this HTML, JS and CSS schema_json: a text of JSON schema for the object being edited annotations: schema annotations dictionary object_key: a key of an object being edited rest_url: a REST endpoint for object GET/PUT operation exit_url: a URL to go to after the editor form is dismissed extra_args: extra request params passed back in GET and POST save_method: how the data should be saved to the server (put|upload) delete_url: optional URL for delete operation delete_message: string. Optional custom delete confirmation message delete_method: optional HTTP method for delete operation auto_return: whether to return to the exit_url on successful save read_only: optional flag; if set, removes Save and Delete operations required_modules: list of inputex modules required for this editor extra_css_files: list of extra CSS files to be included extra_js_files: list of extra JS files to be included delete_button_caption: string. A caption for the 'Delete' button save_button_caption: a caption for the 'Save' button exit_button_caption: a caption for the 'Close' button Returns: The HTML, JS and CSS text that will instantiate an object editor. """ required_modules = required_modules or ALL_MODULES if not delete_message: kind = transforms.loads(schema_json).get('description') if not kind: kind = 'Generic Object' delete_message = 'Are you sure you want to delete this %s?' % kind # construct parameters get_url = rest_url get_args = {'key': object_key} post_url = rest_url post_args = {'key': object_key} if extra_args: get_args.update(extra_args) post_args.update(extra_args) if read_only: post_url = '' post_args = '' custom_rte_tag_icons = [] for tag, tag_class in tags.get_tag_bindings().items(): custom_rte_tag_icons.append({ 'name': tag, 'iconUrl': tag_class().get_icon_url()}) template_values = { 'enabled': custom_module.enabled, 'schema': schema_json, 'get_url': '%s?%s' % (get_url, urllib.urlencode(get_args, True)), 'save_url': post_url, 'save_args': transforms.dumps(post_args), 'exit_button_caption': exit_button_caption, 'exit_url': exit_url, 'required_modules': COMMON_REQUIRED_MODULES + required_modules, 'extra_css_files': extra_css_files or [], 'extra_js_files': extra_js_files or [], 'schema_annotations': [ (item[0], transforms.dumps(item[1])) for item in annotations], 'save_method': save_method, 'auto_return': auto_return, 'delete_button_caption': delete_button_caption, 'save_button_caption': save_button_caption, 'custom_rte_tag_icons': transforms.dumps(custom_rte_tag_icons), 'delete_message': delete_message, } if delete_url and not read_only: template_values['delete_url'] = delete_url if delete_method: template_values['delete_method'] = delete_method if appengine_config.BUNDLE_LIB_FILES: template_values['bundle_lib_files'] = True return jinja2.utils.Markup(handler.get_template( 'oeditor.html', [os.path.dirname(__file__)] ).render(template_values))