2014-11-07 14:24:08 +01:00
|
|
|
# This file is part galatea_cms module for Tryton.
|
|
|
|
# The COPYRIGHT file at the top level of this repository contains
|
|
|
|
# the full copyright notices and license terms.
|
2014-05-27 09:45:10 +02:00
|
|
|
from trytond.model import ModelSQL, ModelView, fields
|
2015-02-07 13:47:12 +01:00
|
|
|
from trytond.pool import Pool
|
|
|
|
from trytond.pyson import Bool, Equal, Eval, In, Not
|
2015-02-19 10:23:35 +01:00
|
|
|
from trytond.transaction import Transaction
|
2015-02-02 16:57:31 +01:00
|
|
|
|
2015-02-07 13:47:12 +01:00
|
|
|
from trytond.modules.galatea import GalateaVisiblePage
|
|
|
|
from trytond.modules.galatea.tools import slugify
|
2014-05-27 09:45:10 +02:00
|
|
|
|
2015-02-02 16:57:31 +01:00
|
|
|
__all__ = ['Menu', 'Article', 'ArticleWebsite', 'Block',
|
|
|
|
'Carousel', 'CarouselItem']
|
2014-05-27 09:45:10 +02:00
|
|
|
|
|
|
|
|
|
|
|
class Menu(ModelSQL, ModelView):
|
|
|
|
"Menu CMS"
|
|
|
|
__name__ = 'galatea.cms.menu'
|
2015-02-02 16:57:31 +01:00
|
|
|
_rec_name = 'name_used'
|
2015-02-22 15:30:30 +01:00
|
|
|
_order = [('parent', 'ASC'), ('sequence', 'ASC'), ('id', 'ASC')]
|
2015-02-02 16:57:31 +01:00
|
|
|
|
|
|
|
name = fields.Char('Name', translate=True, states={
|
|
|
|
'readonly': Eval('name_uri', False),
|
|
|
|
}, depends=['name_uri'])
|
2015-02-03 08:47:28 +01:00
|
|
|
name_uri = fields.Boolean('Use URI\'s name', states={
|
|
|
|
'invisible': ((Eval('target_type', '') != 'internal_uri')
|
|
|
|
| ~Bool(Eval('target_uri'))),
|
|
|
|
}, depends=['target_type', 'target_uri'])
|
2015-02-02 16:57:31 +01:00
|
|
|
name_used = fields.Function(fields.Char('Name', translate=True,
|
|
|
|
required=True),
|
2015-02-03 08:47:28 +01:00
|
|
|
'on_change_with_name', searcher='search_name_used')
|
2014-05-27 09:45:10 +02:00
|
|
|
code = fields.Char('Code', required=True,
|
|
|
|
help='Internal code.')
|
2015-02-02 16:57:31 +01:00
|
|
|
target_type = fields.Selection([
|
|
|
|
('internal_uri', 'Internal URI'),
|
|
|
|
('external_url', 'External URL'),
|
|
|
|
], 'Type', required=True)
|
|
|
|
target_uri = fields.Many2One('galatea.uri', 'Target URI', states={
|
|
|
|
'invisible': Eval('target_type', '') != 'internal_uri',
|
|
|
|
}, depends=['target_uri'])
|
|
|
|
target_url = fields.Char('Target URL', states={
|
2015-02-03 08:47:28 +01:00
|
|
|
'invisible': Eval('target_type', '') != 'external_url',
|
2015-02-02 16:57:31 +01:00
|
|
|
}, depends=['target_type'])
|
2015-02-23 20:25:30 +01:00
|
|
|
url = fields.Function(fields.Char('URL'),
|
|
|
|
'get_url')
|
2014-05-27 09:45:10 +02:00
|
|
|
parent = fields.Many2One("galatea.cms.menu", "Parent", select=True)
|
|
|
|
left = fields.Integer('Left', required=True, select=True)
|
|
|
|
right = fields.Integer('Right', required=True, select=True)
|
|
|
|
childs = fields.One2Many('galatea.cms.menu', 'parent', 'Children')
|
|
|
|
sequence = fields.Integer('Sequence')
|
2014-06-27 11:52:20 +02:00
|
|
|
nofollow = fields.Boolean('Nofollow',
|
|
|
|
help='Add attribute in links to not search engines continue')
|
2015-02-02 16:57:31 +01:00
|
|
|
active = fields.Boolean('Active', select=True)
|
|
|
|
# TODO: add website field? add domain in target_uri parent
|
|
|
|
# TODO: I think next fields should go to another module
|
|
|
|
css = fields.Char('CSS',
|
|
|
|
help='Class CSS in menu.')
|
|
|
|
icon = fields.Char('Icon',
|
|
|
|
help='Icon name show in menu.')
|
|
|
|
login = fields.Boolean('Login', help='Allow login users')
|
|
|
|
manager = fields.Boolean('Manager', help='Allow manager users')
|
2014-05-27 09:45:10 +02:00
|
|
|
|
2015-02-23 20:25:30 +01:00
|
|
|
@classmethod
|
|
|
|
def __setup__(cls):
|
|
|
|
super(Menu, cls).__setup__()
|
|
|
|
cls._order.insert(0, ('sequence', 'ASC'))
|
|
|
|
cls._order.insert(1, ('id', 'ASC'))
|
|
|
|
|
2015-02-02 16:57:31 +01:00
|
|
|
@fields.depends('name_uri', 'target_uri', 'name')
|
|
|
|
def on_change_with_name(self, name=None):
|
2015-02-03 08:47:28 +01:00
|
|
|
return (self.target_uri.name if self.name_uri and self.target_uri
|
2015-02-02 16:57:31 +01:00
|
|
|
else self.name)
|
2014-05-27 09:45:10 +02:00
|
|
|
|
2015-02-03 08:47:28 +01:00
|
|
|
@classmethod
|
|
|
|
def search_name_used(cls, name, clause):
|
|
|
|
return [
|
|
|
|
['OR', [
|
|
|
|
('name_uri', '=', True),
|
|
|
|
('target_uri.name',) + tuple(clause[1:]),
|
|
|
|
], [
|
|
|
|
('name_uri', '=', False),
|
|
|
|
('name',) + tuple(clause[1:]),
|
|
|
|
]],
|
|
|
|
]
|
|
|
|
|
2015-02-23 20:25:30 +01:00
|
|
|
def get_url(self, name):
|
|
|
|
return (self.target_url if self.target_type == 'external_url'
|
|
|
|
else (self.target_uri.uri if self.target_uri else '#'))
|
|
|
|
|
2014-05-27 09:45:10 +02:00
|
|
|
@staticmethod
|
|
|
|
def default_left():
|
|
|
|
return 0
|
|
|
|
|
|
|
|
@staticmethod
|
|
|
|
def default_right():
|
|
|
|
return 0
|
|
|
|
|
|
|
|
@staticmethod
|
|
|
|
def default_sequence():
|
|
|
|
return 1
|
|
|
|
|
2015-02-02 16:57:31 +01:00
|
|
|
@staticmethod
|
|
|
|
def default_active():
|
|
|
|
return True
|
|
|
|
|
2014-05-27 09:45:10 +02:00
|
|
|
@classmethod
|
|
|
|
def validate(cls, menus):
|
|
|
|
super(Menu, cls).validate(menus)
|
|
|
|
cls.check_recursion(menus)
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def copy(cls, menus, default=None):
|
|
|
|
if default is None:
|
|
|
|
default = {}
|
|
|
|
|
|
|
|
default['left'] = 0
|
|
|
|
default['right'] = 0
|
|
|
|
|
2015-02-02 16:57:31 +01:00
|
|
|
# new_menus = []
|
|
|
|
# for menu in menus:
|
|
|
|
# new_menu, = super(Menu, cls).copy([menu], default=default)
|
|
|
|
# new_menus.append(new_menu)
|
|
|
|
# return new_menus
|
|
|
|
return super(Menu, cls).copy(menus, default=default)
|
2014-05-27 09:45:10 +02:00
|
|
|
|
|
|
|
|
2015-02-07 13:47:12 +01:00
|
|
|
class Article(GalateaVisiblePage, ModelSQL, ModelView):
|
2014-05-27 09:45:10 +02:00
|
|
|
"Article CMS"
|
|
|
|
__name__ = 'galatea.cms.article'
|
2015-02-02 16:57:31 +01:00
|
|
|
websites = fields.Many2Many('galatea.cms.article-galatea.website',
|
2015-02-07 13:47:12 +01:00
|
|
|
'article', 'website', 'Websites', required=True)
|
2014-05-27 09:45:10 +02:00
|
|
|
description = fields.Text('Description', required=True, translate=True,
|
2015-02-02 16:57:31 +01:00
|
|
|
help='You could write wiki markup to create html content. Formats '
|
|
|
|
'text following the MediaWiki '
|
|
|
|
'(http://meta.wikimedia.org/wiki/Help:Editing) syntax.')
|
|
|
|
markup = fields.Selection([
|
|
|
|
(None, ''),
|
|
|
|
('wikimedia', 'WikiMedia'),
|
|
|
|
('rest', 'ReStructuredText'),
|
|
|
|
], 'Markup')
|
|
|
|
metadescription = fields.Char('Meta Description', translate=True,
|
|
|
|
help='Almost all search engines recommend it to be shorter '
|
2014-05-27 09:45:10 +02:00
|
|
|
'than 155 characters of plain text')
|
2015-02-02 16:57:31 +01:00
|
|
|
metakeywords = fields.Char('Meta Keywords', translate=True,
|
2014-05-27 09:45:10 +02:00
|
|
|
help='Separated by comma')
|
2015-02-02 16:57:31 +01:00
|
|
|
metatitle = fields.Char('Meta Title', translate=True)
|
2014-09-09 13:11:02 +02:00
|
|
|
attachments = fields.One2Many('ir.attachment', 'resource', 'Attachments')
|
2014-05-27 09:45:10 +02:00
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def __setup__(cls):
|
|
|
|
super(Article, cls).__setup__()
|
2015-02-18 10:47:15 +01:00
|
|
|
|
|
|
|
domain_clause = ('allowed_models.model', 'in', ['galatea.cms.article'])
|
|
|
|
if domain_clause not in cls.template.domain:
|
|
|
|
cls.template.domain.append(domain_clause)
|
|
|
|
|
2014-05-27 09:45:10 +02:00
|
|
|
cls._error_messages.update({
|
|
|
|
'delete_articles': ('You can not delete '
|
|
|
|
'articles because you will get error 404 NOT Found. '
|
|
|
|
'Dissable active field.'),
|
|
|
|
})
|
|
|
|
|
2015-02-02 16:57:31 +01:00
|
|
|
@classmethod
|
|
|
|
def default_websites(cls):
|
|
|
|
Website = Pool().get('galatea.website')
|
|
|
|
websites = Website.search([('active', '=', True)])
|
|
|
|
return [w.id for w in websites]
|
|
|
|
|
|
|
|
@classmethod
|
2015-02-07 13:47:12 +01:00
|
|
|
def calc_uri_vals(cls, record_vals):
|
|
|
|
# TODO: calc parent and template?
|
2015-02-18 10:47:15 +01:00
|
|
|
uri_vals = super(Article, cls).calc_uri_vals(record_vals)
|
|
|
|
if 'template' in record_vals:
|
|
|
|
uri_vals['template'] = record_vals['template']
|
|
|
|
return uri_vals
|
2015-02-02 16:57:31 +01:00
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def delete(cls, articles):
|
2015-02-19 10:23:35 +01:00
|
|
|
if Transaction().user != 1:
|
|
|
|
# TODO: change by a user warning
|
|
|
|
cls.raise_user_error('delete_articles')
|
|
|
|
super(Article, cls).delete(articles)
|
2015-02-02 16:57:31 +01:00
|
|
|
|
|
|
|
|
|
|
|
class ArticleWebsite(ModelSQL):
|
|
|
|
'Galatea CMS Article - Website'
|
|
|
|
__name__ = 'galatea.cms.article-galatea.website'
|
|
|
|
article = fields.Many2One('galatea.cms.article', 'Article',
|
|
|
|
ondelete='CASCADE', select=True, required=True)
|
|
|
|
website = fields.Many2One('galatea.website', 'Website',
|
|
|
|
ondelete='RESTRICT', select=True, required=True)
|
2014-07-16 11:54:17 +02:00
|
|
|
|
2014-05-27 09:45:10 +02:00
|
|
|
|
|
|
|
class Block(ModelSQL, ModelView):
|
|
|
|
"Block CMS"
|
|
|
|
__name__ = 'galatea.cms.block'
|
|
|
|
name = fields.Char('Name', required=True,
|
|
|
|
on_change=['name', 'code', 'slug'])
|
|
|
|
code = fields.Char('Code', required=True, help='Internal code.')
|
|
|
|
type = fields.Selection([
|
|
|
|
('image', 'Image'),
|
|
|
|
('remote_image', 'Remote Image'),
|
|
|
|
('custom_code', 'Custom Code'),
|
|
|
|
], 'Type', required=True)
|
2015-02-02 16:57:31 +01:00
|
|
|
file = fields.Many2One('galatea.static.file', 'File', states={
|
2014-05-27 09:45:10 +02:00
|
|
|
'required': Equal(Eval('type'), 'image'),
|
|
|
|
'invisible': Not(Equal(Eval('type'), 'image'))
|
|
|
|
})
|
2015-02-02 16:57:31 +01:00
|
|
|
remote_image_url = fields.Char('Remote Image URL', states={
|
2014-05-27 09:45:10 +02:00
|
|
|
'required': Equal(Eval('type'), 'remote_image'),
|
|
|
|
'invisible': Not(Equal(Eval('type'), 'remote_image'))
|
|
|
|
})
|
|
|
|
custom_code = fields.Text('Custom Code', translate=True,
|
|
|
|
states={
|
|
|
|
'required': Equal(Eval('type'), 'custom_code'),
|
|
|
|
'invisible': Not(Equal(Eval('type'), 'custom_code'))
|
|
|
|
},
|
|
|
|
help='You could write wiki markup to create html content. Formats text following '
|
|
|
|
'the MediaWiki (http://meta.wikimedia.org/wiki/Help:Editing) syntax.')
|
|
|
|
height = fields.Integer('Height',
|
|
|
|
states = {
|
|
|
|
'invisible': Not(In(Eval('type'), ['image', 'remote_image']))
|
|
|
|
})
|
|
|
|
width = fields.Integer('Width',
|
|
|
|
states = {
|
|
|
|
'invisible': Not(In(Eval('type'), ['image', 'remote_image']))
|
|
|
|
})
|
|
|
|
alternative_text = fields.Char('Alternative Text',
|
|
|
|
states = {
|
|
|
|
'invisible': Not(In(Eval('type'), ['image', 'remote_image']))
|
|
|
|
})
|
|
|
|
click_url = fields.Char('Click URL', translate=True,
|
|
|
|
states = {
|
|
|
|
'invisible': Not(In(Eval('type'), ['image', 'remote_image']))
|
|
|
|
})
|
|
|
|
active = fields.Boolean('Active', select=True)
|
2014-09-09 13:11:02 +02:00
|
|
|
attachments = fields.One2Many('ir.attachment', 'resource', 'Attachments')
|
2015-01-15 11:19:05 +01:00
|
|
|
visibility = fields.Selection([
|
|
|
|
('public','Public'),
|
|
|
|
('register','Register'),
|
|
|
|
('manager','Manager'),
|
|
|
|
], 'Visibility', required=True)
|
2014-05-27 09:45:10 +02:00
|
|
|
|
|
|
|
@staticmethod
|
|
|
|
def default_active():
|
|
|
|
'Return True'
|
|
|
|
return True
|
|
|
|
|
|
|
|
@staticmethod
|
|
|
|
def default_type():
|
|
|
|
'Return Image'
|
|
|
|
return 'image'
|
|
|
|
|
2015-01-15 11:19:05 +01:00
|
|
|
@staticmethod
|
|
|
|
def default_visibility():
|
|
|
|
return 'public'
|
|
|
|
|
2014-05-27 09:45:10 +02:00
|
|
|
def on_change_name(self):
|
|
|
|
res = {}
|
|
|
|
if self.name and not self.code:
|
|
|
|
res['code'] = slugify(self.name)
|
|
|
|
return res
|
2014-06-12 19:37:16 +02:00
|
|
|
|
|
|
|
|
|
|
|
class Carousel(ModelSQL, ModelView):
|
|
|
|
"Carousel CMS"
|
|
|
|
__name__ = 'galatea.cms.carousel'
|
|
|
|
name = fields.Char('Name', translate=True,
|
|
|
|
required=True, on_change=['name', 'code'])
|
|
|
|
code = fields.Char('Code', required=True,
|
|
|
|
help='Internal code. Use characters az09')
|
|
|
|
active = fields.Boolean('Active', select=True)
|
|
|
|
items = fields.One2Many('galatea.cms.carousel.item', 'carousel', 'Items')
|
|
|
|
|
|
|
|
@staticmethod
|
|
|
|
def default_active():
|
|
|
|
return True
|
|
|
|
|
|
|
|
def on_change_name(self):
|
|
|
|
res = {}
|
|
|
|
if self.name and not self.code:
|
|
|
|
res['code'] = slugify(self.name)
|
|
|
|
return res
|
|
|
|
|
|
|
|
|
|
|
|
class CarouselItem(ModelSQL, ModelView):
|
|
|
|
"Carousel Item CMS"
|
|
|
|
__name__ = 'galatea.cms.carousel.item'
|
|
|
|
carousel = fields.Many2One("galatea.cms.carousel", "Carousel", required=True)
|
|
|
|
name = fields.Char('Label', translate=True, required=True)
|
|
|
|
link = fields.Char('Link', translate=True,
|
|
|
|
help='URL absolute')
|
|
|
|
image = fields.Char('Image', translate=True,
|
|
|
|
help='Image with URL absolute')
|
|
|
|
sublabel = fields.Char('Sublabel', translate=True,
|
|
|
|
help='In case text carousel, second text')
|
|
|
|
description = fields.Char('Description', translate=True,
|
|
|
|
help='In cas text carousel, description text')
|
|
|
|
html = fields.Text('HTML', translate=True,
|
|
|
|
help='HTML formated item - Content carousel-inner')
|
|
|
|
active = fields.Boolean('Active', select=True)
|
|
|
|
sequence = fields.Integer('Sequence')
|
|
|
|
|
|
|
|
@staticmethod
|
|
|
|
def default_active():
|
|
|
|
return True
|
|
|
|
|
|
|
|
@staticmethod
|
|
|
|
def default_sequence():
|
|
|
|
return 1
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def __setup__(cls):
|
|
|
|
super(CarouselItem, cls).__setup__()
|
|
|
|
cls._order.insert(0, ('sequence', 'ASC'))
|
|
|
|
cls._order.insert(1, ('id', 'ASC'))
|