def blog_publish(blog_id): user = auth.is_logged_in(request) blog = Blog.load(blog_id) permission = auth.is_blog_publisher(user, blog) queue_length = Queue.job_counts(blog=blog) if queue_length > 0: start_message = template('queue/queue_run_include', queue=Queue.jobs(blog), percentage_complete=0, blog=blog, break_path='{}/blog/{}/publish/break'.format(BASE_URL, blog.id) ) Queue.start(blog, queue_length) else: start_message = "Queue empty." tags = template_tags(blog_id=blog.id, user=user) # return template('queue/queue_run_ui', start=queue_length, start_message=start_message, action_url="../../blog/{}/publish/progress/{}".format(blog.id, queue_length), title='Publishing queue progress', # search_context=(search_context['blog_queue'], blog), menu=generate_menu('blog_queue', blog), **tags.__dict__)
def media_edit_output(tags): return template('edit/media', icons=icons, menu=generate_menu('blog_edit_media', tags.media), search_context=(search_contexts['blog_media'], tags.blog), **tags.__dict__)
def blog_create(site_id): user = auth.is_logged_in(request) site = Site.load(site_id) permission = auth.is_site_admin(user, site) new_blog = Blog( name="", description="", url="", path="") tags = template_tags(site_id=site.id, user=user) tags.blog = new_blog from core.libs import pytz themes = Theme.select() return template('ui/ui_blog_settings', section_title="Create new blog", # search_context=(search_context['sites'], None), menu=generate_menu('site_create_blog', site), nav_default='all', timezones=pytz.all_timezones, themes=themes, ** tags.__dict__ )
def blog_publish(blog_id): user = auth.is_logged_in(request) blog = Blog.load(blog_id) permission = auth.is_blog_publisher(user, blog) queue_length = Queue.job_counts(blog=blog) if queue_length > 0: start_message = template('queue/queue_run_include', queue=Queue.jobs(blog), percentage_complete=0, blog=blog, break_path='{}/blog/{}/publish/break'.format( BASE_URL, blog.id)) Queue.start(blog, queue_length) else: start_message = "Queue empty." tags = template_tags(blog_id=blog.id, user=user) # return template( 'queue/queue_run_ui', start=queue_length, start_message=start_message, action_url="../../blog/{}/publish/progress/{}".format( blog.id, queue_length), title='Publishing queue progress', # search_context=(search_context['blog_queue'], blog), menu=generate_menu('blog_queue', blog), **tags.__dict__)
def main_ui(): ''' Top level UI This will eventually become a full-blown user dashboard. Right now it just returns a list of sites in the system. All users for the system can see this dashboard. ''' user = auth.is_logged_in(request) # TODO: replace with actual user-centric setting try: from settings import MAX_RECENT_PAGES except ImportError: MAX_RECENT_PAGES = 10 recent_pages = Page.select().where(Page.user == user).order_by( Page.modified_date.desc()).limit(MAX_RECENT_PAGES) your_blogs = user.blogs() tpl = template('ui/ui_dashboard', search_context=(search_contexts['sites'], None), menu=generate_menu('system_menu', None), recent_pages=recent_pages, your_blogs=your_blogs, **template_tags(user=user).__dict__) return tpl
def main_ui(): ''' Top level UI This will eventually become a full-blown user dashboard. Right now it just returns a list of sites in the system. All users for the system can see this dashboard. ''' user = auth.is_logged_in(request) # TODO: replace with actual user-centric setting try: from settings import MAX_RECENT_PAGES except ImportError: MAX_RECENT_PAGES = 10 recent_pages = Page.select().where( Page.user == user).order_by( Page.modified_date.desc()).limit(MAX_RECENT_PAGES) your_blogs = user.blogs() tpl = template('ui/ui_dashboard', search_context=(search_contexts['sites'], None), menu=generate_menu('system_menu', None), recent_pages=recent_pages, your_blogs=your_blogs, **template_tags(user=user).__dict__ ) return tpl
def blog_new_page(blog_id): ''' Displays UI for newly created (unsaved) page ''' user = auth.is_logged_in(request) blog = Blog.load(blog_id) permission = auth.is_blog_member(user, blog) tags = template_tags(blog=blog, user=user) tags.page = Page() referer = request.headers.get('Referer') if referer is None: referer = BASE_URL + "/blog/" + str(blog.id) blog_new_page = tags.page for n in new_page_submission_fields: blog_new_page.__setattr__(n, "") if n in request.query: blog_new_page.__setattr__(n, request.query.getunicode(n)) import datetime blog_new_page.blog = blog blog_new_page.user = user blog_new_page.publication_date = datetime.datetime.utcnow() blog_new_page.basename = '' from core.cms import save_action_list from core.ui import kv kv_ui_data = kv.ui(blog_new_page.kv_list()) try: html_editor_settings = Template.get( Template.blog == blog, Template.title == 'HTML Editor Init', Template.template_type == template_type.system).body except Template.DoesNotExist: from core.static import html_editor_settings return template( 'edit/page', menu=generate_menu('create_page', blog), parent_path=referer, # search_context=(search_context['blog'], blog), html_editor_settings=html_editor_settings, sidebar=sidebar.render_sidebar(panel_set='edit_page', status_badge=status_badge, save_action=save_action, save_action_list=save_action_list, kv_ui=kv_ui_data, kv_object='Page', kv_objectid=None, **tags.__dict__), **tags.__dict__)
def new_category(blog_id): from core.models import db with db.atomic() as txn: user = auth.is_logged_in(request) blog = Blog.load(blog_id) permission = auth.is_blog_editor(user, blog) category_list = [n for n in blog.categories] category = Category(id=0, title='', blog=blog) top_level_category = Category( id=None, title='[Top-level category]', parent=None ) category_list.insert(0, top_level_category) tags = template_tags( blog=blog, user=user) if request.method == "POST": with db.atomic() as txn: category_title = request.forms.getunicode('category_title') try: parent_category = int(request.forms.getunicode('category_parent')) except ValueError: parent_category = None with db.atomic() as txn: category = Category(blog=blog, title=category_title, parent_category=parent_category ) category.save() redirect('{}/blog/{}/category/{}'.format( BASE_URL, blog.id, category.id)) tpl = template('edit/category', category=category, category_list=category_list, menu=generate_menu('blog_new_category', category), search_context=(search_contexts['sites'], None), **tags.__dict__) return tpl
def template_edit_output(tags): return template('edit/template', icons=icons, search_context=(search_contexts['blog'], tags.blog), menu=generate_menu('blog_edit_template', tags.template), sidebar=sidebar.render_sidebar( panel_set='edit_template', publishing_mode=publishing_mode, types=template_type, **tags.__dict__), **tags.__dict__)
def page_edit(page_id): ''' UI for editing a page in a blog ''' user = auth.is_logged_in(request) page = Page.load(page_id) permission = auth.is_page_editor(user, page) status = None referer = request.headers.get('Referer') if (referer is None or page.modified_date is None or re.match(re.escape(BASE_URL + "/blog/" + str(page.blog.id)), referer) is None): referer = BASE_URL + "/blog/" + str(page.blog.id) if page.modified_date is None: status = utils.Status( type='info', message="Page <b>{}</b> created.".format(page.for_log)) page.modified_date = datetime.datetime.utcnow() page.save(user) tags = template_tags(page=page, user=user, status=status) from core.ui import kv kv_ui_data = kv.ui(page.kv_list()) tpl = template('edit/page', menu=generate_menu('edit_page', page), parent_path=referer, # search_context=(search_context['blog'], page.blog), html_editor_settings=html_editor_settings(page.blog), sidebar=sidebar.render_sidebar( panel_set='edit_page', status_badge=status_badge, save_action_list=save_action_list, save_action=save_action, kv_ui=kv_ui_data, kv_object='Page', kv_objectid=page.id, **tags.__dict__), msg_float=False, **tags.__dict__) logger.info("Page {} opened for editing by {}.".format( page.for_log, user.for_log)) return tpl
def master_context(users, path, root_path): return { 'users':users, 'search_context':(search_contexts['sites'], None), 'menu':generate_menu('system_manage_users', None), 'title':'List all users', 'path':root_path, 'nav_default': path, 'nav_tabs': ( ('basic', root_path + '/basic', 'Basic',), ('permissions', root_path + '/permissions', 'Permissions') ) }
def blog_settings_output(tags): from core.libs import pytz timezones = pytz.all_timezones path = '/blog/{}/settings/'.format(tags.blog.id) return template( 'ui/ui_blog_settings', # search_context=(search_context['blog'], tags.blog), timezones=timezones, menu=generate_menu('blog_settings', tags.blog), nav_tabs=(('basic', path + 'basic', 'Basic'), ('dirs', path + 'dirs', 'Directories')), **tags.__dict__)
def blog_settings_output(tags): from core.libs import pytz timezones = pytz.all_timezones path = '/blog/{}/settings/'.format(tags.blog.id) return template('ui/ui_blog_settings', # search_context=(search_context['blog'], tags.blog), timezones=timezones, menu=generate_menu('blog_settings', tags.blog), nav_tabs=( ('basic', path + 'basic', 'Basic'), ('dirs', path + 'dirs', 'Directories') ), **tags.__dict__)
def page_edit(page_id): ''' UI for editing a page in a blog ''' user = auth.is_logged_in(request) page = Page.load(page_id) permission = auth.is_page_editor(user, page) status = None referer = request.headers.get('Referer') if (referer is None or page.modified_date is None or re.match(re.escape(BASE_URL + "/blog/" + str(page.blog.id)), referer) is None): referer = BASE_URL + "/blog/" + str(page.blog.id) if page.modified_date is None: status = utils.Status(type='info', message="Page <b>{}</b> created.".format( page.for_log)) page.modified_date = datetime.datetime.utcnow() page.save(user) tags = template_tags(page=page, user=user, status=status) from core.ui import kv kv_ui_data = kv.ui(page.kv_list()) tpl = template( 'edit/page', menu=generate_menu('edit_page', page), parent_path=referer, # search_context=(search_context['blog'], page.blog), html_editor_settings=html_editor_settings(page.blog), sidebar=sidebar.render_sidebar(panel_set='edit_page', status_badge=status_badge, save_action_list=save_action_list, save_action=save_action, kv_ui=kv_ui_data, kv_object='Page', kv_objectid=page.id, **tags.__dict__), msg_float=False, **tags.__dict__) logger.info("Page {} opened for editing by {}.".format( page.for_log, user.for_log)) return tpl
def plugin_settings(plugin_id, errormsg=None): user = auth.is_logged_in(request) permission = auth.is_sys_admin(user) plugin = Plugin.get(Plugin.id == plugin_id) tags = template_tags(user=user) tpl = template('system/plugin', plugin_ui=plugin.ui(), search_context=(search_contexts['sites'], None), menu=generate_menu('system_plugin_data', plugin), **tags.__dict__) return tpl
def template_set_default(template_id): ''' UI for setting a given template as the default for an archive type ''' user = auth.is_logged_in(request) tpl = Template.load(template_id) blog = Blog.load(tpl.blog.id) permission = auth.is_blog_designer(user, blog) auth.check_template_lock(blog) tags = template_tags(template=tpl, user=user) from core.utils import Status import settings if request.forms.getunicode('confirm') == user.logout_nonce: # check for form submission # setting should be done by way of class object # theme? blog? template? # blog.set_default_archive_template(template,{archive_type.index...}) status = Status( type='success', close=False, message= 'Template <b>{}</b> was successfully refreshed from theme <b>{}</b>.' .format(tpl.for_display, tpl.theme.for_display), action='Return to template', url='{}/template/{}/edit'.format(settings.BASE_URL, tpl.id)) tags.status = status else: pass from core.models import archive_defaults return template('edit/template-set-default', icons=icons, search_context=(search_contexts['blog'], tags.blog), menu=generate_menu('blog_edit_template', tags.template), sidebar=sidebar.render_sidebar( panel_set='edit_template', publishing_mode=publishing_mode, types=template_type, **tags.__dict__), archive_defaults=archive_defaults, **tags.__dict__)
def plugin_settings(plugin_id, errormsg=None): user = auth.is_logged_in(request) permission = auth.is_sys_admin(user) plugin = Plugin.get(Plugin.id == plugin_id) tags = template_tags( user=user) tpl = template('system/plugin', plugin_ui=plugin.ui(), search_context=(search_contexts['sites'], None), menu=generate_menu('system_plugin_data', plugin), **tags.__dict__) return tpl
def new_category(blog_id): from core.models import db with db.atomic() as txn: user = auth.is_logged_in(request) blog = Blog.load(blog_id) permission = auth.is_blog_editor(user, blog) category_list = [n for n in blog.categories] category = Category(id=0, title='', blog=blog) top_level_category = Category(id=None, title='[Top-level category]', parent=None) category_list.insert(0, top_level_category) tags = template_tags(blog=blog, user=user) if request.method == "POST": with db.atomic() as txn: category_title = request.forms.getunicode('category_title') try: parent_category = int( request.forms.getunicode('category_parent')) except ValueError: parent_category = None with db.atomic() as txn: category = Category(blog=blog, title=category_title, parent_category=parent_category) category.save() redirect('{}/blog/{}/category/{}'.format(BASE_URL, blog.id, category.id)) tpl = template('edit/category', category=category, category_list=category_list, menu=generate_menu('blog_new_category', category), search_context=(search_contexts['sites'], None), **tags.__dict__) return tpl
def page_revision_restore(page_id, revision_id): user = auth.is_logged_in(request) page = Page.load(page_id) permission = auth.is_page_editor(user, page) page_revision = PageRevision.select().where(PageRevision.id == revision_id).get() status = utils.Status( type='success', message='Page <b>{}</b> has been restored from backup dated {}.'.format(page.for_log, page_revision.modified_date) ) tags = template_tags(page=page, user=user, status=status) page_revision.id = page.id tags.page = page_revision referer = BASE_URL + "/blog/" + str(page.blog.id) # from core.cms import save_action_list # from core.ui_kv import kv_ui from core.ui import kv kv_ui_data = kv.ui(page.kv_list()) # TODO: save action from this doesn't trigger queue run tpl = template('edit/page', status_badge=status_badge, save_action=save_action, menu=generate_menu('edit_page', page), search_context=(search_contexts['blog'], page.blog), html_editor_settings=html_editor_settings(page.blog), sidebar=sidebar.render_sidebar( panel_set='edit_page', status_badge=status_badge, save_action=save_action, save_action_list=save_action_list, kv_ui=kv_ui_data, kv_object='Page', kv_objectid=page.id, **tags.__dict__ ), **tags.__dict__) return tpl
def page_revision_restore(page_id, revision_id): user = auth.is_logged_in(request) page = Page.load(page_id) permission = auth.is_page_editor(user, page) page_revision = PageRevision.select().where( PageRevision.id == revision_id).get() status = utils.Status( type='success', message='Page <b>{}</b> has been restored from backup dated {}.'. format(page.for_log, page_revision.modified_date)) tags = template_tags(page=page, user=user, status=status) page_revision.id = page.id tags.page = page_revision referer = BASE_URL + "/blog/" + str(page.blog.id) # from core.cms import save_action_list # from core.ui_kv import kv_ui from core.ui import kv kv_ui_data = kv.ui(page.kv_list()) # TODO: save action from this doesn't trigger queue run tpl = template('edit/page', status_badge=status_badge, save_action=save_action, menu=generate_menu('edit_page', page), search_context=(search_contexts['blog'], page.blog), html_editor_settings=html_editor_settings(page.blog), sidebar=sidebar.render_sidebar( panel_set='edit_page', status_badge=status_badge, save_action=save_action, save_action_list=save_action_list, kv_ui=kv_ui_data, kv_object='Page', kv_objectid=page.id, **tags.__dict__), **tags.__dict__) return tpl
def edit_user(edit_user, **ka): context = ka.get('context') editing_user = ka.get('editing_user', edit_user) site = ka.get('site') blog = ka.get('blog') tags = ka.get('tags') tags.nav_default = context['nav_default'] tags.nav_tabs = context['nav_tabs'] tpl = template('edit/user_settings', edit_user=edit_user, menu=generate_menu('system_edit_user', edit_user), search_context=(search_contexts['sites'], None), context=None, **tags.__dict__) return tpl
def master_context(users, path, root_path): return { 'users': users, 'search_context': (search_contexts['sites'], None), 'menu': generate_menu('system_manage_users', None), 'title': 'List all users', 'path': root_path, 'nav_default': path, 'nav_tabs': (( 'basic', root_path + '/basic', 'Basic', ), ('permissions', root_path + '/permissions', 'Permissions')) }
def edit_user(edit_user, **ka): context = ka.get('context') editing_user = ka.get('editing_user', edit_user) site = ka.get('site') blog = ka.get('blog') tags = ka.get('tags') tags.nav_default = context['nav_default'] tags.nav_tabs = context['nav_tabs'] tpl = template('edit/user_settings', edit_user=edit_user, menu=generate_menu('system_edit_user', edit_user), search_context=(search_contexts['sites'], None), context=None, **tags.__dict__ ) return tpl
def blog_break_queue(blog_id): user = auth.is_logged_in(request) blog = Blog.load(blog_id) permission = auth.is_blog_publisher(user, blog) Queue.stop(blog) tags = template_tags(blog=blog, user=user) return template( 'queue/queue_run_ui', start=None, action_url='', start_message=''' <p>Queue publishing stopped. Note that queued items are still in the queue, and may still be processed on the next queue run.</p> <p><a href="{}/blog/{}/queue/clear"><button class="btn">Clear the queue</button></a> to remove them entirely.</p> '''.format(BASE_URL, blog_id), title='Publishing queue progress', # search_context=(search_context['blog_queue'], blog), menu=generate_menu('blog_queue', blog), **tags.__dict__)
def blog_break_queue(blog_id): user = auth.is_logged_in(request) blog = Blog.load(blog_id) permission = auth.is_blog_publisher(user, blog) Queue.stop(blog) tags = template_tags(blog=blog, user=user) return template('queue/queue_run_ui', start=None, action_url='', start_message=''' <p>Queue publishing stopped. Note that queued items are still in the queue, and may still be processed on the next queue run.</p> <p><a href="{}/blog/{}/queue/clear"><button class="btn">Clear the queue</button></a> to remove them entirely.</p> '''.format(BASE_URL, blog_id), title='Publishing queue progress', # search_context=(search_context['blog_queue'], blog), menu=generate_menu('blog_queue', blog), **tags.__dict__)
def system_info(): # alt. implementation, less boilerplate? # user, permission = auth.is_sys_admin() user = auth.is_logged_in(request) permission = auth.is_sys_admin(user) tags = template_tags( user=user) python_list = [] environ_list = [] settings_list = [] # Generate interpreter info import os data = os.environ.__dict__['_data'] for n in data: environ_list.append((n, data[n])) # List all settings variables import settings s_dict = settings.__dict__ for n in s_dict: if n is not '__builtins__': settings_list.append((n, s_dict[n])) # List all plugins tpl = template('ui/ui_system_info', menu=generate_menu('system_info', None), search_context=(search_contexts['sites'], None), environ_list=sorted(environ_list), settings_list=sorted(settings_list), **tags.__dict__) return tpl
def system_info(): # alt. implementation, less boilerplate? # user, permission = auth.is_sys_admin() user = auth.is_logged_in(request) permission = auth.is_sys_admin(user) tags = template_tags(user=user) python_list = [] environ_list = [] settings_list = [] # Generate interpreter info import os data = os.environ.__dict__['_data'] for n in data: environ_list.append((n, data[n])) # List all settings variables import settings s_dict = settings.__dict__ for n in s_dict: if n is not '__builtins__': settings_list.append((n, s_dict[n])) # List all plugins tpl = template('ui/ui_system_info', menu=generate_menu('system_info', None), search_context=(search_contexts['sites'], None), environ_list=sorted(environ_list), settings_list=sorted(settings_list), **tags.__dict__) return tpl
def blog_create(site_id): user = auth.is_logged_in(request) site = Site.load(site_id) permission = auth.is_site_admin(user, site) new_blog = Blog(name="", description="", url="", path="") tags = template_tags(site_id=site.id, user=user) tags.blog = new_blog from core.libs import pytz themes = Theme.select() return template( 'ui/ui_blog_settings', section_title="Create new blog", # search_context=(search_context['sites'], None), menu=generate_menu('site_create_blog', site), nav_default='all', timezones=pytz.all_timezones, themes=themes, **tags.__dict__)
def blog_templates(blog_id): ''' List all templates in a given blog ''' user = auth.is_logged_in(request) blog = Blog.load(blog_id) permission = auth.is_blog_designer(user, blog) reason = auth.check_template_lock(blog, True) tags = template_tags(blog_id=blog.id, user=user) tags.status = reason from core.libs.peewee import JOIN_LEFT_OUTER template_list = Template.select(Template, TemplateMapping).join( TemplateMapping, JOIN_LEFT_OUTER).where( (Template.blog == blog)).order_by(Template.title) index_templates = template_list.select( Template, TemplateMapping).where(Template.template_type == template_type.index) page_templates = template_list.select( Template, TemplateMapping).where(Template.template_type == template_type.page) archive_templates = template_list.select( Template, TemplateMapping).where(Template.template_type == template_type.archive) template_includes = template_list.select( Template, TemplateMapping).where(Template.template_type == template_type.include) media_templates = template_list.select( Template, TemplateMapping).where(Template.template_type == template_type.media) code_templates = template_list.select( Template, TemplateMapping).where(Template.template_type == template_type.code) system_templates = template_list.select( Template, TemplateMapping).where(Template.template_type == template_type.system) from core.models import archive_defaults tags.list_items = ( { 'title': 'Index Templates', 'type': template_type.index, 'data': index_templates, 'defaults': archive_defaults[template_type.index] }, { 'title': 'Page Templates', 'type': template_type.page, 'data': page_templates, 'defaults': archive_defaults[template_type.page] }, { 'title': 'Archive Templates', 'type': template_type.archive, 'data': archive_templates, 'defaults': archive_defaults[template_type.archive] }, { 'title': 'Includes', 'type': template_type.include, 'data': template_includes }, { 'title': 'Media Templates', 'type': template_type.media, 'data': media_templates }, { 'title': 'Code', 'type': template_type.code, 'data': code_templates }, { 'title': 'System Templates', 'type': template_type.system, 'data': system_templates }, ) return template('ui/ui_blog_templates', icons=icons, section_title="Templates", publishing_mode=publishing_mode, search_context=(search_contexts['blog_templates'], blog), menu=generate_menu('blog_manage_templates', blog), templates_with_defaults=('Index', 'Page', 'Archive'), **tags.__dict__)
def listing(request, context_object, item_list_object, colset, menu, user=None, rowset_callback=None, errormsg=None, search_ui=None, search_context=None, tags_data={}, msg_float=True): ''' Listing framework. Used to present a searchable and sortable list of objects. request The current request object. context_object An object that provides context for the listing, so that it can be used to generate action buttons, etc. For instance, for a list of pages in a blog, it's the blog object. Example: blog item_list_object The data object from which we derive the actual listing. Example: blog.pages search_ui The description of the search context to use for the search UI. Example: 'blog' search_context The search context object to use to produce search results Example: blog_search_results ''' colset = colsets[colset] action_button = colset.get('buttons', None) # Any action button to be displayed. list_actions = colset.get('list_actions', None) # Any list actions to the shown. if action_button is not None: action_button = ''.join([utils.action_button(n[0], n[1](context_object)) for n in action_button]) else: action_button = None if list_actions is not None: s = [] for n in list_actions: s.append([n[0], n[1](context_object)]) list_actions = s if search_context is None: items_searched, search = None, None else: try: items_searched, search = search_context(request, context_object) except (KeyError, ValueError): items_searched, search = None, None item_list = item_list_object if items_searched is not None: item_list = item_list.where(item_list_object.model_class.id << items_searched) # basic ordering functionality if 'order_by' in request.query: item_list = item_list.order_by( getattr(item_list_object.model_class, request.query['order_by'], 'title').desc() ) # TODO: pass on the pagination parameters # we could do this by keeping a list of the pagination paramters that need to be worked with somewhere # need to figure out how to extract, modify, and replace - see url tools paginator, rowset = utils.generate_paginator(item_list, request) tags = template_tags(search=search, user=user, **tags_data) tags.status = errormsg if errormsg is not None else None # Use 'rowset_callback' to supply a function that can be used # to transform the rowset before display if rowset_callback is not None: rowset = rowset_callback(rowset) if search_ui is not None: tags.search_context = (search_contexts[search_ui], context_object) # also, if we have template_tags handle search objs, # perhaps we should centralize that there instead of # adding the search_context here manually! # TODO: fix inconsistencies where we parse for nonexistent object vs. # object set to None in templates. We should pick a standard behavior return _tpl('listing/listing_ui', paginator=paginator, menu=generate_menu(menu, context_object), rowset=rowset, colset=colset, icons=icons, action=action_button, list_actions=list_actions, msg_float=msg_float, **tags.__dict__)
def blog_save_theme(blog_id): user = auth.is_logged_in(request) blog = Blog.load(blog_id) permission = auth.is_blog_publisher(user, blog) reason = auth.check_template_lock(blog) tags = template_tags(blog=blog, user=user) from core.utils import Status, create_basename_core if request.method == 'POST': theme = Theme( title=request.forms.getunicode('theme_title'), description=request.forms.getunicode('theme_description'), json='') export = blog.export_theme(theme.title, theme.description, user) from settings import THEME_FILE_PATH # , _sep import os directory_name = create_basename_core(theme.title) dirs = [x[0] for x in os.walk(THEME_FILE_PATH)] dir_name_ext = 0 dir_name_full = directory_name while 1: if dir_name_full in dirs: dir_name_ext += 1 dir_name_full = directory_name + "-" + str(dir_name_ext) continue else: break dir_name_final = os.path.join(THEME_FILE_PATH, dir_name_full) os.makedirs(dir_name_final) theme.json = dir_name_full theme.save() Template.update(theme=theme).where(Template.blog == blog).execute() TemplateRevision.update(theme=theme).where(TemplateRevision.blog == blog).execute() blog.theme = theme blog.theme_modified = False blog.save() for n in export: with open(os.path.join(dir_name_final, n), "w", encoding='utf-8') as output_file: output_file.write(export[n]) save_tpl = 'listing/report' status = Status( type='success', close=False, message=''' Theme <b>{}</b> was successfully saved from blog <b>{}</b>. '''.format('', blog.for_display, ''), action='Return to theme list', url='{}/blog/{}/themes'.format( BASE_URL, blog.id) ) else: save_tpl = 'edit/theme_save' status = None tags.status = status if reason is None else reason import datetime # TODO: eventually this will be migrated to the report function # but it's a little complex for that now due to the funtion logic return template(save_tpl, menu=generate_menu('blog_save_theme', blog), # search_context=(search_context['blog'], blog), theme_title=blog.theme.title + " (Revised {})".format(datetime.datetime.now()), theme_description=blog.theme.description, msg_float=False, ** tags.__dict__)
def system_new_user(): from core.models import db user = auth.is_logged_in(request) permission = auth.is_sys_admin(user) nav_tabs = None status = None from core.models import User if request.method == 'POST': new_name = request.forms.getunicode('user_name') new_email = request.forms.getunicode('user_email') new_password = request.forms.getunicode('user_password') new_password_confirm = request.forms.getunicode('user_password_confirm') from core.error import UserCreationError from core.libs import peewee # TODO: make this into a confirmation function a la what we did with blog settings new_user = User( name=new_name, email=new_email, password=new_password, password_confirm=new_password_confirm) try: new_user.save_pwd() except UserCreationError as e: status = utils.Status( type='danger', no_sure=True, message='There were problems creating the new user:'******'danger', no_sure=True, message='There were problems creating the new user:'******'The new user\'s email or username is the same as another user\'s. Emails and usernames must be unique.'] ) except Exception as e: raise e else: db.commit() from settings import BASE_URL return redirect(BASE_URL + '/system/user/{}'.format(new_user.id)) else: new_user = User(name='', email='', password='') tags = template_tags(user=user) tags.status = status tpl = template('edit/user_settings', edit_user=new_user, menu=generate_menu('system_create_user', new_user), search_context=(search_contexts['sites'], None), nav_tabs=nav_tabs, nav_default='basic', **tags.__dict__ ) return tpl
def blog_save_theme(blog_id): user = auth.is_logged_in(request) blog = Blog.load(blog_id) permission = auth.is_blog_publisher(user, blog) reason = auth.check_template_lock(blog) tags = template_tags(blog=blog, user=user) from core.utils import Status, create_basename_core if request.method == 'POST': theme = Theme( title=request.forms.getunicode('theme_title'), description=request.forms.getunicode('theme_description'), json='') export = blog.export_theme(theme.title, theme.description, user) from settings import THEME_FILE_PATH # , _sep import os directory_name = create_basename_core(theme.title) dirs = [x[0] for x in os.walk(THEME_FILE_PATH)] dir_name_ext = 0 dir_name_full = directory_name while 1: if dir_name_full in dirs: dir_name_ext += 1 dir_name_full = directory_name + "-" + str(dir_name_ext) continue else: break dir_name_final = os.path.join(THEME_FILE_PATH, dir_name_full) os.makedirs(dir_name_final) theme.json = dir_name_full theme.save() Template.update(theme=theme).where(Template.blog == blog).execute() TemplateRevision.update(theme=theme).where( TemplateRevision.blog == blog).execute() blog.theme = theme blog.theme_modified = False blog.save() for n in export: with open(os.path.join(dir_name_final, n), "w", encoding='utf-8') as output_file: output_file.write(export[n]) save_tpl = 'listing/report' status = Status(type='success', close=False, message=''' Theme <b>{}</b> was successfully saved from blog <b>{}</b>. '''.format('', blog.for_display, ''), action='Return to theme list', url='{}/blog/{}/themes'.format(BASE_URL, blog.id)) else: save_tpl = 'edit/theme_save' status = None tags.status = status if reason is None else reason import datetime # TODO: eventually this will be migrated to the report function # but it's a little complex for that now due to the funtion logic return template( save_tpl, menu=generate_menu('blog_save_theme', blog), # search_context=(search_context['blog'], blog), theme_title=blog.theme.title + " (Revised {})".format(datetime.datetime.now()), theme_description=blog.theme.description, msg_float=False, **tags.__dict__)
def report(tags, menu, obj, msg_float=False): return _tpl('listing/report', menu=generate_menu(menu, obj), msg_float=msg_float, **tags.__dict__)
def blog_new_page(blog_id): ''' Displays UI for newly created (unsaved) page ''' user = auth.is_logged_in(request) blog = Blog.load(blog_id) permission = auth.is_blog_member(user, blog) tags = template_tags( blog=blog, user=user) tags.page = Page() referer = request.headers.get('Referer') if referer is None: referer = BASE_URL + "/blog/" + str(blog.id) blog_new_page = tags.page for n in new_page_submission_fields: blog_new_page.__setattr__(n, "") if n in request.query: blog_new_page.__setattr__(n, request.query.getunicode(n)) import datetime blog_new_page.blog = blog blog_new_page.user = user blog_new_page.publication_date = datetime.datetime.utcnow() blog_new_page.basename = '' from core.cms import save_action_list from core.ui import kv kv_ui_data = kv.ui(blog_new_page.kv_list()) try: html_editor_settings = Template.get( Template.blog == blog, Template.title == 'HTML Editor Init', Template.template_type == template_type.system ).body except Template.DoesNotExist: from core.static import html_editor_settings return template('edit/page', menu=generate_menu('create_page', blog), parent_path=referer, # search_context=(search_context['blog'], blog), html_editor_settings=html_editor_settings, sidebar=sidebar.render_sidebar( panel_set='edit_page', status_badge=status_badge, save_action=save_action, save_action_list=save_action_list, kv_ui=kv_ui_data, kv_object='Page', kv_objectid=None, **tags.__dict__), **tags.__dict__)
def tag_edit(blog_id, tag_id): user = auth.is_logged_in(request) blog = Blog.load(blog_id) permission = auth.is_blog_editor(user, blog) auth.check_tag_editing_lock(blog) try: tag = Tag.get(Tag.id == tag_id, Tag.blog == blog_id) except Tag.DoesNotExist: raise Tag.DoesNotExist("No such tag #{} in blog {}.".format( tag_id, blog.for_log)) tags = template_tags(user=user) from core.utils import html_escape if request.method == "POST": new_tag_name = request.forms.getunicode('tag_name') if new_tag_name != tag.tag: try: Tag.get(Tag.tag == new_tag_name) except Tag.DoesNotExist: tag_count = tag.pages.count() msg = "Tag changed from {} to <b>{}</b>. {} pages (and their archives) have been queued for republishing.".format( tag.for_log, html_escape(new_tag_name), tag_count) tag.tag = new_tag_name tag.save() if tag_count > 0: from core.cms import queue from core.models import db with db.atomic() as txn: queue.queue_page_actions(tag.pages.published) queue.queue_ssi_actions(blog) queue.queue_index_actions(blog, True) tags.status = Status(type='info', message=msg) else: msg = "Tag not renamed. A tag with the name '{}' already exists.".format( html_escape(new_tag_name)) tags.status = Status(type='danger', message=msg, no_sure=True) else: tag_modified = tag_recently_modified(tag) if tag_modified: tags.status = Status(type='danger', message=tag_modified, no_sure=True) tpl = template('edit/tag', menu=generate_menu('blog_edit_tag', tag), search_context=(search_contexts['sites'], None), tag=tag, **tags.__dict__) return tpl
def blog_templates(blog_id): ''' List all templates in a given blog ''' user = auth.is_logged_in(request) blog = Blog.load(blog_id) permission = auth.is_blog_designer(user, blog) reason = auth.check_template_lock(blog, True) tags = template_tags(blog_id=blog.id, user=user) tags.status = reason from core.libs.peewee import JOIN_LEFT_OUTER template_list = Template.select(Template, TemplateMapping).join( TemplateMapping, JOIN_LEFT_OUTER).where( (Template.blog == blog) ).order_by(Template.title) index_templates = template_list.select(Template, TemplateMapping).where( Template.template_type == template_type.index) page_templates = template_list.select(Template, TemplateMapping).where( Template.template_type == template_type.page) archive_templates = template_list.select(Template, TemplateMapping).where( Template.template_type == template_type.archive) template_includes = template_list.select(Template, TemplateMapping).where( Template.template_type == template_type.include) media_templates = template_list.select(Template, TemplateMapping).where( Template.template_type == template_type.media) code_templates = template_list.select(Template, TemplateMapping).where( Template.template_type == template_type.code) system_templates = template_list.select(Template, TemplateMapping).where( Template.template_type == template_type.system) from core.models import archive_defaults tags.list_items = ( {'title':'Index Templates', 'type': template_type.index, 'data':index_templates, 'defaults': archive_defaults[template_type.index]}, {'title':'Page Templates', 'type': template_type.page, 'data':page_templates, 'defaults':archive_defaults[template_type.page]}, {'title':'Archive Templates', 'type': template_type.archive, 'data':archive_templates, 'defaults': archive_defaults[template_type.archive]}, {'title':'Includes', 'type': template_type.include, 'data':template_includes}, {'title':'Media Templates', 'type': template_type.media, 'data':media_templates}, {'title':'Code', 'type': template_type.code, 'data':code_templates}, {'title':'System Templates', 'type': template_type.system, 'data':system_templates}, ) return template('ui/ui_blog_templates', icons=icons, section_title="Templates", publishing_mode=publishing_mode, search_context=(search_contexts['blog_templates'], blog), menu=generate_menu('blog_manage_templates', blog), templates_with_defaults=('Index', 'Page', 'Archive'), ** tags.__dict__)
def blog_import(blog_id): user = auth.is_logged_in(request) blog = Blog.load(blog_id) permission = auth.is_blog_publisher(user, blog) reason = auth.check_template_lock(blog, True) tags = template_tags(blog=blog, user=user) import os, settings import_path = os.path.join(settings.APPLICATION_PATH, "data", "import.json") tags.status = reason if request.method == "POST": from core.models import db tpl = '' with db.atomic() as txn: import json from core.utils import string_to_date import_path = request.forms.getunicode('import_path') with open(import_path, 'r', encoding='utf8') as f: json_data = json.load(f) from core.models import page_status, MediaAssociation, Category from core.error import PageNotChanged from core.libs.peewee import InterfaceError from core.cms import media_filetypes format_str = "<b>{}</b> / (<i>{}</i>)" # TODO: go in chunks of 50 or something? # allow graceful disconnection? for n in json_data: q = [] n_id = n['id'] q.append("Checking {}".format(n_id)) changed = False found = False match = Page.kv_get('legacy_id', n_id) if match.count() > 0: if match[0].object_ref.blog == blog: found = True q.append(match[0].key + "/" + match[0].value + " / Exists: " + format_str.format(n['title'], n_id)) existing_entry = Page.load(match[0].objectid) update = existing_entry.kv_get('update').count() # raise Exception(update) q.append('{} / {}'.format( string_to_date( n['modified_date']).replace(tzinfo=None), existing_entry.modified_date)) if string_to_date(n['modified_date']).replace( tzinfo=None ) <= existing_entry.modified_date and update == 0: q.append('Existing page {} not changed.'.format( existing_entry.id)) else: changed = True q.append( 'Updating data for existing page {}.'.format( existing_entry.id)) existing_entry.title = n['title'] existing_entry.text = n['text'] existing_entry.basename = n['basename'] existing_entry.excerpt = n['excerpt'] existing_entry.created_date = string_to_date( n['created_date']).replace(tzinfo=None) existing_entry.modified_date = string_to_date( n['modified_date']).replace(tzinfo=None) existing_entry.publication_date = string_to_date( n['publication_date']).replace(tzinfo=None) try: existing_entry.save( user, False, False, 'New revision from import') except PageNotChanged: pass except InterfaceError: raise Exception( "Error saving {}. Check the JSON to make sure it's valid." .format(n_id)) for media in existing_entry.media: media.kv_del() existing_entry.clear_categories() existing_entry.clear_kvs() existing_entry.clear_tags() existing_entry.clear_media() entry = existing_entry if found is False: q.append("Creating: " + format_str.format(n['title'], n_id)) changed = True new_entry = Page( title=n['title'], text=n['text'], basename=n['basename'], excerpt=n['excerpt'], user=user, blog=blog, created_date=string_to_date(n['created_date']), publication_date=string_to_date(n['publication_date']), modified_date=string_to_date(n['modified_date']), ) new_entry.modified_date = new_entry.publication_date if n['status'] in ('Publish', 'Published', 'Live'): new_entry.status = page_status.published new_entry.save(user) entry = new_entry q.append("New ID: {}".format(entry.id)) # Everything from here on out is if changed: # Register a legacy ID for the page entry.kv_set("legacy_id", n["id"]) entry.kv_set("legacy_user", n["user_id"]) # Category assignments categories = n['categories'] if categories == []: saved_page_category = PageCategory.create( page=entry, category=blog.default_category, primary=True).save() else: primary = True for category in categories: cat_exists = False category_id = category['id'] existing_category = Category.kv_get( 'legacy_id', category_id) if existing_category.count() > 0: if existing_category[ 0].object_ref.blog == blog: cat_exists = True if cat_exists is False: q.append('Created new category {}/{}'.format( category_id, category['name'])) new_category = Category.create( blog=blog, title=category['name'], parent_category=getattr( category, 'parent', None)) new_category.save() new_category.kv_set('legacy_id', category_id) else: new_category = Category.load( existing_category[0].objectid) q.append( 'Added to existing category {}/{}'.format( new_category.id, category['name'])) saved_page_category = PageCategory.create( page=entry, category=new_category, primary=primary).save() primary = False # Check to make sure a default category exists for the whole blog. # If not, assign one based on the lowest ID. # This can always be reassigned later. # Register tags tags_added, tags_existing, _ = Tag.add_or_create( n['tags'], page=entry) q.append('Tags added: {}'.format(','.join( n.tag for n in tags_added))) q.append('Tags existing: {}'.format(','.join( n.tag for n in tags_existing))) # Register KVs kvs = n['kvs'] for key in kvs: if key != "": value = kvs[key] entry.kv_set(key, value) q.append('KV: {}:{}'.format(key, value)) # Register media media = n['media'] for m in media: if 'path' not in m: continue path = os.path.split(m['path']) try: new_media = Media.get(Media.url == m['url']) except: new_media = Media(filename=path[1], path=m['path'], url=m['url'], type=media_filetypes.image, created_date=string_to_date( m['created_date']), modified_date=string_to_date( m['modified_date']), friendly_name=m['friendly_name'], user=user, blog=blog, site=blog.site) # TODO: RBF try: new_media.save() except Exception: continue media_association = MediaAssociation(media=new_media, page=entry) media_association.save() # Save legacy ID to KV on media if 'id' in m: new_media.kv_set('legacy_id', m['id']) q.append('IMG: {}'.format(new_media.url)) # add tags for media q.append('Tags: {}'.format(m['tags'])) new_tags = Tag.add_or_create(m['tags'], media=new_media) kvs = m['kvs'] for key in kvs: value = kvs[key] new_media.kv_set(key, value) q.append('KV: {}:{}'.format(key, value)) fileinfo.build_pages_fileinfos((entry, )) fileinfo.build_archives_fileinfos((entry, )) tpl += ('<p>'.join(q)) + '<hr/>' return tpl # TODO: # Import or create categories as needed # Categories in export will need to have parent-child data # categories should have legacy identifiers where possible too # Import image files, assign those legacy KV identifiers # Modify URLs for imported images in posts # Make importing of image assets optional else: tpl = template( 'ui/ui_blog_import', menu=generate_menu('blog_import', blog), # search_context=(search_context['blog'], blog), import_path=import_path, **tags.__dict__) return tpl
def report(tags, menu, obj, msg_float=False): return _tpl('listing/report', menu=generate_menu(menu, obj), msg_float=msg_float, ** tags.__dict__ )
def blog_create_save(site_id): user = auth.is_logged_in(request) site = Site.load(site_id) permission = auth.is_site_admin(user, site) errors = [] new_blog = Blog( site=site, name=request.forms.getunicode('blog_name'), description=request.forms.getunicode('blog_description'), url=request.forms.getunicode('blog_url'), path=request.forms.getunicode('blog_path'), set_timezone=request.forms.getunicode('blog_timezone'), # theme=get_default_theme(), theme=Theme.default_theme() ) try: new_blog.validate() except Exception as e: errors.extend(e.args[0]) if len(errors) == 0: from core.libs.peewee import IntegrityError try: new_blog.setup(user, Theme.default_theme()) # new_blog.theme) except IntegrityError as e: from core.utils import field_error errors.append(field_error(e)) if len(errors) > 0: status = utils.Status( type='danger', no_sure=True, message='The blog could not be created due to the following problems:', message_list=errors) from core.libs import pytz tags = template_tags(site=site, user=user) tags.status = status tags.blog = new_blog themes = Theme.select() return template('ui/ui_blog_settings', section_title="Create new blog", # search_context=(search_context['sites'], None), menu=generate_menu('site_create_blog', site), nav_default='all', themes=themes, timezones=pytz.all_timezones, ** tags.__dict__ ) else: tags = template_tags(user=user, site=site, blog=new_blog) status = utils.Status( type='success', message=''' Blog <b>{}</b> was successfully created. You can <a href="{}/blog/{}/newpage">start posting</a> immediately. '''.format( new_blog.for_display, BASE_URL, new_blog.id) ) tags.status = status return report(tags, 'site_create_blog', site)
def edit_category(blog_id, category_id): user = auth.is_logged_in(request) blog = Blog.load(blog_id) permission = auth.is_blog_admin(user, blog) category = Category.load(category_id, blog_id=blog.id) auth.check_category_editing_lock(blog) category_list = [n for n in blog.categories] top_level_category = Category(id=None, title='[Top-level category]', parent=None) category_list.insert(0, top_level_category) tags = template_tags(blog=blog, user=user) from core.utils import Status status = [] if request.method == "POST": new_category_title = request.forms.getunicode('category_title') old_category_title = category.title if new_category_title != old_category_title: category.title = new_category_title category.save() status.append([ 'Category <b>{}</b> was renamed to <b>{}</b>.', [old_category_title, new_category_title] ]) old_parent_category = category.parent_category try: new_parent_category = int( request.forms.getunicode('category_parent')) except ValueError: new_parent_category = None new_basename = request.forms.getunicode('category_basename') if category.basename != new_basename: category.basename = new_basename category.save() status.append(['Category basename was changed.', []]) if old_parent_category != new_parent_category: category.parent_category = new_parent_category category.save() if new_parent_category is not None: new_category = Category.load(category_id=new_parent_category, blog=blog) else: new_category = top_level_category status.append([ 'Category <b>{}</b> was reparented to <b>{}</b>.', [category.title, new_category.for_log] ]) if request.forms.getunicode('default') == "Y": clear_default_categories = Category.update(default=False).where( Category.blog == blog, Category.default == True) clear_default_categories.execute() category.default = True category.save() status.append([ 'Category <b>{}</b> was set to default for blog <b>{}</b>.', [category.title, blog.for_log] ]) if len(status) > 0: message = '' vals = [] for n in status: message += n[0] for m in n[1]: vals.append(m) vals.append('{}/blog/{}/purge'.format(BASE_URL, blog.id)) tags.status = Status( type='success', message=message + '<br/><a href="{}">Purge and republish this blog</a> to make these changes take effect.', vals=vals) # from core.ui_kv import kv_ui from core.ui import kv kv_ui_data = kv.ui(category.kv_list()) from core.ui import sidebar tags.sidebar = sidebar.render_sidebar( panel_set='edit_category', # status_badge=status_badge, kv_object='Category', kv_objectid=category.id, kv_ui=kv_ui_data) tpl = template('edit/category', category=category, category_list=category_list, menu=generate_menu('blog_edit_category', category), search_context=(search_contexts['sites'], None), **tags.__dict__) return tpl
def system_new_user(): from core.models import db user = auth.is_logged_in(request) permission = auth.is_sys_admin(user) nav_tabs = None status = None from core.models import User if request.method == 'POST': new_name = request.forms.getunicode('user_name') new_email = request.forms.getunicode('user_email') new_password = request.forms.getunicode('user_password') new_password_confirm = request.forms.getunicode( 'user_password_confirm') from core.error import UserCreationError from core.libs import peewee # TODO: make this into a confirmation function a la what we did with blog settings new_user = User(name=new_name, email=new_email, password=new_password, password_confirm=new_password_confirm) try: new_user.save_pwd() except UserCreationError as e: status = utils.Status( type='danger', no_sure=True, message='There were problems creating the new user:'******'danger', no_sure=True, message='There were problems creating the new user:'******'The new user\'s email or username is the same as another user\'s. Emails and usernames must be unique.' ]) except Exception as e: raise e else: db.commit() from settings import BASE_URL return redirect(BASE_URL + '/system/user/{}'.format(new_user.id)) else: new_user = User(name='', email='', password='') tags = template_tags(user=user) tags.status = status tpl = template('edit/user_settings', edit_user=new_user, menu=generate_menu('system_create_user', new_user), search_context=(search_contexts['sites'], None), nav_tabs=nav_tabs, nav_default='basic', **tags.__dict__) return tpl
def blog_create_save(site_id): user = auth.is_logged_in(request) site = Site.load(site_id) permission = auth.is_site_admin(user, site) errors = [] new_blog = Blog( site=site, name=request.forms.getunicode('blog_name'), description=request.forms.getunicode('blog_description'), url=request.forms.getunicode('blog_url'), path=request.forms.getunicode('blog_path'), set_timezone=request.forms.getunicode('blog_timezone'), # theme=get_default_theme(), theme=Theme.default_theme()) try: new_blog.validate() except Exception as e: errors.extend(e.args[0]) if len(errors) == 0: from core.libs.peewee import IntegrityError try: new_blog.setup(user, Theme.default_theme()) # new_blog.theme) except IntegrityError as e: from core.utils import field_error errors.append(field_error(e)) if len(errors) > 0: status = utils.Status( type='danger', no_sure=True, message= 'The blog could not be created due to the following problems:', message_list=errors) from core.libs import pytz tags = template_tags(site=site, user=user) tags.status = status tags.blog = new_blog themes = Theme.select() return template( 'ui/ui_blog_settings', section_title="Create new blog", # search_context=(search_context['sites'], None), menu=generate_menu('site_create_blog', site), nav_default='all', themes=themes, timezones=pytz.all_timezones, **tags.__dict__) else: tags = template_tags(user=user, site=site, blog=new_blog) status = utils.Status(type='success', message=''' Blog <b>{}</b> was successfully created. You can <a href="{}/blog/{}/newpage">start posting</a> immediately. '''.format(new_blog.for_display, BASE_URL, new_blog.id)) tags.status = status return report(tags, 'site_create_blog', site)
def edit_category(blog_id, category_id): user = auth.is_logged_in(request) blog = Blog.load(blog_id) permission = auth.is_blog_admin(user, blog) category = Category.load(category_id, blog_id=blog.id) auth.check_category_editing_lock(blog) category_list = [n for n in blog.categories] top_level_category = Category( id=None, title='[Top-level category]', parent=None ) category_list.insert(0, top_level_category) tags = template_tags( blog=blog, user=user) from core.utils import Status status = [] if request.method == "POST": new_category_title = request.forms.getunicode('category_title') old_category_title = category.title if new_category_title != old_category_title: category.title = new_category_title category.save() status.append( ['Category <b>{}</b> was renamed to <b>{}</b>.', [old_category_title, new_category_title]]) old_parent_category = category.parent_category try: new_parent_category = int(request.forms.getunicode('category_parent')) except ValueError: new_parent_category = None new_basename = request.forms.getunicode('category_basename') if category.basename != new_basename: category.basename = new_basename category.save() status.append(['Category basename was changed.', []]) if old_parent_category != new_parent_category: category.parent_category = new_parent_category category.save() if new_parent_category is not None: new_category = Category.load( category_id=new_parent_category, blog=blog) else: new_category = top_level_category status.append(['Category <b>{}</b> was reparented to <b>{}</b>.', [category.title, new_category.for_log]]) if request.forms.getunicode('default') == "Y": clear_default_categories = Category.update( default=False).where( Category.blog == blog, Category.default == True) clear_default_categories.execute() category.default = True category.save() status.append(['Category <b>{}</b> was set to default for blog <b>{}</b>.', [category.title, blog.for_log]]) if len(status) > 0: message = '' vals = [] for n in status: message += n[0] for m in n[1]: vals.append(m) vals.append('{}/blog/{}/purge'.format(BASE_URL, blog.id)) tags.status = Status(type='success', message=message + '<br/><a href="{}">Purge and republish this blog</a> to make these changes take effect.', vals=vals) # from core.ui_kv import kv_ui from core.ui import kv kv_ui_data = kv.ui(category.kv_list()) from core.ui import sidebar tags.sidebar = sidebar.render_sidebar( panel_set='edit_category', # status_badge=status_badge, kv_object='Category', kv_objectid=category.id, kv_ui=kv_ui_data) tpl = template('edit/category', category=category, category_list=category_list, menu=generate_menu('blog_edit_category', category), search_context=(search_contexts['sites'], None), **tags.__dict__) return tpl
def listing(request, context_object, item_list_object, colset, menu, user=None, rowset_callback=None, errormsg=None, search_ui=None, search_context=None, tags_data={}, msg_float=True): ''' Listing framework. Used to present a searchable and sortable list of objects. request The current request object. context_object An object that provides context for the listing, so that it can be used to generate action buttons, etc. For instance, for a list of pages in a blog, it's the blog object. Example: blog item_list_object The data object from which we derive the actual listing. Example: blog.pages search_ui The description of the search context to use for the search UI. Example: 'blog' search_context The search context object to use to produce search results Example: blog_search_results ''' colset = colsets[colset] action_button = colset.get('buttons', None) # Any action button to be displayed. list_actions = colset.get('list_actions', None) # Any list actions to the shown. if action_button is not None: action_button = ''.join([ utils.action_button(n[0], n[1](context_object)) for n in action_button ]) else: action_button = None if list_actions is not None: s = [] for n in list_actions: s.append([n[0], n[1](context_object)]) list_actions = s if search_context is None: items_searched, search = None, None else: try: items_searched, search = search_context(request, context_object) except (KeyError, ValueError): items_searched, search = None, None item_list = item_list_object if items_searched is not None: item_list = item_list.where( item_list_object.model_class.id << items_searched) # basic ordering functionality if 'order_by' in request.query: item_list = item_list.order_by( getattr(item_list_object.model_class, request.query['order_by'], 'title').desc()) # TODO: pass on the pagination parameters # we could do this by keeping a list of the pagination paramters that need to be worked with somewhere # need to figure out how to extract, modify, and replace - see url tools paginator, rowset = utils.generate_paginator(item_list, request) tags = template_tags(search=search, user=user, **tags_data) tags.status = errormsg if errormsg is not None else None # Use 'rowset_callback' to supply a function that can be used # to transform the rowset before display if rowset_callback is not None: rowset = rowset_callback(rowset) if search_ui is not None: tags.search_context = (search_contexts[search_ui], context_object) # also, if we have template_tags handle search objs, # perhaps we should centralize that there instead of # adding the search_context here manually! # TODO: fix inconsistencies where we parse for nonexistent object vs. # object set to None in templates. We should pick a standard behavior return _tpl('listing/listing_ui', paginator=paginator, menu=generate_menu(menu, context_object), rowset=rowset, colset=colset, icons=icons, action=action_button, list_actions=list_actions, msg_float=msg_float, **tags.__dict__)
def tag_edit(blog_id, tag_id): user = auth.is_logged_in(request) blog = Blog.load(blog_id) permission = auth.is_blog_editor(user, blog) auth.check_tag_editing_lock(blog) try: tag = Tag.get(Tag.id == tag_id, Tag.blog == blog_id) except Tag.DoesNotExist: raise Tag.DoesNotExist("No such tag #{} in blog {}.".format( tag_id, blog.for_log)) tags = template_tags( user=user) from core.utils import html_escape if request.method == "POST": new_tag_name = request.forms.getunicode('tag_name') if new_tag_name != tag.tag: try: Tag.get(Tag.tag == new_tag_name) except Tag.DoesNotExist: tag_count = tag.pages.count() msg = "Tag changed from {} to <b>{}</b>. {} pages (and their archives) have been queued for republishing.".format( tag.for_log, html_escape(new_tag_name), tag_count) tag.tag = new_tag_name tag.save() if tag_count > 0: from core.cms import queue from core.models import db with db.atomic() as txn: queue.queue_page_actions(tag.pages.published) queue.queue_ssi_actions(blog) queue.queue_index_actions(blog, True) tags.status = Status( type='info', message=msg ) else: msg = "Tag not renamed. A tag with the name '{}' already exists.".format( html_escape(new_tag_name) ) tags.status = Status( type='danger', message=msg, no_sure=True) else: tag_modified = tag_recently_modified(tag) if tag_modified: tags.status = Status( type='danger', message=tag_modified, no_sure=True) tpl = template('edit/tag', menu=generate_menu('blog_edit_tag', tag), search_context=(search_contexts['sites'], None), tag=tag, **tags.__dict__) return tpl
def blog_import (blog_id): user = auth.is_logged_in(request) blog = Blog.load(blog_id) permission = auth.is_blog_publisher(user, blog) reason = auth.check_template_lock(blog, True) tags = template_tags(blog=blog, user=user) import os, settings import_path = os.path.join( settings.APPLICATION_PATH, "data", "import.json") tags.status = reason if request.method == "POST": from core.models import db tpl = '' with db.atomic() as txn: import json from core.utils import string_to_date import_path = request.forms.getunicode('import_path') with open(import_path, 'r', encoding='utf8') as f: json_data = json.load(f) from core.models import page_status, MediaAssociation, Category from core.error import PageNotChanged from core.libs.peewee import InterfaceError from core.cms import media_filetypes format_str = "<b>{}</b> / (<i>{}</i>)" # TODO: go in chunks of 50 or something? # allow graceful disconnection? for n in json_data: q = [] n_id = n['id'] q.append("Checking {}".format(n_id)) changed = False found = False match = Page.kv_get('legacy_id', n_id) if match.count() > 0: if match[0].object_ref.blog == blog: found = True q.append(match[0].key + "/" + match[0].value + " / Exists: " + format_str.format(n['title'], n_id)) existing_entry = Page.load(match[0].objectid) update = existing_entry.kv_get('update').count() # raise Exception(update) q.append('{} / {}'.format(string_to_date(n['modified_date']).replace(tzinfo=None), existing_entry.modified_date )) if string_to_date(n['modified_date']).replace(tzinfo=None) <= existing_entry.modified_date and update == 0: q.append('Existing page {} not changed.'.format(existing_entry.id)) else: changed = True q.append('Updating data for existing page {}.'.format(existing_entry.id)) existing_entry.title = n['title'] existing_entry.text = n['text'] existing_entry.basename = n['basename'] existing_entry.excerpt = n['excerpt'] existing_entry.created_date = string_to_date(n['created_date']).replace(tzinfo=None) existing_entry.modified_date = string_to_date(n['modified_date']).replace(tzinfo=None) existing_entry.publication_date = string_to_date(n['publication_date']).replace(tzinfo=None) try: existing_entry.save(user, False, False, 'New revision from import') except PageNotChanged: pass except InterfaceError: raise Exception("Error saving {}. Check the JSON to make sure it's valid.".format(n_id)) for media in existing_entry.media: media.kv_del() existing_entry.clear_categories() existing_entry.clear_kvs() existing_entry.clear_tags() existing_entry.clear_media() entry = existing_entry if found is False: q.append("Creating: " + format_str.format(n['title'], n_id)) changed = True new_entry = Page( title=n['title'], text=n['text'], basename=n['basename'], excerpt=n['excerpt'], user=user, blog=blog, created_date=string_to_date(n['created_date']), publication_date=string_to_date(n['publication_date']), modified_date=string_to_date(n['modified_date']), ) new_entry.modified_date = new_entry.publication_date if n['status'] in ('Publish', 'Published', 'Live'): new_entry.status = page_status.published new_entry.save(user) entry = new_entry q.append("New ID: {}".format(entry.id)) # Everything from here on out is if changed: # Register a legacy ID for the page entry.kv_set("legacy_id", n["id"]) entry.kv_set("legacy_user", n["user_id"]) # Category assignments categories = n['categories'] if categories == []: saved_page_category = PageCategory.create( page=entry, category=blog.default_category, primary=True).save() else: primary = True for category in categories: cat_exists = False category_id = category['id'] existing_category = Category.kv_get('legacy_id', category_id) if existing_category.count() > 0: if existing_category[0].object_ref.blog == blog: cat_exists = True if cat_exists is False: q.append('Created new category {}/{}'.format( category_id, category['name'] )) new_category = Category.create( blog=blog, title=category['name'], parent_category=getattr(category, 'parent', None) ) new_category.save() new_category.kv_set('legacy_id', category_id ) else: new_category = Category.load(existing_category[0].objectid) q.append('Added to existing category {}/{}'.format( new_category.id, category['name'] )) saved_page_category = PageCategory.create( page=entry, category=new_category, primary=primary ).save() primary = False # Check to make sure a default category exists for the whole blog. # If not, assign one based on the lowest ID. # This can always be reassigned later. # Register tags tags_added, tags_existing, _ = Tag.add_or_create( n['tags'], page=entry) q.append('Tags added: {}'.format(','.join(n.tag for n in tags_added))) q.append('Tags existing: {}'.format(','.join(n.tag for n in tags_existing))) # Register KVs kvs = n['kvs'] for key in kvs: if key != "": value = kvs[key] entry.kv_set(key, value) q.append('KV: {}:{}'.format(key, value)) # Register media media = n['media'] for m in media: if 'path' not in m: continue path = os.path.split(m['path']) try: new_media = Media.get(Media.url == m['url']) except: new_media = Media( filename=path[1], path=m['path'], url=m['url'], type=media_filetypes.image, created_date=string_to_date(m['created_date']), modified_date=string_to_date(m['modified_date']), friendly_name=m['friendly_name'], user=user, blog=blog, site=blog.site ) # TODO: RBF try: new_media.save() except Exception: continue media_association = MediaAssociation( media=new_media, page=entry) media_association.save() # Save legacy ID to KV on media if 'id' in m: new_media.kv_set('legacy_id', m['id']) q.append('IMG: {}'.format(new_media.url)) # add tags for media q.append('Tags: {}'.format(m['tags'])) new_tags = Tag.add_or_create(m['tags'], media=new_media) kvs = m['kvs'] for key in kvs: value = kvs[key] new_media.kv_set(key, value) q.append('KV: {}:{}'.format(key, value)) fileinfo.build_pages_fileinfos((entry,)) fileinfo.build_archives_fileinfos((entry,)) tpl += ('<p>'.join(q)) + '<hr/>' return tpl # TODO: # Import or create categories as needed # Categories in export will need to have parent-child data # categories should have legacy identifiers where possible too # Import image files, assign those legacy KV identifiers # Modify URLs for imported images in posts # Make importing of image assets optional else: tpl = template('ui/ui_blog_import', menu=generate_menu('blog_import', blog), # search_context=(search_context['blog'], blog), import_path=import_path, **tags.__dict__) return tpl