415 lines
12 KiB
Python
415 lines
12 KiB
Python
from flask import Blueprint, render_template, current_app, abort, g, \
|
|
request, url_for, session, flash, redirect
|
|
from galatea.tryton import tryton
|
|
from galatea.utils import get_tryton_language
|
|
from flask.ext.paginate import Pagination
|
|
from flask.ext.babel import gettext as _, lazy_gettext
|
|
from flask.ext.mail import Mail, Message
|
|
from trytond.config import config as tryton_config
|
|
from whoosh import index
|
|
from whoosh.qparser import MultifieldParser
|
|
import os
|
|
|
|
tutorial = Blueprint('tutorial', __name__, template_folder='templates')
|
|
|
|
DISPLAY_MSG = lazy_gettext('Displaying <b>{start} - {end}</b> of <b>{total}</b>')
|
|
|
|
Website = tryton.pool.get('galatea.website')
|
|
Tutorial = tryton.pool.get('galatea.tutorial')
|
|
Comment = tryton.pool.get('galatea.tutorial.comment')
|
|
User = tryton.pool.get('galatea.user')
|
|
|
|
GALATEA_WEBSITE = current_app.config.get('TRYTON_GALATEA_SITE')
|
|
LIMIT = current_app.config.get('TRYTON_PAGINATION_TUTORIAL_LIMIT', 20)
|
|
COMMENTS = current_app.config.get('TRYTON_TUTORIAL_COMMENTS', True)
|
|
WHOOSH_MAX_LIMIT = current_app.config.get('WHOOSH_MAX_LIMIT', 500)
|
|
TUTORIAL_SCHEMA_PARSE_FIELDS = ['title', 'content']
|
|
|
|
def _visibility():
|
|
visibility = ['public']
|
|
if session.get('logged_in'):
|
|
visibility.append('register')
|
|
if session.get('manager'):
|
|
visibility.append('manager')
|
|
return visibility
|
|
|
|
@tutorial.route("/search/", methods=["GET"], endpoint="search")
|
|
@tryton.transaction()
|
|
def search(lang):
|
|
'''Search'''
|
|
websites = Website.search([
|
|
('id', '=', GALATEA_WEBSITE),
|
|
], limit=1)
|
|
if not websites:
|
|
abort(404)
|
|
website, = websites
|
|
|
|
WHOOSH_TUTORIAL_DIR = current_app.config.get('WHOOSH_TUTORIAL_DIR')
|
|
if not WHOOSH_TUTORIAL_DIR:
|
|
abort(404)
|
|
|
|
db_name = current_app.config.get('TRYTON_DATABASE')
|
|
locale = get_tryton_language(lang)
|
|
|
|
schema_dir = os.path.join(tryton_config.get('database', 'path'),
|
|
db_name, 'whoosh', WHOOSH_TUTORIAL_DIR, locale.lower())
|
|
|
|
if not os.path.exists(schema_dir):
|
|
abort(404)
|
|
|
|
#breadcumbs
|
|
breadcrumbs = [{
|
|
'slug': url_for('.tutorials', lang=g.language),
|
|
'name': _('Tutorial'),
|
|
}, {
|
|
'slug': url_for('.search', lang=g.language),
|
|
'name': _('Search'),
|
|
}]
|
|
|
|
q = request.args.get('q')
|
|
if not q:
|
|
return render_template('tutorial-search.html',
|
|
tutorials=[],
|
|
breadcrumbs=breadcrumbs,
|
|
pagination=None,
|
|
q=None,
|
|
)
|
|
|
|
# Get tutorials from schema results
|
|
try:
|
|
page = int(request.args.get('page', 1))
|
|
except ValueError:
|
|
page = 1
|
|
|
|
# limit
|
|
if request.args.get('limit'):
|
|
try:
|
|
limit = int(request.args.get('limit'))
|
|
session['tutorial_limit'] = limit
|
|
except:
|
|
limit = LIMIT
|
|
else:
|
|
limit = session.get('tutorial_limit', LIMIT)
|
|
|
|
# Search
|
|
ix = index.open_dir(schema_dir)
|
|
query = q.replace('+', ' AND ').replace('-', ' NOT ')
|
|
query = MultifieldParser(TUTORIAL_SCHEMA_PARSE_FIELDS, ix.schema).parse(query)
|
|
|
|
with ix.searcher() as s:
|
|
all_results = s.search_page(query, 1, pagelen=WHOOSH_MAX_LIMIT)
|
|
total = all_results.scored_length()
|
|
results = s.search_page(query, page, pagelen=LIMIT) # by pagination
|
|
res = [result.get('id') for result in results]
|
|
|
|
domain = [
|
|
('id', 'in', res),
|
|
('active', '=', True),
|
|
('visibility', 'in', _visibility()),
|
|
]
|
|
order = [('tutorial_create_date', 'DESC'), ('id', 'DESC')]
|
|
|
|
tutorials = Tutorial.search(domain, order=order)
|
|
|
|
pagination = Pagination(page=page, total=total, per_page=limit, display_msg=DISPLAY_MSG, bs_version='3')
|
|
|
|
return render_template('tutorial-search.html',
|
|
website=website,
|
|
tutorials=tutorials,
|
|
pagination=pagination,
|
|
breadcrumbs=breadcrumbs,
|
|
q=q,
|
|
)
|
|
|
|
@tutorial.route("/comment", methods=['POST'], endpoint="comment")
|
|
@tryton.transaction()
|
|
def comment(lang):
|
|
'''Add Comment'''
|
|
websites = Website.search([
|
|
('id', '=', GALATEA_WEBSITE),
|
|
], limit=1)
|
|
if not websites:
|
|
abort(404)
|
|
website, = websites
|
|
|
|
tutorial = request.form.get('tutorial')
|
|
comment = request.form.get('comment')
|
|
|
|
domain = [
|
|
('id', '=', tutorial),
|
|
('active', '=', True),
|
|
('visibility', 'in', _visibility()),
|
|
('websites', 'in', [GALATEA_WEBSITE]),
|
|
]
|
|
tutorials = Tutorial.search(domain, limit=1)
|
|
if not tutorials:
|
|
abort(404)
|
|
tutorial, = tutorials
|
|
|
|
if not website.tutorial_comment:
|
|
flash(_('Not available to publish comments.'), 'danger')
|
|
elif not website.tutorial_anonymous and not session.get('user'):
|
|
flash(_('Not available to publish comments and anonymous users.' \
|
|
' Please, login in'), 'danger')
|
|
elif not comment or not tutorial:
|
|
flash(_('Add a comment to publish.'), 'danger')
|
|
else:
|
|
c = Comment()
|
|
c.tutorial = tutorial['id']
|
|
c.user = session['user'] if session.get('user') \
|
|
else website.tutorial_anonymous_user.id
|
|
c.description = comment
|
|
c.save()
|
|
flash(_('Comment published successfully.'), 'success')
|
|
|
|
mail = Mail(current_app)
|
|
|
|
mail_to = current_app.config.get('DEFAULT_MAIL_SENDER')
|
|
subject = '%s - %s' % (current_app.config.get('TITLE'), _('New comment published'))
|
|
msg = Message(subject,
|
|
body = render_template('emails/tutorial-comment-text.jinja', tutorial=tutorial, comment=comment),
|
|
html = render_template('emails/tutorial-comment-html.jinja', tutorial=tutorial, comment=comment),
|
|
sender = mail_to,
|
|
recipients = [mail_to])
|
|
mail.send(msg)
|
|
|
|
return redirect(url_for('.tutorial', lang=g.language, slug=tutorial['slug']))
|
|
|
|
@tutorial.route("/<slug>", endpoint="tutorial")
|
|
@tryton.transaction()
|
|
def tutorial_detail(lang, slug):
|
|
'''Tutorial detail'''
|
|
websites = Website.search([
|
|
('id', '=', GALATEA_WEBSITE),
|
|
], limit=1)
|
|
if not websites:
|
|
abort(404)
|
|
website, = websites
|
|
|
|
tutorials = Tutorial.search([
|
|
('slug', '=', slug),
|
|
('active', '=', True),
|
|
('visibility', 'in', _visibility()),
|
|
('websites', 'in', [GALATEA_WEBSITE]),
|
|
], limit=1)
|
|
|
|
if not tutorials:
|
|
abort(404)
|
|
tutorial, = tutorials
|
|
|
|
breadcrumbs = [{
|
|
'slug': url_for('.tutorials', lang=g.language),
|
|
'name': _('Tutorial'),
|
|
}, {
|
|
'slug': url_for('.tutorial', lang=g.language, slug=tutorial.slug),
|
|
'name': tutorial.name,
|
|
}]
|
|
|
|
return render_template('tutorial-tutorial.html',
|
|
website=website,
|
|
tutorial=tutorial,
|
|
breadcrumbs=breadcrumbs,
|
|
)
|
|
|
|
@tutorial.route("/key/<key>", endpoint="key")
|
|
@tryton.transaction()
|
|
def key(lang, key):
|
|
'''Tutorials by Key'''
|
|
websites = Website.search([
|
|
('id', '=', GALATEA_WEBSITE),
|
|
], limit=1)
|
|
if not websites:
|
|
abort(404)
|
|
website, = websites
|
|
|
|
# view
|
|
if request.args.get('view'):
|
|
view = 'list'
|
|
if request.args.get('view') == 'grid':
|
|
view = 'grid'
|
|
session['tutorial_view'] = view
|
|
|
|
try:
|
|
page = int(request.args.get('page', 1))
|
|
except ValueError:
|
|
page = 1
|
|
|
|
# limit
|
|
if request.args.get('limit'):
|
|
try:
|
|
limit = int(request.args.get('limit'))
|
|
session['tutorial_limit'] = limit
|
|
except:
|
|
limit = LIMIT
|
|
else:
|
|
limit = session.get('tutorial_limit', LIMIT)
|
|
|
|
domain = [
|
|
('metakeywords', 'ilike', '%'+key+'%'),
|
|
('active', '=', True),
|
|
('visibility', 'in', _visibility()),
|
|
('websites', 'in', [GALATEA_WEBSITE]),
|
|
]
|
|
total = Tutorial.search_count(domain)
|
|
offset = (page-1)*limit
|
|
|
|
order = [('tutorial_create_date', 'DESC'), ('id', 'DESC')]
|
|
tutorials = Tutorial.search(domain, offset, limit, order)
|
|
|
|
pagination = Pagination(page=page, total=total, per_page=limit, display_msg=DISPLAY_MSG, bs_version='3')
|
|
|
|
#breadcumbs
|
|
breadcrumbs = [{
|
|
'slug': url_for('.tutorials', lang=g.language),
|
|
'name': _('Tutorial'),
|
|
}, {
|
|
'slug': url_for('.key', lang=g.language, key=key),
|
|
'name': key,
|
|
}]
|
|
|
|
return render_template('tutorial-key.html',
|
|
website=website,
|
|
tutorials=tutorials,
|
|
pagination=pagination,
|
|
breadcrumbs=breadcrumbs,
|
|
key=key,
|
|
)
|
|
|
|
@tutorial.route("/user/<user>", endpoint="user")
|
|
@tryton.transaction()
|
|
def users(lang, user):
|
|
'''Tutorials by User'''
|
|
websites = Website.search([
|
|
('id', '=', GALATEA_WEBSITE),
|
|
], limit=1)
|
|
if not websites:
|
|
abort(404)
|
|
website, = websites
|
|
|
|
try:
|
|
user = int(user)
|
|
except:
|
|
abort(404)
|
|
|
|
users = User.search([
|
|
('id', '=', user)
|
|
], limit=1)
|
|
if not users:
|
|
abort(404)
|
|
user, = users
|
|
|
|
# view
|
|
if request.args.get('view'):
|
|
view = 'list'
|
|
if request.args.get('view') == 'grid':
|
|
view = 'grid'
|
|
session['tutorial_view'] = view
|
|
|
|
try:
|
|
page = int(request.args.get('page', 1))
|
|
except ValueError:
|
|
page = 1
|
|
|
|
# limit
|
|
if request.args.get('limit'):
|
|
try:
|
|
limit = int(request.args.get('limit'))
|
|
session['tutorial_limit'] = limit
|
|
except:
|
|
limit = LIMIT
|
|
else:
|
|
limit = session.get('tutorial_limit', LIMIT)
|
|
|
|
domain = [
|
|
('user', '=', user.id),
|
|
('active', '=', True),
|
|
('visibility', 'in', _visibility()),
|
|
('websites', 'in', [GALATEA_WEBSITE]),
|
|
]
|
|
total = Tutorial.search_count(domain)
|
|
offset = (page-1)*limit
|
|
|
|
if not total:
|
|
abort(404)
|
|
|
|
order = [('tutorial_create_date', 'DESC'), ('id', 'DESC')]
|
|
tutorials = Tutorial.search(domain, offset, limit, order)
|
|
|
|
pagination = Pagination(page=page, total=total, per_page=limit, display_msg=DISPLAY_MSG, bs_version='3')
|
|
|
|
#breadcumbs
|
|
breadcrumbs = [{
|
|
'slug': url_for('.tutorials', lang=g.language),
|
|
'name': _('Tutorial'),
|
|
}, {
|
|
'slug': url_for('.user', lang=g.language, user=user.id),
|
|
'name': user.rec_name,
|
|
}]
|
|
|
|
return render_template('tutorial-user.html',
|
|
website=website,
|
|
tutorials=tutorials,
|
|
user=user,
|
|
pagination=pagination,
|
|
breadcrumbs=breadcrumbs,
|
|
)
|
|
|
|
@tutorial.route("/", endpoint="tutorials")
|
|
@tryton.transaction()
|
|
def tutorials(lang):
|
|
'''Tutorials'''
|
|
websites = Website.search([
|
|
('id', '=', GALATEA_WEBSITE),
|
|
], limit=1)
|
|
if not websites:
|
|
abort(404)
|
|
website, = websites
|
|
|
|
# view
|
|
if request.args.get('view'):
|
|
view = 'list'
|
|
if request.args.get('view') == 'grid':
|
|
view = 'grid'
|
|
session['tutorial_view'] = view
|
|
|
|
try:
|
|
page = int(request.args.get('page', 1))
|
|
except ValueError:
|
|
page = 1
|
|
|
|
# limit
|
|
if request.args.get('limit'):
|
|
try:
|
|
limit = int(request.args.get('limit'))
|
|
session['tutorial_limit'] = limit
|
|
except:
|
|
limit = LIMIT
|
|
else:
|
|
limit = session.get('tutorial_limit', LIMIT)
|
|
|
|
domain = [
|
|
('active', '=', True),
|
|
('visibility', 'in', _visibility()),
|
|
('websites', 'in', [GALATEA_WEBSITE]),
|
|
]
|
|
total = Tutorial.search_count(domain)
|
|
offset = (page-1)*limit
|
|
|
|
order = [('tutorial_create_date', 'DESC'), ('id', 'DESC')]
|
|
tutorials = Tutorial.search(domain, offset, limit, order)
|
|
|
|
pagination = Pagination(page=page, total=total, per_page=limit, display_msg=DISPLAY_MSG, bs_version='3')
|
|
|
|
#breadcumbs
|
|
breadcrumbs = [{
|
|
'slug': url_for('.tutorials', lang=g.language),
|
|
'name': _('Tutorial'),
|
|
}]
|
|
|
|
return render_template('tutorials.html',
|
|
website=website,
|
|
tutorials=tutorials,
|
|
pagination=pagination,
|
|
breadcrumbs=breadcrumbs,
|
|
)
|