Initial commit

This commit is contained in:
resteve 2013-05-10 11:51:51 +02:00
commit ae044730c0
32 changed files with 9688 additions and 0 deletions

14
COPYRIGHT Executable file
View File

@ -0,0 +1,14 @@
Copyright (C) 2013 Zikzakmedia SL.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.

27
INSTALL Executable file
View File

@ -0,0 +1,27 @@
Installing Flask Apps Tryton
============================
Prerequisites
-------------
* Flask (https://pypi.python.org/pypi/Flask)
Configuration
-------------
config.ini
* APP NAME
config.cfg
* Debug
* Template
* Language
PKG-INFO
--------
Create a ln in your packages to get information module:
src/account$ ln -s trytond_account.egg-info/PKG-INFO PKG-INFO

30
README Normal file
View File

@ -0,0 +1,30 @@
Flask-AppsTryton
================
Flask-AppsTryton is a Flask App to list tryton modules and information.
Installing
----------
See INSTALL
Support
-------
For more information or if you encounter any problems with this module,
please contact the programmers at
Zikzakmedia
--------------
website: http://www.zikzakmedia.com/
email: zikzak@zikzakmedia.com
License
-------
See LICENSE
Copyright
---------
See COPYRIGHT

170
app.py Normal file
View File

@ -0,0 +1,170 @@
#This file is part appstryton app for Flask.
#The COPYRIGHT file at the top level of this repository contains
#the full copyright notices and license terms.
import os
import json
import ConfigParser
import pkg_resources
from pkginfo import *
import datetime
from flask import Flask, render_template, request, abort
from flask.ext.babel import Babel, gettext as _
from flask.ext.cache import Cache
from urlparse import urljoin
from werkzeug.contrib.atom import AtomFeed
from modescription import get_description, read_rst
def get_config():
'''Get values from cfg file'''
conf_file = '%s/config.ini' % os.path.dirname(os.path.realpath(__file__))
config = ConfigParser.ConfigParser()
config.read(conf_file)
results = {}
for section in config.sections():
results[section] = {}
for option in config.options(section):
results[section][option] = config.get(section, option)
return results
def create_app(config=None):
'''Create Flask APP'''
cfg = get_config()
app_name = cfg['flask']['app_name']
app = Flask(app_name)
app.config.from_pyfile(config)
return app
def get_template(app, tpl):
'''Get template'''
return "%s/%s" % (app.config.get('TEMPLATE'), tpl)
def parse_setup(filename):
globalsdict = {} # put predefined things here
localsdict = {} # will be populated by executed script
execfile(filename, globalsdict, localsdict)
return localsdict
def get_lang():
return app.config.get('LANGUAGE')
conf_file = '%s/config.cfg' % os.path.dirname(os.path.realpath(__file__))
app = create_app(conf_file)
app.config['BABEL_DEFAULT_LOCALE'] = get_lang()
babel = Babel(app)
cache = Cache(app)
@app.errorhandler(404)
def page_not_found(e):
return render_template(get_template(app, '404.html')), 404
def make_external(url):
return urljoin(request.url_root, url)
def get_module(modules, module):
'''Return dict of base data module'''
return (item for item in modules if item["module_name"] == module).next()
def get_info_module(src):
'''Return dict of info module'''
try:
info = UnpackedSDist(src)
except:
info = None
return info
def get_modules():
'''Return list of info dict module'''
modules = []
tocs = []
name_toc = None
add_toc = True
for ep in pkg_resources.iter_entry_points('trytond.modules'):
module_name = ep.module_name.split('.')[-1]
name = ' '.join([n.capitalize() for n in module_name.split('_')])
group = name.split(' ')[0]
src = '%s/setup.py' % ep.dist.location
info = get_info_module(src)
if name_toc != group:
name_toc = group
tocs.append(group)
add_toc = True
else:
name_toc = group
add_toc = False
mod = {
'group': group,
'name': name,
'module_name': module_name,
'version': ep.dist.version,
'location': ep.dist.location,
'info': info,
}
if add_toc:
mod['toc'] = name_toc
modules.append(mod)
return modules, tocs
@app.route('/')
@cache.cached(timeout=120)
def index():
modules, tocs = get_modules()
return render_template(get_template(app, 'index.html'), modules=modules, tocs=tocs)
@app.route('/<slug>/')
@cache.cached(timeout=120)
def info(slug):
modules_by_category = []
lang = get_lang()
modules, tocs = get_modules()
module = get_module(modules, slug)
if module:
group = module['group']
for mod in modules:
if mod['group'] == group:
modules_by_category.append({
'name': mod['name'],
'module_name': mod['module_name'],
})
src = '%s/setup.py' % module['location']
info = get_info_module(src)
if info:
module['info'] = info
description = get_description(lang, module['location'], module['name'])
if description:
module['description'] = description
return render_template(get_template(app, 'info.html'), module=module, tocs=modules_by_category)
else:
abort(404)
@app.route('/modules.atom')
@cache.cached(timeout=120)
def modules_feed():
feed = AtomFeed('Tryton Modules',
feed_url=request.url, url=request.url_root)
modules, tocs = get_modules()
for module in modules:
description = ''
print module
if module['info']:
description = module['info'].summary
url = ''
feed.add(module['name'], unicode(description),
content_type='html',
author=app.config.get('AUTHOR'),
url=make_external(module['module_name']),
updated=datetime.datetime.now(),
published=datetime.datetime.now())
return feed.get_response()
if __name__ == "__main__":
app.run()

3
babel.cfg Normal file
View File

@ -0,0 +1,3 @@
[python: **.py]
[jinja2: **/templates/**.html]
extensions=jinja2.ext.autoescape,jinja2.ext.with_

11
config.cfg.template Normal file
View File

@ -0,0 +1,11 @@
DEBUG = True
DEBUG_LOG = 'logs/debug.log'
ERROR_LOG = 'logs/error.log'
ADMINS = ('user@domain.com',)
TITLE = 'Tryton Modules'
TEMPLATE = 'default'
LANGUAGE = 'es'
AUTHOR = 'Zikzakmedia'
ANALYTICS = ''
CACHE_TYPE = 'simple'

2
config.ini.template Normal file
View File

@ -0,0 +1,2 @@
[flask]
APP_NAME = 'appstryton'

59
messages.pot Normal file
View File

@ -0,0 +1,59 @@
# Translations template for PROJECT.
# Copyright (C) 2013 ORGANIZATION
# This file is distributed under the same license as the PROJECT project.
# FIRST AUTHOR <EMAIL@ADDRESS>, 2013.
#
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: PROJECT VERSION\n"
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
"POT-Creation-Date: 2013-05-10 11:50+0200\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Generated-By: Babel 0.9.6\n"
#: templates/default/index.html:7
msgid "Table of contents"
msgstr ""
#: templates/default/info.html:8
msgid "Summary"
msgstr ""
#: templates/default/info.html:9
msgid "Version"
msgstr ""
#: templates/default/info.html:10
msgid "Author"
msgstr ""
#: templates/default/info.html:11
msgid "Licence"
msgstr ""
#: templates/default/info.html:12
msgid "Project"
msgstr ""
#: templates/default/info.html:13
msgid "Download"
msgstr ""
#: templates/default/info.html:16
msgid "Module Description"
msgstr ""
#: templates/default/info.html:21
msgid "Other modules"
msgstr ""
#: templates/default/info.html:25
msgid "All list modules"
msgstr ""

64
modescription.py Normal file
View File

@ -0,0 +1,64 @@
#This file is part appstryton app for Flask.
#The COPYRIGHT file at the top level of this repository contains
#the full copyright notices and license terms.
import os
import docutils.core
def get_description(lang, src, name):
'''Get Description module from doc rst'''
description = ''
doc_path = '%s/doc/%s/index.rst' % (src, lang)
if os.path.exists(doc_path):
return read_rst(doc_path)
doc_path = '%s/doc/index.rst' % (path)
if os.path.exists(doc_path):
return read_rst(doc_path)
def read_rst(doc_path):
f = open(doc_path, "r")
description = f.read()
def rst2html(source, source_path=None, source_class=docutils.io.StringInput,
destination_path=None, reader=None, reader_name='standalone',
parser=None, parser_name='restructuredtext', writer=None,
writer_name='html', settings=None, settings_spec=None,
settings_overrides=None, config_section=None,
enable_exit_status=None):
"""
Set up & run a `Publisher`, and return a dictionary of document parts.
Dictionary keys are the names of parts, and values are Unicode strings;
encoding is up to the client. For programmatic use with string I/O.
For encoded string input, be sure to set the 'input_encoding' setting to
the desired encoding. Set it to 'unicode' for unencoded Unicode string
input. Here's how::
publish_parts(..., settings_overrides={'input_encoding': 'unicode'})
Parameters: see `publish_programmatically`.
"""
output, pub = docutils.core.publish_programmatically(
source=source, source_path=source_path, source_class=source_class,
destination_class=docutils.io.StringOutput,
destination=None, destination_path=destination_path,
reader=reader, reader_name=reader_name,
parser=parser, parser_name=parser_name,
writer=writer, writer_name=writer_name,
settings=settings, settings_spec=settings_spec,
settings_overrides=settings_overrides,
config_section=config_section,
enable_exit_status=enable_exit_status)
return pub.writer.parts['fragment'], pub.document.reporter.max_level, pub.settings.record_dependencies
output, error_level, deps = rst2html(
description, settings_overrides={
'initial_header_level': 2,
'record_dependencies': True,
'stylesheet_path': None,
'link_stylesheet': True,
'syntax_highlight': 'short',
})
return output

4
requirements.txt Normal file
View File

@ -0,0 +1,4 @@
pkginfo>=1.0
Flask-Cache>=0.12
docutils>=0.10
Flask-Babel>=0.8

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

5262
static/default/css/bootstrap.css vendored Normal file

File diff suppressed because it is too large Load Diff

9
static/default/css/bootstrap.min.css vendored Normal file

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,62 @@
body {
padding-top: 60px;
}
@media (max-width: 979px) {
body {
padding-top: 0px;
}
}
.posted { font-size: 10px; color: #333333}
.pull-right { padding-top:10px}
.dropdown a { color:#fff}
.hide-title { display: none; visibility: hidden}
#sourcelink { display: none; visibility: hidden}
/* Banner */
#banner-box h2 { margin-left:30px}
#banner-box p { margin-left:25px}
#banner-box .bottons{ margin-top: 60px}
.banner { padding: 30px 0; background-color: #6980a1; font-size: 18px; color: #e3e3e3; margin-top: 20px; border-radius: 6px}
.banner p { padding: 0 10px}
/* FAQ */
#contents { float: right; margin-left:10px; padding-top:10px; padding-left:5px; width: 250px; border-left: 1px solid #bfbfbf; font-size:12px; color:#6666}
#contents .topic-title { display: none; visibility: hidden}
/* About */
.about { margin-top: 40px; margin-bottom: 40px}
.about > div { margin-bottom: 20px}
.about h3 { margin: 0; text-align: left; font-size: 14px}
.about i {margin-right: 8px; font-size: 1.3em}
/*Footer */
hr .footer { margin: 10px 0; border: 0}
/* Footer - Logos*/
#footer-box { border:1px solid #ebebeb; border-top:1px solid #f2f2f2; -webkit-border-radius:5px; -moz-border-radius:5px; border-radius:5px);}
.logos { }
.logos h3 { padding-left:6px; font-size:11px; color:#999; font-weight:normal}
.logos h3 a { font-weight:normal; color:#5b80b2; margin-left:5px}
.logos a { margin-left:20px}
.logos p {}
.logos .first { margin-right:15px}
/* Footer - Box blue */
#footer-site { margin-top: 10px; margin-bottom:10px}
.site-box { border-radius:5px; background:#5b80b2; background:-webkit-gradient(linear, 0 0, 0 bottom, from(#7b99c1), to(#557299)); background:-moz-linear-gradient(#7b99c1, #557299); background:linear-gradient(#7b99c1, #557299); -pie-background:linear-gradient(#7b99c1, #557299); -webkit-border-radius:5px; -moz-border-radius:5px}
.site-copyright { font-size:12px; color:#fefefe; padding:10px 15px}
.site-copyright p { margin:0}
.site-copyright p a { color:#fefefe; font-weight:normal}
/*Descarga */
#linux h2 { font-size: 16px; padding-left: 25px; border-bottom:1px solid #f2f2f2; background: url(../img/linux.png) no-repeat left center}
#windows h2 { font-size: 16px; padding-left: 25px; border-bottom:1px solid #f2f2f2; background: url(../img/windows.png) no-repeat left center}
#macos-x h2 { font-size: 16px; padding-left: 25px; border-bottom:1px solid #f2f2f2; background: url(../img/macos.png) no-repeat left center}
#android h2 { font-size: 16px; padding-left: 25px; border-bottom:1px solid #f2f2f2; background: url(../img/android.png) no-repeat left center}
/*Demo */
#descargar h2 { font-size: 16px; padding-left: 25px; border-bottom:1px solid #f2f2f2; background: url(../img/descargar.png) no-repeat left center}
#conectar h2 { font-size: 16px; padding-left: 25px; border-bottom:1px solid #f2f2f2; background: url(../img/conectar.png) no-repeat left center}
#demo h2 { font-size: 16px; padding-left: 25px; border-bottom:1px solid #f2f2f2; background: url(../img/tour.png) no-repeat left center}

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

361
static/default/js/bootstrap-tooltip.js vendored Normal file
View File

@ -0,0 +1,361 @@
/* ===========================================================
* bootstrap-tooltip.js v2.3.1
* http://twitter.github.com/bootstrap/javascript.html#tooltips
* Inspired by the original jQuery.tipsy by Jason Frame
* ===========================================================
* Copyright 2012 Twitter, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ========================================================== */
!function ($) {
"use strict"; // jshint ;_;
/* TOOLTIP PUBLIC CLASS DEFINITION
* =============================== */
var Tooltip = function (element, options) {
this.init('tooltip', element, options)
}
Tooltip.prototype = {
constructor: Tooltip
, init: function (type, element, options) {
var eventIn
, eventOut
, triggers
, trigger
, i
this.type = type
this.$element = $(element)
this.options = this.getOptions(options)
this.enabled = true
triggers = this.options.trigger.split(' ')
for (i = triggers.length; i--;) {
trigger = triggers[i]
if (trigger == 'click') {
this.$element.on('click.' + this.type, this.options.selector, $.proxy(this.toggle, this))
} else if (trigger != 'manual') {
eventIn = trigger == 'hover' ? 'mouseenter' : 'focus'
eventOut = trigger == 'hover' ? 'mouseleave' : 'blur'
this.$element.on(eventIn + '.' + this.type, this.options.selector, $.proxy(this.enter, this))
this.$element.on(eventOut + '.' + this.type, this.options.selector, $.proxy(this.leave, this))
}
}
this.options.selector ?
(this._options = $.extend({}, this.options, { trigger: 'manual', selector: '' })) :
this.fixTitle()
}
, getOptions: function (options) {
options = $.extend({}, $.fn[this.type].defaults, this.$element.data(), options)
if (options.delay && typeof options.delay == 'number') {
options.delay = {
show: options.delay
, hide: options.delay
}
}
return options
}
, enter: function (e) {
var defaults = $.fn[this.type].defaults
, options = {}
, self
this._options && $.each(this._options, function (key, value) {
if (defaults[key] != value) options[key] = value
}, this)
self = $(e.currentTarget)[this.type](options).data(this.type)
if (!self.options.delay || !self.options.delay.show) return self.show()
clearTimeout(this.timeout)
self.hoverState = 'in'
this.timeout = setTimeout(function() {
if (self.hoverState == 'in') self.show()
}, self.options.delay.show)
}
, leave: function (e) {
var self = $(e.currentTarget)[this.type](this._options).data(this.type)
if (this.timeout) clearTimeout(this.timeout)
if (!self.options.delay || !self.options.delay.hide) return self.hide()
self.hoverState = 'out'
this.timeout = setTimeout(function() {
if (self.hoverState == 'out') self.hide()
}, self.options.delay.hide)
}
, show: function () {
var $tip
, pos
, actualWidth
, actualHeight
, placement
, tp
, e = $.Event('show')
if (this.hasContent() && this.enabled) {
this.$element.trigger(e)
if (e.isDefaultPrevented()) return
$tip = this.tip()
this.setContent()
if (this.options.animation) {
$tip.addClass('fade')
}
placement = typeof this.options.placement == 'function' ?
this.options.placement.call(this, $tip[0], this.$element[0]) :
this.options.placement
$tip
.detach()
.css({ top: 0, left: 0, display: 'block' })
this.options.container ? $tip.appendTo(this.options.container) : $tip.insertAfter(this.$element)
pos = this.getPosition()
actualWidth = $tip[0].offsetWidth
actualHeight = $tip[0].offsetHeight
switch (placement) {
case 'bottom':
tp = {top: pos.top + pos.height, left: pos.left + pos.width / 2 - actualWidth / 2}
break
case 'top':
tp = {top: pos.top - actualHeight, left: pos.left + pos.width / 2 - actualWidth / 2}
break
case 'left':
tp = {top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left - actualWidth}
break
case 'right':
tp = {top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left + pos.width}
break
}
this.applyPlacement(tp, placement)
this.$element.trigger('shown')
}
}
, applyPlacement: function(offset, placement){
var $tip = this.tip()
, width = $tip[0].offsetWidth
, height = $tip[0].offsetHeight
, actualWidth
, actualHeight
, delta
, replace
$tip
.offset(offset)
.addClass(placement)
.addClass('in')
actualWidth = $tip[0].offsetWidth
actualHeight = $tip[0].offsetHeight
if (placement == 'top' && actualHeight != height) {
offset.top = offset.top + height - actualHeight
replace = true
}
if (placement == 'bottom' || placement == 'top') {
delta = 0
if (offset.left < 0){
delta = offset.left * -2
offset.left = 0
$tip.offset(offset)
actualWidth = $tip[0].offsetWidth
actualHeight = $tip[0].offsetHeight
}
this.replaceArrow(delta - width + actualWidth, actualWidth, 'left')
} else {
this.replaceArrow(actualHeight - height, actualHeight, 'top')
}
if (replace) $tip.offset(offset)
}
, replaceArrow: function(delta, dimension, position){
this
.arrow()
.css(position, delta ? (50 * (1 - delta / dimension) + "%") : '')
}
, setContent: function () {
var $tip = this.tip()
, title = this.getTitle()
$tip.find('.tooltip-inner')[this.options.html ? 'html' : 'text'](title)
$tip.removeClass('fade in top bottom left right')
}
, hide: function () {
var that = this
, $tip = this.tip()
, e = $.Event('hide')
this.$element.trigger(e)
if (e.isDefaultPrevented()) return
$tip.removeClass('in')
function removeWithAnimation() {
var timeout = setTimeout(function () {
$tip.off($.support.transition.end).detach()
}, 500)
$tip.one($.support.transition.end, function () {
clearTimeout(timeout)
$tip.detach()
})
}
$.support.transition && this.$tip.hasClass('fade') ?
removeWithAnimation() :
$tip.detach()
this.$element.trigger('hidden')
return this
}
, fixTitle: function () {
var $e = this.$element
if ($e.attr('title') || typeof($e.attr('data-original-title')) != 'string') {
$e.attr('data-original-title', $e.attr('title') || '').attr('title', '')
}
}
, hasContent: function () {
return this.getTitle()
}
, getPosition: function () {
var el = this.$element[0]
return $.extend({}, (typeof el.getBoundingClientRect == 'function') ? el.getBoundingClientRect() : {
width: el.offsetWidth
, height: el.offsetHeight
}, this.$element.offset())
}
, getTitle: function () {
var title
, $e = this.$element
, o = this.options
title = $e.attr('data-original-title')
|| (typeof o.title == 'function' ? o.title.call($e[0]) : o.title)
return title
}
, tip: function () {
return this.$tip = this.$tip || $(this.options.template)
}
, arrow: function(){
return this.$arrow = this.$arrow || this.tip().find(".tooltip-arrow")
}
, validate: function () {
if (!this.$element[0].parentNode) {
this.hide()
this.$element = null
this.options = null
}
}
, enable: function () {
this.enabled = true
}
, disable: function () {
this.enabled = false
}
, toggleEnabled: function () {
this.enabled = !this.enabled
}
, toggle: function (e) {
var self = e ? $(e.currentTarget)[this.type](this._options).data(this.type) : this
self.tip().hasClass('in') ? self.hide() : self.show()
}
, destroy: function () {
this.hide().$element.off('.' + this.type).removeData(this.type)
}
}
/* TOOLTIP PLUGIN DEFINITION
* ========================= */
var old = $.fn.tooltip
$.fn.tooltip = function ( option ) {
return this.each(function () {
var $this = $(this)
, data = $this.data('tooltip')
, options = typeof option == 'object' && option
if (!data) $this.data('tooltip', (data = new Tooltip(this, options)))
if (typeof option == 'string') data[option]()
})
}
$.fn.tooltip.Constructor = Tooltip
$.fn.tooltip.defaults = {
animation: true
, placement: 'top'
, selector: false
, template: '<div class="tooltip"><div class="tooltip-arrow"></div><div class="tooltip-inner"></div></div>'
, trigger: 'hover focus'
, title: ''
, delay: 0
, html: false
, container: false
}
/* TOOLTIP NO CONFLICT
* =================== */
$.fn.tooltip.noConflict = function () {
$.fn.tooltip = old
return this
}
}(window.jQuery);

2276
static/default/js/bootstrap.js vendored Normal file

File diff suppressed because it is too large Load Diff

6
static/default/js/bootstrap.min.js vendored Normal file

File diff suppressed because one or more lines are too long

4
static/default/js/jquery-1.7.2.min.js vendored Normal file

File diff suppressed because one or more lines are too long

BIN
static/images/nan-tic.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

BIN
static/images/python.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

View File

@ -0,0 +1,14 @@
{% extends "{{ config['TEMPLATE'] }}/layout.html" %}
{% block title %}404, Page Not Found{% endblock %}
{% block body %}
<div class="row">
<div class="error">
<h1>404, Page Not Found</h1>
<blockquote>
<p>The requested page,</p>
<p>cannot be found — </p>
<p>We're sorry.</p>
</blockquote>
</div>
</div>
{% endblock %}

View File

@ -0,0 +1,25 @@
<div id="footer-box" class="row logos">
<div class="span8">
<h3>Desarrolladores</h3>
<p>
<a href="http://www.nan-tic.com/"><img src="{{ url_for('static', filename='images/nan-tic.png') }}" alt="Nan TIC"></a>
<a href="http://www.zikzakmedia.com/es/acerca-de-tryton"><img src="{{ url_for('static', filename='images/zikzakmedia.png') }}" alt="Zikzakmedia"></a>
</p>
</div>
<div class="span4">
<h3>Hacemos uso de</h3>
<p>
<a href="http://www.python.org/" class="first"><img src="{{ url_for('static', filename='images/python.png') }}" alt="Python"></a>
</p>
</div>
</div>
<div id="footer-site" class="row site-box site-copyright">
<div class="span12">
<p class="left">Tryton ERP es una iniciativa de NaN·tic y
Zikzakmedia para la implementación y divulgación de Tryton como ERP
libre para la pequeña y mediana empresa. Se trata de una iniciativa
privada que no pretende reemplazar, ni comunicar en nombre del conjunto
de la comunidad Tryton. Tryton es una marca registrada por la Fundación Tryton.</p>
</div>
</div>

View File

@ -0,0 +1,24 @@
{% extends "default/layout.html" %}
{% block title %}Apps Tryton{% endblock %}
{% block body %}
<div class="row">
<div class="span12">
<div class="contents topic" id="contents">
<p class="topic-title first">{{ _("Table of contents") }}</p>
<ul class="simple">
{% for toc in tocs %}<li><a class="reference internal" href="#{{ toc }}">{{ toc }}</a></li>{% endfor %}
</ul>
</div>
<div class="tooltip-apps">
{% for module in modules %}{% if module.toc %}<div class="section" id="{{ module.toc }}"><strong>{{ module.toc }}</strong></div>{% endif %}
<p><strong><a href="{{ module.module_name }}" alt="{{ module.name }}" {% if module.info.summary %}data-toggle="tooltip" data-placement="bottom" title="{{ module.info.summary }}"{% else %}title="{{ module.name }}"{% endif %}>{{ module.name }}</a></strong></p>{% endfor %}
</div>
</div>
</div>
<script type="text/javascript">
$('.tooltip-apps').tooltip({
selector: "a[data-toggle=tooltip]"
})
</script>
{% endblock %}

View File

@ -0,0 +1,28 @@
{% extends "default/layout.html" %}
{% block title %}{{ module.name }}{% endblock %}
{% block body %}
<div class="row">
<div class="span8">
<div class="sub-header"><h2>{{ module.name }}</h2></div>
{% if module.info %}<table class="table table-striped table-condensed">
<tr><th>{{ _("Summary") }}</th><td>{{ module.info.summary }}</td></tr>
<tr><th>{{ _("Version") }}</th><td>{{ module.info.version }}</td></tr>
<tr><th>{{ _("Author") }}</th><td>{{ module.info.author }}</td></tr>
<tr><th>{{ _("Licence") }}</th><td>{{ module.info.license }}</td></tr>
<tr><th>{{ _("Project") }}</th><td><a href="{{ module.info.home_page }}" title="Project {{ module.name }}" alt="Project {{ module.name }}">{{ module.info.home_page }}</a></td></tr>
<tr><th>{{ _("Download") }}</th><td><a href="{{ module.info.download_url }}" title="Download {{ module.name }}" alt="Download {{ module.name }}">{{ module.info.download_url }}</a></td></tr>
</table>{% endif %}
<div id="module_description" class="sub-header">
<h3>{{ _("Module Description") }}</h3>
</div>
<p>{{ module.description|safe}}</p>
</div>
<div class="span4">
<h4>{{ _("Other modules") }}</h4>
<ul class="simple">
{% for toc in tocs %}<li><a class="reference internal" href="/{{ toc.module_name }}/" id="id1">{{ toc.name }}</a></li>{% endfor %}
</ul>
<p><a class="btn" title="{{ _("All list modules") }}" href="/">{{ _("All list modules") }}</a></p>
</div>
</div>
{% endblock %}

View File

@ -0,0 +1,32 @@
<!DOCTYPE html>
<html lang="{{ config['LANGUAGE'] }}">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="title" content="Serveis de Tryton i OpenERP en el núvol">
<meta name="description" content="Serveis de Tryton i OpenERP per la PyME">
<meta name="author" content="{{ config['AUTHOR'] }}">
<title>{% block title %}{% endblock %} - {{ config['TITLE'] }}</title>
<link href="{{ url_for('static', filename='default/css/bootstrap.css') }}" rel="stylesheet" type="text/css">
<link href="{{ url_for('static', filename='default/css/bootstrap-responsive.css') }}" rel="stylesheet" type="text/css">
<link href="{{ url_for('static', filename='default/css/custom.css') }}" rel="stylesheet" type="text/css">
<script src="{{ url_for('static', filename='default/js/jquery-1.7.2.min.js') }}" type="text/javascript"></script>
<script src="{{ url_for('static', filename='default/js/bootstrap.min.js') }}" type="text/javascript"></script>
<script src="{{ url_for('static', filename='default/js/bootstrap-tooltip.js') }}" type="text/javascript"></script>
<link href="{{ url_for('modules_feed') }}" rel="alternate" title="Tryton Modules" type="application/atom+xml">
</head>
<body>
{% include 'default/nav.html' %}
<div class="container-fluid" id="container-fluid">
<div class="row-fluid">
<div class="span2"></div>
<div class="span8">
{% block body %}{% endblock %}
<hr>
{% include 'default/footer.html' %}
</div>
</div>
</div>
{{ config['ANALYTICS'] }}
</body>

View File

@ -0,0 +1,24 @@
<div class="navbar navbar-fixed-top">
<div class="navbar-inner">
<div class="container">
<a class="btn btn-navbar" data-toggle="collapse" data-target=".nav-collapse">
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</a>
<a class="brand" href="/" alt="{{ config['TITLE'] }}" title="{{ config['TITLE'] }}">{{ config['TITLE'] }}</a>
<div class="nav-collapse collapse">
<ul class="nav">
<li><a href="http://www.tryton-erp.es/tryton.html">Tryton</a></li>
<li><a href="http://doc.tryton-erp.es">Documentación</a></li>
<li><a href="http://apps.tryton-erp.es">Apps</a></li>
<li><a href="http://www.tryton-erp.es/demo.html">Demo</a></li>
<li><a href="http://www.tryton-erp.es/descarga.html">Descarga</a></li>
<li><a href="http://www.tryton-erp.es/traducciones.html">Traducciones</a></li>
<li><a href="http://www.tryton-erp.es/fundacion.html">Fundación</a></li>
<li><a href="http://www.tryton-erp.es/novedades/">Novedades</a></li>
</ul>
</div>
</div>
</div>
</div>

Binary file not shown.

View File

@ -0,0 +1,59 @@
# Spanish translations for PROJECT.
# Copyright (C) 2013 ORGANIZATION
# This file is distributed under the same license as the PROJECT project.
# FIRST AUTHOR <EMAIL@ADDRESS>, 2013.
#
msgid ""
msgstr ""
"Project-Id-Version: PROJECT VERSION\n"
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
"POT-Creation-Date: 2013-05-10 11:50+0200\n"
"PO-Revision-Date: 2013-05-10 11:50+0100\n"
"Last-Translator: Raimon Esteve <resteve@zikzakmedia.com>\n"
"Language-Team: es <LL@li.org>\n"
"Plural-Forms: nplurals=2; plural=(n != 1)\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Generated-By: Babel 0.9.6\n"
#: templates/default/index.html:7
msgid "Table of contents"
msgstr "Tabla de contenidos"
#: templates/default/info.html:8
msgid "Summary"
msgstr "Descripción"
#: templates/default/info.html:9
msgid "Version"
msgstr "Versión"
#: templates/default/info.html:10
msgid "Author"
msgstr "Autor"
#: templates/default/info.html:11
msgid "Licence"
msgstr "Licencia"
#: templates/default/info.html:12
msgid "Project"
msgstr "Proyecto"
#: templates/default/info.html:13
msgid "Download"
msgstr "Descarga"
#: templates/default/info.html:16
msgid "Module Description"
msgstr "Descripción del módulo"
#: templates/default/info.html:21
msgid "Other modules"
msgstr "Módulos similares"
#: templates/default/info.html:25
msgid "All list modules"
msgstr "Todos los módulos"