Пример #1
0
def deploy_single(path):
    """
    Deploy a single project to S3 and, if configured, to our servers.
    """
    require('settings', provided_by=[production, staging])
    slug, abspath = utils.parse_path(path)
    graphic_root = '%s/%s' % (abspath, slug)
    s3_root = '%s/graphics/%s' % (app_config.PROJECT_SLUG, slug)
    graphic_assets = '%s/assets' % graphic_root
    s3_assets = '%s/assets' % s3_root
    graphic_node_modules = '%s/node_modules' % graphic_root

    graphic_config = load_graphic_config(graphic_root)

    use_assets = getattr(graphic_config, 'USE_ASSETS', True)
    default_max_age = getattr(graphic_config, 'DEFAULT_MAX_AGE',
                              None) or app_config.DEFAULT_MAX_AGE
    assets_max_age = getattr(graphic_config, 'ASSETS_MAX_AGE',
                             None) or app_config.ASSETS_MAX_AGE
    update_copy(path)
    if use_assets:
        error = assets.sync(path)
        if error:
            return

    render.render(path)
    flat.deploy_folder(
        graphic_root,
        s3_root,
        headers={'Cache-Control': 'max-age=%i' % default_max_age},
        ignore=[
            '%s/*' % graphic_assets,
            '%s/*' % graphic_node_modules,
            # Ignore files unused on static S3 server
            '*.xls',
            '*.xlsx',
            '*.pyc',
            '*.py',
            '*.less',
            '*.bak',
            '%s/base_template.html' % graphic_root,
            '%s/child_template.html' % graphic_root,
            '%s/README.md' % graphic_root
        ])

    if use_assets:
        flat.deploy_folder(
            graphic_assets,
            s3_assets,
            headers={'Cache-Control': 'max-age=%i' % assets_max_age},
            ignore=['%s/private/*' % graphic_assets])

    # Need to explicitly point to index.html for the AWS staging link
    file_suffix = ''
    if env.settings == 'staging':
        file_suffix = 'index.html'

    print ''
    print '%s URL: %s/graphics/%s/%s' % (
        env.settings.capitalize(), app_config.S3_BASE_URL, slug, file_suffix)
Пример #2
0
def _graphics_detail(slug):
    """
    Renders a parent.html index with child.html embedded as iframe.
    """
    from flask import request

    graphic_path = '%s/%s' % (app_config.GRAPHICS_PATH, slug)

    # NOTE: Parent must load pym.js from same source as child to prevent version conflicts!
    context = make_context(asset_depth=2, root_path=graphic_path)
    context['slug'] = slug

    template = 'parent.html'

    try:
        graphic_config = load_graphic_config(graphic_path)
        context.update(graphic_config.__dict__)

        if hasattr(graphic_config, 'COPY_GOOGLE_DOC_KEY') and graphic_config.COPY_GOOGLE_DOC_KEY:
            copy_path = '%s/%s.xlsx' % (graphic_path, slug)

            if request.args.get('refresh'):
                oauth.get_document(graphic_config.COPY_GOOGLE_DOC_KEY, copy_path)

            context['COPY'] = copytext.Copy(filename=copy_path)
    except IOError:
        pass

    return make_response(render_template(template, **context))
Пример #3
0
def _graphics_detail(slug):
    """
    Renders a parent.html index with child.html embedded as iframe.
    """
    from flask import request

    graphic_path = '%s/%s' % (app_config.GRAPHICS_PATH, slug)

    # NOTE: Parent must load pym.js from same source as child to prevent
    # version conflicts!
    context = make_context(asset_depth=2, root_path=graphic_path)
    context['slug'] = slug
    context['type'] = 'graphics'  # From previous commit
    context['var_name'] = slug.replace('-', '_')

    template = 'parent.html'

    if not os.path.exists('%s/%s/js/lib/pym.js' % (app_config.GRAPHICS_PATH, slug)):
        template = 'parent_old.html'

    try:
        graphic_config = load_graphic_config(graphic_path)
        context.update(graphic_config.__dict__)

        if hasattr(graphic_config, 'COPY_GOOGLE_DOC_KEY') and graphic_config.COPY_GOOGLE_DOC_KEY:
            copy_path = '%s/%s.xlsx' % (graphic_path, slug)

            if request.args.get('refresh'):
                oauth.get_document(graphic_config.COPY_GOOGLE_DOC_KEY, copy_path)

            context['COPY'] = copytext.Copy(filename=copy_path)
    except IOError:
        pass

    return make_response(render_template(template, **context))
def _templates_detail(slug):
    """
    Renders a parent.html index with child.html embedded as iframe.
    """
    from flask import request

    template_path = '%s/%s' % (app_config.TEMPLATES_PATH, slug)
    base_template_path = '%s/%s' % (app_config.TEMPLATES_PATH, '_base')

    # NOTE: Parent must load pym.js from same source as child to prevent version conflicts!
    context = make_context(asset_depth=2, root_path=template_path)
    context['slug'] = slug

    try:
        graphic_config = load_graphic_config(template_path, [base_template_path])
        context.update(graphic_config.__dict__)

        if hasattr(graphic_config, 'COPY_GOOGLE_DOC_KEY') and graphic_config.COPY_GOOGLE_DOC_KEY:
            copy_path = '%s/%s.xlsx' % (template_path, slug)

            if request.args.get('refresh'):
                oauth.get_document(graphic_config.COPY_GOOGLE_DOC_KEY, copy_path)

            context['COPY'] = copytext.Copy(filename=copy_path)
    except IOError:
        pass

    return make_response(render_template('parent.html', **context))
Пример #5
0
def _graphics_child(slug):
    """
    Renders a child.html for embedding.
    """
    from flask import g
    alt_path = getattr(g, 'alt_path', None)
    if alt_path:
        graphic_path = alt_path
    else:
        graphic_path = '%s/%s' % (app_config.GRAPHICS_PATH, slug)

    # Fallback for legacy projects w/o child templates
    if not os.path.exists('%s/child_template.html' % graphic_path):
        with open('%s/child.html' % graphic_path) as f:
            contents = f.read()

        return contents

    context = make_context(asset_depth=2, root_path=graphic_path)
    context['slug'] = slug
    context['var_name'] = slug.replace('-', '_')

    env = Environment(loader=FileSystemLoader(graphic_path))

    try:
        graphic_config = load_graphic_config(graphic_path)
        context.update(graphic_config.__dict__)

        if hasattr(graphic_config, 'JINJA_FILTER_FUNCTIONS'):
            for func in graphic_config.JINJA_FILTER_FUNCTIONS:
                env.filters[func.__name__] = func

        if hasattr(graphic_config, 'COPY_GOOGLE_DOC_KEY') and graphic_config.COPY_GOOGLE_DOC_KEY:
            copy_path = '%s/%s.xlsx' % (graphic_path, slug)

            # Trim strings to avoid whitespace issues
            copy = copytext.Copy(filename=copy_path)
            for sheet in copy._copy:
                worksheet = copy[sheet]
                for row in worksheet:
                    stripped = []
                    for item in row._row:
                        if isinstance(item, str) or isinstance(item, unicode):
                            stripped.append(item.strip())
                        else:
                            stripped.append(item)
                    row._row = stripped

            context['COPY'] = copy
    except IOError:
        pass

    env.globals.update(render=render_with_context)
    env.filters['smarty'] = smarty_filter
    template = env.get_template('child_template.html')

    return make_response(template.render(**context))
Пример #6
0
def deploy(slug):
    """
    Deploy the latest app to S3 and, if configured, to our servers.
    """
    require('settings', provided_by=[production, staging])

    if not slug:
        print 'You must specify a project slug, like this: "deploy:slug"'
        return

    graphic_root = '%s/%s' % (app_config.GRAPHICS_PATH, slug)
    s3_root = '%s/graphics/%s' % (app_config.PROJECT_SLUG, slug)
    graphic_assets = '%s/assets' % graphic_root
    s3_assets = '%s/assets' % s3_root

    graphic_config = load_graphic_config(graphic_root)

    use_assets = getattr(graphic_config, 'USE_ASSETS', True)
    default_max_age = getattr(graphic_config, 'DEFAULT_MAX_AGE', None) or app_config.DEFAULT_MAX_AGE
    assets_max_age = getattr(graphic_config, 'ASSETS_MAX_AGE', None) or app_config.ASSETS_MAX_AGE

    update_copy(slug)

    if use_assets:
        assets.sync(slug)

    render.render(slug)

    flat.deploy_folder(
        graphic_root,
        s3_root,
        headers={
            'Cache-Control': 'max-age=%i' % default_max_age
        },
        ignore=['%s/*' % graphic_assets]
    )

    # Deploy parent assets
    flat.deploy_folder(
        'www',
        app_config.PROJECT_SLUG,
        headers={
            'Cache-Control': 'max-age=%i' % default_max_age
        }
    )

    if use_assets:
        flat.deploy_folder(
            graphic_assets,
            s3_assets,
            headers={
                'Cache-Control': 'max-age=%i' % assets_max_age
            }
        )

    print ''
    print '%s URL: %s/graphics/%s/' % (env.settings.capitalize(), app_config.S3_BASE_URL, slug)
Пример #7
0
def _templates_detail(slug):
    """
    Renders a parent.html index with child.html embedded as iframe.
    """
    from flask import request

    template_path = '%s/%s' % (app_config.TEMPLATES_PATH, slug)
    base_template_path = '%s/%s' % (app_config.TEMPLATES_PATH, '_base')

    # NOTE: Parent must load pym.js from same source as child to prevent version conflicts!
    context = make_context(asset_depth=2, root_path=template_path)
    context['slug'] = slug

    try:
        graphic_config = load_graphic_config(template_path, [base_template_path])
        context.update(graphic_config.__dict__)

        if hasattr(graphic_config, 'COPY_GOOGLE_DOC_KEY') and graphic_config.COPY_GOOGLE_DOC_KEY:
            copy_path = '%s/%s.xlsx' % (template_path, slug)

            if request.args.get('refresh'):
                oauth.get_document(graphic_config.COPY_GOOGLE_DOC_KEY, copy_path)

            context['COPY'] = copytext.Copy(filename=copy_path)

        if hasattr(graphic_config, 'AIRTABLE_ENDPOINTS') and graphic_config.AIRTABLE_ENDPOINTS and request.args.get('refresh'):
            for airtable_endpoint in graphic_config.AIRTABLE_ENDPOINTS:
                copy_path = '%s/%s.json' % (template_path, airtable_endpoint['name'])

                results = []
                url = airtable_endpoint['url']

                print 'downloading %s' % airtable_endpoint['name']

                while True:
                    response = requests.get(url)
                    response.raise_for_status()

                    data = json.loads(response.text)

                    results = results + data['records']

                    if 'offset' in data:
                        offset = data['offset']
                        url = '%s&offset=%s' % (airtable_endpoint['url'], offset)
                    else:
                        break

                print '%s records found' % len(results)

                with open(copy_path, 'w+') as outfile:
                    json.dump(results, outfile)

    except IOError:
        pass

    return make_response(render_template('parent.html', **context))
Пример #8
0
def copy_spreadsheet(slug):
    """
    Copy the COPY spreadsheet
    """
    _check_credentials()

    config_path = '%s/%s/' % (app_config.GRAPHICS_PATH, slug)
    graphic_config = load_graphic_config(config_path)

    if not hasattr(
            graphic_config,
            'COPY_GOOGLE_DOC_KEY') or not graphic_config.COPY_GOOGLE_DOC_KEY:
        print 'Skipping spreadsheet creation. (COPY_GOOGLE_DOC_KEY is not defined in %s/graphic_config.py.)' % slug
        return

    metadata = {'title': '%s GRAPHIC COPY' % slug}
    try:
        if app_config.DRIVE_SPREADSHEETS_FOLDER:
            metadata['parents'] = [{
                'id': app_config.DRIVE_SPREADSHEETS_FOLDER
            }]
    except AttributeError:
        pass

    kwargs = {
        'credentials': get_credentials(),
        'url':
        SPREADSHEET_COPY_URL_TEMPLATE % graphic_config.COPY_GOOGLE_DOC_KEY,
        'method': 'POST',
        'headers': {
            'Content-Type': 'application/json'
        },
        'body': json.dumps(metadata),
    }

    resp = app_config.authomatic.access(**kwargs)

    if resp.status == 200:
        spreadsheet_key = resp.data['id']
        spreadsheet_url = SPREADSHEET_VIEW_TEMPLATE % spreadsheet_key
        print 'New spreadsheet created successfully!'
        print 'View it online at %s' % spreadsheet_url
        utils.replace_in_file('%s/graphic_config.py' % config_path,
                              graphic_config.COPY_GOOGLE_DOC_KEY,
                              spreadsheet_key)

        return True
    else:
        utils.replace_in_file('%s/graphic_config.py' % config_path,
                              graphic_config.COPY_GOOGLE_DOC_KEY, '')
    print 'Error creating spreadsheet (status code %s) with message %s' % (
        resp.status, resp.reason)
    if resp.status == 404:
        print 'Please make sure you modify the DRIVE_SPREADSHEETS_FOLDER in app_config.py. Check the configuration section on the README.'
    return False
Пример #9
0
def _graphics_child(slug):
    """
    Renders a child.html for embedding.
    """
    graphic_path = '%s/%s' % (app_config.GRAPHICS_PATH, slug)
    print graphic_path

    # Fallback for legacy projects w/o child templates
    if not os.path.exists('%s/child_template.html' % graphic_path):
        with open('%s/child.html' % graphic_path) as f:
            contents = f.read()

        return contents

    context = make_context(asset_depth=2, root_path=graphic_path)
    context['slug'] = slug
    context['var_name'] = slug.replace('-', '_')

    env = Environment(loader=FileSystemLoader(graphic_path))

    try:
        graphic_config = load_graphic_config(graphic_path)
        context.update(graphic_config.__dict__)

        if hasattr(graphic_config, 'JINJA_FILTER_FUNCTIONS'):
            for func in graphic_config.JINJA_FILTER_FUNCTIONS:
                env.filters[func.__name__] = func

        if hasattr(graphic_config, 'COPY_GOOGLE_DOC_KEY') and graphic_config.COPY_GOOGLE_DOC_KEY:
            copy_path = '%s/%s.xlsx' % (graphic_path, slug)

            context['COPY'] = copytext.Copy(filename=copy_path)

        if hasattr(graphic_config, 'AIRTABLE_ENDPOINTS') and graphic_config.AIRTABLE_ENDPOINTS:
            context['AIRTABLE_DATA'] = []

            results = []
            for airtable_endpoint in graphic_config.AIRTABLE_ENDPOINTS:
                copy_path = '%s/%s.json' % (graphic_path, airtable_endpoint['name'])

                with open(copy_path) as infile:
                    results = infile.read()

                context['AIRTABLE_DATA'].append({
                        'name': airtable_endpoint['name'],
                        'data': results
                    })
    except IOError:
        pass

    env.globals.update(render=render_with_context)
    env.filters['smarty'] = smarty_filter
    template = env.get_template('child_template.html')

    return make_response(template.render(**context))
Пример #10
0
def deploy_single(path):
    """
    Deploy a single project to S3 and, if configured, to our servers.
    """
    require('settings', provided_by=[production, staging])
    slug, abspath = utils.parse_path(path)
    graphic_root = '%s/%s' % (abspath, slug)
    s3_root = '%s/graphics/%s' % (app_config.PROJECT_SLUG, slug)
    graphic_assets = '%s/assets' % graphic_root
    s3_assets = '%s/assets' % s3_root
    graphic_node_modules = '%s/node_modules' % graphic_root

    graphic_config = load_graphic_config(graphic_root)

    use_assets = getattr(graphic_config, 'USE_ASSETS', True)
    default_max_age = getattr(graphic_config, 'DEFAULT_MAX_AGE', None) or app_config.DEFAULT_MAX_AGE
    assets_max_age = getattr(graphic_config, 'ASSETS_MAX_AGE', None) or app_config.ASSETS_MAX_AGE
    update_copy(path)
    if use_assets:
        error = assets.sync(path)
        if error:
            return

    render.render(path)
    flat.deploy_folder(
        graphic_root,
        s3_root,
        headers={
            'Cache-Control': 'max-age=%i' % default_max_age
        },
        ignore=['%s/*' % graphic_assets, '%s/*' % graphic_node_modules,
                # Ignore files unused on static S3 server
                '*.xls', '*.xlsx', '*.pyc', '*.py', '*.less', '*.bak',
                '%s/base_template.html' % graphic_root,
                '%s/child_template.html' % graphic_root,
                '%s/README.md' % graphic_root]
    )

    if use_assets:
        flat.deploy_folder(
            graphic_assets,
            s3_assets,
            headers={
                'Cache-Control': 'max-age=%i' % assets_max_age
            },
            ignore=['%s/private/*' % graphic_assets]
        )

    # Need to explicitly point to index.html for the AWS staging link
    file_suffix = ''
    if env.settings == 'staging':
        file_suffix = 'index.html'

    print ''
    print '%s URL: %s/graphics/%s/%s' % (env.settings.capitalize(), app_config.S3_BASE_URL, slug, file_suffix)
Пример #11
0
def deploy_single(slug):
    """
    Deploy a single project to S3 and, if configured, to our servers.
    """
    require('settings', provided_by=[production, staging])

    graphic_root = '%s/%s' % (app_config.GRAPHICS_PATH, slug)
    s3_root = '%s/graphics/%s' % (app_config.PROJECT_SLUG, slug)
    graphic_assets = '%s/assets' % graphic_root
    s3_assets = '%s/assets' % s3_root

    graphic_config = load_graphic_config(graphic_root)

    use_assets = getattr(graphic_config, 'USE_ASSETS', True)
    default_max_age = getattr(graphic_config, 'DEFAULT_MAX_AGE', None) or app_config.DEFAULT_MAX_AGE
    assets_max_age = getattr(graphic_config, 'ASSETS_MAX_AGE', None) or app_config.ASSETS_MAX_AGE

    update_copy(slug)

    if use_assets:
        assets.sync(slug)

    render.render(slug)

    flat.deploy_folder(
        graphic_root,
        s3_root,
        headers={
            'Cache-Control': 'max-age=%i' % default_max_age
        },
        ignore=['%s/*' % graphic_assets]
    )

    # Deploy parent assets
    flat.deploy_folder(
        'www',
        app_config.PROJECT_SLUG,
        headers={
            'Cache-Control': 'max-age=%i' % default_max_age
        }
    )

    if use_assets:
        flat.deploy_folder(
            graphic_assets,
            s3_assets,
            headers={
                'Cache-Control': 'max-age=%i' % assets_max_age
            }
        )

    print ''
    print '%s URL: %s/graphics/%s/' % (env.settings.capitalize(), app_config.S3_BASE_URL, slug)
Пример #12
0
def download_copy(slug):
    """
    Downloads cloud data.
    """
    graphic_path = '%s/%s' % (app_config.GRAPHICS_PATH, slug)
    try:
        graphic_config = load_graphic_config(graphic_path)
    except (ImportError, IOError):
        print '%s/graphic_config.py does not exist.' % slug
        return

    download_google_sheet(slug, graphic_config)
    download_airtable_sheets(slug, graphic_config)
Пример #13
0
def _templates_child(slug):
    """
    Renders a child.html for embedding.
    """
    template_path = '%s/%s' % (app_config.TEMPLATES_PATH, slug)
    base_template_path = '%s/%s' % (app_config.TEMPLATES_PATH, '_base')

    # Fallback for legacy projects w/o child templates
    if not os.path.exists('%s/child_template.html' % template_path):
        with open('%s/child.html' % template_path) as f:
            contents = f.read()

        return contents

    context = make_context(asset_depth=2, root_path=template_path)
    context['slug'] = slug

    env = Environment(loader=FileSystemLoader([
        template_path,
        '%s/_base' % app_config.TEMPLATES_PATH])
    )

    try:
        graphic_config = load_graphic_config(
            template_path, [base_template_path])
        context.update(graphic_config.__dict__)

        if hasattr(graphic_config, 'JINJA_FILTER_FUNCTIONS'):
            for func in graphic_config.JINJA_FILTER_FUNCTIONS:
                env.filters[func.__name__] = func

        if hasattr(graphic_config, 'COPY_GOOGLE_DOC_KEY') and graphic_config.COPY_GOOGLE_DOC_KEY:
            copy_path = '%s/%s.xlsx' % (template_path, slug)

            context['COPY'] = copytext.Copy(filename=copy_path)
    except IOError:
        pass

    env.globals.update(render=render_with_context)
    env.filters['smarty'] = smarty_filter
    template = env.get_template('child_template.html')

    # Save for uploading to S3.
    html = template.render(**context)
    with open('%s/child.html' % template_path, "w") as filename:
        html = html.replace('.less', '.css')
        filename.write(html)

    return make_response(template.render(**context))
Пример #14
0
def copy_spreadsheet(slug):
    """
    Copy the COPY spreadsheet
    """
    _check_credentials()

    config_path = '%s/%s/' % (app_config.GRAPHICS_PATH, slug)
    graphic_config = load_graphic_config(config_path)

    if not hasattr(
            graphic_config,
            'COPY_GOOGLE_DOC_KEY') or not graphic_config.COPY_GOOGLE_DOC_KEY:
        print 'Skipping spreadsheet creation. (COPY_GOOGLE_DOC_KEY is not defined in %s/graphic_config.py.)' % slug
        return

    kwargs = {
        'credentials': get_credentials(),
        'url':
        SPREADSHEET_COPY_URL_TEMPLATE % graphic_config.COPY_GOOGLE_DOC_KEY,
        'method': 'POST',
        'headers': {
            'Content-Type': 'application/json'
        },
        'body': json.dumps({
            'title': '%s GRAPHIC COPY' % slug,
        }),
    }

    resp = app_config.authomatic.access(**kwargs)

    if resp.status == 200:
        spreadsheet_key = resp.data['id']
        spreadsheet_url = SPREADSHEET_VIEW_TEMPLATE % spreadsheet_key
        print 'New spreadsheet created successfully!'
        print 'View it online at %s' % spreadsheet_url
        utils.replace_in_file('%s/graphic_config.py' % config_path,
                              graphic_config.COPY_GOOGLE_DOC_KEY,
                              spreadsheet_key)

        return True
    else:
        utils.replace_in_file(config_path, graphic_config.COPY_GOOGLE_DOC_KEY,
                              '')

    print 'Error creating spreadsheet (status code %s) with message %s' % (
        resp.status, resp.reason)
    return False
Пример #15
0
def _graphics_detail(slug):
    """
    Renders a parent.html index with child.html embedded as iframe.
    """
    from flask import request, g

    alt_path = getattr(g, 'alt_path', None)
    if alt_path:
        graphic_path = alt_path
    else:
        graphic_path = '%s/%s' % (app_config.GRAPHICS_PATH, slug)

    # NOTE: Parent must load pym.js from same source as child to prevent version conflicts!
    context = make_context(asset_depth=2, root_path=graphic_path)
    context['slug'] = slug
    context['var_name'] = slug.replace('-', '_')

    # Use local_pym for legacy graphics
    local_pym = getattr(g, 'local_pym', None)
    context['LOCAL_PYM'] = local_pym
    # warning message
    custom_location = getattr(g, 'custom_location', None)
    context['CUSTOM_LOCATION'] = custom_location

    template = 'parent.html'

    try:
        graphic_config = load_graphic_config(graphic_path)
        context.update(graphic_config.__dict__)

        if hasattr(graphic_config, 'COPY_GOOGLE_DOC_KEY') and graphic_config.COPY_GOOGLE_DOC_KEY:
            copy_path = '%s/%s.xlsx' % (graphic_path, slug)

            if request.args.get('refresh'):
                oauth.get_document(graphic_config.COPY_GOOGLE_DOC_KEY, copy_path)

            context['COPY'] = copytext.Copy(filename=copy_path)
    except IOError:
        pass

    try:
        env = Environment(loader=FileSystemLoader(graphic_path))
        template = env.get_template('parent.html')
        return make_response(template.render(**context))
    except TemplateNotFound:
        return make_response(render_template(template, **context))
Пример #16
0
def _graphics_detail(slug):
    """
    Renders a parent.html index with child.html embedded as iframe.
    """
    from flask import request, g

    alt_path = getattr(g, 'alt_path', None)
    if alt_path:
        graphic_path = alt_path
    else:
        graphic_path = '%s/%s' % (app_config.GRAPHICS_PATH, slug)

    # NOTE: Parent must load pym.js from same source as child to prevent version conflicts!
    context = make_context(asset_depth=2, root_path=graphic_path)
    context['slug'] = slug
    context['var_name'] = slug.replace('-', '_')

    # Use local_pym for legacy graphics
    local_pym = getattr(g, 'local_pym', None)
    context['LOCAL_PYM'] = local_pym
    # warning message
    custom_location = getattr(g, 'custom_location', None)
    context['CUSTOM_LOCATION'] = custom_location

    template = 'parent.html'

    try:
        graphic_config = load_graphic_config(graphic_path)
        context.update(graphic_config.__dict__)

        if hasattr(graphic_config, 'COPY_GOOGLE_DOC_KEY') and graphic_config.COPY_GOOGLE_DOC_KEY:
            copy_path = '%s/%s.xlsx' % (graphic_path, slug)

            if request.args.get('refresh'):
                oauth.get_document(graphic_config.COPY_GOOGLE_DOC_KEY, copy_path)

            context['COPY'] = copytext.Copy(filename=copy_path)
    except IOError:
        pass

    try:
        env = Environment(loader=FileSystemLoader(graphic_path))
        template = env.get_template('parent.html')
        return make_response(template.render(**context))
    except TemplateNotFound:
        return make_response(render_template(template, **context))
Пример #17
0
def copy_spreadsheet(slug):
    """
    Copy the COPY spreadsheet
    """
    _check_credentials()

    config_path = '%s/%s/' % (app_config.GRAPHICS_PATH, slug)
    graphic_config = load_graphic_config(config_path)

    if not hasattr(graphic_config, 'COPY_GOOGLE_DOC_KEY') or not graphic_config.COPY_GOOGLE_DOC_KEY:
        print 'Skipping spreadsheet creation. (COPY_GOOGLE_DOC_KEY is not defined in %s/graphic_config.py.)' % slug
        return

    metadata = {'title': '%s GRAPHIC COPY' % slug}
    try:
        if app_config.DRIVE_SPREADSHEETS_FOLDER:
            metadata['parents'] = [{
                'id': app_config.DRIVE_SPREADSHEETS_FOLDER}]
    except AttributeError:
        pass

    kwargs = {
        'credentials': get_credentials(),
        'url': SPREADSHEET_COPY_URL_TEMPLATE % graphic_config.COPY_GOOGLE_DOC_KEY,
        'method': 'POST',
        'headers': {'Content-Type': 'application/json'},
        'body': json.dumps(metadata),
    }

    resp = app_config.authomatic.access(**kwargs)

    if resp.status == 200:
        spreadsheet_key = resp.data['id']
        spreadsheet_url = SPREADSHEET_VIEW_TEMPLATE % spreadsheet_key
        print 'New spreadsheet created successfully!'
        print 'View it online at %s' % spreadsheet_url
        utils.replace_in_file('%s/graphic_config.py' % config_path , graphic_config.COPY_GOOGLE_DOC_KEY, spreadsheet_key)

        return True
    else:
        utils.replace_in_file('%s/graphic_config.py' % config_path, graphic_config.COPY_GOOGLE_DOC_KEY, '')
    print 'Error creating spreadsheet (status code %s) with message %s' % (resp.status, resp.reason)
    if resp.status == 404:
        print 'Please make sure you modify the DRIVE_SPREADSHEETS_FOLDER in app_config.py. Check the configuration section on the README.'
    return False
Пример #18
0
def deploy_to_production(slug):
    require('settings', provided_by=[production, staging])

    graphic_root = '%s/%s' % (app_config.GRAPHICS_PATH, slug)
    graphic_assets = '%s/assets' % graphic_root
    graphic_config = load_graphic_config(graphic_root)
    default_max_age = getattr(graphic_config, 'DEFAULT_MAX_AGE', None) or app_config.DEFAULT_MAX_AGE

    flat.deploy_folder(
        graphic_root,
        slug,
        headers={
            'Cache-Control': 'max-age=%i' % default_max_age
        },
        ignore=['%s/*' % graphic_assets]
    )

    write_meta_json(slug, 'deploy')
Пример #19
0
def deploy_to_production(slug):
    require('settings', provided_by=[production, staging])

    graphic_root = '%s/%s' % (app_config.GRAPHICS_PATH, slug)
    graphic_assets = '%s/assets' % graphic_root
    graphic_config = load_graphic_config(graphic_root)
    default_max_age = getattr(graphic_config, 'DEFAULT_MAX_AGE', None) or app_config.DEFAULT_MAX_AGE

    flat.deploy_folder(
        graphic_root,
        slug,
        headers={
            'Cache-Control': 'max-age=%i' % default_max_age
        },
        ignore=['%s/*' % graphic_assets]
    )

    write_meta_json(slug, 'deploy')
Пример #20
0
    def decorated_function(*args, **kwargs):
        from flask import request

        if request.path.startswith('/graphics/'):
            slug = request.path.split('/')[-2]
            graphic_path = '%s/%s' % (app_config.GRAPHICS_PATH, slug)

            try:
                graphic_config = load_graphic_config(graphic_path)
            except IOError:
                return f(*args, **kwargs)

            credentials = get_credentials()

            if hasattr(graphic_config, 'COPY_GOOGLE_DOC_KEY') and graphic_config.COPY_GOOGLE_DOC_KEY and (not credentials or not credentials.valid):
                return redirect(url_for('_oauth.oauth_alert'))

        return f(*args, **kwargs)
Пример #21
0
def download_copy(slug):
    """
    Downloads a Google Doc as an .xlsx file.
    """
    graphic_path = '%s/%s' % (app_config.GRAPHICS_PATH, slug)

    try:
        graphic_config = load_graphic_config(graphic_path)
    except IOError:
        print '%s/graphic_config.py does not exist.' % slug
        return

    if not hasattr(graphic_config, 'COPY_GOOGLE_DOC_KEY') or not graphic_config.COPY_GOOGLE_DOC_KEY:
        print 'COPY_GOOGLE_DOC_KEY is not defined in %s/graphic_config.py.' % slug
        return

    copy_path = os.path.join(graphic_path, '%s.xlsx' % slug)
    get_document(graphic_config.COPY_GOOGLE_DOC_KEY, copy_path)
Пример #22
0
    def decorated_function(*args, **kwargs):
        from flask import request

        if request.path.startswith('/graphics/'):
            slug = request.path.split('/')[-2]
            graphic_path = '%s/%s' % (app_config.GRAPHICS_PATH, slug)

            try:
                graphic_config = load_graphic_config(graphic_path)
            except IOError:
                return f(*args, **kwargs)

            credentials = get_credentials()

            if hasattr(graphic_config, 'COPY_GOOGLE_DOC_KEY') and graphic_config.COPY_GOOGLE_DOC_KEY and (not credentials or not credentials.valid):
                return redirect(url_for('_oauth.oauth_alert'))

        return f(*args, **kwargs)
Пример #23
0
def open_spreadsheet(slug):
    """
    Open the spreadsheet associated with a given slug
    """

    config_path, _ = _search_graphic_slug(slug)
    try:
        graphic_config = load_graphic_config(config_path)
    except ImportError:
        print 'graphic_config.py not found for %s on graphics or graphics-archive repos' % slug
        return

    if not hasattr(graphic_config, 'COPY_GOOGLE_DOC_KEY') or not graphic_config.COPY_GOOGLE_DOC_KEY:
        print 'There seems to be no spreadsheet linked to that slug. (COPY_GOOGLE_DOC_KEY is not defined in %s/graphic_config.py.)' % slug
        return

    spreadsheet_url = SPREADSHEET_VIEW_TEMPLATE % graphic_config.COPY_GOOGLE_DOC_KEY
    webbrowser.open_new(spreadsheet_url)
Пример #24
0
def open_spreadsheet(slug):
    """
    Open the spreadsheet associated with a given slug
    """

    config_path, _ = _search_graphic_slug(slug)
    try:
        graphic_config = load_graphic_config(config_path)
    except ImportError:
        print 'graphic_config.py not found for %s on graphics or graphics-archive repos' % slug
        return

    if not hasattr(graphic_config, 'COPY_GOOGLE_DOC_KEY') or not graphic_config.COPY_GOOGLE_DOC_KEY:
        print 'There seems to be no spreadsheet linked to that slug. (COPY_GOOGLE_DOC_KEY is not defined in %s/graphic_config.py.)' % slug
        return

    spreadsheet_url = SPREADSHEET_VIEW_TEMPLATE % graphic_config.COPY_GOOGLE_DOC_KEY
    webbrowser.open_new(spreadsheet_url)
Пример #25
0
def download_copy(slug):
    """
    Downloads a Google Doc as an .xlsx file.
    """
    graphic_path = '%s/%s' % (app_config.GRAPHICS_PATH, slug)

    try:
        graphic_config = load_graphic_config(graphic_path)
    except IOError:
        print '%s/graphic_config.py does not exist.' % slug
        return

    if not hasattr(graphic_config, 'COPY_GOOGLE_DOC_KEY') or not graphic_config.COPY_GOOGLE_DOC_KEY:
        print 'COPY_GOOGLE_DOC_KEY is not defined in %s/graphic_config.py.' % slug
        return

    copy_path = os.path.join(graphic_path, '%s.xlsx' % slug)
    get_document(graphic_config.COPY_GOOGLE_DOC_KEY, copy_path)
Пример #26
0
def _graphics_child(slug):
    """
    Renders a child.html for embedding.
    """
    from flask import g
    alt_path = getattr(g, 'alt_path', None)
    if alt_path:
        graphic_path = alt_path
    else:
        graphic_path = '%s/%s' % (app_config.GRAPHICS_PATH, slug)

    # Fallback for legacy projects w/o child templates
    if not os.path.exists('%s/child_template.html' % graphic_path):
        with open('%s/child.html' % graphic_path) as f:
            contents = f.read()

        return contents

    context = make_context(asset_depth=2, root_path=graphic_path)
    context['slug'] = slug
    context['var_name'] = slug.replace('-', '_')

    env = Environment(loader=FileSystemLoader(graphic_path))

    try:
        graphic_config = load_graphic_config(graphic_path)
        context.update(graphic_config.__dict__)

        if hasattr(graphic_config, 'JINJA_FILTER_FUNCTIONS'):
            for func in graphic_config.JINJA_FILTER_FUNCTIONS:
                env.filters[func.__name__] = func

        if hasattr(graphic_config, 'COPY_GOOGLE_DOC_KEY') and graphic_config.COPY_GOOGLE_DOC_KEY:
            copy_path = '%s/%s.xlsx' % (graphic_path, slug)

            context['COPY'] = copytext.Copy(filename=copy_path)
    except IOError:
        pass

    env.globals.update(render=render_with_context)
    env.filters['smarty'] = smarty_filter
    template = env.get_template('child_template.html')

    return make_response(template.render(**context))
Пример #27
0
def _templates_child(slug):
    """
    Renders a child.html for embedding.
    """
    template_path = '%s/%s' % (app_config.TEMPLATES_PATH, slug)
    base_template_path = '%s/%s' % (app_config.TEMPLATES_PATH, '_base')

    # Fallback for legacy projects w/o child templates
    if not os.path.exists('%s/child_template.html' % template_path):
        with open('%s/child.html' % template_path) as f:
            contents = f.read()

        return contents

    context = make_context(asset_depth=2, root_path=template_path)
    context['slug'] = slug

    env = Environment(loader=FileSystemLoader(
        [template_path, '%s/_base' % app_config.TEMPLATES_PATH]))

    try:
        graphic_config = load_graphic_config(template_path,
                                             [base_template_path])
        context.update(graphic_config.__dict__)

        if hasattr(graphic_config, 'JINJA_FILTER_FUNCTIONS'):
            for func in graphic_config.JINJA_FILTER_FUNCTIONS:
                env.filters[func.__name__] = func

        if hasattr(
                graphic_config,
                'COPY_GOOGLE_DOC_KEY') and graphic_config.COPY_GOOGLE_DOC_KEY:
            copy_path = '%s/%s.xlsx' % (template_path, slug)

            context['COPY'] = copytext.Copy(filename=copy_path)
    except IOError:
        pass

    env.globals.update(render=render_with_context)
    template = env.get_template('child_template.html')

    return make_response(template.render(**context))
Пример #28
0
def get_graphic_template_variables(path, graphic_number):
    """
    Generates the template variables for each graphic
    """
    slug, abspath = utils.parse_path(path)
    graphic_path = '%s/%s' % (abspath, slug)

    ## Get Spreadsheet Path
    try:
        graphic_config = load_graphic_config(graphic_path)
    except IOError:
        print '%s/graphic_config.py does not exist.' % slug
        return

    if not hasattr(
            graphic_config,
            'COPY_GOOGLE_DOC_KEY') or not graphic_config.COPY_GOOGLE_DOC_KEY:
        print 'COPY_GOOGLE_DOC_KEY is not defined in %s/graphic_config.py.' % slug
        return

    ## Generate Links From Slug
    spreadsheet_id = graphic_config.COPY_GOOGLE_DOC_KEY
    app_id = slug

    ## Update Spreadsheet
    copy_path = os.path.join(graphic_path, '%s.xlsx' % slug)
    get_document(graphic_config.COPY_GOOGLE_DOC_KEY, copy_path)

    ## Get Sheet Data
    copy = copytext.Copy(filename=copy_path)
    sheet = copy['labels']

    note = {
        "spreadsheet_id": spreadsheet_id,
        "app_id": app_id,
        "graphic_number": graphic_number + 1,
        "sheet": sheet,
    }

    return note
Пример #29
0
def copy_spreadsheet(slug):
    """
    Copy the COPY spreadsheet
    """
    _check_credentials()

    config_path = '%s/%s/' % (app_config.GRAPHICS_PATH, slug)
    graphic_config = load_graphic_config(config_path)

    if not hasattr(graphic_config, 'COPY_GOOGLE_DOC_KEY') or not graphic_config.COPY_GOOGLE_DOC_KEY:
        print 'Skipping spreadsheet creation. (COPY_GOOGLE_DOC_KEY is not defined in %s/graphic_config.py.)' % slug
        return

    kwargs = {
        'credentials': get_credentials(),
        'url': SPREADSHEET_COPY_URL_TEMPLATE % graphic_config.COPY_GOOGLE_DOC_KEY,
        'method': 'POST',
        'headers': {'Content-Type': 'application/json'},
        'body': json.dumps({
            'title': '%s GRAPHIC COPY' % slug,
        }),
    }

    resp = app_config.authomatic.access(**kwargs)

    if resp.status == 200:
        spreadsheet_key = resp.data['id']
        spreadsheet_url = SPREADSHEET_VIEW_TEMPLATE % spreadsheet_key
        print 'New spreadsheet created successfully!'
        print 'View it online at %s' % spreadsheet_url
        utils.replace_in_file('%s/graphic_config.py' % config_path , graphic_config.COPY_GOOGLE_DOC_KEY, spreadsheet_key)

        return True

        utils.replace_in_file(config_path, graphic_config.COPY_GOOGLE_DOC_KEY, '')

    print 'Error creating spreadsheet (status code %s) with message %s' % (resp.status, resp.reason)
    return False
Пример #30
0
def get_graphic_template_variables(path, graphic_number):
    """
    Generates the template variables for each graphic
    """
    slug, abspath = utils.parse_path(path)
    graphic_path = '%s/%s' % (abspath, slug)

    ## Get Spreadsheet Path
    try:
        graphic_config = load_graphic_config(graphic_path)
    except IOError:
        print '%s/graphic_config.py does not exist.' % slug
        return

    if not hasattr(graphic_config, 'COPY_GOOGLE_DOC_KEY') or not graphic_config.COPY_GOOGLE_DOC_KEY:
        print 'COPY_GOOGLE_DOC_KEY is not defined in %s/graphic_config.py.' % slug
        return

    ## Generate Links From Slug
    spreadsheet_id = graphic_config.COPY_GOOGLE_DOC_KEY
    app_id = slug

    ## Update Spreadsheet
    copy_path = os.path.join(graphic_path, '%s.xlsx' % slug)
    get_document(graphic_config.COPY_GOOGLE_DOC_KEY, copy_path)

    ## Get Sheet Data
    copy = copytext.Copy(filename=copy_path)
    sheet = copy['labels']

    note = {
        "spreadsheet_id": spreadsheet_id,
        "app_id": app_id,
        "graphic_number": graphic_number + 1,
        "sheet": sheet,
    }

    return note
Пример #31
0
def _graphics_child(slug):
    """
    Renders a child.html for embedding.
    """
    graphic_path = '%s/%s' % (app_config.GRAPHICS_PATH, slug)
    print graphic_path

    # Fallback for legacy projects w/o child templates
    if not os.path.exists('%s/child_template.html' % graphic_path):
        with open('%s/child.html' % graphic_path) as f:
            contents = f.read()

        return contents

    context = make_context(asset_depth=2, root_path=graphic_path)
    context['slug'] = slug

    env = Environment(loader=FileSystemLoader(graphic_path))

    try:
        graphic_config = load_graphic_config(graphic_path)
        context.update(graphic_config.__dict__)

        if hasattr(graphic_config, 'JINJA_FILTER_FUNCTIONS'):
            for func in graphic_config.JINJA_FILTER_FUNCTIONS:
                env.filters[func.__name__] = func

        if hasattr(graphic_config, 'COPY_GOOGLE_DOC_KEY') and graphic_config.COPY_GOOGLE_DOC_KEY:
            copy_path = '%s/%s.xlsx' % (graphic_path, slug)

            context['COPY'] = copytext.Copy(filename=copy_path)
    except IOError:
        pass

    env.globals.update(render=render_with_context)
    template = env.get_template('child_template.html')

    return make_response(template.render(**context))
Пример #32
0
def copy_spreadsheet(slug):
    """
    Copy the COPY spreadsheet
    """
    _check_credentials()

    config_path = "%s/%s/" % (app_config.GRAPHICS_PATH, slug)
    graphic_config = load_graphic_config(config_path)

    if not hasattr(graphic_config, "COPY_GOOGLE_DOC_KEY") or not graphic_config.COPY_GOOGLE_DOC_KEY:
        print "Skipping spreadsheet creation. (COPY_GOOGLE_DOC_KEY is not defined in %s/graphic_config.py.)" % slug
        return

    kwargs = {
        "credentials": get_credentials(),
        "url": SPREADSHEET_COPY_URL_TEMPLATE % graphic_config.COPY_GOOGLE_DOC_KEY,
        "method": "POST",
        "headers": {"Content-Type": "application/json"},
        "body": json.dumps({"title": "%s GRAPHIC COPY" % slug}),
    }

    resp = app_config.authomatic.access(**kwargs)

    if resp.status == 200:
        spreadsheet_key = resp.data["id"]
        spreadsheet_url = SPREADSHEET_VIEW_TEMPLATE % spreadsheet_key
        print "New spreadsheet created successfully!"
        print "View it online at %s" % spreadsheet_url
        utils.replace_in_file("%s/graphic_config.py" % config_path, graphic_config.COPY_GOOGLE_DOC_KEY, spreadsheet_key)

        return True

        utils.replace_in_file(config_path, graphic_config.COPY_GOOGLE_DOC_KEY, "")

    print "Error creating spreadsheet (status code %s) with message %s" % (resp.status, resp.reason)
    return False
Пример #33
0
def deploy_single(slug):
    """
    Deploy a single project to S3 and, if configured, to our servers.
    """
    require('settings', provided_by=[production, staging])

    graphic_root = '%s/%s' % (app_config.GRAPHICS_PATH, slug)
    s3_root = '%s/graphics/%s' % (app_config.PROJECT_SLUG, slug)
    graphic_assets = '%s/assets' % graphic_root
    s3_assets = '%s/assets' % s3_root

    # New to The Lens. Check if fallback image has been created
    if not os.path.isfile('%s/fallback.png' % graphic_root):
        print 'Render a fallback image before deploying. ' + \
            'Run "fab render.save_fallback_image:slug".'
        return

    graphic_config = load_graphic_config(graphic_root)

    use_assets = getattr(graphic_config, 'USE_ASSETS', True)
    default_max_age = getattr(
        graphic_config, 'DEFAULT_MAX_AGE', None) or app_config.DEFAULT_MAX_AGE
    assets_max_age = getattr(
        graphic_config, 'ASSETS_MAX_AGE', None) or app_config.ASSETS_MAX_AGE

    update_copy(slug)

    if use_assets:
        assets.sync(slug)

    render.render(slug)

    flat.deploy_folder(
        graphic_root,
        s3_root,
        headers={
            'Cache-Control': 'max-age=%i' % default_max_age
        },
        ignore=['%s/*' % graphic_assets]
    )

    # Deploy parent assets
    flat.deploy_folder(
        'www',
        app_config.PROJECT_SLUG,
        headers={
            'Cache-Control': 'max-age=%i' % default_max_age
        }
    )

    if use_assets:
        flat.deploy_folder(
            graphic_assets,
            s3_assets,
            headers={
                'Cache-Control': 'max-age=%i' % assets_max_age
            }
        )

    print '\n%s URL: %s/graphics/%s/' % (
        env.settings.capitalize(), app_config.S3_BASE_URL, slug)
Пример #34
0
def copy_spreadsheet(slug):
    """
    Copy the template Google spreadsheet into the graphics folder on Drive.
    """
    _check_credentials()

    config_path = '%s/%s/' % (app_config.GRAPHICS_PATH, slug)
    graphic_config = load_graphic_config(config_path)

    new_file_key = graphic_config.COPY_GOOGLE_DOC_KEY

    if not hasattr(graphic_config, 'COPY_GOOGLE_DOC_KEY') or not new_file_key:
        print 'Skipping spreadsheet creation. (COPY_GOOGLE_DOC_KEY is not ' + \
            'defined in %s/graphic_config.py.)' % slug
        return

    req_url = SPREADSHEET_COPY_URL_TEMPLATE % graphic_config.COPY_GOOGLE_DOC_KEY
    kwargs = {
        'credentials': get_credentials(),
        'url': req_url,
        'method': 'POST',
        'headers': {'Content-Type': 'application/json'},
        'body': json.dumps({
            'title': slug
        }),
    }

    resp = app_config.authomatic.access(**kwargs)

    if resp.status == 200:  # Sucessfully created file
        print resp
        spreadsheet_key = resp.data['id']

        # Copy file in Drive from 'templates' to 'graphics' directory.
        graphics_dir_key = '0B95Rq71MRLfHY0gxUURqbS1tWDg'  # TODO: move to cfg
        request_url = 'https://www.googleapis.com/drive/v2/files/' + \
            '%s/parents' % spreadsheet_key
        kwargs = {
            'credentials': get_credentials(),
            'url': request_url,
            'method': 'POST',
            'headers': {'Content-Type': 'application/json'},
            'body': json.dumps({
                'id': graphics_dir_key
            })
        }
        resp2 = app_config.authomatic.access(**kwargs)

        if resp2.status == 200:  # Successfully copied file to 'graphics' folder
            # Delete old file from 'templates' directory.
            templates_dir_key = '0B95Rq71MRLfHeTlSNmtnWmEwQ28'
            request_url = 'https://www.googleapis.com/drive/v2/files/' + \
                '%s/parents/%s' % (spreadsheet_key, templates_dir_key)
            kwargs = {
                'credentials': get_credentials(),
                'url': request_url,
                'method': 'DELETE',
                'headers': {'Content-Type': 'application/json'}
            }
            resp3 = app_config.authomatic.access(**kwargs)

            if resp3.status == 204:  # Successfully deleted old file
                spreadsheet_url = SPREADSHEET_VIEW_TEMPLATE % spreadsheet_key
                print 'New spreadsheet created successfully!'
                # local('open %s' % spreadsheet_url)
                print 'View it online at %s' % spreadsheet_url
                utils.replace_in_file(
                    '%s/graphic_config.py' % config_path,
                    graphic_config.COPY_GOOGLE_DOC_KEY,
                    spreadsheet_key)

                return True

                utils.replace_in_file(
                    config_path, graphic_config.COPY_GOOGLE_DOC_KEY, '')

    print 'Error creating spreadsheet (status code %s) with message %s' % (
        resp.status, resp.reason)
    return False
Пример #35
0
def deploy_single(path):
    """
    Deploy a single project to S3 and, if configured, to our servers.
    """
    require('settings', provided_by=[production, staging])
    SLACK_TOKEN = os.environ.get('SLACK_TOKEN')

    if SLACK_TOKEN == None:
        print "Can't find the Slack Token. Source your bash."
        return

    slack_client = SlackClient(SLACK_TOKEN)
    slug, abspath = utils.parse_path(path)
    graphic_root = '%s/%s' % (abspath, slug)
    s3_root = '%s/%s' % (app_config.PROJECT_SLUG, slug)
    graphic_assets = '%s/assets' % graphic_root
    s3_assets = '%s/assets' % s3_root
    graphic_node_modules = '%s/node_modules' % graphic_root

    graphic_config = load_graphic_config(graphic_root)

    use_assets = getattr(graphic_config, 'USE_ASSETS', True)
    default_max_age = getattr(graphic_config, 'DEFAULT_MAX_AGE', None) or app_config.DEFAULT_MAX_AGE
    assets_max_age = getattr(graphic_config, 'ASSETS_MAX_AGE', None) or app_config.ASSETS_MAX_AGE
    update_copy(path)
    if use_assets:
        error = assets.sync(path)
        if error:
            return

    render.render(path)
    flat.deploy_folder(
        graphic_root,
        s3_root,
        headers={
            'Cache-Control': 'max-age=%i' % default_max_age
        },
        ignore=['%s/*' % graphic_assets, '%s/*' % graphic_node_modules,
                # Ignore files unused on static S3 server
                '*.xls', '*.xlsx', '*.pyc', '*.py', '*.less', '*.bak',
                '%s/base_template.html' % graphic_root,
                '%s/child_template.html' % graphic_root]
    )

    if use_assets:
        flat.deploy_folder(
            graphic_assets,
            s3_assets,
            headers={
                'Cache-Control': 'max-age=%i' % assets_max_age
            },
            ignore=['%s/private/*' % graphic_assets]
        )
    def get_start_message(slug):
        result = slack_client.api_call(
            "search.messages",
            query= '{0} in:charts'.format(slug),
        )
        if result['messages']['matches'][0].get('attachments') != None:
            print 'found attachments'
            if result['messages']['matches'][0]['attachments'][0]['title'] == slug:
                print 'found it'
                return result['messages']['matches'][0]['ts']
        if result['messages']['matches'][0].get('previous') != None:
            print 'found previous'
            if 'attachments' in result['messages']['matches'][0]['previous']:
                if result['messages']['matches'][0]['previous']['attachments'][0]['title'] == slug:
                    print 'found in previous mention'
                    return result['messages']['matches'][0]['previous']['ts']
        if result['messages']['matches'][0].get('previous_2') != None:
            print 'its in previous_2'
            if 'attachments' in result['messages']['matches'][0]['previous_2']:
                print 'attachemnts in prevous_2 '
                if result['messages']['matches'][0]['previous_2']['attachments'][0]['title'] == slug:
                    print 'found in previous_2 mention'
                    return result['messages']['matches'][0]['previous_2']['ts']
        else:
            print('Not found')
            print(result['messages']['matches'][0])
    def send_thread_message(message, ts):
            slack_client.api_call(
                "chat.postMessage",
                channel='#charts',
                text=message,
                username='******',
                icon_emoji=':bowtie:',
                thread_ts=ts,
        )
    if env.settings == 'production':
        message = 'Updated final link'
    else:
        message = 'Updated review link'
    """message_search_results = get_start_message(slug)
    if message_search_results != None:
        send_thread_message(message, message_search_results)
        print 'message sent'"""
    print ''
    print '%s URL: %s/%s/index.html' % (env.settings.capitalize(), app_config.S3_BASE_URL, slug)