Update
This commit is contained in:
Vyacheslav Anzhiganov 2016-10-17 02:10:57 +03:00
parent 2082686edd
commit bb88a18336
41 changed files with 24450 additions and 159 deletions

BIN
FreeSans.ttf Normal file

Binary file not shown.

BIN
FreeSansBold.ttf Normal file

Binary file not shown.

BIN
FreeSansBoldOblique.ttf Normal file

Binary file not shown.

BIN
FreeSansOblique.ttf Normal file

Binary file not shown.

View file

@ -119,6 +119,10 @@ class Users(PgSQLModel):
def hash_password(password):
return md5(password).hexdigest()
@staticmethod
def get_by_id(user_id):
return Users.select().where(Users.id == user_id).get()
class UsersRecoveryCodes(PgSQLModel):
user = ForeignKeyField(Users)
@ -155,6 +159,11 @@ class UsersBalance(PgSQLModel):
user = ForeignKeyField(Users)
balance = FloatField(default=0, null=False)
@staticmethod
def get_by_account(user_id):
x = UsersBalance.select(UsersBalance.balance).where(UsersBalance.user == user_id).get()
return x.balance
class UsersBalanceTransactions(PgSQLModel):
"""
@ -164,10 +173,11 @@ class UsersBalanceTransactions(PgSQLModel):
amount = FloatField(default=0, null=False)
created = DateTimeField(default=datetime.datetime.now)
notified = IntegerField(null=False, default=0)
# success
# process
# fail
# success, process, fail
status = TextField(null=False)
# robokassa, webmoney, yandex_money, rbk_money, alfaclick, sberbank_online, paypal, invoice
method = CharField(null=False, default=0)
details = JSONField(default='{}')
class SSHKeys(PgSQLModel):
@ -258,6 +268,11 @@ class Vms(PgSQLModel):
x.execute()
return True
@staticmethod
def get_state(vm_id):
c = Vms.select(Vms.status).where(Vms.id == vm_id).first()
return c.status
class Tasks(PgSQLModel):
id = UUIDField(primary_key=True, unique=True)
@ -270,6 +285,12 @@ class Tasks(PgSQLModel):
status = IntegerField(null=False, default=0)
plain = TextField()
@staticmethod
def exists_active_tasks(user_id):
if Tasks.select().where(Tasks.user == user_id, Tasks.status != 2).count() == 0:
return False
return True
# @staticmethod
# def set_task(datacenter_id, server_id, task, status, **args):
# task_id = uuid.uuid4()

View file

@ -11,6 +11,7 @@ from SWSCloudCore.models import database
from SWSCloudServerAPI.ServerAPI import viewServerAPI
from SWSCloudWeb.views import viewHomepage
from SWSCloudWeb.views.account import viewAccount
from SWSCloudWeb.views.bills import viewBills
from SWSCloudWeb.views.compute.containers import viewContainers
from SWSCloudWeb.views.compute.vms import viewVMs
from SWSCloudWeb.views.payments import viewPayments
@ -34,11 +35,13 @@ app.register_blueprint(viewKB)
app.register_blueprint(viewDocuments)
# /tasks
app.register_blueprint(viewTasks)
# /containers
# /compute
app.register_blueprint(viewContainers)
app.register_blueprint(viewVMs)
# /id
app.register_blueprint(viewAccount)
# /billing
app.register_blueprint(viewBills)
# /payments
app.register_blueprint(viewPayments)
# /api

File diff suppressed because one or more lines are too long

Binary file not shown.

After

Width:  |  Height:  |  Size: 103 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 137 KiB

File diff suppressed because one or more lines are too long

View file

@ -94,3 +94,7 @@ ul#features-list li {
.compute-node-item div {
padding: 10px;
}
#account_bills {
color: white;
}

View file

@ -1,6 +1,6 @@
<footer>
<div class="row">
<div class="large-4 columns">
<div class="large-4 medium-4 columns">
<b>{{ _('Поддержка') }}</b>
<ul>
{% if g.settings.get('SUPPORT_TEL', None) %}
@ -12,14 +12,14 @@
<li><a href="{{ url_for('support.index') }}">{{ _('Форма обратной связи') }}</a></li>
</ul>
</div>
<div class="large-4 columns"><b>{{ _('Сообщество') }}</b>
<div class="large-4 medium-4 columns"><b>{{ _('Сообщество') }}</b>
<ul>
<li><a href="/blog">{{ _('Блог') }}</a></li>
<li><a href="/blog">{{ _('Facebook') }}</a></li>
<li><a href="/blog">{{ _('Twitter') }}</a></li>
</ul>
</div>
<div class="large-4 columns">
<div class="large-4 medium-4 columns">
<p>2009&minus;2016 &copy; GoCloud.ru</p>
<script type="text/javascript" src="//yastatic.net/es5-shims/0.0.2/es5-shims.min.js" charset="utf-8"></script>
<script type="text/javascript" src="//yastatic.net/share2/share.js" charset="utf-8"></script>
@ -30,3 +30,14 @@
{% if g.settings['footer_code'] %}
{{ g.settings['footer_code']|safe }}
{% endif %}
{% if session['user_id'] %}
<script>
$.getJSON( "/bills/account.json", function( data ) {
$('#account_bills').text(' (' + data.balance + 'руб.)');
if (data.balance <= 100) {
$('#account_bills').css('color', 'red');
}
});
</script>
{% endif %}

View file

@ -13,7 +13,7 @@
{% if session['user_id'] %}
<ul class="right">
<li><a href="{{ url_for('account.index') }}">{{ _('Учётная запись') }}</a></li>
<li><a href="{{ url_for('account.billing') }}">{{ _('Биллинг') }}</a></li>
<li><a href="{{ url_for('bills.index') }}">{{ _('Счёт') }}<span id="account_bills"></span></a></li>
<li><a href="{{ url_for('account.logout') }}">{{ _('Выход') }}</a></li>
</ul>
<ul class="left">

View file

@ -0,0 +1,5 @@
<ul class="inline-list">
<li><a href="{{ url_for('.index') }}">Счёт</a></li>
<li><a href="{{ url_for('.payments') }}">Платежи</a></li>
<li><a href="{{ url_for('.charge') }}">Пополнить баланс</a></li>
</ul>

View file

@ -0,0 +1,54 @@
{% extends "default/_layout.html" %}
{% block title %}Баланс{% endblock %}
{% block content %}
<div class="row">
<div class="large-12 columns">
<h2>Счёт / Пополнить баланс</h2>
</div>
<div class="large-12 columns">
{% include "default/billing/_menu.html" %}
</div>
</div>
<div class="row">
<div class="large-12 column">
<h5>Электронные платёжные системы</h5>
</div>
{% if g.settings['PAY_ROBOKASSA_ENABLED'] == "1" %}
<form action="{{ url_for('payments.robokassa', action='process') }}" method="post">
<div class="large-3 columns">
<img src="{{ url_for('static', filename='images/payment/robokassa.png') }}" style="margin: 10px; width: 150px;" />
</div>
<div class="large-6 columns">
<select name="amount">
<option value="500">500 рублей</option>
<option value="1000">1000 рублей</option>
<option value="2000">2000 рублей</option>
<option value="5000">5000 рублей</option>
</select>
</div>
<div class="large-3 columns">
<input type="submit" value="Оплатить" class="button postfix" />
</div>
</form>
{% endif %}
<!--<div class="large-12 column">-->
<!--<div class="row">-->
<!--<div class="large-12 column">-->
<!--<h5>Безналичные переводы</h5>-->
<!--</div>-->
<!--<div class="large-12 column">-->
<!--<table class="table">-->
<!--<tr>-->
<!--<td></td>-->
<!--<td></td>-->
<!--</tr>-->
<!--</table>-->
<!--</div>-->
<!--</div>-->
<!--</div>-->
</div>
{% endblock %}

View file

@ -0,0 +1,19 @@
{% extends "default/_layout.html" %}
{% block title %}Счёт{% endblock %}
{% block content %}
<div class="row">
<div class="large-12 columns">
<h2>Счёт</h2>
</div>
<div class="large-12 columns">
{% include "default/billing/_menu.html" %}
</div>
</div>
<div class="row">
<div class="large-6 columns">
<p>Баланс: {{ user_balance }} рублей</p>
</div>
</div>
{% endblock %}

View file

@ -8,50 +8,22 @@
<h2>Учётная запись</h2>
</div>
<div class="large-12 columns">
{% include "default/id/_menu.html" %}
{% include "default/billing/_menu.html" %}
</div>
</div>
<div class="row">
<div class="large-12 columns">
<h3>Баланс</h3>
</div>
</div>
<div class="row">
<div class="large-6 columns">
<p>Баланс: {{ user_balance }} рублей</p>
<hr/>
</div>
</div>
<div class="row">
<div class="large-12 columns">
<h4>Пополнить</h4>
</div>
{% if g.settings['PAY_ROBOKASSA_ENABLED'] == "1" %}
<form action="{{ url_for('payments.robokassa', action='process') }}" method="post">
<div class="large-3 columns">
<img src="{{ url_for('static', filename='images/payment/robokassa.png') }}" style="margin: 10px; width: 150px;" />
</div>
<div class="large-6 columns">
<select name="amount">
<option value="500">500 рублей</option>
<option value="1000">1000 рублей</option>
<option value="2000">2000 рублей</option>
<option value="5000">5000 рублей</option>
</select>
</div>
<div class="large-3 columns">
<input type="submit" value="Оплатить" class="button postfix" />
</div>
</form>
{% endif %}
<div class="large-6 columns">
<h4>История платежей</h4>
<table width="100%">
<thead>
<tr>
<th>Сумма</th>
<th>ID</th>
<th>Дата</th>
<th>Сумма</th>
<th>Описание</th>
<th>Статус</th>
<th>Способ оплаты</th>
<th>Дата оплаты</th>
</tr>
</thead>
<tbody>

View file

@ -4,10 +4,10 @@
{% block content %}
<div class="row">
<div class="large-6 columns">
<div class="large-6 medium-6 columns">
<h3>Список контейнеров</h3>
</div>
<div class="large-6 columns text-right">
<div class="large-6 medium-6 columns text-right">
<a href="{{ url_for('containers.create') }}" class="button small">&plus; Новый контейнер</a>
</div>
</div>

View file

@ -4,10 +4,10 @@
{% block content %}
<div class="row">
<div class="large-6 columns">
<div class="large-6 medium-6 columns">
<h3>{{ _('Список виртуальных машин') }}</h3>
</div>
<div class="large-6 columns text-right">
<div class="large-6 medium-6 columns text-right">
<a href="{{ url_for('vms.create') }}" class="button success small">&plus; Новый сервер</a>
</div>
</div>

View file

@ -11,25 +11,63 @@
<div class="row">
<div class="large-12 columns">
<h4>{{_('Статус')}}</h4>
{% if vm.status == 0 %}
<p style="color: red">{{_('Неактивен')}}</p>
{% else %}
<p style="color: green">{{_('Активен')}}</p>
{% if vm['status'] == 0 %}
{% set vm_status = _('Неактивно') %}
{% set vm_details_show = True %}
{% elif vm['status'] == 1 %}
{% set vm_status = _('Активно') %}
{% set vm_details_show = True %}
{% elif vm['status'] == 2 %}
{% set vm_status = _('Процесс активации') %}
{% set vm_details_show = True %}
{% elif vm['status'] == 3 %}
{% set vm_status = _('Процесс деактивации') %}
{% set vm_details_show = True %}
{% elif vm['status'] == 4 %}
{% set vm_status = _('Создание...') %}
{% set vm_details_show = False %}
{% elif vm['status'] == 5 %}
{% set vm_status = _('Удаление...') %}
{% set vm_details_show = False %}
{% endif %}
<form action="{{ url_for('vms.settings', vm_id=vm.id) }}" method="post">
<input type="hidden" name="action" value="set_status">
<div class="input-group">
<select name="status">
<option value="active">{{_('Активировать')}}</option>
<option value="inactive">{{_('Деактивировать')}}</option>
</select>
<p class="success">Статус: {{vm_status}}</p>
<div id="vm_controls">
<a href="#" id="action_start" class="button" onclick="set_state('{{vm.id}}', 'start');">{{_('Запустить')}}</a>
<a href="#" id="action_stop" class="button" onclick="set_state('{{vm.id}}', 'stop');">{{_('Остановить')}}</a>
</div>
<input type="submit" value="{{_('Изменить статус')}}" class="button success small">
</form>
<h4>{{ _('Удалить') }}</h4>
<a href="{{ url_for('vms.delete', vm_id=vm.id) }}">
<button class="button alert">{{_('Удалить')}}</button>
</a>
<p>{{ _('После удаления виртуального сервера данные на сервере также будут безвозвратно удалены.') }}</p>
<a href="{{ url_for('vms.delete', vm_id=vm.id) }}" class="button alert">{{ _('Удалить') }}</a>
</div>
</div>
<script>
function set_state(vm_id, action) {
$.ajax({
type: "POST",
url: "/compute/vms/state.json",
dataType: "json",
success: function (msg) {
if (msg.status == 0) {} else {location.reload(true);}
},
data: {'vm_id': vm_id, 'action': action}
});
}
function get_state(vm_id) {
$.getJSON("/compute/vms/state.json?vm_id=" + vm_id, function( data ) {
$('#vm_controls #action_start').removeClass('secondary').removeClass('success');
$('#vm_controls #action_stop').removeClass('secondary').removeClass('primary');
if (data.status == 0) {
$('#vm_controls #action_start').addClass('secondary');
$('#vm_controls #action_stop').addClass('primary');
} else if (data.status == 1) {
$('#vm_controls #action_start').addClass('secondary');
$('#vm_controls #action_stop').addClass('primary');
}
});
}
get_state('{{ vm.id }}');
</script>
{% endblock %}

View file

@ -0,0 +1,46 @@
{% extends "default/_layout.html" %}
{% block title %}Статистика{% endblock %}
{% block head %}
<script type="text/javascript">
var datapoints = [
{% for s in stats_memory %}
{
new Date({{ s.year };;}, {{ s.month }}, {{ s.day }}, {{ s.hour }}, {{ s.minute }}),
{
{
s.data | float / 1024 / 1024
}
}
},
{% endfor %}
]
$(function () {
$("#chartContainer").CanvasJSChart({
data: [
{
toolTipContent: "{y} мбайт",
type: "line",
markerSize: 5,
color: "rgba(54,158,173,.7)",
dataPoints: datapoints
}
]
});
});
</script>
<script type="text/javascript" src="{{ url_for('static', filename='js/vendor/jquery.canvasjs.min.js') }}"></script>
{% endblock %}
{% block content %}
<div class="row">
<div class="large-12 columns">
<h3>Статистика</h3>
</div>
</div>
<div class="row">
<div id="chartContainer" style="height: 300px; width: 100%;">
</div>
</div>
{% endblock %}

View file

@ -71,7 +71,6 @@
<li>Удобная панель управления позволяет легко и удобно администрировать арендованные виртуальные ресурсы.</li>
<li>Развернутая инфраструктура и резервированная телекоммуникационная сеть</li>
<li>Готовность к развёртыванию через несколько минут</li>
<li>Несколько центров обработки данных по всему миру</li>
<li>Неограниченный трафик</li>
</ul>
</div>

View file

@ -1,4 +1,4 @@
<form action="{{ url_for('account.edit') }}" method="post">
<form action="{{ url_for('account.edit_action') }}" method="post">
<input type="hidden" name="update_information" value="1">
<!-- BILLING BLOCK -->
<label for="fname">Имя</label>

View file

@ -1,6 +1,5 @@
<ul class="inline-list">
<li><a href="{{ url_for('account.index') }}">Учётная запись</a></li>
<li><a href="{{ url_for('account.billing') }}">Биллинг</a></li>
{# <li><a href="{{ url_for('account.settings') }}">Настройки</a></li>#}
<li><a href="{{ url_for('account.password_update') }}">Смена пароля</a></li>
<li><a href="{{ url_for('account.sshkey') }}">SSH ключ</a></li>

View file

@ -0,0 +1,104 @@
<!doctype html>
<html class="no-js" lang="en">
<head>
<meta charset="utf-8" />
<meta http-equiv="x-ua-compatible" content="ie=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Облачный хостинг GoCloud</title>
<link rel="stylesheet" href="{{ url_for('static', filename='assets/css/app.css') }}">
</head>
<body>
<div data-sticky-container>
<div class="title-bar" data-responsive-toggle="example-menu" data-hide-for="large">
<button class="menu-icon" type="button" data-toggle></button>
<div class="title-bar-title">GoCloud</div>
</div>
<div class="title-bar" data-sticky data-options="marginTop:0;" style="width:100%" id="example-menu">
<div class="hide-for-small-only hide-for-medium-only">
<div class="title-bar-left">
<ul class="dropdown menu" data-dropdown-menu>
<li class="menu-text">GoCloud</li>
<li><a href="{{url_for('homepage.index')}}">Виртуальные сервера</a></li>
<!--<li><a href="dns.html">DNS</a></li>-->
<li><a href="{{url_for('homepage.index', page='pricing')}}">Цены</a></li>
</ul>
</div>
<div class="title-bar-right">
{% if session['user_id'] %}
<ul class="menu">
<li><a href="{{ url_for('account.index') }}">{{ _('Учётная запись') }}</a></li>
<li><a href="{{ url_for('bills.index') }}">{{ _('Счёт') }}<span id="account_bills"></span></a></li>
<li><a href="{{ url_for('account.logout') }}">{{ _('Выход') }}</a></li>
</ul>
{% else %}
<ul class="menu">
<li><a href="{{url_}}"><a href="{{ url_for('account.login') }}">{{ _('Вход') }}</a></a></li>
<li><a href="{{ url_for('account.registration') }}">{{ _('Регистрация') }}</a></li>
</ul>
{% endif %}
</div>
</div>
<div class="hide-for-large">
<div class="title-bar-left">
<ul class="dropdown menu vertical" data-dropdown-menu>
<li><a href="index.html">Виртуальные сервера</a></li>
<li><a href="dns.html">DNS</a></li>
<li><a href="pricing.html">Цены</a></li>
<li><a href="">Войти</a></li>
<li><a href="">Зарегистрироваться</a></li>
</ul>
</div>
</div>
</div>
</div>
{% block content %}{% endblock %}
<footer>
<hr>
<div class="row">
<div class="large-4 columns text-center">
<b>Поддержка</b>
<ul>
<!--<li>+7 499 702-02-36</li>-->
<li>support@gocloud.ru</li>
</ul>
</div>
<div class="large-4 columns text-center">
<b>Сообщество</b>
<ul>
<li><a href="/blog/">Блог</a></li>
</ul>
</div>
<div class="large-4 columns text-center">
<b>Разработчики</b>
<ul>
<!--<li><a href="/api/">API</a></li>-->
<li><a href="https://github.com/gocloudru/">Github</a></li>
</ul>
</div>
</div>
<div class="row">
<div class="large-12 columns">
<p class="copyright">2009-2016 © GoCloud.ru</p>
</div>
</div>
</footer>
<script src="{{ url_for('static', filename='assets/js/app.js') }}"></script>
{% if g.settings['footer_code'] %}
{{ g.settings['footer_code']|safe }}
{% endif %}
{% if session['user_id'] %}
<script>
$.getJSON( "/bills/account.json", function( data ) {
$('#account_bills').text(' (' + data.balance + 'руб.)');
if (data.balance <= 100) {
$('#account_bills').css('color', 'black');
}
});
</script>
{% endif %}
</body>
</html>

View file

@ -0,0 +1,29 @@
<div class="testimonial-wrap">
<div class="row">
<div class="large-12 columns centered-text">
<h2>Наши клиенты говорят о нас!</h2>
</div>
</div>
<div class="row">
<div class="large-6 columns testimonial">
<div class="quote">
<p>Размещаем свой интернет магазин на сервере уже несколько лет, поддержка всегда даёт хорошие рекомендации по оптимизации работы сайта. Очень доволен.</p>
</div>
<div class="student">
<div class="photo"> </div>
<p>Дмитрий Ерхан</p>
<p>DE-AVTO.RU</p>
</div>
</div>
<div class="large-6 columns testimonial">
<div class="quote">
<p>При помощи удобного, интуитивно понятный интерфейса без проблем заказала несколько виртуальных серверов для своего проекта. Проект работает быстро. Служба поддержки работает необыкновенно быстро.</p>
</div>
<div class="student">
<div class="photo"><img src="{{ url_for('static', filename='assets/img/testimonials/anassstasss.jpg') }}"></div>
<p>Анастасия Кравченко</p>
<p>PicTube.ru</p>
</div>
</div>
</div>
</div>

View file

@ -0,0 +1,26 @@
{% extends "layouts/default.html" %}
{% block content %}
<div id="home-jumbotron">
<div class="row">
<div class="large-12 columns">
<h1>DNS</h1>
<h2>Удобный инструмент для редактирования содержания зоны, настройки DNS и управления доменами</h2>
</div>
</div>
</div>
<div class="row">
<div class="large-12 columns">
<h2>Услуга DNS</h2>
<p><b>DNS</b> (англ. Domain Name System — система доменных имён) — компьютерная распределённая система для получения информации о доменах. Чаще всего используется для получения IP-адреса по имени хоста (компьютера или устройства), получения информации о маршрутизации почты, обслуживающих узлах для протоколов в домене - <i>Wikipedia</i>.</p>
<p>Делегировав домен на сервера <code>ns1.cloudns.ru</code> и <code>ns2.cloudns.ru</code> появится возможность управлять записями через панель управления и API.</p>
<h2>Гео-таргетинг</h2>
<p>Возможность конфигурации зон для различных регионов с целью разделения трафика. Часто используется для настройки CDN.</p>
<h2>API</h2>
<p>Поддерживает добавление, удаление зон, создание и редактирование записей. Позволит интегрировать управление DNS в своё приложение</p>
</div>
</div>
{% include "macros/testimonials.html" %}
{% endblock %}

View file

@ -0,0 +1,60 @@
{% extends "gocloud2016/layouts/default.html" %}
{% block content %}
<div id="home-jumbotron">
<div class="row">
<div class="large-12 columns">
<h1>Облачный хостинг</h1>
<h2>Виртуальный сервер от 590 рублей в месяц</h2>
<h2>
<a href="{{ url_for('account.registration') }}" class="button success">Создать виртуальный сервер</a>
</h2>
</div>
</div>
</div>
<div class="pricing">
<div class="row">
<div class="large-3 medium-12 small-12 columns">
<ul class="pricing-table">
<li class="title">G1</li>
<li class="price">590 <small>руб./мес.</small></li>
<li class="bullet-item">Процессор <span>1</span></li>
<li class="bullet-item">Память <span>б</span></li>
<li class="bullet-item">Диск <span>20Гб</span></li>
<li class="cta-button"><a class="button" href="{{ url_for('vms.create') }}">Создать сервер</a></li>
</ul>
</div>
<div class="large-3 medium-12 small-12 columns">
<ul class="pricing-table">
<li class="title">G2</li>
<li class="price">1080 <small>руб./мес.</small></li>
<li class="bullet-item">Процессор <span>2</span></li>
<li class="bullet-item">Память <span>б</span></li>
<li class="bullet-item">Диск <span>30Гб</span></li>
<li class="cta-button"><a class="button" href="{{ url_for('vms.create') }}">Создать сервер</a></li>
</ul>
</div>
<div class="large-3 medium-12 small-12 columns">
<ul class="pricing-table">
<li class="title">G4</li>
<li class="price">2050 <small>руб./мес.</small></li>
<li class="bullet-item">Процессор <span>2</span></li>
<li class="bullet-item">Память <span>б</span></li>
<li class="bullet-item">Диск <span>50Гб</span></li>
<li class="cta-button"><a class="button" href="{{ url_for('vms.create') }}">Создать сервер</a></li>
</ul>
</div>
<div class="large-3 medium-12 small-12 columns">
<ul class="pricing-table">
<li class="title">G8</li>
<li class="price">3900 <small>руб./мес.</small></li>
<li class="bullet-item">Процессор <span>4</span></li>
<li class="bullet-item">Память <span>б</span></li>
<li class="bullet-item">Диск <span>80Гб</span></li>
<li class="cta-button"><a class="button" href="{{ url_for('vms.create') }}">Создать сервер</a></li>
</ul>
</div>
</div>
</div>
{% endblock %}

View file

@ -0,0 +1,83 @@
{% extends "gocloud2016/layouts/default.html" %}
{% block content %}
<div class="row">
<div class="large-12 columns">
<h2>Цены</h2>
</div>
</div>
<div class="row">
<div class="large-12 columns">
<h3>Виртуальные сервера</h3>
<table>
<thead>
<tr>
<th>&nbsp;</th>
<th>Процессор</th>
<th>Память</th>
<th>Диск</th>
<th>Цена</th>
</tr>
</thead>
<tbody>
<tr>
<td>G1</td>
<td>1</td>
<td>1 Гб</td>
<td>20 Гб</td>
<td>590 руб./мес.</td>
</tr>
<tr>
<td>G2</td>
<td>2</td>
<td>2 Гб</td>
<td>30 Гб</td>
<td>1080 руб./мес.</td>
</tr>
<tr>
<td>G4</td>
<td>2</td>
<td>4 Гб</td>
<td>50 Гб</td>
<td>2050 руб./мес.</td>
</tr>
<tr>
<td>G8</td>
<td>4</td>
<td>8 Гб</td>
<td>80 Гб</td>
<td>3900 руб./мес.</td>
</tr>
</tbody>
</table>
<!-- h3>DNS</h3>
<table>
<thead>
<tr>
<th>&nbsp;</th>
<th>Записей</th>
<th>Запросов</th>
<th>Слоёв</th>
<th>Цена</th>
</tr>
</thead>
<tbody>
<tr>
<td>Стандартный</td>
<td>&infin;</td>
<td>&infin;</td>
<td>1</td>
<td>Бесплатно</td>
</tr>
<tr>
<td>Гео</td>
<td>&infin;</td>
<td>&infin;</td>
<td>10</td>
<td>250 руб./мес.</td>
</tr>
</tbody>
</table -->
</div>
</div>
{% endblock %}

View file

@ -0,0 +1,414 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Style Guide</title>
<link rel="stylesheet" href="assets/css/app.css">
<link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/highlight.js/8.9.1/styles/github.min.css">
<!-- Style guide-specific CSS goes here. -->
<style>
/* This styles individual sections of the style guide */
.ss-section:not(:last-child) {
padding-bottom: 4rem;
border-bottom: 2px solid #ccc;
margin-bottom: 4rem;
}
/* This styles code blocks used for examples. */
.ss-code code {
display: block;
padding: 1rem;
overflow-x: scroll;
margin-bottom: 1.5rem;
}
/* This styles the example rows used in the grid documentation. */
.row.display {
background: #eee;
font-size: 11px;
margin-bottom: 10px;
line-height: 2rem;
border: solid 1px #c6c6c6;
margin-left: 0 !important;
margin-right: 0 !important; }
.row.display .columns:nth-child(2), .row.display .columns.small-centered, .row.display .columns.large-centered {
background: #e1e1e1; }
.row.display .columns.color-end {
background: #d4d4d4; }
/* This styles the color blocks used in the color documentation. */
.color-block {
border-radius: 2px;
display: block;
padding: 8px 8px 6px;
color: #333;
text-transform: uppercase;
border: 1px solid #ddd;
box-shadow: 0 0 8px rgba(0, 0, 0, 0.1);
}
.color-block span {
display: block;
width: 100%;
height: 100px;
margin-bottom: 0.42857rem;
}
</style>
</head>
<body>
<div class="column row">
<h1>Client Style Guide</h1>
<p class="lead">This style guide was built with Foundation for Sites. For more information on how to use this responsive front-end framework, check out the documentation, get help from the Foundation community, or request immediate technical support.</p>
<a href="http://foundation.zurb.com/docs/" class="button">Visit the Docs</a>
<a href="http://foundation.zurb.com/forum/" class="secondary button">Foundation Forum</a>
<a href="http://foundation.zurb.com/business/business-support.html" class="secondary button">Technical Support</a>
</div>
<div class="column row"><div class="row collapse">
<div class="large-3 medium-4 columns" data-sticky-container>
<ul class="vertical menu">
<li><a href="#the-grid">The Grid</a></li>
<li><a href="#colors">Colors</a></li>
<li><a href="#typography">Typography</a></li>
<li><a href="#buttons">Buttons</a></li>
<li><a href="#forms">Forms</a></li>
<li><a href="#new-section">New Section</a></li>
</ul>
</div>
<div class="large-9 medium-8 columns">
<section class="ss-section" id="the-grid">
<h1>The Grid</h1><p class="lead">Problem: You&#39;ve got tons of content, each needing different sized vertical columns, and don&#39;t know how to quick and easily get it all done. Solution: The awesome grid!</p>
<hr>
<h2>Overview</h2><p>The grid is built around two key elements: rows and columns. Rows create a max-width and contain the columns, and columns create the final structure. Everything on your page that you don&#39;t give a specific structural style to should be within a row or column.</p>
<hr>
<h2>Nesting</h2><p>In the Grid you can nest columns down as far as you&#39;d like. Just embed rows inside columns and go from there. Each embedded row can contain up to 12 columns.</p>
<hr>
<h2>How to Use</h2><p>Using this framework is easy. Here&#39;s how your code will look when you use a series of <div> tags to create vertical columns.</p>
<div class="ss-code"><pre><code class="html"><span class="hljs-tag">&lt;<span class="hljs-title">div</span> <span class="hljs-attribute">class</span>=<span class="hljs-value">"row"</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-title">div</span> <span class="hljs-attribute">class</span>=<span class="hljs-value">"small-6 medium-4 large-3 columns"</span>&gt;</span>...<span class="hljs-tag">&lt;/<span class="hljs-title">div</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-title">div</span> <span class="hljs-attribute">class</span>=<span class="hljs-value">"small-6 medium-8 large-9 columns"</span>&gt;</span>...<span class="hljs-tag">&lt;/<span class="hljs-title">div</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-title">div</span>&gt;</span></code></pre></div><div class="row display">
<div class="small-12 large-4 columns">4</div>
<div class="small-12 large-4 columns">4</div>
<div class="small-12 large-4 columns">4</div>
</div>
<div class="row display">
<div class="small-12 large-3 columns">3</div>
<div class="small-12 large-6 columns">6</div>
<div class="small-12 large-3 columns">3</div>
</div>
<div class="row display">
<div class="small-12 large-2 columns">2</div>
<div class="small-12 large-8 columns">8</div>
<div class="small-12 large-2 columns">2</div>
</div>
<div class="row display">
<div class="small-12 large-3 columns">3</div>
<div class="small-12 large-9 columns">9</div>
</div>
<div class="row display">
<div class="small-12 large-4 columns">4</div>
<div class="small-12 large-8 columns">8</div>
</div>
<div class="row display">
<div class="small-12 large-5 columns">5</div>
<div class="small-12 large-7 columns">7</div>
</div>
<div class="row display">
<div class="small-12 large-6 columns">6</div>
<div class="small-12 large-6 columns">6</div>
</div>
<hr>
<h2>Nesting Rows</h2><p>In the Grid you can nest columns down as far as you&#39;d like. Just embed rows inside columns and go from there. Each embedded row can contain up to 12 columns.</p>
<div class="ss-code"><pre><code class="html"><span class="hljs-tag">&lt;<span class="hljs-title">div</span> <span class="hljs-attribute">class</span>=<span class="hljs-value">"row"</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-title">div</span> <span class="hljs-attribute">class</span>=<span class="hljs-value">"small-8 columns"</span>&gt;</span>8
<span class="hljs-tag">&lt;<span class="hljs-title">div</span> <span class="hljs-attribute">class</span>=<span class="hljs-value">"row"</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-title">div</span> <span class="hljs-attribute">class</span>=<span class="hljs-value">"small-8 columns"</span>&gt;</span>8 Nested
<span class="hljs-tag">&lt;<span class="hljs-title">div</span> <span class="hljs-attribute">class</span>=<span class="hljs-value">"row"</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-title">div</span> <span class="hljs-attribute">class</span>=<span class="hljs-value">"small-8 columns"</span>&gt;</span>8 Nested Again<span class="hljs-tag">&lt;/<span class="hljs-title">div</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-title">div</span> <span class="hljs-attribute">class</span>=<span class="hljs-value">"small-4 columns"</span>&gt;</span>4<span class="hljs-tag">&lt;/<span class="hljs-title">div</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-title">div</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-title">div</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-title">div</span> <span class="hljs-attribute">class</span>=<span class="hljs-value">"small-4 columns"</span>&gt;</span>4<span class="hljs-tag">&lt;/<span class="hljs-title">div</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-title">div</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-title">div</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-title">div</span> <span class="hljs-attribute">class</span>=<span class="hljs-value">"small-4 columns"</span>&gt;</span>4<span class="hljs-tag">&lt;/<span class="hljs-title">div</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-title">div</span>&gt;</span></code></pre></div><div class="row display">
<div class="small-8 columns">8
<div class="row">
<div class="small-8 columns">8 Nested
<div class="row">
<div class="small-8 columns">8 Nested Again</div>
<div class="small-4 columns">4</div>
</div>
</div>
<div class="small-4 columns">4</div>
</div>
</div>
<div class="small-4 columns">4</div>
</div>
<hr>
<h2>Small Grid</h2><p>As you&#39;ve probably noticed in the examples above, you have access to a small, medium, and large grid. If you know that your grid structure will be the same for small devices as it will be on large devices, just use the small grid. You can override your small grid classes by adding medium or large grid classes.</p>
<div class="ss-code"><pre><code class="html"><span class="hljs-tag">&lt;<span class="hljs-title">div</span> <span class="hljs-attribute">class</span>=<span class="hljs-value">"row"</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-title">div</span> <span class="hljs-attribute">class</span>=<span class="hljs-value">"small-2 columns"</span>&gt;</span>2<span class="hljs-tag">&lt;/<span class="hljs-title">div</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-title">div</span> <span class="hljs-attribute">class</span>=<span class="hljs-value">"small-10 columns"</span>&gt;</span>10, last<span class="hljs-tag">&lt;/<span class="hljs-title">div</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-title">div</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-title">div</span> <span class="hljs-attribute">class</span>=<span class="hljs-value">"row"</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-title">div</span> <span class="hljs-attribute">class</span>=<span class="hljs-value">"small-3 columns"</span>&gt;</span>3<span class="hljs-tag">&lt;/<span class="hljs-title">div</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-title">div</span> <span class="hljs-attribute">class</span>=<span class="hljs-value">"small-9 columns"</span>&gt;</span>9, last<span class="hljs-tag">&lt;/<span class="hljs-title">div</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-title">div</span>&gt;</span></code></pre></div><div class="row display">
<div class="small-2 columns">2</div>
<div class="small-10 columns">10, last</div>
</div>
<div class="row display">
<div class="small-3 columns">3</div>
<div class="small-9 columns">9, last</div>
</div>
</section>
<section class="ss-section" id="colors">
<h1>Colors</h1><p class="lead">Below you can find the different values we created that support the primary color variable you can change at any time in <code>_settings.scss</code></p>
<hr>
<div class="row up-1 medium-up-3 large-up-5">
<div class="column">
<div class="color-block">
<span style="background: #2199e8"></span>
#2199e8
</div>
</div>
<div class="column">
<div class="color-block">
<span style="background: #3adb76"></span>
#3adb76
</div>
</div>
<div class="column">
<div class="color-block">
<span style="background: #ffae00"></span>
#ffae00
</div>
</div>
<div class="column">
<div class="color-block">
<span style="background: #ec5840"></span>
#ec5840
</div>
</div>
<div class="column">
<div class="color-block">
<span style="background: #0a0a0a"></span>
#0a0a0a
</div>
</div>
</div>
</section>
<section class="ss-section" id="typography">
<h1>Typography</h1><p class="lead">This design uses Helvetica Neue for headings and paragraph text.</p>
<hr>
<h2>Headings</h2><p>Headings are used to denote different sections of content, usually consisting of related paragraphs and other HTML elements. They range from h1 to h6 and should be styled in a clear hierarchy (i.e., largest to smallest)</p>
<hr>
<h2>Paragraphs</h2><p>Paragraphs are groups of sentences, each with a lead (first sentence) and transition (last sentence). They are block level elements, meaning they stack vertically when repeated. Use them as such.</p>
<hr>
<h1>Heading Level 1</h1>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Hic quibusdam ratione sunt dolorum, qui illo maxime doloremque accusantium cum libero eum, a optio odio placeat debitis ullam aut non distinctio.</p>
<h2>Heading Level 2</h2>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Hic quibusdam ratione sunt dolorum, qui illo maxime doloremque accusantium cum libero eum, a optio odio placeat debitis ullam aut non distinctio.</p>
<h3>Heading Level 3</h3>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Hic quibusdam ratione sunt dolorum, qui illo maxime doloremque accusantium cum libero eum, a optio odio placeat debitis ullam aut non distinctio.</p>
<h4>Heading Level 4</h4>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Hic quibusdam ratione sunt dolorum, qui illo maxime doloremque accusantium cum libero eum, a optio odio placeat debitis ullam aut non distinctio.</p>
<h5>Heading Level 5</h5>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Hic quibusdam ratione sunt dolorum, qui illo maxime doloremque accusantium cum libero eum, a optio odio placeat debitis ullam aut non distinctio.</p>
<h6>Heading Level 6</h6>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Hic quibusdam ratione sunt dolorum, qui illo maxime doloremque accusantium cum libero eum, a optio odio placeat debitis ullam aut non distinctio.</p>
</section>
<section class="ss-section" id="buttons">
<h1>Buttons</h1><p class="lead">Buttons are tied to an action of some kind, whether that button is on a cheese dispenser or launches the rocket that you&#39;re strapped to. On the web, we follow similar conventions.</p>
<hr>
<h2>Primary Buttons</h2><p>These buttons are primary calls to action and should be used sparingly. Their size can be adjusted with the <code>.tiny</code>, <code>.small</code>, and <code>.large</code> classes.</p>
<div class="ss-code"><pre><code class="html"><span class="hljs-tag">&lt;<span class="hljs-title">a</span> <span class="hljs-attribute">href</span>=<span class="hljs-value">"#"</span> <span class="hljs-attribute">class</span>=<span class="hljs-value">"primary large button"</span>&gt;</span>Large button<span class="hljs-tag">&lt;/<span class="hljs-title">a</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-title">a</span> <span class="hljs-attribute">href</span>=<span class="hljs-value">"#"</span> <span class="hljs-attribute">class</span>=<span class="hljs-value">"primary button"</span>&gt;</span>Regular button<span class="hljs-tag">&lt;/<span class="hljs-title">a</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-title">a</span> <span class="hljs-attribute">href</span>=<span class="hljs-value">"#"</span> <span class="hljs-attribute">class</span>=<span class="hljs-value">"primary small button"</span>&gt;</span>Small button<span class="hljs-tag">&lt;/<span class="hljs-title">a</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-title">a</span> <span class="hljs-attribute">href</span>=<span class="hljs-value">"#"</span> <span class="hljs-attribute">class</span>=<span class="hljs-value">"primary tiny button"</span>&gt;</span>Tiny button<span class="hljs-tag">&lt;/<span class="hljs-title">a</span>&gt;</span></code></pre></div>
<div class="ss-code-live"><a href="#" class="primary large button">Large button</a>
<a href="#" class="primary button">Regular button</a>
<a href="#" class="primary small button">Small button</a>
<a href="#" class="primary tiny button">Tiny button</a></div><hr>
<h2>Secondary Buttons</h2><p>These buttons are used for less important, secondary actions on a page.</p>
<div class="ss-code"><pre><code class="html"><span class="hljs-tag">&lt;<span class="hljs-title">a</span> <span class="hljs-attribute">href</span>=<span class="hljs-value">"#"</span> <span class="hljs-attribute">class</span>=<span class="hljs-value">"secondary large button"</span>&gt;</span>Large button<span class="hljs-tag">&lt;/<span class="hljs-title">a</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-title">a</span> <span class="hljs-attribute">href</span>=<span class="hljs-value">"#"</span> <span class="hljs-attribute">class</span>=<span class="hljs-value">"secondary button"</span>&gt;</span>Regular button<span class="hljs-tag">&lt;/<span class="hljs-title">a</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-title">a</span> <span class="hljs-attribute">href</span>=<span class="hljs-value">"#"</span> <span class="hljs-attribute">class</span>=<span class="hljs-value">"secondary small button"</span>&gt;</span>Small button<span class="hljs-tag">&lt;/<span class="hljs-title">a</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-title">a</span> <span class="hljs-attribute">href</span>=<span class="hljs-value">"#"</span> <span class="hljs-attribute">class</span>=<span class="hljs-value">"secondary tiny button"</span>&gt;</span>Tiny button<span class="hljs-tag">&lt;/<span class="hljs-title">a</span>&gt;</span></code></pre></div>
<div class="ss-code-live"><a href="#" class="secondary large button">Large button</a>
<a href="#" class="secondary button">Regular button</a>
<a href="#" class="secondary small button">Small button</a>
<a href="#" class="secondary tiny button">Tiny button</a></div>
</section>
<section class="ss-section" id="forms">
<h1>Forms</h1><p class="lead">Use forms to allow users to interact with the site and provide information to the company.</p>
<hr>
<h2>Elements of a Form</h2><p>A form should be marked up using its default HTML properties. The ones we make use of include (in hierarchical order):</p>
<ul>
<li>Form</li>
<li>Label</li>
<li>Input</li>
<li>Select</li>
<li>Text area</li>
<li>Button</li>
</ul>
<hr>
<h2>How to Use</h2><p>Make forms great and easy to use with the following rules:</p>
<ul>
<li>Wrap checkboxes and radio buttons within labels for larger hit areas, and be sure to set the for, name, and id attributes for all applicable elements.</li>
<li>Series of checkboxes and radio buttons below within a <code>&lt;ul class=&quot;inline-list&quot;&gt;</code>.</li>
<li>Before selecting any set of fields to use for a required input, explore other options (e.g., radio buttons over select lists).</li>
</ul>
<hr>
<h2>Learn All About Forms</h2><p>Check out the <a href="http://foundation.zurb.com/sites/docs">Foundation Docs</a> to learn about how flexible our forms are for creating different layouts. It works perfectly with the grid to meet all your form needs.</p>
<hr>
<h2>Form Layouts</h2><p>Form elements in Foundation are styled based on their type attribute rather than a class. Inputs in Foundation have another major advantage — they are full width by default. That means that inputs will run as wide as the column that contains them. However, you have two options which make these forms extremely versatile:</p>
<ul>
<li>You can size inputs using column sizes, like <code>.medium-6</code>, <code>.small-6</code>.</li>
<li>You can create row elements inside your form and use columns for the form, including inputs, labels and more. Rows inside a form inherit some special padding to even up input spacing.</li>
</ul>
<hr>
<h2>Form Example</h2><div class="ss-code"><pre><code class="html"><span class="hljs-tag">&lt;<span class="hljs-title">form</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-title">div</span> <span class="hljs-attribute">class</span>=<span class="hljs-value">"row"</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-title">div</span> <span class="hljs-attribute">class</span>=<span class="hljs-value">"large-12 columns"</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-title">label</span>&gt;</span>Label<span class="hljs-tag">&lt;/<span class="hljs-title">label</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-title">input</span> <span class="hljs-attribute">type</span>=<span class="hljs-value">"text"</span> <span class="hljs-attribute">placeholder</span>=<span class="hljs-value">"placeholder"</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-title">div</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-title">div</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-title">div</span> <span class="hljs-attribute">class</span>=<span class="hljs-value">"row"</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-title">div</span> <span class="hljs-attribute">class</span>=<span class="hljs-value">"large-6 columns"</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-title">label</span>&gt;</span>Label<span class="hljs-tag">&lt;/<span class="hljs-title">label</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-title">input</span> <span class="hljs-attribute">type</span>=<span class="hljs-value">"text"</span> <span class="hljs-attribute">placeholder</span>=<span class="hljs-value">"placeholder"</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-title">div</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-title">div</span> <span class="hljs-attribute">class</span>=<span class="hljs-value">"large-6 columns"</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-title">div</span> <span class="hljs-attribute">class</span>=<span class="hljs-value">"row collapse"</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-title">label</span>&gt;</span>Label<span class="hljs-tag">&lt;/<span class="hljs-title">label</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-title">div</span> <span class="hljs-attribute">class</span>=<span class="hljs-value">"input-group"</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-title">input</span> <span class="hljs-attribute">class</span>=<span class="hljs-value">"input-group-field"</span> <span class="hljs-attribute">type</span>=<span class="hljs-value">"text"</span> <span class="hljs-attribute">placeholder</span>=<span class="hljs-value">"placeholder"</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-title">span</span> <span class="hljs-attribute">class</span>=<span class="hljs-value">"input-group-label"</span>&gt;</span>.com<span class="hljs-tag">&lt;/<span class="hljs-title">span</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-title">div</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-title">div</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-title">div</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-title">div</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-title">div</span> <span class="hljs-attribute">class</span>=<span class="hljs-value">"row"</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-title">div</span> <span class="hljs-attribute">class</span>=<span class="hljs-value">"large-12 columns"</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-title">label</span>&gt;</span>Select Box<span class="hljs-tag">&lt;/<span class="hljs-title">label</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-title">select</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-title">option</span> <span class="hljs-attribute">value</span>=<span class="hljs-value">"good"</span>&gt;</span>Good<span class="hljs-tag">&lt;/<span class="hljs-title">option</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-title">option</span> <span class="hljs-attribute">value</span>=<span class="hljs-value">"better"</span>&gt;</span>Better<span class="hljs-tag">&lt;/<span class="hljs-title">option</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-title">option</span> <span class="hljs-attribute">value</span>=<span class="hljs-value">"best"</span>&gt;</span>Best<span class="hljs-tag">&lt;/<span class="hljs-title">option</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-title">select</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-title">div</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-title">div</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-title">div</span> <span class="hljs-attribute">class</span>=<span class="hljs-value">"row"</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-title">div</span> <span class="hljs-attribute">class</span>=<span class="hljs-value">"large-6 columns"</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-title">label</span>&gt;</span>Choose Your Favorite<span class="hljs-tag">&lt;/<span class="hljs-title">label</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-title">input</span> <span class="hljs-attribute">type</span>=<span class="hljs-value">"radio"</span> <span class="hljs-attribute">name</span>=<span class="hljs-value">"radio1"</span> <span class="hljs-attribute">value</span>=<span class="hljs-value">"radio1"</span> <span class="hljs-attribute">id</span>=<span class="hljs-value">"radio1"</span>&gt;</span><span class="hljs-tag">&lt;<span class="hljs-title">label</span> <span class="hljs-attribute">for</span>=<span class="hljs-value">"radio1"</span>&gt;</span>Red<span class="hljs-tag">&lt;/<span class="hljs-title">label</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-title">input</span> <span class="hljs-attribute">type</span>=<span class="hljs-value">"radio"</span> <span class="hljs-attribute">name</span>=<span class="hljs-value">"radio2"</span> <span class="hljs-attribute">value</span>=<span class="hljs-value">"radio2"</span> <span class="hljs-attribute">id</span>=<span class="hljs-value">"radio2"</span>&gt;</span><span class="hljs-tag">&lt;<span class="hljs-title">label</span> <span class="hljs-attribute">for</span>=<span class="hljs-value">"radio2"</span>&gt;</span>Blue<span class="hljs-tag">&lt;/<span class="hljs-title">label</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-title">div</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-title">div</span> <span class="hljs-attribute">class</span>=<span class="hljs-value">"large-6 columns"</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-title">label</span>&gt;</span>Check these out<span class="hljs-tag">&lt;/<span class="hljs-title">label</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-title">input</span> <span class="hljs-attribute">id</span>=<span class="hljs-value">"checkbox1"</span> <span class="hljs-attribute">type</span>=<span class="hljs-value">"checkbox"</span>&gt;</span><span class="hljs-tag">&lt;<span class="hljs-title">label</span> <span class="hljs-attribute">for</span>=<span class="hljs-value">"checkbox1"</span>&gt;</span>Checkbox 1<span class="hljs-tag">&lt;/<span class="hljs-title">label</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-title">input</span> <span class="hljs-attribute">id</span>=<span class="hljs-value">"checkbox2"</span> <span class="hljs-attribute">type</span>=<span class="hljs-value">"checkbox"</span>&gt;</span><span class="hljs-tag">&lt;<span class="hljs-title">label</span> <span class="hljs-attribute">for</span>=<span class="hljs-value">"checkbox2"</span>&gt;</span>Checkbox 2<span class="hljs-tag">&lt;/<span class="hljs-title">label</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-title">div</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-title">div</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-title">div</span> <span class="hljs-attribute">class</span>=<span class="hljs-value">"row"</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-title">div</span> <span class="hljs-attribute">class</span>=<span class="hljs-value">"large-12 columns"</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-title">label</span>&gt;</span>Textarea Label<span class="hljs-tag">&lt;/<span class="hljs-title">label</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-title">textarea</span> <span class="hljs-attribute">placeholder</span>=<span class="hljs-value">"placeholder"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-title">textarea</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-title">div</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-title">div</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-title">form</span>&gt;</span></code></pre></div>
<div class="ss-code-live"><form>
<div class="row">
<div class="large-12 columns">
<label>Label</label>
<input type="text" placeholder="placeholder">
</div>
</div>
<div class="row">
<div class="large-6 columns">
<label>Label</label>
<input type="text" placeholder="placeholder">
</div>
<div class="large-6 columns">
<div class="row collapse">
<label>Label</label>
<div class="input-group">
<input class="input-group-field" type="text" placeholder="placeholder">
<span class="input-group-label">.com</span>
</div>
</div>
</div>
</div>
<div class="row">
<div class="large-12 columns">
<label>Select Box</label>
<select>
<option value="good">Good</option>
<option value="better">Better</option>
<option value="best">Best</option>
</select>
</div>
</div>
<div class="row">
<div class="large-6 columns">
<label>Choose Your Favorite</label>
<input type="radio" name="radio1" value="radio1" id="radio1"><label for="radio1">Red</label>
<input type="radio" name="radio2" value="radio2" id="radio2"><label for="radio2">Blue</label>
</div>
<div class="large-6 columns">
<label>Check these out</label>
<input id="checkbox1" type="checkbox"><label for="checkbox1">Checkbox 1</label>
<input id="checkbox2" type="checkbox"><label for="checkbox2">Checkbox 2</label>
</div>
</div>
<div class="row">
<div class="large-12 columns">
<label>Textarea Label</label>
<textarea placeholder="placeholder"></textarea>
</div>
</div>
</form></div>
</section>
<section class="ss-section" id="new-section">
<h1>New Section</h1><p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Tempora omnis suscipit id ut laborum recusandae molestias hic aliquid <strong>expedita!</strong> <a href="zurb.com">Non dicta</a>, autem obcaecati error, id ab voluptate unde culpa nulla.</p>
<div class="ss-code"><pre><code class="html"><span class="hljs-tag">&lt;<span class="hljs-title">a</span> <span class="hljs-attribute">href</span>=<span class="hljs-value">"#"</span> <span class="hljs-attribute">class</span>=<span class="hljs-value">"button"</span>&gt;</span>Button<span class="hljs-tag">&lt;/<span class="hljs-title">a</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-title">a</span> <span class="hljs-attribute">href</span>=<span class="hljs-value">"#"</span> <span class="hljs-attribute">class</span>=<span class="hljs-value">"button"</span>&gt;</span>Button<span class="hljs-tag">&lt;/<span class="hljs-title">a</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-title">a</span> <span class="hljs-attribute">href</span>=<span class="hljs-value">"#"</span> <span class="hljs-attribute">class</span>=<span class="hljs-value">"button"</span>&gt;</span>Button<span class="hljs-tag">&lt;/<span class="hljs-title">a</span>&gt;</span></code></pre></div>
<div class="ss-code-live"><a href="#" class="button">Button</a>
<a href="#" class="button">Button</a>
<a href="#" class="button">Button</a></div>
</section>
</div>
</div></div>
<script src="assets/js/app.js"></script>
</body>
</html>

View file

@ -6,6 +6,7 @@ from flask import Blueprint
viewHomepage = Blueprint('homepage', __name__)
@viewHomepage.route('/')
def index():
return render_template('default/homepage/index.html')
@viewHomepage.route('/', defaults={'page': 'index'})
@viewHomepage.route('/<page>.html')
def index(page):
return render_template('gocloud2016/pages/%s.html' % page)

View file

@ -29,15 +29,12 @@ def index():
return render_template(
'default/id/index.html',
user=cud.details_get(),
user_details=cud.details_get()
)
user=cud.details_get(), user_details=cud.details_get())
@viewAccount.route('/edit.html', methods=['GET', 'POST'])
@viewAccount.route('/edit.html', methods=['GET'])
@requires_login
def edit():
cu = ControllerUsers()
cud = ControllerUsersDetails(session['user_id'])
# Проверяем есть ли детали пользователя.
@ -45,7 +42,22 @@ def edit():
# Если нет, то создаём
cud.details_create()
if request.method == "POST":
return render_template(
'default/id/edit.html',
user=cud.details_get(),
user_details=cud.details_get())
@viewAccount.route('/edit.html', methods=['POST'])
@requires_login
def edit_action():
cud = ControllerUsersDetails(session['user_id'])
# Проверяем есть ли детали пользователя.
if not cud.details_exists():
# Если нет, то создаём
cud.details_create()
if not request.form['zipcode'].isdigit():
flash(u'Индекс должен содержать только цифры')
return redirect(url_for('account.edit'))
@ -61,42 +73,13 @@ def edit():
)
return redirect(url_for('account.edit'))
return render_template(
'default/id/edit.html',
user=cud.details_get(),
user_details=cud.details_get()
)
@viewAccount.route('/settings', methods=['GET', 'POST'])
@requires_login
def settings():
return render_template(
'default/id/index.html',
user_details=ControllerUsers(session['user_id']).get()
)
@viewAccount.route('/billing', methods=['GET', 'POST'])
@requires_login
def billing():
user_id = session['user_id']
cub = ControllerBilling()
if not cub.exists(user_id):
cub.create(user_id, balance=0)
# TODO: move to function
user_details = models.Users.select().where(
models.Users.id == session['user_id']
).get()
return render_template(
'default/id/balance.html',
user_details=user_details,
user_balance=cub.get(user_id),
history=cub.transactions_get(user_id)
)
user_details=ControllerUsers(session['user_id']).get())
@viewAccount.route('/registration.html', methods=['GET', 'POST'])
@ -162,7 +145,6 @@ def registration():
@viewAccount.route('/login.html', methods=['GET'])
def login():
cu = ControllerUsers()
return render_template("default/id/login.html")

View file

@ -0,0 +1,74 @@
# coding: utf-8
import validators
from flask import Blueprint, g, render_template, session, redirect, url_for, jsonify
from flask import request, flash
from SWSCloudCore.controllers.billing import ControllerBilling
from SWSCloudCore.controllers.common import ControllerMessagesEmail
from SWSCloudCore.controllers.users import ControllerAPI
from SWSCloudCore.controllers.users import ControllerSSHKey
from SWSCloudCore.controllers.users import ControllerUsers
from SWSCloudCore.controllers.users import ControllerUsersDetails
from SWSCloudCore.controllers.users import ControllerUsersRecoveryCodes
from SWSCloudCore import models
from SWSCloudWeb.common import requires_login
viewBills = Blueprint('bills', __name__, url_prefix='/bills')
@viewBills.route('/')
@requires_login
def index():
user_id = session['user_id']
cub = ControllerBilling()
if not cub.exists(user_id):
cub.create(user_id, balance=0)
return render_template(
'default/billing/index.html',
user_details=models.Users.get_by_id(user_id),
user_balance=cub.get(user_id))
@viewBills.route('/charge.html')
@requires_login
def charge():
user_id = session['user_id']
cub = ControllerBilling()
if not cub.exists(user_id):
cub.create(user_id, balance=0)
return render_template(
'default/billing/charge.html',
user_details=models.Users.get_by_id(user_id))
@viewBills.route('/payments.html')
@requires_login
def payments():
user_id = session['user_id']
cub = ControllerBilling()
if not cub.exists(user_id):
cub.create(user_id, balance=0)
return render_template(
'default/billing/payments.html',
history=cub.transactions_get(user_id))
@viewBills.route('/account.json')
@requires_login
def account_balance_json():
if not session.get('user_id'):
return jsonify({}), 403
user_id = session.get('user_id')
cub = ControllerBilling()
if not cub.exists(user_id):
cub.create(user_id, balance=0)
return jsonify(balance=models.UsersBalance.get_by_account(user_id))

View file

@ -15,33 +15,23 @@ from SWSCloudCore.controllers.ips import ControllerIps
from SWSCloudCore.controllers.tasks import ControllerTasks
from SWSCloudCore.controllers.users import ControllerSSHKey
from SWSCloudCore.controllers.users import ControllerUsers
from SWSCloudWeb.common import requires_login
viewContainers = Blueprint('containers', __name__, url_prefix='/compute/containers')
@viewContainers.route('/')
@requires_login
def index():
# check session
if not ControllerUsers().check_session():
return redirect(url_for("account.logout"))
# auth user
if not ControllerUsers().auth(session['email'], session['password']):
return redirect(url_for("account.logout"))
return render_template(
'default/containers/index.html',
'default/compute/containers/index.html',
# get containers list
containers=ControllerContainers(session['user_id']).get_items())
@viewContainers.route('/create', methods=['GET', 'POST'])
@requires_login
def create():
# check session
if not ControllerUsers().check_session():
return redirect(url_for("account.logout"))
# auth user
if not ControllerUsers().auth(session['email'], session['password']):
return redirect(url_for("account.logout"))
user_balance = ControllerBilling().get(session['user_id'])
user_ssh = ControllerSSHKey(session['user_id'])
@ -139,19 +129,14 @@ def create():
datacenters = ControllerDataCenters().get()
#
return render_template(
'default/containers/create.html',
'default/compute/containers/create.html',
datacenters=datacenters
)
@viewContainers.route('/delete/<uuid:container_id>.html', methods=['GET', 'POST'])
@requires_login
def delete(container_id):
# check session
if not ControllerUsers().check_session():
return redirect(url_for("account.logout"))
# auth user
if not ControllerUsers().auth(session['email'], session['password']):
return redirect(url_for("account.logout"))
#
containers = ControllerContainers(session['user_id'])
# check the user have a selected rule
@ -177,20 +162,14 @@ def delete(container_id):
flash(u'Контейнер был удалён')
return redirect(url_for('containers.index'))
return render_template(
'default/containers/delete.html',
'default/compute/containers/delete.html',
container=container_details
)
@viewContainers.route('/settings/<uuid:container_id>', methods=['GET', 'POST'])
@requires_login
def settings(container_id):
# check session
if not ControllerUsers().check_session():
return redirect(url_for("account.logout"))
# auth user
if not ControllerUsers().auth(session['email'], session['password']):
return redirect(url_for("account.logout"))
containers = ControllerContainers(session['user_id'])
# check the user have a selected rule
@ -234,19 +213,14 @@ def settings(container_id):
return redirect(url_for('containers.settings', container_id=container_id))
return render_template(
'default/containers/settings.html',
'default/compute/containers/settings.html',
container=container_details
)
@viewContainers.route('/stats/<uuid:container_id>.html')
@requires_login
def stats(container_id):
# check session
if not ControllerUsers().check_session():
return redirect(url_for("account.logout"))
# auth user
if not ControllerUsers().auth(session['email'], session['password']):
return redirect(url_for("account.logout"))
# init
containers = ControllerContainers(session['user_id'])
# check the user have a selected rule
@ -273,7 +247,6 @@ def stats(container_id):
})
# return
return render_template(
'default/containers/stats.html',
'default/compute/containers/stats.html',
container=container_details,
stats_memory=statistics
)
stats_memory=statistics)

View file

@ -3,8 +3,7 @@
import uuid
import dateutil.parser
import datetime
from flask import Blueprint, g, redirect, render_template, request, session, jsonify
from flask import url_for, flash
from flask import Blueprint, g, redirect, render_template, request, session, jsonify, url_for, flash
from SWSCloudCore.controllers.billing import ControllerBilling
from SWSCloudCore.controllers.common import ControllerCommon
@ -19,6 +18,7 @@ from SWSCloudCore.controllers.plans import ControllerPlans
from SWSCloudWeb.common import requires_login
from SWSStatisticsClient import SWSStatisticsClient
from SWSCloudCore.models import Vms, Tasks
viewVMs = Blueprint('vms', __name__, url_prefix='/compute/vms')
@ -202,7 +202,7 @@ def delete(vm_id):
return redirect(url_for('vms.index'))
# get container details
return render_template('default/vms/delete.html', vm=vms.get(vm_id))
return render_template('default/compute/vms/delete.html', vm=vms.get(vm_id))
@viewVMs.route('/delete/<uuid:vm_id>.html', methods=['POST'])
@ -363,3 +363,63 @@ def stats_json(vm_id):
read_bytes=read_bytes / 1024 / 1024,
))
return jsonify(network=calc_diff_list(statistics), status=0)
@viewVMs.route('/state.json')
@requires_login
def state_json():
user_id = session.get('user_id')
vm_id = request.args.get('vm_id')
if not ControllerVMS(user_id).exists(vm_id):
return jsonify(status=1, message='instance not exists')
return jsonify(state=Vms.get_state(vm_id), status=0)
@viewVMs.route('/state.json', methods=['POST'])
@requires_login
def state_json_set():
user_id = session.get('user_id')
vm_id = request.form.get('vm_id')
# start, stop, destroy
state = request.form.get('action')
if not ControllerVMS(user_id).exists(vm_id):
return jsonify(status=1, message='instance not exists')
vm = ControllerVMS(session['user_id'])
# get container details
vm_details = vm.get(vm_id=vm_id)
if Tasks.exists_active_tasks(user_id):
flash('Task already exists in queue')
return jsonify(status=3, message='Task already exists in queue')
if state == 'stop':
vm.status_set(vm_id, 3)
# Создание задания
ControllerTasks(session['user_id']).create(
vm_details.datacenter.id,
vm_details.server.id,
'vm_stop',
0,
vm_id=vm_id
)
return jsonify(status=0)
if state == 'start':
balance = ControllerBilling().get(session['user_id'])
if balance <= 0:
flash(u'Недостаточно средств на балансе.', category='info')
return jsonify(status=1, message=u'Недостаточно средств на балансе.')
vm.set_status(vm_id, 2)
# Создание задания
ControllerTasks(session.get('user_id')).create(
vm_details.datacenter.id,
vm_details.server.id,
'vm_start',
0,
vm_id=vm_details.id)
return jsonify(status=0)
return jsonify(status=2, messages='Method undefined')

View file

@ -0,0 +1,34 @@
# coding: utf-8
import os
from flask import render_template
from flask import Blueprint
from flask import redirect
from flask import url_for
viewDocuments = Blueprint('documents', __name__, url_prefix='/documents')
# @viewDocuments.route('/')
# def index():
# kb_markdown = ''
# for ss in file('kb/index.md', 'r'):
# kb_markdown += ss
#
# return render_template('default/kb/index.html', kb_markdown=kb_markdown)
@viewDocuments.route('/<document_name>.html')
def view(document_name):
if not os.path.exists('docs/%s.md' % document_name):
return redirect(url_for('homepage.index'))
#
print document_name
doc_markdown = u''
for ss in file('docs/%s.md' % document_name, 'r'):
doc_markdown += ss.decode('UTF-8')
#
return render_template(
'default/documents/index.html',
doc_markdown=doc_markdown
)

185
cloud-invoicer.py Normal file
View file

@ -0,0 +1,185 @@
# coding: utf-8
html = u"""
<!doctype html>
<html>
<head>
<title>Бланк "Счет на оплату"</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<style>
body { width: 210mm; margin-left: auto; margin-right: auto; border: 1px #efefef solid; font-size: 11pt;}
table.invoice_bank_rekv { border-collapse: collapse; border: 1px solid; }
table.invoice_bank_rekv > tbody > tr > td, table.invoice_bank_rekv > tr > td { border: 1px solid; }
table.invoice_items { border: 1px solid; border-collapse: collapse;}
table.invoice_items td, table.invoice_items th { border: 1px solid;}
</style>
</head>
<body>
<table width="100%">
<tr>
<td>&nbsp;</td>
<td style="width: 155mm;">
<div style="width:155mm; ">
Внимание! Оплата данного счета означает согласие с условиями поставки товара. Уведомление об оплате
обязательно, в противном случае не гарантируется наличие товара на складе. Товар отпускается по факту
прихода денег на р/с Поставщика, самовывозом, при наличии доверенности и паспорта.
</div>
</td>
</tr>
<tr>
<td colspan="2">
<div style="text-align:center; font-weight:bold;">
Образец заполнения платежного поручения </div>
</td>
</tr>
</table>
<table width="100%" cellpadding="2" cellspacing="2" class="invoice_bank_rekv">
<tr>
<td colspan="2" rowspan="2" style="min-height:13mm; width: 105mm;">
<table width="100%" border="0" cellpadding="0" cellspacing="0" style="height: 13mm;">
<tr>
<td valign="top">
<div>Укажите название банка</div>
</td>
</tr>
<tr>
<td valign="bottom" style="height: 3mm;">
<div style="font-size:10pt;">
Банк получателя
</div>
</td>
</tr>
</table>
</td>
<td style="min-height:7mm;height:auto; width: 25mm;">
<div>БИK</div>
</td>
<td rowspan="2" style="vertical-align: top; width: 60mm;">
<div style=" height: 7mm; line-height: 7mm; vertical-align: middle;">Бик банка</div>
<div>Счет банка</div>
</td>
</tr>
<tr>
<td style="width: 25mm;">
<div>Сч. </div>
</td>
</tr>
<tr>
<td style="min-height:6mm; height:auto; width: 50mm;">
<div>ИНН 0000000</div>
</td>
<td style="min-height:6mm; height:auto; width: 55mm;">
<div>КПП </div>
</td>
<td rowspan="2" style="min-height:19mm; height:auto; vertical-align: top; width: 25mm;">
<div>Сч. </div>
</td>
<td rowspan="2" style="min-height:19mm; height:auto; vertical-align: top; width: 60mm;">
<div>Расчетный счет</div>
</td>
</tr>
<tr>
<td colspan="2" style="min-height:13mm; height:auto;">
<table border="0" cellpadding="0" cellspacing="0" style="height: 13mm; width: 105mm;">
<tr>
<td valign="top">
<div>Название организации</div>
</td>
</tr>
<tr>
<td valign="bottom" style="height: 3mm;">
<div style="font-size: 10pt;">Получатель</div>
</td>
</tr>
</table>
</td>
</tr>
</table>
<br/>
<div style="font-weight: bold; font-size: 16pt; padding-left:5px;">
Счет 0 от 15.10.2016</div>
<br/>
<div style="background-color:#000000; width:100%; font-size:1px; height:2px;">&nbsp;</div>
<table width="100%">
<tr>
<td style="width: 30mm;">
<div style=" padding-left:2px;">Поставщик: </div>
</td>
<td>
<div style="font-weight:bold; padding-left:2px;">
Укажите полной название продающей организации </div>
</td>
</tr>
<tr>
<td style="width: 30mm;">
<div style=" padding-left:2px;">Покупатель: </div>
</td>
<td>
<div style="font-weight:bold; padding-left:2px;">
Укажите полной название покупающей организации </div>
</td>
</tr>
</table>
<table class="invoice_items" width="100%" cellpadding="2" cellspacing="2">
<thead>
<tr>
<th style="width:13mm;"></th>
<th style="width:20mm;">Код</th>
<th>Товар</th>
<th style="width:20mm;">Кол-во</th>
<th style="width:17mm;">Ед.</th>
<th style="width:27mm;">Цена</th>
<th style="width:27mm;">Сумма</th>
</tr>
</thead>
<tbody >
</tbody>
</table>
<table border="0" width="100%" cellpadding="1" cellspacing="1">
<tr>
<td></td>
<td style="width:27mm; font-weight:bold; text-align:right;">Итого:</td>
<td style="width:27mm; font-weight:bold; text-align:right;">0.00</td>
</tr>
</table>
<br />
<div>
Всего наименований 0 на сумму 0.00 рублей.<br />
Ноль рублей 00 копеек</div>
<br /><br />
<div style="background-color:#000000; width:100%; font-size:1px; height:2px;">&nbsp;</div>
<br/>
<div>Руководитель ______________________ (Фамилия И.О.)</div>
<br/>
<div>Главный бухгалтер ______________________ (Фамилия И.О.)</div>
<br/>
<div style="width: 85mm;text-align:center;">М.П.</div>
<br/>
<div style="width:800px;text-align:left;font-size:10pt;">Счет действителен к оплате в течении трех дней.</div>
</body>
</html>
"""
print type(html)
pdf = MyFPDF()
# First page
pdf.add_page()
pdf.write_html(str(html))
pdf.output('html.pdf', 'F')
# pdf = fpdf.FPDF(format='A4')
# pdf.add_page()
# pdf.set_font("Arial", size=12)
# # pdf.cell(200, 10, txt="Welcome to Python!", ln=1, align="C")
# pdf.cell(200, 10, txt=x, ln=1, align="C")
# pdf.cell(200,10,'Powered by FPDF',0,1,'C')
# pdf.output("tutorial.pdf")

121
cloud-invoicer2.py Normal file
View file

@ -0,0 +1,121 @@
# coding: utf-8
from decimal import Decimal
from lxml import etree, objectify
from reportlab.lib import colors
from reportlab.lib.pagesizes import letter
from reportlab.lib.styles import getSampleStyleSheet
from reportlab.lib.units import inch, mm
from reportlab.pdfgen import canvas
from reportlab.platypus import Paragraph, Table, TableStyle
from reportlab.pdfbase import pdfmetrics
from reportlab.pdfbase.ttfonts import TTFont
########################################################################
class PDFOrder(object):
""""""
# ----------------------------------------------------------------------
def __init__(self, xml_file, pdf_file):
"""Constructor"""
self.xml_file = xml_file
self.pdf_file = pdf_file
self.xml_obj = self.getXMLObject()
# ----------------------------------------------------------------------
def coord(self, x, y, unit=1):
"""
# http://stackoverflow.com/questions/4726011/wrap-text-in-a-table-reportlab
Вспомогательный класс для позиционирования в объектах Canvas
"""
x, y = x * unit, self.height - y * unit
return x, y
# ----------------------------------------------------------------------
def createPDF(self):
"""
Создаём PDF на основании XML данных
"""
self.canvas = canvas.Canvas(self.pdf_file, pagesize=letter)
pdfmetrics.registerFont(TTFont('FreeSans', 'FreeSans.ttf'))
self.canvas.setFont('FreeSans', 32)
# self.canvas.setFont('Times-Roman', 20)
width, self.height = letter
styles = getSampleStyleSheet()
xml = self.xml_obj
address = str(""" <font size="9">
Доставка:<br/>
ewdewfewfйцуцйу<br/>
%s<br/>
%s<br/>
%s<br/>
%s<br/>
</font>
""") % (xml.address1, xml.address2, xml.address3, xml.address4)
p = Paragraph(address, styles["Normal"])
p.wrapOn(self.canvas, width, self.height)
p.drawOn(self.canvas, *self.coord(18, 40, mm))
order_number = '<font size="14"><b>Order #%s </b></font>' % xml.order_number
p = Paragraph(order_number, styles["Normal"])
p.wrapOn(self.canvas, width, self.height)
p.drawOn(self.canvas, *self.coord(18, 50, mm))
data = []
data.append(["Item ID", "Name", "Price", "Quantity", "Total"])
grand_total = 0
for item in xml.order_items.iterchildren():
row = []
row.append(item.id)
row.append(item.name)
row.append(item.price)
row.append(item.quantity)
total = Decimal(str(item.price)) * Decimal(str(item.quantity))
row.append(str(total))
grand_total += total
data.append(row)
data.append(["", "", "", "Grand Total:", grand_total])
t = Table(data, 1.5 * inch)
t.setStyle(TableStyle([
('INNERGRID', (0,0), (-1,-1), 0.25, colors.black),
('BOX', (0,0), (-1,-1), 0.25, colors.black)
]))
t.wrapOn(self.canvas, width, self.height)
t.drawOn(self.canvas, *self.coord(18, 85, mm))
txt = "Thank you for your business!"
p = Paragraph(txt, styles["Normal"])
p.wrapOn(self.canvas, width, self.height)
p.drawOn(self.canvas, *self.coord(18, 95, mm))
# ----------------------------------------------------------------------
def getXMLObject(self):
"""
Открываем XML документ и возвращаем lxml XML документ
"""
with open(self.xml_file) as f:
xml = f.read()
return objectify.fromstring(xml)
#----------------------------------------------------------------------
def savePDF(self):
"""
Сохраняем PDF
"""
self.canvas.save()
#----------------------------------------------------------------------
if __name__ == "__main__":
xml = "order.xml"
pdf = "letter.pdf"
doc = PDFOrder(xml, pdf)
doc.createPDF()
doc.savePDF()

57
letter.pdf Normal file
View file

@ -0,0 +1,57 @@
%PDF-1.4
%“Œ‹ž ReportLab Generated PDF document http://www.reportlab.com
1 0 obj
<< /F1 2 0 R /F2 3 0 R /F3 4 0 R >>
endobj
2 0 obj
<< /BaseFont /Helvetica /Encoding /WinAnsiEncoding /Name /F1 /Subtype /Type1 /Type /Font >>
endobj
3 0 obj
<< /BaseFont /ZapfDingbats /Encoding /ZapfDingbatsEncoding /Name /F2 /Subtype /Type1 /Type /Font >>
endobj
4 0 obj
<< /BaseFont /Helvetica-Bold /Encoding /WinAnsiEncoding /Name /F3 /Subtype /Type1 /Type /Font >>
endobj
5 0 obj
<< /Contents 9 0 R /MediaBox [ 0 0 612 792 ] /Parent 8 0 R /Resources << /Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] >> /Rotate 0 /Trans << >>
/Type /Page >>
endobj
6 0 obj
<< /Outlines 10 0 R /PageMode /UseNone /Pages 8 0 R /Type /Catalog >>
endobj
7 0 obj
<< /Author (anonymous) /CreationDate (D:20161016043545-03'00') /Creator (ReportLab PDF Library - www.reportlab.com) /Keywords () /ModDate (D:20161016043545-03'00') /Producer (ReportLab PDF Library - www.reportlab.com)
/Subject (unspecified) /Title (untitled) /Trapped /False >>
endobj
8 0 obj
<< /Count 1 /Kids [ 5 0 R ] /Type /Pages >>
endobj
9 0 obj
<< /Filter [ /ASCII85Decode /FlateDecode ] /Length 735 >>
stream
GasJPgN)"%&;KYAnN1Qb2mh$p3r4rMVN;4S9M8:0o\'IG#dN4>AdE<^Be<hY@c;s8q=i@@FtJURd5T$fOTF5_E-4g)1.YG2KeFQoJ8+#&rd#f(=\4%YGebF-,<qiQl'Vh@an4dMP`TG>kQ+u/`Zr=3r2g^b-k.lUmI^LCk74u@CK)JQ#\18LWr5OS(-LdAS.D-;?`\=9'WQ4E)2H=GYuQ&Q:IVk]/;C:l,6%eP0-JM^Zo*hl9jJh13EmLqHkqBD>Fd\H2g+u@9V&>(\Lr(ZQ1*g4Q1/*N?/uhi?OS@-82hCT,T;,0dWmd#HA`%oY>R#_4KDHdZUmAd&#4H%(AsJ1C4KcP[FDkE/;>k(8W,b"d_+GdLB1<BW$RY%:1"40!+_$"V>@5R;R"gGohPUPnc7,oXVAuZmRX:!mDlIV+%o0q+r6%6G_c\l:h4ZQ0a*n,/G=3b/IIli@D4@7"^rsL,8!"o'B7*N6I_.<76^h:?OIIk_oRsp`I=[aXl(P.[]4MPhpSe,6WhKr^h$#^6Q'EJ(Cf#9[g^o.O'pVP1<l/9g\KR2>FGms]h6\mnF++Nc#`c[5M^T0T1R[^UYMBR$o3nG#;>SA&Z)_+*ZRTi=A]Th,)r\&#?IWGdY82-R'\?<!NN$c<6bWHVXIL#)60S&<+<jAYeJb)DkoSHQqsV@:.N>%O@5Fq@s],dSsSJJS`X-9'K]D3V<LYJ[Au3rWiC:C+3rf(rW.VMNog~>endstream
endobj
10 0 obj
<< /Count 0 /Type /Outlines >>
endobj
xref
0 11
0000000000 65535 f
0000000075 00000 n
0000000129 00000 n
0000000239 00000 n
0000000357 00000 n
0000000472 00000 n
0000000669 00000 n
0000000757 00000 n
0000001057 00000 n
0000001119 00000 n
0000001949 00000 n
trailer
<< /ID
% ReportLab generated PDF document -- digest (http://www.reportlab.com)
[(F\377\262C\004ZI\203\233\321\244^\250\251\025\300) (F\377\262C\004ZI\203\233\321\244^\250\251\025\300)]
/Info 7 0 R /Root 6 0 R /Size 11 >>
startxref
1999
%%EOF

28
order.xml Normal file
View file

@ -0,0 +1,28 @@
<?xml version="1.0"?> <invoice>
<order_number>456789</order_number>
<customer_id>789654</customer_id>
<address1>John Doe</address1>
<address2>123 Dickens Road</address2>
<address3>Johnston, IA 55555</address3>
<address4/>
<order_items>
<item>
<id>11123</id>
<name>Expo Dry Erase Pen</name>
<price>1.99</price>
<quantity>5</quantity>
</item>
<item>
<id>22245</id>
<name>Cisco IP Phone 7942</name>
<price>300</price>
<quantity>1</quantity>
</item>
<item>
<id>33378</id>
<name>Waste Basket</name>
<price>9.99</price>
<quantity>1</quantity>
</item>
</order_items>
</invoice>

BIN
tutorial.pdf Normal file

Binary file not shown.