def render_custom(request, template, context=None): if context is None: context = {} # add toolbar if it's an authorized user if request.is_mobile: if template == 'base.html': template = 'base.html' else: context['base'] = 'mobile/base.html' t = select_template(['mobile/' + template, template]) else: if request.session.get('customizing'): if template == 'base.html': template = 'dashboard/look/preview.html' panels = Stork(request.site.theme) context.update({ 'styles': panels.style_tags(), 'toolbar': panels.toolbar(), 'base': 'dashboard/look/preview.html', 'pre_base': panels['layout'].as_template(staged=True), }) else: context.update({ 'base': 'base.html', 'pre_base': request.site.template() }) t = get_template(template) c = RequestContext(request, context) rendered = t.render(c) return HttpResponse(rendered)
def import_theme(theme_dir, name=None): try: shutil.rmtree('tmp') except OSError: pass shutil.copytree(theme_dir, 'tmp') theme_dir = os.path.abspath('tmp') manifest = yaml.load(open(os.path.join(theme_dir, 'manifest.yaml')).read()) asset_dir = os.path.join(theme_dir, 'assets') try: screenshot = os.path.join(asset_dir, manifest.pop('screenshot')) except: raise KeyError("Screenshot file missing or improperly specified.") try: description = manifest.pop('description') except: raise KeyError("No description provided.") try: target = manifest.pop('dirname') except: raise KeyError("No dirname provided for theme assets.") asset_target = os.path.join(settings.MEDIA_ROOT, 'theme-assets', target) notes = manifest.pop('notes', '') theme, created = Theme.objects.get_or_create(name=manifest.pop('name'), defaults=dict( private=False, description=description)) theme.screenshot.save( screenshot.rsplit('/', 1)[1], ContentFile(open(screenshot).read())) os.remove(screenshot) stork = Stork(theme) stork.save() switch = { Html: set_html, Image: set_image, CSS: set_css, Swatch: set_swatch, Font: set_font } for name, panel in manifest.items(): for component_id, values in panel.items(): component = stork[component_id] instance = component.instance switch[component.model](instance, asset_dir, values) try: os.makedirs(asset_target) except: pass for f in os.listdir(asset_dir): shutil.move(os.path.join(asset_dir, f), os.path.join(asset_target, f)) shutil.rmtree(theme_dir)
def script_tag(request): stork = Stork(request.site.theme) return direct_to_template(request, template='stork/main.js', extra_context={ 'swatch_json': stork.swatch_json(), 'font_json': stork.font_json() })
def test_outputs_swatch_json(): theme = Theme.objects.create(name='test') panels = Stork(theme, config_path='stork/tests/fixtures/valid.yml') panels.save() swatch_json_as_list = json.loads(panels.swatch_json()) assert swatch_json_as_list == [ s.for_json() for s in panels.swatches ]
def new_site_setup(sender, instance, created, **kwargs): if created: schedule = Schedule.objects.create(site=instance, master=True) Location.objects.create(site=instance, schedule=schedule) theme = Theme.objects.create(name=instance.name) sms = SmsSettings.objects.create(reseller_network=instance.reseller_network) instance.sms = sms stork = Stork(theme) stork.save() instance.theme = theme instance.save()
def new_site_setup(sender, instance, created, **kwargs): if created: schedule = Schedule.objects.create(site=instance, master=True) Location.objects.create(site=instance, schedule=schedule) theme = Theme.objects.create(name=instance.name) sms = SmsSettings.objects.create( reseller_network=instance.reseller_network) instance.sms = sms stork = Stork(theme) stork.save() instance.theme = theme instance.save()
def test_outputs_valid_css(): theme = Theme.objects.create(name='test') panels = Stork(theme, config_path='stork/tests/fixtures/valid.yml') panels.save() css = panels.css() parsed = cssutils.parseString(css) rule_count = 0 for component in panels.component_cache: if hasattr(component, 'properties'): rule_count += len(component.properties) else: rule_count += 1 assert len(parsed.cssRules) == rule_count
def font_data(self): stork = Stork(self.theme) data = dict((font.id, { 'stack': font.instance.font.stack, 'font_face': font.get_mobile_css() }) for font in stork.fonts) return {'md5': hashlib.md5(json.dumps(data)).hexdigest(), 'data': data}
def test_components_have_unique_keys(): panels = Stork(config_path='stork/tests/fixtures/valid.yml') for panel in panels: for group in panel: for component in group: assert component.key == '%s-%s' % (panel.name.lower(), component.name.lower())
def test_all_components_are_in_cache(): panels = Stork(config_path='stork/tests/fixtures/valid.yml') for panel in panels: for group in panel: for component in group: assert component in [v for k, v in panels.component_cache] assert panels[component.key] == component
def image_css(request, key): stork = Stork(request.site.theme) component = stork[key] css = component.get_css(request.POST.get('tiling')) return HttpResponse( json.dumps({ 'css': css, 'style_tag': '#' + component.style_tag_id }))
def font_css(request, selection_key, selected=None): stork = Stork(request.site.theme) component = stork[selection_key] if selected is not None: css = component.get_css(FontStack.objects.get(id=selected)) else: css = component.get_css() response = HttpResponse(mimetype='text/css') response.write(css) return response
def test_render_as_json(): panels = Stork(config_path='stork/tests/fixtures/valid.yml') swatch = panels['foo-baz'] swatch_as_array = [ swatch.get_picker_id(), "#" + swatch.style_tag_id, swatch.get_hidden_input_id(), swatch.get_selector_prop() ] assert swatch_as_array == swatch.for_json()
def stage_image(request, key): stork = Stork(request.site.theme) component = stork[key] form = component.form_instance(request.POST, request.FILES) form.save() return HttpResponse( json.dumps({ 'style_tag': '#' + component.style_tag_id, 'css': component.get_css(), 'component': key, 'url': component.instance.staged_image.url }))
def test_compresses_css(): theme = Theme.objects.create(name='test') panels = Stork(theme, config_path='stork/tests/fixtures/valid.yml') panels.save() css = panels.css() compressed = panels.compressed_css() assert len(css) > len(compressed)
def remove_image(request, key): stork = Stork(request.site.theme) component = stork[key] instance = component.instance real_delete = False if bool(instance.staged_image) and not request.POST.has_key( '%s-stale' % key): instance.staged_image.delete() else: real_delete = True return HttpResponse( json.dumps({ 'style_tag': '#' + component.style_tag_id, 'css': '' if real_delete else component.get_css(), 'component': key, 'delete': real_delete, }))
def theme_detail(request, theme_id): site = request.site theme = get_object_or_404(Theme, id=theme_id, private=False) if request.method == 'POST': old_theme = site.theme old_theme.delete() new_theme = Theme.objects.create() Stork(theme).copy_to(new_theme) site.theme = new_theme site.save() # trigger cache refresh new_theme.save() messages.success( request, "Theme changed successfully. <a href='/'>Have a look</a> or <a href='%s'>Start customizing it!</a>" % reverse('dashboard_look')) return HttpResponseRedirect(reverse('theme_list')) return direct_to_template(request, 'dashboard/look/theme_detail.html', {'theme': theme})
def handle_noargs(self, **options): s = Stork() config = {} for p in s.panels: pdict = {} if hasattr(p, 'component'): config[ p. name] = '<path relative to the "assets" directory or blank if none>' else: for g in p.groups: for c in g.components: if c.model.__name__ == 'Image': pdict[c.id] = { 'path': '<path relative to the "assets" directory or blank if none>', 'tiling': '<true or false>' } else: pdict[c.id] = '<edit value>' config[p.name] = pdict config['name'] = '<put name of this theme here>' config['dirname'] = '<name of /media/assets subdirectory>' config['description'] = '<flowery speak about this theme>' config['screenshot'] = '<path relative to the "assets" directory>' config['notes'] = '<tips for using the theme or blank>' print """ # This is your theme manifest file. It provides the crucial data for importing # a custom theme. It should go in a directory or a zip file with a # subdirectory titled "assets" containing any and all files you would like # uploaded as part of the theme. # # Files referenced as part of configuring user-selectable images with have their # new paths automatically generated. Paths in the config below are assumed to be # relative to the assets directory. Any other files will also be uploaded and # can be referenced at /static/theme-assets/<theme folder name>/<file name>. # # Edit the values below to match your theme. ---""" print yaml.dump(config, indent=2, default_flow_style=False)
def revert_html(request, key): stork = Stork(request.site.theme) stork[key].revert() return HttpResponseRedirect(request.META['HTTP_REFERER'])
def preview_html(request, key): stork = Stork(request.site.theme) stork[key].save(request.POST) return HttpResponseRedirect(request.META['HTTP_REFERER'])
def test_swatch_requires_properties(): panels = Stork(config_path='stork/tests/fixtures/no_swatch_properties.yml')
def save(request, redirect_to, callback=None): stork = Stork(request.site.theme) stork.save(request.POST, request.FILES) return HttpResponse("OK")
def test_swatch_requires_default(): panels = Stork(config_path='stork/tests/fixtures/no_swatch_default.yml')
def test_correct_subclass_is_assigned(): panels = Stork(config_path='stork/tests/fixtures/valid.yml') assert isinstance(panels['foo-baz'], SwatchComponent) assert isinstance(panels['bar-quux'], FontComponent)
def build_css(theme): stork = Stork(theme) return ';\n'.join("$%s: rgba(%s,%s)" % (swatch.id, swatch.instance.color, swatch.instance.alpha) for swatch in stork.swatches) + ";"
def test_create_panels(): panels = Stork(config_path='stork/tests/fixtures/valid.yml') assert len(panels) == 2
def test_component_groups_link_back_to_panels(): panels = Stork(config_path='stork/tests/fixtures/valid.yml') for panel in panels: for group in panel: assert group.panel == panel
def test_duplicate_panel_names(): Stork(config_path='stork/tests/fixtures/duplicate_panels.yml')
def test_component_groups_contain_components(): panels = Stork(config_path='stork/tests/fixtures/valid.yml') for panel in panels: for group in panel: for component in group: assert isinstance(component, BaseComponent)
def test_panel_contents_are_component_groups(): panels = Stork(config_path='stork/tests/fixtures/valid.yml') for panel in panels: for group in panel: assert isinstance(group, ComponentGroup)
def template(self): from tiger.stork import Stork stork = Stork(self.theme) return stork['layout'].as_template()