[MERGE] upstream
bzr revid: fme@openerp.com-20131014095642-qxl7ceqptfsj215l
|
@ -0,0 +1,23 @@
|
|||
# Spanish (Argentina) translation for openobject-addons
|
||||
# Copyright (c) 2013 Rosetta Contributors and Canonical Ltd 2013
|
||||
# This file is distributed under the same license as the openobject-addons package.
|
||||
# FIRST AUTHOR <EMAIL@ADDRESS>, 2013.
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: openobject-addons\n"
|
||||
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"POT-Creation-Date: 2012-12-21 17:04+0000\n"
|
||||
"PO-Revision-Date: 2013-10-07 21:16+0000\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: Spanish (Argentina) <es_AR@li.org>\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-Launchpad-Export-Date: 2013-10-08 05:42+0000\n"
|
||||
"X-Generator: Launchpad (build 16799)\n"
|
||||
|
||||
#. module: account_accountant
|
||||
#: model:ir.actions.client,name:account_accountant.action_client_account_menu
|
||||
msgid "Open Accounting Menu"
|
||||
msgstr ""
|
|
@ -0,0 +1,23 @@
|
|||
# Estonian translation for openobject-addons
|
||||
# Copyright (c) 2013 Rosetta Contributors and Canonical Ltd 2013
|
||||
# This file is distributed under the same license as the openobject-addons package.
|
||||
# FIRST AUTHOR <EMAIL@ADDRESS>, 2013.
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: openobject-addons\n"
|
||||
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"POT-Creation-Date: 2012-12-21 17:05+0000\n"
|
||||
"PO-Revision-Date: 2013-10-09 14:39+0000\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: Estonian <et@li.org>\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-Launchpad-Export-Date: 2013-10-10 04:41+0000\n"
|
||||
"X-Generator: Launchpad (build 16799)\n"
|
||||
|
||||
#. module: account_cancel
|
||||
#: view:account.invoice:0
|
||||
msgid "Cancel"
|
||||
msgstr ""
|
|
@ -1,30 +1,28 @@
|
|||
# Estonian translation for openobject-addons
|
||||
# Copyright (c) 2011 Rosetta Contributors and Canonical Ltd 2011
|
||||
# Copyright (c) 2013 Rosetta Contributors and Canonical Ltd 2013
|
||||
# This file is distributed under the same license as the openobject-addons package.
|
||||
# FIRST AUTHOR <EMAIL@ADDRESS>, 2011.
|
||||
# FIRST AUTHOR <EMAIL@ADDRESS>, 2013.
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: openobject-addons\n"
|
||||
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"POT-Creation-Date: 2012-12-03 16:03+0000\n"
|
||||
"PO-Revision-Date: 2011-10-10 19:33+0000\n"
|
||||
"Last-Translator: Aare Vesi <Unknown>\n"
|
||||
"POT-Creation-Date: 2012-12-21 17:05+0000\n"
|
||||
"PO-Revision-Date: 2013-10-09 14:40+0000\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: Estonian <et@li.org>\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-Launchpad-Export-Date: 2012-12-04 05:53+0000\n"
|
||||
"X-Generator: Launchpad (build 16335)\n"
|
||||
"X-Launchpad-Export-Date: 2013-10-10 04:41+0000\n"
|
||||
"X-Generator: Launchpad (build 16799)\n"
|
||||
|
||||
#. module: base_crypt
|
||||
#: model:ir.model,name:base_crypt.model_res_users
|
||||
#. module: auth_crypt
|
||||
#: field:res.users,password_crypt:0
|
||||
msgid "Encrypted Password"
|
||||
msgstr "Krüpteeritud Parool"
|
||||
|
||||
#. module: auth_crypt
|
||||
#: model:ir.model,name:auth_crypt.model_res_users
|
||||
msgid "Users"
|
||||
msgstr ""
|
||||
|
||||
#, python-format
|
||||
#~ msgid "Error"
|
||||
#~ msgstr "Viga"
|
||||
|
||||
#~ msgid "res.users"
|
||||
#~ msgstr "res.users"
|
||||
msgstr "Kasutajad"
|
||||
|
|
|
@ -0,0 +1,23 @@
|
|||
# Estonian translation for openobject-addons
|
||||
# Copyright (c) 2013 Rosetta Contributors and Canonical Ltd 2013
|
||||
# This file is distributed under the same license as the openobject-addons package.
|
||||
# FIRST AUTHOR <EMAIL@ADDRESS>, 2013.
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: openobject-addons\n"
|
||||
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"POT-Creation-Date: 2012-12-21 17:05+0000\n"
|
||||
"PO-Revision-Date: 2013-10-09 14:34+0000\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: Estonian <et@li.org>\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-Launchpad-Export-Date: 2013-10-10 04:41+0000\n"
|
||||
"X-Generator: Launchpad (build 16799)\n"
|
||||
|
||||
#. module: auth_oauth_signup
|
||||
#: model:ir.model,name:auth_oauth_signup.model_res_users
|
||||
msgid "Users"
|
||||
msgstr "Kasutajad"
|
|
@ -0,0 +1,185 @@
|
|||
# Hindi translation for openobject-addons
|
||||
# Copyright (c) 2013 Rosetta Contributors and Canonical Ltd 2013
|
||||
# This file is distributed under the same license as the openobject-addons package.
|
||||
# FIRST AUTHOR <EMAIL@ADDRESS>, 2013.
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: openobject-addons\n"
|
||||
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"POT-Creation-Date: 2012-12-21 17:05+0000\n"
|
||||
"PO-Revision-Date: 2013-10-09 05:55+0000\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: Hindi <hi@li.org>\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-Launchpad-Export-Date: 2013-10-10 04:41+0000\n"
|
||||
"X-Generator: Launchpad (build 16799)\n"
|
||||
|
||||
#. module: base_report_designer
|
||||
#: model:ir.model,name:base_report_designer.model_base_report_sxw
|
||||
msgid "base.report.sxw"
|
||||
msgstr "base.report.sxw"
|
||||
|
||||
#. module: base_report_designer
|
||||
#: view:base_report_designer.installer:0
|
||||
msgid "OpenERP Report Designer Configuration"
|
||||
msgstr ""
|
||||
|
||||
#. module: base_report_designer
|
||||
#: view:base_report_designer.installer:0
|
||||
msgid ""
|
||||
"This plug-in allows you to create/modify OpenERP Reports into OpenOffice "
|
||||
"Writer."
|
||||
msgstr ""
|
||||
|
||||
#. module: base_report_designer
|
||||
#: view:base.report.sxw:0
|
||||
msgid "Upload the modified report"
|
||||
msgstr ""
|
||||
|
||||
#. module: base_report_designer
|
||||
#: view:base.report.file.sxw:0
|
||||
msgid "The .SXW report"
|
||||
msgstr ""
|
||||
|
||||
#. module: base_report_designer
|
||||
#: model:ir.model,name:base_report_designer.model_base_report_designer_installer
|
||||
msgid "base_report_designer.installer"
|
||||
msgstr ""
|
||||
|
||||
#. module: base_report_designer
|
||||
#: model:ir.model,name:base_report_designer.model_base_report_rml_save
|
||||
msgid "base.report.rml.save"
|
||||
msgstr ""
|
||||
|
||||
#. module: base_report_designer
|
||||
#: view:base_report_designer.installer:0
|
||||
msgid "Configure"
|
||||
msgstr ""
|
||||
|
||||
#. module: base_report_designer
|
||||
#: view:base_report_designer.installer:0
|
||||
msgid "title"
|
||||
msgstr ""
|
||||
|
||||
#. module: base_report_designer
|
||||
#: field:base.report.file.sxw,report_id:0
|
||||
#: field:base.report.sxw,report_id:0
|
||||
msgid "Report"
|
||||
msgstr ""
|
||||
|
||||
#. module: base_report_designer
|
||||
#: view:base.report.rml.save:0
|
||||
msgid "The RML Report"
|
||||
msgstr ""
|
||||
|
||||
#. module: base_report_designer
|
||||
#: model:ir.ui.menu,name:base_report_designer.menu_action_report_designer_wizard
|
||||
msgid "Report Designer"
|
||||
msgstr ""
|
||||
|
||||
#. module: base_report_designer
|
||||
#: field:base_report_designer.installer,name:0
|
||||
msgid "File name"
|
||||
msgstr ""
|
||||
|
||||
#. module: base_report_designer
|
||||
#: view:base.report.file.sxw:0
|
||||
#: view:base.report.sxw:0
|
||||
msgid "Get a report"
|
||||
msgstr ""
|
||||
|
||||
#. module: base_report_designer
|
||||
#: view:base_report_designer.installer:0
|
||||
#: model:ir.actions.act_window,name:base_report_designer.action_report_designer_wizard
|
||||
msgid "OpenERP Report Designer"
|
||||
msgstr ""
|
||||
|
||||
#. module: base_report_designer
|
||||
#: view:base.report.sxw:0
|
||||
msgid "Continue"
|
||||
msgstr ""
|
||||
|
||||
#. module: base_report_designer
|
||||
#: field:base.report.rml.save,file_rml:0
|
||||
msgid "Save As"
|
||||
msgstr ""
|
||||
|
||||
#. module: base_report_designer
|
||||
#: help:base_report_designer.installer,plugin_file:0
|
||||
msgid ""
|
||||
"OpenObject Report Designer plug-in file. Save as this file and install this "
|
||||
"plug-in in OpenOffice."
|
||||
msgstr ""
|
||||
|
||||
#. module: base_report_designer
|
||||
#: view:base.report.rml.save:0
|
||||
msgid "Save RML FIle"
|
||||
msgstr ""
|
||||
|
||||
#. module: base_report_designer
|
||||
#: field:base.report.file.sxw,file_sxw:0
|
||||
#: field:base.report.file.sxw,file_sxw_upload:0
|
||||
msgid "Your .SXW file"
|
||||
msgstr ""
|
||||
|
||||
#. module: base_report_designer
|
||||
#: view:base_report_designer.installer:0
|
||||
msgid "Installation and Configuration Steps"
|
||||
msgstr ""
|
||||
|
||||
#. module: base_report_designer
|
||||
#: field:base_report_designer.installer,description:0
|
||||
msgid "Description"
|
||||
msgstr ""
|
||||
|
||||
#. module: base_report_designer
|
||||
#: view:base.report.file.sxw:0
|
||||
msgid ""
|
||||
"This is the template of your requested report.\n"
|
||||
"Save it as a .SXW file and open it with OpenOffice.\n"
|
||||
"Don't forget to install the OpenERP SA OpenOffice package to modify it.\n"
|
||||
"Once it is modified, re-upload it in OpenERP using this wizard."
|
||||
msgstr ""
|
||||
|
||||
#. module: base_report_designer
|
||||
#: model:ir.actions.act_window,name:base_report_designer.action_view_base_report_sxw
|
||||
msgid "Base Report sxw"
|
||||
msgstr ""
|
||||
|
||||
#. module: base_report_designer
|
||||
#: model:ir.model,name:base_report_designer.model_base_report_file_sxw
|
||||
msgid "base.report.file.sxw"
|
||||
msgstr ""
|
||||
|
||||
#. module: base_report_designer
|
||||
#: field:base_report_designer.installer,plugin_file:0
|
||||
msgid "OpenObject Report Designer Plug-in"
|
||||
msgstr ""
|
||||
|
||||
#. module: base_report_designer
|
||||
#: model:ir.actions.act_window,name:base_report_designer.action_report_designer_installer
|
||||
msgid "OpenERP Report Designer Installation"
|
||||
msgstr ""
|
||||
|
||||
#. module: base_report_designer
|
||||
#: view:base.report.sxw:0
|
||||
msgid "Cancel"
|
||||
msgstr ""
|
||||
|
||||
#. module: base_report_designer
|
||||
#: view:base.report.sxw:0
|
||||
msgid "or"
|
||||
msgstr ""
|
||||
|
||||
#. module: base_report_designer
|
||||
#: model:ir.model,name:base_report_designer.model_ir_actions_report_xml
|
||||
msgid "ir.actions.report.xml"
|
||||
msgstr ""
|
||||
|
||||
#. module: base_report_designer
|
||||
#: view:base.report.sxw:0
|
||||
msgid "Select your report"
|
||||
msgstr ""
|
|
@ -0,0 +1,33 @@
|
|||
# Estonian translation for openobject-addons
|
||||
# Copyright (c) 2013 Rosetta Contributors and Canonical Ltd 2013
|
||||
# This file is distributed under the same license as the openobject-addons package.
|
||||
# FIRST AUTHOR <EMAIL@ADDRESS>, 2013.
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: openobject-addons\n"
|
||||
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"POT-Creation-Date: 2012-12-21 17:05+0000\n"
|
||||
"PO-Revision-Date: 2013-10-09 14:42+0000\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: Estonian <et@li.org>\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-Launchpad-Export-Date: 2013-10-10 04:41+0000\n"
|
||||
"X-Generator: Launchpad (build 16799)\n"
|
||||
|
||||
#. module: claim_from_delivery
|
||||
#: view:stock.picking.out:0
|
||||
msgid "Claims"
|
||||
msgstr "Nõuded"
|
||||
|
||||
#. module: claim_from_delivery
|
||||
#: model:res.request.link,name:claim_from_delivery.request_link_claim_from_delivery
|
||||
msgid "Delivery Order"
|
||||
msgstr "Tarnetellimus"
|
||||
|
||||
#. module: claim_from_delivery
|
||||
#: model:ir.actions.act_window,name:claim_from_delivery.action_claim_from_delivery
|
||||
msgid "Claim From Delivery"
|
||||
msgstr ""
|
|
@ -0,0 +1,85 @@
|
|||
# Estonian translation for openobject-addons
|
||||
# Copyright (c) 2013 Rosetta Contributors and Canonical Ltd 2013
|
||||
# This file is distributed under the same license as the openobject-addons package.
|
||||
# FIRST AUTHOR <EMAIL@ADDRESS>, 2013.
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: openobject-addons\n"
|
||||
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"POT-Creation-Date: 2012-12-21 17:05+0000\n"
|
||||
"PO-Revision-Date: 2013-10-09 15:39+0000\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: Estonian <et@li.org>\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-Launchpad-Export-Date: 2013-10-10 04:41+0000\n"
|
||||
"X-Generator: Launchpad (build 16799)\n"
|
||||
|
||||
#. module: crm_todo
|
||||
#: model:ir.model,name:crm_todo.model_project_task
|
||||
msgid "Task"
|
||||
msgstr "Ülesanne"
|
||||
|
||||
#. module: crm_todo
|
||||
#: view:crm.lead:0
|
||||
msgid "Timebox"
|
||||
msgstr "Ajalahter"
|
||||
|
||||
#. module: crm_todo
|
||||
#: view:crm.lead:0
|
||||
msgid "Lead"
|
||||
msgstr ""
|
||||
|
||||
#. module: crm_todo
|
||||
#: view:crm.lead:0
|
||||
msgid "For cancelling the task"
|
||||
msgstr "Ülesande katkestamiseks"
|
||||
|
||||
#. module: crm_todo
|
||||
#: view:crm.lead:0
|
||||
msgid "Next"
|
||||
msgstr "Järgmine"
|
||||
|
||||
#. module: crm_todo
|
||||
#: model:ir.actions.act_window,name:crm_todo.crm_todo_action
|
||||
#: model:ir.ui.menu,name:crm_todo.menu_crm_todo
|
||||
msgid "My Tasks"
|
||||
msgstr "Minu ülesanded"
|
||||
|
||||
#. module: crm_todo
|
||||
#: view:crm.lead:0
|
||||
#: field:crm.lead,task_ids:0
|
||||
msgid "Tasks"
|
||||
msgstr "Ülesanded"
|
||||
|
||||
#. module: crm_todo
|
||||
#: view:crm.lead:0
|
||||
msgid "Done"
|
||||
msgstr "Valmis"
|
||||
|
||||
#. module: crm_todo
|
||||
#: view:crm.lead:0
|
||||
msgid "Cancel"
|
||||
msgstr "Katkesta"
|
||||
|
||||
#. module: crm_todo
|
||||
#: model:ir.model,name:crm_todo.model_crm_lead
|
||||
msgid "Lead/Opportunity"
|
||||
msgstr ""
|
||||
|
||||
#. module: crm_todo
|
||||
#: field:project.task,lead_id:0
|
||||
msgid "Lead / Opportunity"
|
||||
msgstr ""
|
||||
|
||||
#. module: crm_todo
|
||||
#: view:crm.lead:0
|
||||
msgid "For changing to done state"
|
||||
msgstr ""
|
||||
|
||||
#. module: crm_todo
|
||||
#: view:crm.lead:0
|
||||
msgid "Previous"
|
||||
msgstr "Eelmine"
|
|
@ -133,7 +133,7 @@ class hr_si_project(osv.osv_memory):
|
|||
|
||||
def check_state(self, cr, uid, ids, context=None):
|
||||
obj_model = self.pool.get('ir.model.data')
|
||||
emp_id = self.default_get(cr, uid, context)['emp_id']
|
||||
emp_id = self.default_get(cr, uid, ['emp_id'], context)['emp_id']
|
||||
# get the latest action (sign_in or out) for this employee
|
||||
cr.execute('select action from hr_attendance where employee_id=%s and action in (\'sign_in\',\'sign_out\') order by name desc limit 1', (emp_id,))
|
||||
res = (cr.fetchone() or ('sign_out',))[0]
|
||||
|
|
|
@ -143,7 +143,7 @@ function openerp_pos_widgets(instance, module){ //module is instance.point_of_sa
|
|||
var self = this;
|
||||
this._super();
|
||||
this.$el.click(function(){
|
||||
self.order.selectLine(this.model);
|
||||
self.order.selectLine(self.model);
|
||||
self.trigger('order_line_selected');
|
||||
});
|
||||
if(this.model.is_selected()){
|
||||
|
|
|
@ -93,8 +93,7 @@
|
|||
</div>
|
||||
</div>
|
||||
<div class="oe_right oe_button_box" name="buttons" groups="base.group_user">
|
||||
<button name="%(act_project_project_2_project_task_all)d" string="Tasks"
|
||||
type="action" attrs="{'invisible':[('use_tasks','=', 0)]}"/>
|
||||
<field name="tasks" widget="x2many_counter" string="Tasks" attrs="{'invisible':[('use_tasks','=', False)]}" options='{"views": [[false, "kanban"], [false, "tree"], [false, "form"], [false, "calendar"], [false, "gantt"], [false, "graph"]]}'/>
|
||||
<button name="attachment_tree_view" string="Documents" type="object"/>
|
||||
</div>
|
||||
<group>
|
||||
|
|
|
@ -12,14 +12,14 @@ OpenERP Website CMS
|
|||
'depends': ['web', 'share'],
|
||||
'installable': True,
|
||||
'data': [
|
||||
'views/views.xml',
|
||||
'data/website_data.xml',
|
||||
'security/ir.model.access.csv',
|
||||
'views/website_templates.xml',
|
||||
'views/website_views.xml',
|
||||
'views/snippets.xml',
|
||||
'views/themes.xml',
|
||||
'website_data.xml',
|
||||
'website_view.xml',
|
||||
'security/ir.model.access.csv',
|
||||
],
|
||||
'demo': [
|
||||
'website_demo.xml',
|
||||
'data/website_demo.xml',
|
||||
]
|
||||
}
|
||||
|
|
|
@ -7,18 +7,27 @@ import json
|
|||
import logging
|
||||
import os
|
||||
import datetime
|
||||
import re
|
||||
|
||||
from sys import maxint
|
||||
|
||||
import psycopg2
|
||||
import slugify
|
||||
import werkzeug
|
||||
import werkzeug.exceptions
|
||||
import werkzeug.utils
|
||||
import werkzeug.wrappers
|
||||
from PIL import Image
|
||||
|
||||
try:
|
||||
from slugify import slugify
|
||||
except ImportError:
|
||||
def slugify(s, max_length=None):
|
||||
spaceless = re.sub(r'\s+', '-', s)
|
||||
specialless = re.sub(r'[^-_a-z0-9]', '', spaceless)
|
||||
return specialless[:max_length]
|
||||
|
||||
import openerp
|
||||
from openerp.osv import fields
|
||||
from openerp.addons.website.models import website
|
||||
from openerp.addons.web import http
|
||||
from openerp.addons.web.http import request
|
||||
|
@ -53,7 +62,7 @@ class Website(openerp.addons.web.controllers.main.Home):
|
|||
def pagenew(self, path, noredirect=NOPE):
|
||||
module = 'website'
|
||||
# completely arbitrary max_length
|
||||
idname = slugify.slugify(path, max_length=50)
|
||||
idname = slugify(path, max_length=50)
|
||||
|
||||
request.cr.execute('SAVEPOINT pagenew')
|
||||
imd = request.registry['ir.model.data']
|
||||
|
@ -251,11 +260,16 @@ class Website(openerp.addons.web.controllers.main.Home):
|
|||
def publish(self, id, object):
|
||||
_id = int(id)
|
||||
_object = request.registry[object]
|
||||
|
||||
obj = _object.browse(request.cr, request.uid, _id)
|
||||
|
||||
values = {}
|
||||
if 'website_published' in _object._all_columns:
|
||||
values['website_published'] = not obj.website_published
|
||||
if 'website_published_datetime' in _object._all_columns and values.get('website_published'):
|
||||
values['website_published_datetime'] = fields.datetime.now()
|
||||
_object.write(request.cr, request.uid, [_id],
|
||||
{'website_published': not obj.website_published},
|
||||
context=request.context)
|
||||
values, context=request.context)
|
||||
|
||||
obj = _object.browse(request.cr, request.uid, _id)
|
||||
return obj.website_published and True or False
|
||||
|
||||
|
|
|
@ -36,17 +36,22 @@
|
|||
|
||||
<record id="action_website" model="ir.actions.act_url">
|
||||
<field name="name">Website</field>
|
||||
<field name="url">/</field>
|
||||
<field name="target">self</field>
|
||||
</record>
|
||||
<record id="action_website_tutorial" model="ir.actions.act_url">
|
||||
<field name="name">Website With Tutorial</field>
|
||||
<field name="url">/?tutorial=true</field>
|
||||
<field name="target">self</field>
|
||||
</record>
|
||||
|
||||
<record id="menu_website" model="ir.ui.menu">
|
||||
<field name="name">Website</field>
|
||||
<field name="sequence" eval="510"/>
|
||||
<field name="action" ref="action_website"/>
|
||||
</record>
|
||||
|
||||
<record id="base.open_menu" model="ir.actions.todo">
|
||||
<field name="action_id" ref="action_website"/>
|
||||
<field name="action_id" ref="action_website_tutorial"/>
|
||||
<field name="state">open</field>
|
||||
</record>
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
import ir_fields
|
||||
import view
|
||||
import ir_ui_view
|
||||
import website
|
||||
import ir_rule
|
||||
|
|
|
@ -144,7 +144,7 @@ class website(osv.osv):
|
|||
qweb_context.update(values)
|
||||
|
||||
qweb_context.update(
|
||||
_request=request, # begin with underscore to mark this attribute as unsafe
|
||||
request=request, # TODO maybe rename to _request to mark this attribute as unsafe
|
||||
json=simplejson,
|
||||
website=request.website,
|
||||
url_for=url_for,
|
||||
|
|
|
@ -0,0 +1,22 @@
|
|||
jQuery Nearest Element plugin
|
||||
======
|
||||
|
||||
**Full documentation is at <http://gilmoreorless.github.io/jquery-nearest/>**
|
||||
|
||||
**Demo:** <http://gilmoreorless.github.io/jquery-nearest/demo.html>
|
||||
|
||||
Method signatures:
|
||||
|
||||
* `$.nearest({x, y}, selector)` - find `$(selector)` closest to x/y point on screen
|
||||
* `$(elem).nearest(selector)` - find `$(selector)` closest to elem
|
||||
* `$(elemSet).nearest({x, y})` - filter `$(elemSet)` and return closest to x/y point on screen
|
||||
|
||||
Reverse logic:
|
||||
|
||||
* `$.furthest()`
|
||||
* `$(elem).furthest()`
|
||||
|
||||
Intersecting/touching:
|
||||
|
||||
* `$.touching()`
|
||||
* `$(elem).touching()`
|
|
@ -0,0 +1,12 @@
|
|||
{
|
||||
"name": "jquery-nearest",
|
||||
"version": "1.2.1",
|
||||
"main": "jquery.nearest.js",
|
||||
"ignore": [
|
||||
"**/.*",
|
||||
"test"
|
||||
],
|
||||
"dependencies": {
|
||||
"jquery": ">=1.4"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,223 @@
|
|||
/*!
|
||||
* jQuery Nearest plugin v1.2.1
|
||||
*
|
||||
* Finds elements closest to a single point based on screen location and pixel dimensions
|
||||
* http://gilmoreorless.github.com/jquery-nearest/
|
||||
* Open source under the MIT licence: http://gilmoreorless.mit-license.org/2011/
|
||||
*
|
||||
* Requires jQuery 1.4 or above
|
||||
* Also supports Ben Alman's "each2" plugin for faster looping (if available)
|
||||
*/
|
||||
|
||||
/**
|
||||
* Method signatures:
|
||||
*
|
||||
* $.nearest({x, y}, selector) - find $(selector) closest to point
|
||||
* $(elem).nearest(selector) - find $(selector) closest to elem
|
||||
* $(elemSet).nearest({x, y}) - filter $(elemSet) and return closest to point
|
||||
*
|
||||
* Also:
|
||||
* $.furthest()
|
||||
* $(elem).furthest()
|
||||
*
|
||||
* $.touching()
|
||||
* $(elem).touching()
|
||||
*/
|
||||
;(function ($, undefined) {
|
||||
|
||||
/**
|
||||
* Internal method that does the grunt work
|
||||
*
|
||||
* @param mixed selector Any valid jQuery selector providing elements to filter
|
||||
* @param hash options Key/value list of options for matching elements
|
||||
* @param mixed thisObj (optional) Any valid jQuery selector that represents self
|
||||
* for the "includeSelf" option
|
||||
* @return array List of matching elements, can be zero length
|
||||
*/
|
||||
var rPerc = /^([\d.]+)%$/;
|
||||
function nearest(selector, options, thisObj) {
|
||||
// Normalise selector and dimensions
|
||||
selector || (selector = 'div'); // I STRONGLY recommend passing in a selector
|
||||
var $container = $(options.container),
|
||||
containerOffset = $container.offset() || {left: 0, top: 0},
|
||||
containerDims = [
|
||||
containerOffset.left + $container.width(),
|
||||
containerOffset.top + $container.height()
|
||||
],
|
||||
percProps = {x: 0, y: 1, w: 0, h: 1},
|
||||
prop, match;
|
||||
for (prop in percProps) if (percProps.hasOwnProperty(prop)) {
|
||||
match = rPerc.exec(options[prop]);
|
||||
if (match) {
|
||||
options[prop] = containerDims[percProps[prop]] * match[1] / 100;
|
||||
}
|
||||
}
|
||||
|
||||
// Get elements and work out x/y points
|
||||
var $all = $(selector),
|
||||
cache = [],
|
||||
furthest = !!options.furthest,
|
||||
checkX = !!options.checkHoriz,
|
||||
checkY = !!options.checkVert,
|
||||
compDist = furthest ? 0 : Infinity,
|
||||
point1x = parseFloat(options.x) || 0,
|
||||
point1y = parseFloat(options.y) || 0,
|
||||
point2x = parseFloat(point1x + options.w) || point1x,
|
||||
point2y = parseFloat(point1y + options.h) || point1y,
|
||||
tolerance = options.tolerance || 0,
|
||||
hasEach2 = !!$.fn.each2,
|
||||
// Shortcuts to help with compression
|
||||
min = Math.min,
|
||||
max = Math.max;
|
||||
|
||||
// Normalise the remaining options
|
||||
if (!options.includeSelf && thisObj) {
|
||||
$all = $all.not(thisObj);
|
||||
}
|
||||
if (tolerance < 0) {
|
||||
tolerance = 0;
|
||||
}
|
||||
// Loop through all elements and check their positions
|
||||
$all[hasEach2 ? 'each2' : 'each'](function (i, elem) {
|
||||
var $this = hasEach2 ? elem : $(this),
|
||||
off = $this.offset(),
|
||||
x = off.left,
|
||||
y = off.top,
|
||||
w = $this.outerWidth(),
|
||||
h = $this.outerHeight(),
|
||||
x2 = x + w,
|
||||
y2 = y + h,
|
||||
maxX1 = max(x, point1x),
|
||||
minX2 = min(x2, point2x),
|
||||
maxY1 = max(y, point1y),
|
||||
minY2 = min(y2, point2y),
|
||||
intersectX = minX2 >= maxX1,
|
||||
intersectY = minY2 >= maxY1,
|
||||
distX, distY, distT, isValid;
|
||||
if (
|
||||
// .nearest() / .furthest()
|
||||
(checkX && checkY) ||
|
||||
// .touching()
|
||||
(!checkX && !checkY && intersectX && intersectY) ||
|
||||
// .nearest({checkVert: false})
|
||||
(checkX && intersectY) ||
|
||||
// .nearest({checkHoriz: false})
|
||||
(checkY && intersectX)
|
||||
) {
|
||||
distX = intersectX ? 0 : maxX1 - minX2;
|
||||
distY = intersectY ? 0 : maxY1 - minY2;
|
||||
distT = intersectX || intersectY ?
|
||||
max(distX, distY) :
|
||||
Math.sqrt(distX * distX + distY * distY);
|
||||
isValid = furthest ?
|
||||
distT >= compDist - tolerance :
|
||||
distT <= compDist + tolerance;
|
||||
if (isValid) {
|
||||
compDist = furthest ?
|
||||
max(compDist, distT) :
|
||||
min(compDist, distT);
|
||||
cache.push({
|
||||
node: this,
|
||||
dist: distT
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
// Make sure all cached items are within tolerance range
|
||||
var len = cache.length,
|
||||
filtered = [],
|
||||
compMin, compMax,
|
||||
i, item;
|
||||
if (len) {
|
||||
if (furthest) {
|
||||
compMin = compDist - tolerance;
|
||||
compMax = compDist;
|
||||
} else {
|
||||
compMin = compDist;
|
||||
compMax = compDist + tolerance;
|
||||
}
|
||||
for (i = 0; i < len; i++) {
|
||||
item = cache[i];
|
||||
if (item.dist >= compMin && item.dist <= compMax) {
|
||||
filtered.push(item.node);
|
||||
}
|
||||
}
|
||||
}
|
||||
return filtered;
|
||||
}
|
||||
|
||||
$.each(['nearest', 'furthest', 'touching'], function (i, name) {
|
||||
|
||||
// Internal default options
|
||||
// Not exposed publicly because they're method-dependent and easily overwritten anyway
|
||||
var defaults = {
|
||||
x: 0, // X position of top left corner of point/region
|
||||
y: 0, // Y position of top left corner of point/region
|
||||
w: 0, // Width of region
|
||||
h: 0, // Height of region
|
||||
tolerance: 1, // Distance tolerance in pixels, mainly to handle fractional pixel rounding bugs
|
||||
container: document, // Container of objects for calculating %-based dimensions
|
||||
furthest: name == 'furthest', // Find max distance (true) or min distance (false)
|
||||
includeSelf: false, // Include 'this' in search results (t/f) - only applies to $(elem).func(selector) syntax
|
||||
checkHoriz: name != 'touching', // Check variations in X axis (t/f)
|
||||
checkVert: name != 'touching' // Check variations in Y axis (t/f)
|
||||
};
|
||||
|
||||
/**
|
||||
* $.nearest() / $.furthest() / $.touching()
|
||||
*
|
||||
* Utility functions for finding elements near a specific point or region on screen
|
||||
*
|
||||
* @param hash point Co-ordinates for the point or region to measure from
|
||||
* "x" and "y" keys are required, "w" and "h" keys are optional
|
||||
* @param mixed selector Any valid jQuery selector that provides elements to filter
|
||||
* @param hash options (optional) Extra filtering options
|
||||
* Not technically needed as the options could go on the point object,
|
||||
* but it's good to have a consistent API
|
||||
* @return jQuery object containing matching elements in selector
|
||||
*/
|
||||
$[name] = function (point, selector, options) {
|
||||
if (!point || point.x === undefined || point.y === undefined) {
|
||||
return $([]);
|
||||
}
|
||||
var opts = $.extend({}, defaults, point, options || {});
|
||||
return $(nearest(selector, opts));
|
||||
};
|
||||
|
||||
/**
|
||||
* SIGNATURE 1:
|
||||
* $(elem).nearest(selector) / $(elem).furthest(selector) / $(elem).touching(selector)
|
||||
*
|
||||
* Finds all elements in selector that are nearest to/furthest from elem
|
||||
*
|
||||
* @param mixed selector Any valid jQuery selector that provides elements to filter
|
||||
* @param hash options (optional) Extra filtering options
|
||||
* @return jQuery object containing matching elements in selector
|
||||
*
|
||||
* SIGNATURE 2:
|
||||
* $(elemSet).nearest(point) / $(elemSet).furthest(point) / $(elemSet).touching(point)
|
||||
*
|
||||
* Filters elemSet to return only the elements nearest to/furthest from point
|
||||
* Effectively a wrapper for $.nearest(point, elemSet) but with the benefits of method chaining
|
||||
*
|
||||
* @param hash point Co-ordinates for the point or region to measure from
|
||||
* @return jQuery object containing matching elements in elemSet
|
||||
*/
|
||||
$.fn[name] = function (selector, options) {
|
||||
var opts;
|
||||
if (selector && $.isPlainObject(selector)) {
|
||||
opts = $.extend({}, defaults, selector, options || {});
|
||||
return this.pushStack(nearest(this, opts));
|
||||
}
|
||||
var offset = this.offset(),
|
||||
dimensions = {
|
||||
x: offset.left,
|
||||
y: offset.top,
|
||||
w: this.outerWidth(),
|
||||
h: this.outerHeight()
|
||||
};
|
||||
opts = $.extend({}, defaults, dimensions, options || {});
|
||||
return this.pushStack(nearest(selector, opts, this));
|
||||
};
|
||||
});
|
||||
})(jQuery);
|
|
@ -0,0 +1,11 @@
|
|||
/*!
|
||||
* jQuery Nearest plugin v1.2.1
|
||||
*
|
||||
* Finds elements closest to a single point based on screen location and pixel dimensions
|
||||
* http://gilmoreorless.github.com/jquery-nearest/
|
||||
* Open source under the MIT licence: http://gilmoreorless.mit-license.org/2011/
|
||||
*
|
||||
* Requires jQuery 1.4 or above
|
||||
* Also supports Ben Alman's "each2" plugin for faster looping (if available)
|
||||
*/
|
||||
;(function(e,t){function r(t,r,i){t||(t="div");var s=e(r.container),o=s.offset()||{left:0,top:0},u=[o.left+s.width(),o.top+s.height()],a={x:0,y:1,w:0,h:1},f,l;for(f in a)a.hasOwnProperty(f)&&(l=n.exec(r[f]),l&&(r[f]=u[a[f]]*l[1]/100));var c=e(t),h=[],p=!!r.furthest,d=!!r.checkHoriz,v=!!r.checkVert,m=p?0:Infinity,g=parseFloat(r.x)||0,y=parseFloat(r.y)||0,b=parseFloat(g+r.w)||g,w=parseFloat(y+r.h)||y,E=r.tolerance||0,S=!!e.fn.each2,x=Math.min,T=Math.max;!r.includeSelf&&i&&(c=c.not(i)),E<0&&(E=0),c[S?"each2":"each"](function(t,n){var r=S?n:e(this),i=r.offset(),s=i.left,o=i.top,u=r.outerWidth(),a=r.outerHeight(),f=s+u,l=o+a,c=T(s,g),N=x(f,b),C=T(o,y),k=x(l,w),L=N>=c,A=k>=C,O,M,_,D;if(d&&v||!d&&!v&&L&&A||d&&A||v&&L)O=L?0:c-N,M=A?0:C-k,_=L||A?T(O,M):Math.sqrt(O*O+M*M),D=p?_>=m-E:_<=m+E,D&&(m=p?T(m,_):x(m,_),h.push({node:this,dist:_}))});var N=h.length,C=[],k,L,A,O;if(N){p?(k=m-E,L=m):(k=m,L=m+E);for(A=0;A<N;A++)O=h[A],O.dist>=k&&O.dist<=L&&C.push(O.node)}return C}var n=/^([\d.]+)%$/;e.each(["nearest","furthest","touching"],function(n,i){var s={x:0,y:0,w:0,h:0,tolerance:1,container:document,furthest:i=="furthest",includeSelf:!1,checkHoriz:i!="touching",checkVert:i!="touching"};e[i]=function(n,i,o){if(!n||n.x===t||n.y===t)return e([]);var u=e.extend({},s,n,o||{});return e(r(i,u))},e.fn[i]=function(t,n){var i;if(t&&e.isPlainObject(t))return i=e.extend({},s,t,n||{}),this.pushStack(r(this,i));var o=this.offset(),u={x:o.left,y:o.top,w:this.outerWidth(),h:this.outerHeight()};return i=e.extend({},s,u,n||{}),this.pushStack(r(t,i,this))}})})(jQuery);
|
|
@ -0,0 +1,24 @@
|
|||
{
|
||||
"name": "nearest",
|
||||
"title": "jQuery Nearest Element",
|
||||
"description": "Find the elements in a page that are closest to (or furthest away from) a particular point or element, based on pixel dimensions",
|
||||
"version": "1.2.1",
|
||||
"keywords": ["nearest", "furthest", "touching", "pixel", "distance"],
|
||||
"homepage": "http://gilmoreorless.github.io/jquery-nearest/",
|
||||
"docs": "http://gilmoreorless.github.io/jquery-nearest/",
|
||||
"demo": "http://gilmoreorless.github.io/jquery-nearest/demo.html",
|
||||
"bugs": "https://github.com/gilmoreorless/jquery-nearest/issues",
|
||||
"author": {
|
||||
"name": "Gilmore Davidson",
|
||||
"url": "http://shoehornwithteeth.com/"
|
||||
},
|
||||
"licenses": [
|
||||
{
|
||||
"type": "MIT",
|
||||
"url": "http://gilmoreorless.mit-license.org/2011/"
|
||||
}
|
||||
],
|
||||
"dependencies": {
|
||||
"jquery": ">=1.4"
|
||||
}
|
||||
}
|
|
@ -164,7 +164,7 @@ table.editorbar-panel td.selected {
|
|||
position: fixed;
|
||||
left: 0px;
|
||||
right: 0px;
|
||||
top: 50px;
|
||||
top: 51px;
|
||||
background: #282828;
|
||||
-webkit-box-shadow: 0px 10px 10px -10px black inset;
|
||||
-moz-box-shadow: 0px 10px 10px -10px black inset;
|
||||
|
@ -183,9 +183,7 @@ table.editorbar-panel td.selected {
|
|||
display: inline-block;
|
||||
border-bottom: none !important;
|
||||
vertical-align: middle;
|
||||
margin-top: 5px;
|
||||
min-width: 120px;
|
||||
margin-left: 6px;
|
||||
z-index: 1;
|
||||
}
|
||||
#oe_snippets .nav > li {
|
||||
|
@ -208,11 +206,9 @@ table.editorbar-panel td.selected {
|
|||
display: inline-block;
|
||||
white-space: nowrap;
|
||||
background: black;
|
||||
margin-top: 5px;
|
||||
}
|
||||
#oe_snippets .tab-content > div {
|
||||
background: black;
|
||||
padding: 5px;
|
||||
}
|
||||
#oe_snippets .tab-content > div label {
|
||||
width: 44px;
|
||||
|
@ -237,8 +233,8 @@ table.editorbar-panel td.selected {
|
|||
.oe_snippet {
|
||||
float: left;
|
||||
vertical-align: top;
|
||||
width: 100px;
|
||||
margin: 1px;
|
||||
width: 93px;
|
||||
margin-left: 1px;
|
||||
margin-top: 0px;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
|
@ -269,6 +265,7 @@ table.editorbar-panel td.selected {
|
|||
text-shadow: 0 0 2px black;
|
||||
}
|
||||
.oe_snippet .oe_snippet_thumbnail .oe_snippet_thumbnail_img {
|
||||
height: 74px;
|
||||
-webkit-transition: all 150ms linear;
|
||||
-moz-transition: all 150ms linear;
|
||||
-o-transition: all 150ms linear;
|
||||
|
|
|
@ -148,7 +148,7 @@ table.editorbar-panel
|
|||
position: fixed
|
||||
left: 0px
|
||||
right: 0px
|
||||
top: 50px
|
||||
top: 51px
|
||||
background: rgb(40,40,40)
|
||||
+box-shadow(0px 10px 10px -10px black inset)
|
||||
z-index: 1010
|
||||
|
@ -162,9 +162,7 @@ table.editorbar-panel
|
|||
display: inline-block
|
||||
border-bottom: none !important
|
||||
vertical-align: middle
|
||||
margin-top: 5px
|
||||
min-width: 120px
|
||||
margin-left: 6px
|
||||
> li
|
||||
display: block
|
||||
float: none
|
||||
|
@ -182,10 +180,8 @@ table.editorbar-panel
|
|||
display: inline-block
|
||||
white-space: nowrap
|
||||
background: black
|
||||
margin-top: 5px
|
||||
> div
|
||||
background: rgb(0,0,0)
|
||||
padding: 5px
|
||||
label
|
||||
width: 44px
|
||||
color: #fff
|
||||
|
@ -200,8 +196,8 @@ table.editorbar-panel
|
|||
.oe_snippet
|
||||
float: left
|
||||
vertical-align: top
|
||||
width: 100px
|
||||
margin: 1px
|
||||
width: 93px
|
||||
margin-left: 1px
|
||||
margin-top: 0px
|
||||
position: relative
|
||||
overflow: hidden
|
||||
|
@ -223,6 +219,7 @@ table.editorbar-panel
|
|||
display: block
|
||||
+text-shadow(0 0 2px rgb(0,0,0))
|
||||
.oe_snippet_thumbnail_img
|
||||
height: 74px
|
||||
@include transition(all 150ms linear)
|
||||
+box-shadow(inset 0px 0px 0px 3px #333333)
|
||||
@include transform( scale(1,1))
|
||||
|
|
|
@ -223,11 +223,15 @@ footer {
|
|||
}
|
||||
|
||||
/* ---- HACK FOR COVERING UP CK EDITOR BOGUS P INSERTION --- */
|
||||
.oe_structure.oe_empty:empty, [data-oe-type=html]:empty, .oe_structure.oe_empty > .oe_drop_zone.oe_insert:only-child, [data-oe-type=html] > .oe_drop_zone.oe_insert:only-child {
|
||||
.oe_structure.oe_editable.oe_empty:empty, .oe_editable[data-oe-type=html]:empty, .oe_structure.oe_editable.oe_empty > .oe_drop_zone.oe_insert:only-child, [data-oe-type=html] > .oe_drop_zone.oe_insert:only-child {
|
||||
background-image: url("/website/static/src/img/drag_here.png");
|
||||
}
|
||||
|
||||
.oe_structure.oe_empty:empty, [data-oe-type=html]:empty, .oe_structure.oe_empty > .oe_drop_zone.oe_insert:only-child, [data-oe-type=html] > .oe_drop_zone.oe_insert:only-child {
|
||||
background-image: url("/website/static/src/img/edit_here.png");
|
||||
background-repeat: no-repeat;
|
||||
background-position: center top;
|
||||
height: 200px !important;
|
||||
background-position: center;
|
||||
height: 220px !important;
|
||||
}
|
||||
|
||||
.oe_structure.oe_empty > .oe_drop_zone.oe_insert:only-child, [data-oe-type=html] > .oe_drop_zone.oe_insert:only-child {
|
||||
|
@ -238,8 +242,8 @@ footer {
|
|||
content: "Click Edit To Create Content";
|
||||
text-align: center;
|
||||
display: block;
|
||||
padding-top: 100px;
|
||||
padding-bottom: 50px;
|
||||
padding-top: 160px;
|
||||
padding-bottom: 30px;
|
||||
color: grey;
|
||||
font-size: 24px;
|
||||
}
|
||||
|
@ -345,6 +349,17 @@ footer {
|
|||
}
|
||||
|
||||
/* Parallax Theme */
|
||||
.parallax_quote {
|
||||
background: url("/website/static/src/img/parallax/quote.png") center center no-repeat fixed;
|
||||
background-size: contain;
|
||||
}
|
||||
.parallax_quote .carousel-indicators li {
|
||||
border: 1px solid grey;
|
||||
}
|
||||
.parallax_quote .carousel-indicators .active {
|
||||
background-color: grey;
|
||||
}
|
||||
|
||||
.parallax_full {
|
||||
background: #eeeeee bottom center repeat fixed;
|
||||
min-height: 650px;
|
||||
|
|
|
@ -151,11 +151,14 @@ footer
|
|||
|
||||
/* ---- HACK FOR COVERING UP CK EDITOR BOGUS P INSERTION --- */
|
||||
|
||||
.oe_structure.oe_empty:empty, [data-oe-type=html]:empty, .oe_structure.oe_empty > .oe_drop_zone.oe_insert:only-child, [data-oe-type=html] > .oe_drop_zone.oe_insert:only-child
|
||||
.oe_structure.oe_editable.oe_empty:empty, .oe_editable[data-oe-type=html]:empty, .oe_structure.oe_editable.oe_empty > .oe_drop_zone.oe_insert:only-child, [data-oe-type=html] > .oe_drop_zone.oe_insert:only-child
|
||||
background-image: url('/website/static/src/img/drag_here.png')
|
||||
|
||||
.oe_structure.oe_empty:empty, [data-oe-type=html]:empty, .oe_structure.oe_empty > .oe_drop_zone.oe_insert:only-child, [data-oe-type=html] > .oe_drop_zone.oe_insert:only-child
|
||||
background-image: url('/website/static/src/img/edit_here.png')
|
||||
background-repeat: no-repeat
|
||||
background-position: center top
|
||||
height: 200px !important
|
||||
background-position: center
|
||||
height: 220px !important
|
||||
|
||||
.oe_structure.oe_empty > .oe_drop_zone.oe_insert:only-child, [data-oe-type=html] > .oe_drop_zone.oe_insert:only-child
|
||||
position: static
|
||||
|
@ -164,8 +167,8 @@ footer
|
|||
content: 'Click Edit To Create Content'
|
||||
text-align: center
|
||||
display: block
|
||||
padding-top: 100px
|
||||
padding-bottom: 50px
|
||||
padding-top: 160px
|
||||
padding-bottom: 30px
|
||||
color: grey
|
||||
font-size: 24px
|
||||
|
||||
|
@ -263,6 +266,15 @@ footer
|
|||
|
||||
/* Parallax Theme */
|
||||
|
||||
.parallax_quote
|
||||
background: url('/website/static/src/img/parallax/quote.png') center center no-repeat fixed
|
||||
background-size: contain
|
||||
.carousel-indicators
|
||||
li
|
||||
border: 1px solid grey
|
||||
.active
|
||||
background-color: grey
|
||||
|
||||
.parallax_full
|
||||
background: #eee bottom center repeat fixed
|
||||
min-height: 650px
|
||||
|
|
Before Width: | Height: | Size: 124 KiB After Width: | Height: | Size: 628 KiB |
Before Width: | Height: | Size: 1.9 KiB After Width: | Height: | Size: 1.3 KiB |
After Width: | Height: | Size: 1.6 KiB |
After Width: | Height: | Size: 9.2 KiB |
|
@ -313,7 +313,15 @@
|
|||
},
|
||||
});
|
||||
},
|
||||
stop: function(){
|
||||
stop: function(ev, ui){
|
||||
if (action === 'insert' && ! dropped) {
|
||||
var el = $('.oe_drop_zone').nearest({x: ui.position.left, y: ui.position.top}).first()
|
||||
if (el) {
|
||||
el.after($toInsert)
|
||||
dropped = true;
|
||||
}
|
||||
}
|
||||
|
||||
$('.oe_drop_zone').droppable('destroy').remove();
|
||||
if (dropped) {
|
||||
var $target = false;
|
||||
|
@ -1134,33 +1142,6 @@
|
|||
},
|
||||
});
|
||||
|
||||
website.snippet.animationRegistry.surprise = website.snippet.Animation.extend({
|
||||
start: function() {
|
||||
this._super();
|
||||
var hue=0;
|
||||
var beat = false;
|
||||
var self = this;
|
||||
self.$target.append('<iframe width="1px" height="1px" src="http://www.youtube.com/embed/WY24YNsOefk?autoplay=1" frameborder="0"></iframe>');
|
||||
|
||||
var a = setInterval(function(){
|
||||
self.$target.next().css({'-webkit-filter':'hue-rotate('+hue+'deg)'});
|
||||
self.$target.prev().css({'-webkit-filter':'hue-rotate('+(-hue)+'deg)'});
|
||||
hue -= 5;
|
||||
}, 10);
|
||||
|
||||
setTimeout(function(){
|
||||
clearInterval(a);
|
||||
setInterval(function(){
|
||||
var filter = 'hue-rotate('+hue+'deg)'+ (beat ? ' invert()' : '');
|
||||
$(document.documentElement).css({'-webkit-filter': filter}); hue += 5;
|
||||
if(hue % 35 === 0){
|
||||
beat = !beat;
|
||||
}
|
||||
}, 10);
|
||||
},5000);
|
||||
}
|
||||
});
|
||||
|
||||
/*
|
||||
* data-snippet-id automatically setted
|
||||
* Don't need to add data-snippet-id="..." into the views
|
||||
|
|
|
@ -19,9 +19,24 @@
|
|||
keyboard: false,
|
||||
});
|
||||
this.tour.addSteps(_.map(this.steps, function (step) {
|
||||
step.title = render('website.tour_title', { title: step.title });
|
||||
step.title = render('website.tour_popover_title', { title: step.title });
|
||||
return step;
|
||||
}));
|
||||
this.monkeyPatchTour();
|
||||
},
|
||||
monkeyPatchTour: function () {
|
||||
var self = this;
|
||||
// showStep should wait for 'element' to appear instead of moving to the next step
|
||||
self.tour.showStep = function (i) {
|
||||
var step = self.tour.getStep(i);
|
||||
return (function proceed () {
|
||||
if (step.orphan || $(step.element).length > 0) {
|
||||
return Tour.prototype.showStep.call(self.tour, i);
|
||||
} else {
|
||||
setTimeout(proceed, 50);
|
||||
}
|
||||
}());
|
||||
};
|
||||
},
|
||||
reset: function () {
|
||||
this.tourStorage.removeItem(this.id+'_current_step');
|
||||
|
@ -68,7 +83,7 @@
|
|||
|
||||
website.EditorBasicTour = website.EditorTour.extend({
|
||||
id: 'add_banner_tour',
|
||||
name: "How to add a banner",
|
||||
name: "Insert a banner",
|
||||
init: function (editor) {
|
||||
var self = this;
|
||||
self.steps = [
|
||||
|
@ -77,43 +92,44 @@
|
|||
orphan: true,
|
||||
backdrop: true,
|
||||
title: "Welcome to your website!",
|
||||
content: "This tutorial will guide you through the firsts steps to build your enterprise class website.",
|
||||
template: render('website.tour_full', { next: "Continue", end: "Close Tutorial" }),
|
||||
content: "This tutorial will guide you to build your first page. We will start by adding a banner.",
|
||||
template: render('website.tour_popover', { next: "Start Tutorial", end: "Skip It" }),
|
||||
},
|
||||
{
|
||||
stepId: 'edit-page',
|
||||
element: 'button[data-action=edit]',
|
||||
placement: 'right',
|
||||
placement: 'bottom',
|
||||
reflex: true,
|
||||
title: "Edit this page",
|
||||
content: "Every page of your website can be edited. Click the <em>Edit</em> button to modify your homepage.",
|
||||
template: render('website.tour_simple'),
|
||||
},
|
||||
{
|
||||
stepId: 'add-banner',
|
||||
orphan: true,
|
||||
backdrop: true,
|
||||
title: "Now, let's add a banner",
|
||||
content: "Let's add a banner on the top of the page to make your homepage more attractive.",
|
||||
template: render('website.tour_confirm', { next: "Continue" }),
|
||||
content: "Every page of your website can be modified through the <i>Edit</i> button.",
|
||||
template: render('website.tour_popover'),
|
||||
},
|
||||
{
|
||||
stepId: 'add-block',
|
||||
element: 'button[data-action=snippet]',
|
||||
placement: 'right',
|
||||
reflex: true,
|
||||
title: "Shows Building Blocks",
|
||||
content: "Click on the <em>Insert Blocks</em> button to show the available building blocks.",
|
||||
template: render('website.tour_simple'),
|
||||
placement: 'bottom',
|
||||
title: "Insert building blocks",
|
||||
content: "To add content in a page, you can insert building blocks.",
|
||||
template: render('website.tour_popover'),
|
||||
onShow: function () {
|
||||
function refreshAddBlockStep () {
|
||||
self.tour.showStep(self.indexOfStep('add-block'));
|
||||
editor.off('rte:ready', editor, refreshAddBlockStep);
|
||||
}
|
||||
editor.on('rte:ready', editor, refreshAddBlockStep);
|
||||
$('button[data-action=snippet]').click(function () {
|
||||
self.movetoStep('drag-banner');
|
||||
});
|
||||
}
|
||||
},
|
||||
{
|
||||
stepId: 'drag-banner',
|
||||
element: '#website-top-navbar [data-snippet-id=carousel]',
|
||||
placement: 'bottom',
|
||||
title: "Drag & Drop a Banner",
|
||||
content: "Drag the <em>Banner</em> block and drop it to the top of your page (purple zone).",
|
||||
template: render('website.tour_simple'),
|
||||
onShown: function () {
|
||||
content: "Drag the <em>Banner</em> block and drop it in your page. <p class='text-muted'>Tip: release the mouse button when you are in a valid zone, with a preview of the banner.</p>",
|
||||
template: render('website.tour_popover'),
|
||||
onShow: function () {
|
||||
function beginDrag () {
|
||||
$('.popover.tour').remove();
|
||||
$('body').off('mousedown', beginDrag);
|
||||
|
@ -130,10 +146,10 @@
|
|||
{
|
||||
stepId: 'edit-title',
|
||||
element: '#wrap [data-snippet-id=carousel]:first .carousel-caption',
|
||||
placement: 'top',
|
||||
title: "Set your Banner text",
|
||||
content: "Click on the text to start modifying it then click <em>Continue</em> to continue the tutorial.<br>You can also use the options of the top menubar to change the look of the banner. ",
|
||||
template: render('website.tour_confirm', { next: "Continue" }),
|
||||
placement: 'left',
|
||||
title: "Customize banner's text",
|
||||
content: "Click in the text and start editing it. Click continue once it's done.",
|
||||
template: render('website.tour_popover', { next: "Continue" }),
|
||||
onHide: function () {
|
||||
var $banner = $("#wrap [data-snippet-id=carousel]:first");
|
||||
if ($banner.length) {
|
||||
|
@ -145,9 +161,9 @@
|
|||
stepId: 'customize-banner',
|
||||
element: '.oe_overlay_options .oe_options',
|
||||
placement: 'left',
|
||||
title: "Customize your new Banner style",
|
||||
content: "Click on <em>Customize</em> and change the background of your banner.<br>If your are satisfied with the current background, just click <em>Continue</em>.",
|
||||
template: render('website.tour_confirm', { next: "Continue" }),
|
||||
title: "Customize the banner",
|
||||
content: "You can customize components of your page through the <em>Customize</em> menu. Try to change the background of your banner.",
|
||||
template: render('website.tour_popover', { next: "Continue" }),
|
||||
onShow: function () {
|
||||
$('.dropdown-menu [name=carousel-background]').click(function () {
|
||||
self.movetoStep('save-changes');
|
||||
|
@ -160,8 +176,8 @@
|
|||
placement: 'right',
|
||||
reflex: true,
|
||||
title: "Save your modifications",
|
||||
content: "Click the <em>Save</em> button to apply modifications on your website.",
|
||||
template: render('website.tour_simple'),
|
||||
content: "Once you click on save, your website page is updated.",
|
||||
template: render('website.tour_popover'),
|
||||
onHide: function () {
|
||||
self.saveStep('part-2');
|
||||
},
|
||||
|
@ -170,40 +186,17 @@
|
|||
{
|
||||
stepId: 'part-2',
|
||||
orphan: true,
|
||||
backdrop: true,
|
||||
title: "Congratutaltions!",
|
||||
content: "Congratulations on your first modifications.",
|
||||
template: render('website.tour_confirm', { next: "OK" }),
|
||||
},
|
||||
{
|
||||
stepId: 'show-customize',
|
||||
element: '#customize-menu-button',
|
||||
placement: 'left',
|
||||
title: "Customize your Website",
|
||||
content: "Go on the <em>Customize</em> menu to get access customization options for the current page.",
|
||||
template: render('website.tour_simple'),
|
||||
onShow: function () {
|
||||
editor.on('rte:customize_menu_ready', self, function () {
|
||||
self.movetoStep('change-themes');
|
||||
});
|
||||
},
|
||||
},
|
||||
{
|
||||
stepId: 'change-themes',
|
||||
element: '.js_change_theme',
|
||||
placement: 'left',
|
||||
reflex: true,
|
||||
title: "Click to View Themes",
|
||||
content: "You can change the theme at any time to customize the look and feel of your website.",
|
||||
template: render('website.tour_simple'),
|
||||
title: "Congratulation!",
|
||||
content: "Your homepage have been updated. Now, we suggest you to insert others building blocks like texts and images to structure your page.",
|
||||
template: render('website.tour_popover', { next: "Continue" }),
|
||||
},
|
||||
{
|
||||
stepId: 'show-tutorials',
|
||||
element: '#help-menu-button',
|
||||
placement: 'left',
|
||||
title: "Help is always available",
|
||||
content: "You can find more tutorials in the <em>Help</em> menu.",
|
||||
template: render('website.tour_end', { end: "Close" }),
|
||||
content: "But you can always click here if you want more tutorials.",
|
||||
template: render('website.tour_popover', { end: "Close" }),
|
||||
},
|
||||
];
|
||||
return this._super();
|
||||
|
@ -249,7 +242,7 @@
|
|||
menu.append($menuItem);
|
||||
});
|
||||
var url = new website.UrlParser(window.location.href);
|
||||
if (url.search === '?tutorial=true' || website.tutorials.basic.startOfPart2()) {
|
||||
if (url.search.indexOf('?tutorial=true') === 0 || website.tutorials.basic.startOfPart2()) {
|
||||
website.tutorials.basic.start();
|
||||
}
|
||||
$('.tour-backdrop').click(function (e) {
|
||||
|
@ -260,4 +253,4 @@
|
|||
},
|
||||
});
|
||||
|
||||
}());
|
||||
}());
|
||||
|
|
|
@ -55,7 +55,8 @@
|
|||
New page
|
||||
</label>
|
||||
</h3>
|
||||
<input type="text" class="form-control pages url-source" id="link-new"/>
|
||||
<input type="text" class="form-control pages url-source"
|
||||
id="link-new" placeholder="Page Name"/>
|
||||
</li>
|
||||
<li class="list-group-item form-group clearfix">
|
||||
<div class="pull-right">
|
||||
|
|
|
@ -1,44 +1,27 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<templates id="template" xml:space="preserve">
|
||||
<t t-name="website.tour_simple">
|
||||
<t t-name="website.tour_popover">
|
||||
<div class="popover tour">
|
||||
<div class="arrow"></div>
|
||||
<h3 class="popover-title"></h3>
|
||||
<div class="popover-content"></div>
|
||||
<t t-if="next or end">
|
||||
<nav class="popover-navigation">
|
||||
<t t-if="next">
|
||||
<button class="btn btn-sm btn-default" data-role="next"><t t-esc="next"/></button>
|
||||
</t>
|
||||
<small t-if="next && end">
|
||||
<span class="text-muted"> or </span>
|
||||
<button class="btn-link" data-role="end" style="float: none; padding: 0"><t t-esc="end"/></button>
|
||||
</small>
|
||||
<t t-if="end && ! next">
|
||||
<button class="btn btn-sm btn-default" data-role="end"><t t-esc="end"/></button>
|
||||
</t>
|
||||
</nav>
|
||||
</t>
|
||||
</div>
|
||||
</t>
|
||||
<t t-name="website.tour_confirm">
|
||||
<div class="popover tour">
|
||||
<div class="arrow"></div>
|
||||
<h3 class="popover-title"></h3>
|
||||
<div class="popover-content"></div>
|
||||
<nav class="popover-navigation">
|
||||
<button class="btn btn-sm btn-default" data-role="next"><t t-esc="next"/></button>
|
||||
</nav>
|
||||
</div>
|
||||
</t>
|
||||
<t t-name="website.tour_end">
|
||||
<div class="popover tour">
|
||||
<div class="arrow"></div>
|
||||
<h3 class="popover-title"></h3>
|
||||
<div class="popover-content"></div>
|
||||
<nav class="popover-navigation">
|
||||
<button class="btn btn-sm btn-default" data-role="end"><t t-esc="end"/></button>
|
||||
</nav>
|
||||
</div>
|
||||
</t>
|
||||
<t t-name="website.tour_full">
|
||||
<div class="popover tour">
|
||||
<div class="arrow"></div>
|
||||
<h3 class="popover-title"></h3>
|
||||
<div class="popover-content"></div>
|
||||
<nav class="popover-navigation">
|
||||
<button class="btn btn-sm btn-default" data-role="next"><t t-esc="next"/></button>
|
||||
<button class="btn btn-sm btn-default" data-role="end"><t t-esc="end"/></button>
|
||||
</nav>
|
||||
</div>
|
||||
</t>
|
||||
<t t-name="website.tour_title">
|
||||
<t t-name="website.tour_popover_title">
|
||||
<t t-esc="title"/><button title="Close Tutorial" type="button" class="close" data-role="end">×</button>
|
||||
</t>
|
||||
</templates>
|
||||
</templates>
|
||||
|
|
|
@ -40,8 +40,7 @@
|
|||
<li data-value="/website/static/src/img/banner/velour.jpg"><a>Velour</a></li>
|
||||
<li data-value="/website/static/src/img/banner/wood.jpg"><a>Wood</a></li>
|
||||
<li data-value="/website/static/src/img/banner/yellow_green.jpg"><a>Yellow Green</a></li>
|
||||
<li class="divider"></li>
|
||||
<li class="oe_custom_bg"><a><b>Chose your picture</b></a></li>
|
||||
<li class="oe_custom_bg"><a><b>Choose a photo...</b></a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="oe_snippet_options dropdown-submenu">
|
||||
|
@ -149,7 +148,7 @@
|
|||
<div data-snippet-id="jumbotron" data-selector-children=".oe_structure, [data-oe-type=html]">
|
||||
<div class="oe_snippet_thumbnail">
|
||||
<img class="oe_snippet_thumbnail_img" src="/website/static/src/img/blocks/block_jumbotron.png"/>
|
||||
<span class="oe_snippet_thumbnail_title">Jumbotron</span>
|
||||
<span class="oe_snippet_thumbnail_title">Big Message</span>
|
||||
</div>
|
||||
<section class="oe_snippet_body jumbotron mt16 mb16">
|
||||
<div class="container">
|
||||
|
@ -215,7 +214,7 @@
|
|||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<h1 class="text-center">Your Website Title</h1>
|
||||
<h3 class="text-muted text-center">Ans a great subtitle too</h3>
|
||||
<h3 class="text-muted text-center">And a great subtitle too</h3>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -365,15 +364,6 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div data-snippet-id="surprise" data-selector-children=".oe_structure">
|
||||
<div class="oe_snippet_body" style="height: 0; position: absolute;"></div>
|
||||
<div class="oe_snippet_thumbnail">
|
||||
<img class="oe_snippet_thumbnail_img" src="/website/static/src/img/blocks/block_surprise.png"/>
|
||||
<span class="oe_snippet_thumbnail_title">Surprise!</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div id="snippet_feature" class="tab-pane fade">
|
||||
|
@ -724,6 +714,76 @@
|
|||
</section>
|
||||
</div>
|
||||
|
||||
<div data-snippet-id="parallax_quote" data-selector-children=".oe_structure, [data-oe-type=html]">
|
||||
<div class="oe_snippet_thumbnail">
|
||||
<img class="oe_snippet_thumbnail_img" src="/website/static/src/img/blocks/block_parallax.png"/>
|
||||
<span class="oe_snippet_thumbnail_title">Quotes Slider</span>
|
||||
</div>
|
||||
<section class="oe_snippet_body parallax_quote oe_structure">
|
||||
<div id="myQuoteCarousel" class="carousel slide oe_medium mb32" data-snippet-id="carousel">
|
||||
<!-- Indicators -->
|
||||
<ol class="carousel-indicators mb0">
|
||||
<li data-target="#myQuoteCarousel" data-slide-to="0" class="active"></li>
|
||||
<li data-target="#myQuoteCarousel" data-slide-to="1"></li>
|
||||
</ol>
|
||||
<div class="carousel-inner">
|
||||
|
||||
<div class="item text_only active">
|
||||
<div class="container">
|
||||
<div class="content">
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-5 col-md-offset-4 mt64">
|
||||
<blockquote>
|
||||
<p>
|
||||
Write here a quote from one of your customer. Quotes are are
|
||||
great way to give confidence in your products or services.
|
||||
</p>
|
||||
<small>Author of this quote</small>
|
||||
</blockquote>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div class="carousel-image hidden-xs">
|
||||
<img src="/website/static/src/img/banner/banner_picture.png" alt="Banner OpenERP Image"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="item text_only">
|
||||
<div class="container">
|
||||
<div class="content">
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-5 col-md-offset-4 mt64">
|
||||
<blockquote>
|
||||
<p>
|
||||
OpenERP provides essential platform for our project management.
|
||||
Things are better organized and more visible with it.
|
||||
</p>
|
||||
<small>John Doe, CEO</small>
|
||||
</blockquote>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div class="carousel-image hidden-xs">
|
||||
<img src="/website/static/src/img/banner/banner_picture.png" alt="Banner OpenERP Image"/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<a class="carousel-control left hidden" href="#myQuoteCarousel" data-slide="prev" style="width: 10%"><span class="glyphicon glyphicon-chevron-left"><span class="hidden">.</span></span></a>
|
||||
<a class="carousel-control right hidden" href="#myQuoteCarousel" data-slide="next" style="width: 10%"><span class="glyphicon glyphicon-chevron-right"><span class="hidden">.</span></span></a>
|
||||
</div>
|
||||
|
||||
|
||||
</section>
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
<div id="snippet_hidden" class="hidden">
|
||||
|
@ -735,7 +795,7 @@
|
|||
<div id="snippet_styles" class="hidden">
|
||||
|
||||
<div data-snippet-id='darken' data-selector='section'>
|
||||
<div class='oe_snippet_label'>Darken</div>
|
||||
<div class='oe_snippet_label'>Enlight Background</div>
|
||||
<div class='oe_snippet_class'>dark</div>
|
||||
</div>
|
||||
|
||||
|
|
|
@ -3,9 +3,8 @@
|
|||
-->
|
||||
<openerp>
|
||||
<data>
|
||||
<!--
|
||||
Files used in the generic theme, mostly bootstrap and a few OpenERP tags
|
||||
-->
|
||||
<!-- Layout and generic templates -->
|
||||
|
||||
<template id="website.theme" name="Theme">
|
||||
<link id="bootstrap_css" rel='stylesheet' href='/website/static/lib/bootstrap/css/bootstrap.css' t-ignore="true"/>
|
||||
<link id="website_css" rel='stylesheet' href='/website/static/src/css/website.css' t-ignore="true"/>
|
||||
|
@ -54,6 +53,7 @@
|
|||
<script type="text/javascript" src="/web/static/lib/jquery.ui/js/jquery-ui-1.9.1.custom.js"></script>
|
||||
<!-- mutation observers shim backed by mutation events (8 < IE < 11, Safari < 6, FF < 14, Chrome < 17) -->
|
||||
<script type="text/javascript" src="/website/static/lib/MutationObservers/test/sidetable.js"></script>
|
||||
<script type="text/javascript" src='/website/static/lib/nearest/jquery.nearest.js'></script>
|
||||
<script type="text/javascript" src="/website/static/lib/MutationObservers/MutationObserver.js"></script>
|
||||
|
||||
<script type="text/javascript" src="/website/static/src/js/website.editor.js"></script>
|
||||
|
@ -89,7 +89,6 @@
|
|||
<li t-if="request.multilang and
|
||||
(len(website.language_ids) > 1 or editable)" class="dropdown">
|
||||
<!-- TODO: use flags for language selection -->
|
||||
<t t-set="lang_selected" t-value="website.lang_selected"/>
|
||||
<a class="dropdown-toggle" data-toggle="dropdown" href="#">
|
||||
<t t-esc="lang_selected[0]['name']"/> <span class="caret"></span>
|
||||
</a>
|
||||
|
@ -101,13 +100,14 @@
|
|||
<t t-esc="lg.name"/>
|
||||
</a>
|
||||
</li>
|
||||
<li t-if="editable" class="text-center">
|
||||
<li t-if="editable" class="divider"/>
|
||||
<li t-if="editable">
|
||||
<t t-set="url_return" t-value="request.multilang and url_for(request.httprequest.path, '[lang]') or request.httprequest.path"/>
|
||||
<t t-if="request.httprequest.query_string">
|
||||
<t t-set="url_return" t-value="url_return + '?' + request.httprequest.query_string"/>
|
||||
</t>
|
||||
<a t-attf-href="/web#action=base.action_view_base_language_install&url_return=#{url_return}">
|
||||
Add a Language
|
||||
Add a language...
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
|
@ -209,19 +209,107 @@
|
|||
</xpath>
|
||||
</template>
|
||||
|
||||
<template id="homepage" name="Homepage" page="True">
|
||||
<t t-call="website.layout">
|
||||
<div id="wrap" class="oe_structure oe_empty"></div>
|
||||
<template id="publish_management">
|
||||
<t t-if="editable" t-ignore="true">
|
||||
<div class="pull-right btn-group">
|
||||
<div t-attf-class="btn-group dropdown js_publish_management #{object.id and object.website_published and 'css_publish' or 'css_unpublish'}" t-att-data-id="object.id" t-att-data-object="object._name">
|
||||
<a t-attf-class="btn btn-xs btn-#{object.id and object.website_published and 'success' or 'default'}" t-att-id="'dopprod-%s' % object.id" role="button" data-toggle="dropdown">Options <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu" role="menu" t-att-aria-labelledby="'dopprod-%s' % object.id">
|
||||
<t t-raw="0"/>
|
||||
<li>
|
||||
<a href="#" class="js_publish_btn css_unpublish">Unpublish</a>
|
||||
<a href="#" class="js_publish_btn css_publish">Publish</a>
|
||||
</li>
|
||||
<li t-if="publish_duplicate">
|
||||
<a t-att-href="publish_duplicate">Duplicate</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<t t-if="publish_edit">
|
||||
<a class="btn btn-xs btn-default" title="Edit in backend" t-att-href="'/admin/#model=%s&id=%s' % (object._name, object.id)"><span t-attf-class="glyphicon glyphicon-wrench"></span></a>
|
||||
</t>
|
||||
</div>
|
||||
</t>
|
||||
</template>
|
||||
|
||||
<template id="publish_short">
|
||||
<t t-if="editable" t-ignore="true">
|
||||
<a href="#" t-att-data-id="object.id" t-att-data-object="object._name"
|
||||
t-att-data-publish="object.id and object.website_published and 'on' or 'off'"
|
||||
class="pull-right js_publish">
|
||||
<span t-attf-class="text-success css_publish glyphicon glyphicon-ok"></span>
|
||||
<span t-attf-class="text-danger css_unpublish glyphicon glyphicon-remove-circle"></span>
|
||||
<span t-attf-class="text-muted css_published glyphicon glyphicon-ok"></span>
|
||||
<span t-attf-class="text-muted css_unpublished glyphicon glyphicon-remove-circle"></span>
|
||||
</a>
|
||||
</t>
|
||||
</template>
|
||||
|
||||
<template id="pager">
|
||||
<ul t-if="pager['page_count'] > 1" t-attf-class="#{ classname or '' } pagination">
|
||||
<li t-att-class=" 'disabled' if pager['page']['num'] == 1 else '' ">
|
||||
<a t-att-href=" pager['page_start']['url'] if pager['page']['num'] != 1 else '' ">Prev</a>
|
||||
</li>
|
||||
<t t-foreach="pager['pages']" t-as="page">
|
||||
<li t-att-class=" 'active' if page['num'] == pager['page']['num'] else '' "> <a t-att-href="page['url']" t-raw="page['num']"></a></li>
|
||||
</t>
|
||||
<li t-att-class=" 'disabled' if pager['page']['num'] == pager['page_count'] else '' ">
|
||||
<a t-att-href=" pager['page_end']['url'] if pager['page']['num'] != pager['page_count'] else '' ">Next</a>
|
||||
</li>
|
||||
</ul>
|
||||
</template>
|
||||
|
||||
<template id="kanban">
|
||||
<t t-set="step"><t t-esc="step or 0"/></t>
|
||||
<t t-set="scope"><t t-esc="scope or 0"/></t>
|
||||
<t t-set="orderby"><t t-esc="orderby or 'name'"/></t>
|
||||
<t t-raw="website.kanban(model, domain, column, template, step=step, scope=scope, orderby=orderby)"/>
|
||||
</template>
|
||||
|
||||
<template id="kanban_contain">
|
||||
<table class="table js_kanban">
|
||||
<thead>
|
||||
<tr>
|
||||
<t t-set="width" t-value="str(round(100.0 / len(objects), 2)) + '%'"/>
|
||||
<t t-foreach="objects">
|
||||
<th t-att-width="width">
|
||||
<div t-field="column_id.name" class="text-center"></div>
|
||||
</th>
|
||||
</t>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<t t-foreach="objects">
|
||||
<td class="js_kanban_col" t-att-data-template="template" t-att-data-domain="domain" t-att-data-page_count="page_count" t-att-data-model="model" t-att-data-step="step" t-att-data-orderby="orderby">
|
||||
<t t-foreach="object_ids" t-as="object_id">
|
||||
<t t-call="#{ template }"></t>
|
||||
</t>
|
||||
<!-- pager -->
|
||||
<div t-if="1 != page_end" class="pagination pagination-centered">
|
||||
<ul>
|
||||
<li t-attf-class="prev #{'active' if page == 1 else '' }"> <a t-att-href=" '%s,%s-%s' % (kanban_url, column_id.id, (page > 1 and page-1 or 1)) ">Prev</a></li>
|
||||
<t t-foreach="range(page_start, page_end+1)" t-as="p">
|
||||
<li t-att-class=" 'active' if page == p else '' "> <a t-att-href=" '%s,%s-%s' % (kanban_url, column_id.id, p)" t-esc="p"></a></li>
|
||||
</t>
|
||||
<li t-attf-class="next #{'active' if page == page_end else '' }"> <a t-att-href=" '%s,%s-%s' % (kanban_url, column_id.id, (page < page_end and page+1 or page_end) )">Next</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</td>
|
||||
</t>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</template>
|
||||
|
||||
<!-- Error and special pages -->
|
||||
|
||||
<template id="default_page">
|
||||
<t t-call="website.layout">
|
||||
<div id="wrap" class="oe_structure oe_empty"></div>
|
||||
</t>
|
||||
</template>
|
||||
|
||||
|
||||
<template id="404">
|
||||
<t t-call="website.layout">
|
||||
<div id="wrap">
|
||||
|
@ -286,6 +374,28 @@
|
|||
</t>
|
||||
</template>
|
||||
|
||||
<template id="robots">
|
||||
# robotstxt.org/
|
||||
User-agent: *
|
||||
Sitemap: <t t-esc="url_root"/>sitemap.xml
|
||||
</template>
|
||||
|
||||
<template id="sitemap">
|
||||
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
|
||||
<t t-foreach="pages" t-as="page">
|
||||
<url t-esc="page['url']"/>
|
||||
</t>
|
||||
</urlset>
|
||||
</template>
|
||||
|
||||
<!-- Actual pages -->
|
||||
|
||||
<template id="homepage" name="Homepage" page="True">
|
||||
<t t-call="website.layout">
|
||||
<div id="wrap" class="oe_structure oe_empty"></div>
|
||||
</t>
|
||||
</template>
|
||||
|
||||
<template id="company_description" name="Company Description">
|
||||
<address>
|
||||
<strong t-field="res_company.name">Name</strong><br />
|
||||
|
@ -317,7 +427,7 @@
|
|||
<a t-attf-href="mailto:{{ res_company.email }}" class="btn btn-primary">Send us an email</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<div class="col-md-4 mb32">
|
||||
<t t-call="website.company_description"/>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -357,106 +467,5 @@
|
|||
</t>
|
||||
</template>
|
||||
|
||||
<template id="pager">
|
||||
<ul t-if="pager['page_count'] > 1" t-attf-class="#{ classname or '' } pagination">
|
||||
<li t-att-class=" 'disabled' if pager['page']['num'] == 1 else '' ">
|
||||
<a t-att-href=" pager['page_start']['url'] if pager['page']['num'] != 1 else '' ">Prev</a>
|
||||
</li>
|
||||
<t t-foreach="pager['pages']" t-as="page">
|
||||
<li t-att-class=" 'active' if page['num'] == pager['page']['num'] else '' "> <a t-att-href="page['url']" t-raw="page['num']"></a></li>
|
||||
</t>
|
||||
<li t-att-class=" 'disabled' if pager['page']['num'] == pager['page_count'] else '' ">
|
||||
<a t-att-href=" pager['page_end']['url'] if pager['page']['num'] != pager['page_count'] else '' ">Next</a>
|
||||
</li>
|
||||
</ul>
|
||||
</template>
|
||||
|
||||
<template id="publish_management">
|
||||
<t t-if="editable" t-ignore="true">
|
||||
<div class="pull-right btn-group">
|
||||
<div t-attf-class="btn-group dropdown js_publish_management #{object.id and object.website_published and 'css_publish' or 'css_unpublish'}" t-att-data-id="object.id" t-att-data-object="object._name">
|
||||
<a t-attf-class="btn btn-xs btn-#{object.id and object.website_published and 'success' or 'default'}" t-att-id="'dopprod-%s' % object.id" role="button" data-toggle="dropdown">Options <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu" role="menu" t-att-aria-labelledby="'dopprod-%s' % object.id">
|
||||
<t t-raw="0"/>
|
||||
<li>
|
||||
<a href="#" class="js_publish_btn css_unpublish">Unpublish</a>
|
||||
<a href="#" class="js_publish_btn css_publish">Publish</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<t t-if="publish_edit">
|
||||
<a class="btn btn-xs btn-default" title="Edit in backend" t-att-href="'/admin/#model=%s&id=%s' % (object._name, object.id)"><span t-attf-class="glyphicon glyphicon-wrench"></span></a>
|
||||
</t>
|
||||
</div>
|
||||
</t>
|
||||
</template>
|
||||
|
||||
<template id="publish_short">
|
||||
<t t-if="editable" t-ignore="true">
|
||||
<a href="#" t-att-data-id="object.id" t-att-data-object="object._name"
|
||||
t-att-data-publish="object.id and object.website_published and 'on' or 'off'"
|
||||
class="pull-right js_publish">
|
||||
<span t-attf-class="text-success css_publish glyphicon glyphicon-ok"></span>
|
||||
<span t-attf-class="text-danger css_unpublish glyphicon glyphicon-remove-circle"></span>
|
||||
<span t-attf-class="text-muted css_published glyphicon glyphicon-ok"></span>
|
||||
<span t-attf-class="text-muted css_unpublished glyphicon glyphicon-remove-circle"></span>
|
||||
</a>
|
||||
</t>
|
||||
</template>
|
||||
|
||||
<template id="kanban">
|
||||
<t t-set="step"><t t-esc="step or 0"/></t>
|
||||
<t t-set="scope"><t t-esc="scope or 0"/></t>
|
||||
<t t-set="orderby"><t t-esc="orderby or 'name'"/></t>
|
||||
<t t-raw="website.kanban(model, domain, column, template, step=step, scope=scope, orderby=orderby)"/>
|
||||
</template>
|
||||
|
||||
<template id="kanban_contain">
|
||||
<table class="table js_kanban">
|
||||
<thead>
|
||||
<tr>
|
||||
<t t-set="width" t-value="str(round(100.0 / len(objects), 2)) + '%'"/>
|
||||
<t t-foreach="objects">
|
||||
<th t-att-width="width">
|
||||
<div t-field="column_id.name" class="text-center"></div>
|
||||
</th>
|
||||
</t>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<t t-foreach="objects">
|
||||
<td class="js_kanban_col" t-att-data-template="template" t-att-data-domain="domain" t-att-data-page_count="page_count" t-att-data-model="model" t-att-data-step="step" t-att-data-orderby="orderby">
|
||||
<t t-foreach="object_ids" t-as="object_id">
|
||||
<t t-call="#{ template }"></t>
|
||||
</t>
|
||||
<!-- pager -->
|
||||
<div t-if="1 != page_end" class="pagination pagination-centered">
|
||||
<ul>
|
||||
<li t-attf-class="prev #{'active' if page == 1 else '' }"> <a t-att-href=" '%s,%s-%s' % (kanban_url, column_id.id, (page > 1 and page-1 or 1)) ">Prev</a></li>
|
||||
<t t-foreach="range(page_start, page_end+1)" t-as="p">
|
||||
<li t-att-class=" 'active' if page == p else '' "> <a t-att-href=" '%s,%s-%s' % (kanban_url, column_id.id, p)" t-esc="p"></a></li>
|
||||
</t>
|
||||
<li t-attf-class="next #{'active' if page == page_end else '' }"> <a t-att-href=" '%s,%s-%s' % (kanban_url, column_id.id, (page < page_end and page+1 or page_end) )">Next</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</td>
|
||||
</t>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</template>
|
||||
<template id="robots">
|
||||
# robotstxt.org/
|
||||
User-agent: *
|
||||
Sitemap: <t t-esc="url_root"/>sitemap.xml
|
||||
</template>
|
||||
<template id="sitemap">
|
||||
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
|
||||
<t t-foreach="pages" t-as="page">
|
||||
<url t-esc="page['url']"/>
|
||||
</t>
|
||||
</urlset>
|
||||
</template>
|
||||
</data>
|
||||
</openerp>
|
|
@ -20,5 +20,5 @@
|
|||
##############################################################################
|
||||
|
||||
import controllers
|
||||
import website_blog
|
||||
import models
|
||||
import wizard
|
||||
|
|
|
@ -32,19 +32,19 @@ OpenERP Blog
|
|||
'author': 'OpenERP SA',
|
||||
'depends': ['knowledge', 'website_mail'],
|
||||
'data': [
|
||||
'website_blog_data.xml',
|
||||
'views/website_blog_classic.xml',
|
||||
'data/website_blog_data.xml',
|
||||
'views/website_blog_views.xml',
|
||||
'views/website_blog_templates.xml',
|
||||
# 'wizard/document_page_create_menu_view.xml',
|
||||
'wizard/document_page_show_diff_view.xml',
|
||||
'security/ir.model.access.csv',
|
||||
'security/website_mail.xml',
|
||||
'security/website_blog.xml',
|
||||
],
|
||||
'demo': [
|
||||
'website_blog_demo.xml'
|
||||
'data/website_blog_demo.xml'
|
||||
],
|
||||
'test': [
|
||||
'test/document_page_test00.yml'
|
||||
'tests/test_website_blog.yml'
|
||||
],
|
||||
'qweb': [
|
||||
'static/src/xml/*.xml'
|
||||
|
|
|
@ -35,10 +35,10 @@ class WebsiteBlog(http.Controller):
|
|||
|
||||
@website.route([
|
||||
'/blog/',
|
||||
'/blog/<int:category_id>/',
|
||||
'/blog/<int:category_id>/<int:blog_post_id>/',
|
||||
'/blog/<int:category_id>/page/<int:page>/',
|
||||
'/blog/<int:category_id>/<int:blog_post_id>/page/<int:page>/',
|
||||
'/blog/<int:blog_post_id>/',
|
||||
'/blog/<int:blog_post_id>/page/<int:page>/',
|
||||
'/blog/cat/<int:category_id>/',
|
||||
'/blog/cat/<int:category_id>/page/<int:page>/',
|
||||
'/blog/tag/',
|
||||
'/blog/tag/<int:tag_id>/',
|
||||
], type='http', auth="public")
|
||||
|
@ -90,11 +90,13 @@ class WebsiteBlog(http.Controller):
|
|||
tag = tag_obj.browse(cr, uid, tag_id, context=context)
|
||||
if category_id:
|
||||
category = category_obj.browse(cr, uid, category_id, context=context)
|
||||
|
||||
if category and blog_post_id:
|
||||
elif blog_post_id:
|
||||
blog_post = blog_post_obj.browse(cr, uid, blog_post_id, context=context)
|
||||
blog_message_ids = blog_post.website_message_ids
|
||||
else:
|
||||
category = blog_post.category_id
|
||||
category_id = category.id
|
||||
|
||||
if not blog_post_id:
|
||||
if category and tag:
|
||||
blog_posts = [cat_post for cat_post in category.blog_post_ids
|
||||
if tag_id in [post_tag.id for post_tag in cat_post.tag_ids]]
|
||||
|
@ -108,7 +110,7 @@ class WebsiteBlog(http.Controller):
|
|||
|
||||
if blog_posts:
|
||||
pager = request.website.pager(
|
||||
url="/blog/%s/" % category_id,
|
||||
url="/blog/cat/%s/" % category_id,
|
||||
total=len(blog_posts),
|
||||
page=page,
|
||||
step=self._category_post_per_page,
|
||||
|
@ -120,7 +122,7 @@ class WebsiteBlog(http.Controller):
|
|||
|
||||
if blog_post:
|
||||
pager = request.website.pager(
|
||||
url="/blog/%s/%s/" % (category_id, blog_post_id),
|
||||
url="/blog/%s/" % blog_post_id,
|
||||
total=len(blog_message_ids),
|
||||
page=page,
|
||||
step=self._post_comment_per_page,
|
||||
|
@ -138,8 +140,8 @@ class WebsiteBlog(http.Controller):
|
|||
nav[year]['months'].append(group)
|
||||
|
||||
values = {
|
||||
'categories': categories,
|
||||
'category': category,
|
||||
'categories': categories,
|
||||
'tag': tag,
|
||||
'blog_post': blog_post,
|
||||
'blog_posts': blog_posts,
|
||||
|
@ -170,13 +172,13 @@ class WebsiteBlog(http.Controller):
|
|||
]
|
||||
return simplejson.dumps(blog_post_data)
|
||||
|
||||
@website.route(['/blog/<int:category_id>/<int:blog_post_id>/post'], type='http', auth="public")
|
||||
def blog_comment(self, category_id=None, blog_post_id=None, **post):
|
||||
@website.route(['/blog/<int:blog_post_id>/post'], type='http', auth="public")
|
||||
def blog_post_comment(self, blog_post_id=None, **post):
|
||||
cr, uid, context = request.cr, request.uid, request.context
|
||||
url = request.httprequest.host_url
|
||||
request.session.body = post.get('body')
|
||||
if request.context['is_public_user']: # purpose of this ?
|
||||
return '%s/admin#action=redirect&url=%s/blog/%s/%s/post' % (url, url, category_id, blog_post_id)
|
||||
return '%s/admin#action=redirect&url=%s/blog/%s/post' % (url, url, blog_post_id)
|
||||
|
||||
if request.session.get('body') and blog_post_id:
|
||||
request.registry['blog.post'].message_post(
|
||||
|
@ -187,17 +189,24 @@ class WebsiteBlog(http.Controller):
|
|||
context=dict(context, mail_create_nosubcribe=True))
|
||||
request.session.body = False
|
||||
|
||||
return werkzeug.utils.redirect("/blog/%s/%s/?unable_editor=1" % (category_id, blog_post_id))
|
||||
return werkzeug.utils.redirect("/blog/%s/?unable_editor=1" % (blog_post_id))
|
||||
|
||||
@website.route(['/blog/<int:category_id>/new'], type='http', auth="public")
|
||||
def create_blog_post(self, category_id=None, **post):
|
||||
def blog_post_create(self, category_id=None, **post):
|
||||
cr, uid, context = request.cr, request.uid, request.context
|
||||
create_context = dict(context, mail_create_nosubscribe=True)
|
||||
blog_post_id = request.registry['blog.post'].create(
|
||||
new_blog_post_id = request.registry['blog.post'].create(
|
||||
request.cr, request.uid, {
|
||||
'category_id': category_id,
|
||||
'name': _("Blog title"),
|
||||
'content': '',
|
||||
'website_published': False,
|
||||
}, context=create_context)
|
||||
return werkzeug.utils.redirect("/blog/%s/%s/?unable_editor=1" % (category_id, blog_post_id))
|
||||
return werkzeug.utils.redirect("/blog/%s/?unable_editor=1" % (new_blog_post_id))
|
||||
|
||||
@website.route(['/blog/<int:blog_post_id>/duplicate'], type='http', auth="public")
|
||||
def blog_post_copy(self, blog_post_id=None, **post):
|
||||
cr, uid, context = request.cr, request.uid, request.context
|
||||
create_context = dict(context, mail_create_nosubscribe=True)
|
||||
new_blog_post_id = request.registry['blog.post'].copy(cr, uid, blog_post_id, {}, context=create_context)
|
||||
return werkzeug.utils.redirect("/blog/%s/?unable_editor=1" % (new_blog_post_id))
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
<!-- <data noupdate="1"> -->
|
||||
<data>
|
||||
|
||||
<!-- jump to blog at install -->
|
||||
<record id="action_open_website" model="ir.actions.act_url">
|
||||
<field name="name">Website Blogs</field>
|
||||
<field name="target">self</field>
|
||||
|
@ -17,15 +18,6 @@
|
|||
<record id="blog_category_1" model="blog.category">
|
||||
<field name="name">News</field>
|
||||
<field name="description">Presentation of new OpenERP features</field>
|
||||
<field name="template">
|
||||
Summary of the feature
|
||||
|
||||
Long explanation
|
||||
|
||||
Conclusion
|
||||
|
||||
Additional ressources
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<!-- Post-related subtypes for messaging / Chatter -->
|
||||
|
@ -41,6 +33,7 @@ Additional ressources
|
|||
<field name="default" eval="False"/>
|
||||
<field name="description">Post Published</field>
|
||||
</record>
|
||||
|
||||
<!-- Project-related subtypes for messaging / Chatter -->
|
||||
<record id="mt_blog_category_post_new" model="mail.message.subtype">
|
||||
<field name="name">New Post</field>
|
||||
|
@ -51,20 +44,11 @@ Additional ressources
|
|||
</record>
|
||||
|
||||
|
||||
<!-- Mail group for the company's jobs -->
|
||||
|
||||
<record id="blog_category_2" model="blog.category">
|
||||
<field name="name">Jobs</field>
|
||||
<field name="description">Job Announces</field>
|
||||
</record>
|
||||
|
||||
<!-- Layout add nav and footer -->
|
||||
|
||||
<template id="footer_custom" inherit_option_id="website.layout" name="Job Announces">
|
||||
<xpath expr="//footer//div[@name='info']/ul" position="inside">
|
||||
<li><a t-href="/blog/%(website_blog.blog_category_2)d/">Jobs</a></li>
|
||||
</xpath>
|
||||
</template>
|
||||
<!-- Mail group for the company's jobs -->
|
||||
<record id="blog_category_2" model="blog.category">
|
||||
<field name="name">Jobs</field>
|
||||
<field name="description">Job Announces</field>
|
||||
</record>
|
||||
|
||||
|
||||
</data>
|
|
@ -8,6 +8,12 @@
|
|||
<field name="name">functional</field>
|
||||
</record>
|
||||
<record id="blog_tag_2" model="blog.tag">
|
||||
<field name="name">technical</field>
|
||||
</record>
|
||||
<record id="blog_tag_3" model="blog.tag">
|
||||
<field name="name">website</field>
|
||||
</record>
|
||||
<record id="blog_tag_4" model="blog.tag">
|
||||
<field name="name">pos</field>
|
||||
</record>
|
||||
|
||||
|
@ -16,6 +22,7 @@
|
|||
<field name="name">OpenERP v8 New Features</field>
|
||||
<field name="category_id" ref="blog_category_1"/>
|
||||
<field name="tag_ids" eval="[(6, 0, [ref('blog_tag_1')])]"/>
|
||||
<field name="website_published" eval="True"/>
|
||||
<field name="content"><![CDATA[
|
||||
<section data-snippet-id='image-text'>
|
||||
<div class="container">
|
||||
|
@ -264,6 +271,7 @@ Think of it as an out-of-the-box solution to boost your business' productivity.
|
|||
<field name="name">Announcig a New Partnership</field>
|
||||
<field name="category_id" ref="blog_category_1"/>
|
||||
<field name="tag_ids" eval="[(6, 0, [ref('blog_tag_1')])]"/>
|
||||
<field name="website_published" eval="True"/>
|
||||
<field name="content"><![CDATA[
|
||||
<section data-snippet-id='image-text'>
|
||||
<div class="container">
|
||||
|
@ -291,7 +299,7 @@ Think of it as an out-of-the-box solution to boost your business' productivity.
|
|||
<div class="row">
|
||||
<div class="col-md-12 text-center mt16 mb32">
|
||||
<h2>
|
||||
Linked with Project Management
|
||||
OpenERP Project Management
|
||||
</h2>
|
||||
<h3 class="text-muted">Infinitely flexible. Incredibly easy to use.</h3>
|
||||
</div>
|
||||
|
@ -313,33 +321,6 @@ Think of it as an out-of-the-box solution to boost your business' productivity.
|
|||
</div>
|
||||
</div>
|
||||
</section>
|
||||
<section class="dark mt16 mb16" data-snippet-id='big-picture'>
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="col-md-12 text-center mt32 mb32">
|
||||
<h2>Work with the hardware you already have...</h2>
|
||||
</div>
|
||||
<div class="col-md-12">
|
||||
<img class="img-responsive" src="/website/static/src/img/big_picture.png" style="margin: 0 auto;"/>
|
||||
</div>
|
||||
<div class="col-md-6 col-md-offset-3 mb16 mt16">
|
||||
<p class="text-center">
|
||||
<b>No installation required</b>
|
||||
</p>
|
||||
<p class="text-center">
|
||||
OpenERP's Point of Sale introduces a super clean
|
||||
interface with no installation required that runs
|
||||
online and offline on modern hardware. Laptops,
|
||||
tablets, industrial POS, it runs on everything.
|
||||
</p>
|
||||
<p class="text-center">
|
||||
<a href="/page/website.contactus">Get more information »</a>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
]]>
|
||||
</field>
|
||||
</record>
|
|
@ -0,0 +1 @@
|
|||
import website_blog
|
|
@ -37,7 +37,6 @@ class BlogCategory(osv.Model):
|
|||
_columns = {
|
||||
'name': fields.char('Name', required=True),
|
||||
'description': fields.text('Description'),
|
||||
'template': fields.html('Template'),
|
||||
'blog_post_ids': fields.one2many(
|
||||
'blog.post', 'category_id',
|
||||
'Blogs',
|
||||
|
@ -62,7 +61,7 @@ class BlogPost(osv.Model):
|
|||
_name = "blog.post"
|
||||
_description = "Blog Post"
|
||||
_inherit = ['mail.thread']
|
||||
_order = 'name'
|
||||
_order = 'write_date DESC'
|
||||
# maximum number of characters to display in summary
|
||||
_shorten_max_char = 250
|
||||
|
||||
|
@ -170,6 +169,16 @@ class BlogPost(osv.Model):
|
|||
self.create_history(cr, uid, ids, vals, context)
|
||||
return result
|
||||
|
||||
def copy(self, cr, uid, id, default=None, context=None):
|
||||
if default is None:
|
||||
default = {}
|
||||
default.update({
|
||||
'website_message_ids': [],
|
||||
'website_published': False,
|
||||
'website_published_datetime': False,
|
||||
})
|
||||
return super(BlogPost, self).copy(cr, uid, id, default=default, context=context)
|
||||
|
||||
def img(self, cr, uid, ids, field='image_small', context=None):
|
||||
post = self.browse(cr, SUPERUSER_ID, ids[0], context=context)
|
||||
return "/website/image?model=%s&field=%s&id=%s" % ('res.users', field, post.create_uid.id)
|
||||
|
@ -177,7 +186,7 @@ class BlogPost(osv.Model):
|
|||
|
||||
class BlogPostHistory(osv.Model):
|
||||
_name = "blog.post.history"
|
||||
_description = "Document Page History"
|
||||
_description = "Blog Post History"
|
||||
_order = 'id DESC'
|
||||
_rec_name = "create_date"
|
||||
|
|
@ -19,11 +19,11 @@
|
|||
#
|
||||
##############################################################################
|
||||
|
||||
from openerp.addons.mail.tests.test_mail_base import TestMailBase
|
||||
from openerp.addons.mail.tests.common import TestMail
|
||||
from openerp.tools import mute_logger, email_split
|
||||
|
||||
|
||||
class TestControllers(TestMailBase):
|
||||
class TestControllers(TestMail):
|
||||
|
||||
def test_00(self):
|
||||
cr, uid = self.cr, self.uid
|
||||
|
|
|
@ -1,29 +1,43 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<openerp>
|
||||
<data>
|
||||
|
||||
<!-- Layout add nav and footer -->
|
||||
<template id="header_footer_custom" inherit_id="website.layout">
|
||||
<xpath expr="//header//ul[@id='top_menu']/li[@name='contactus']" position="before">
|
||||
<li><a href="/blog/%(website_blog.blog_category_1)d/">News</a></li>
|
||||
<li><a t-attf-href="/blog/cat/%(website_blog.blog_category_1)d/">News</a></li>
|
||||
</xpath>
|
||||
<xpath expr="//footer//div[@name='info']/ul" position="inside">
|
||||
<li><a href="/blog/%(website_blog.blog_category_1)d/">News</a></li>
|
||||
<li><a t-attf-href="/blog/cat/%(website_blog.blog_category_1)d/">News</a></li>
|
||||
</xpath>
|
||||
</template>
|
||||
|
||||
<template id="footer_custom" inherit_option_id="website.layout" name="Job Announces">
|
||||
<xpath expr="//footer//div[@name='info']/ul" position="inside">
|
||||
<li><a t-href="/blog/%(website_blog.blog_category_2)d/">Jobs</a></li>
|
||||
</xpath>
|
||||
</template>
|
||||
|
||||
<!-- Blog Post Summary -->
|
||||
<template id="view_blog_post_short" name="Blog Post Summary">
|
||||
<template id="blog_post_short" name="Blog Post Summary">
|
||||
<div>
|
||||
<div class="pull-right">
|
||||
<t t-call="website.publish_management">
|
||||
<t t-set="object" t-value="blog_post"/>
|
||||
<t t-set="publish_edit" t-value="True"/>
|
||||
<t t-set="publish_duplicate" t-value="'/blog/%s/duplicate' % (blog_post.id)"/>
|
||||
</t>
|
||||
</div>
|
||||
<h2 class="text-center">
|
||||
<a t-attf-href="/blog/#{blog_post.category_id.id}/#{blog_post.id}" t-field="blog_post.name"></a>
|
||||
<a t-attf-href="/blog/#{blog_post.id}" t-field="blog_post.name"></a>
|
||||
</h2>
|
||||
<p class="post-meta text-muted text-center">
|
||||
<p class="post-meta text-muted text-center" name='blog_post_data'>
|
||||
<span class="icon-calendar"> <span t-field="blog_post.create_date"/></span> &nbsp;
|
||||
<span class="icon-user"> By <span t-field="blog_post.create_uid"/> &nbsp;</span>
|
||||
<span t-if="len(blog_post.message_ids) > 0" class="icon-comment"> With
|
||||
<a t-if="len(blog_post.message_ids) <= 1" t-attf-href="/blog/#{blog_post.category_id.id}/#{blog_post.id}#comments"><t t-esc="len(blog_post.message_ids)"/> comment</a>
|
||||
<a t-if="len(blog_post.message_ids) > 1" t-attf-href="/blog/#{blog_post.category_id.id}/#{blog_post.id}#comments"><t t-esc="len(blog_post.message_ids)"/> comments</a>
|
||||
<span t-if="len(blog_post.message_ids) > 0" class="icon-comment">
|
||||
<a t-attf-href="/blog/#{blog_post.id}/#comment">
|
||||
<t t-if="len(blog_post.message_ids) <= 1" ><t t-esc="len(blog_post.message_ids)"/> comment</t>
|
||||
<t t-if="len(blog_post.message_ids) > 1"><t t-esc="len(blog_post.message_ids)"/> comments</t>
|
||||
</a>
|
||||
</span>
|
||||
</p>
|
||||
<div t-field="blog_post.shortened_content" class="blog_content"/>
|
||||
|
@ -33,43 +47,56 @@
|
|||
</template>
|
||||
|
||||
<!-- Options: Blog Post Summary: hide author -->
|
||||
<template id="view_blog_post_short_author" inherit_option_id="website_blog.view_blog_post_short" name="Hide Authors">
|
||||
<template id="opt_blog_post_short_author" name="Hide Authors"
|
||||
inherit_option_id="website_blog.blog_post_short">
|
||||
<xpath expr="//span[@class='icon-user']" position="attributes">
|
||||
<attribute name="class">hidden</attribute>
|
||||
</xpath>
|
||||
</template>
|
||||
|
||||
<!-- Options: Blog Post Summary: show category -->
|
||||
<template id="view_blog_post_short_category" inherit_option_id="website_blog.view_blog_post_short" name="Show Blog Name">
|
||||
<template id="opt_blog_post_short_category" name="Blog Name"
|
||||
inherit_option_id="website_blog.blog_post_short">
|
||||
<xpath expr="//span[@class='icon-user']" position="after">
|
||||
<span class="icon-folder-open"> In <span t-field="blog_post.category_id"/> &nbsp;</span>
|
||||
</xpath>
|
||||
</template>
|
||||
|
||||
<!-- Option: Blog Post Summary: show tags -->
|
||||
<template id="opt_blog_post_short_tags" name="Tags"
|
||||
inherit_option_id="website_blog.blog_post_short" inherit_id="website_blog.blog_post_short">
|
||||
<xpath expr="//p[@name='blog_post_data']" position="after">
|
||||
<p class="post-meta text-muted text-center" t-if="len(blog_post.tag_ids)">
|
||||
<span class="icon-tags"/>
|
||||
<t t-foreach="blog_post.tag_ids" t-as="tag">
|
||||
<a t-attf-href="/blog/tag/#{tag.id}" t-esc="tag.name"/> &nbsp;
|
||||
</t>
|
||||
</p>
|
||||
</xpath>
|
||||
</template>
|
||||
|
||||
<!-- Blog Post Complete -->
|
||||
<template id="view_blog_post" name="Blog Post">
|
||||
<template id="blog_post_complete" name="Blog Post">
|
||||
<div>
|
||||
<t t-call="website.publish_management">
|
||||
<t t-set="object" t-value="blog_post"/>
|
||||
<t t-set="publish_edit" t-value="True"/>
|
||||
<t t-set="publish_duplicate" t-value="'/blog/%s/duplicate' % (blog_post.id)"/>
|
||||
</t>
|
||||
</div><div class="clearfix"/>
|
||||
</div>
|
||||
<div class="clearfix"/>
|
||||
|
||||
<h1 class="text-center" t-field="blog_post.name"/>
|
||||
<p class="post-meta text-muted text-center">
|
||||
<p class="post-meta text-muted text-center" name="blog_post_data">
|
||||
<span class="icon-calendar"> <span t-field="blog_post.create_date"/></span> &nbsp;
|
||||
<span class="icon-user"> By <span t-field="blog_post.create_uid"/> &nbsp;</span>
|
||||
<span t-if="len(blog_post.message_ids) > 0" class="icon-comment"> With
|
||||
<a t-if="len(blog_post.message_ids) <= 1" t-attf-href="#comments"><t t-esc="len(blog_post.message_ids)"/> comment</a>
|
||||
<a t-if="len(blog_post.message_ids) > 1" t-attf-href="#comments"><t t-esc="len(blog_post.message_ids)"/> comments</a>
|
||||
<a t-attf-href="#comments">
|
||||
<t t-if="len(blog_post.message_ids) <= 1" ><t t-esc="len(blog_post.message_ids)"/> comment</t>
|
||||
<t t-if="len(blog_post.message_ids) > 1"><t t-esc="len(blog_post.message_ids)"/> comments</t>
|
||||
</a>
|
||||
</span>
|
||||
</p>
|
||||
<p class="post-meta text-muted text-center" t-if="len(blog_post.tag_ids)">
|
||||
<span class="icon-tags"/>
|
||||
<t t-foreach="blog_post.tag_ids" t-as="tag">
|
||||
<a t-attf-href="/blog/tag/#{tag.id}" t-esc="tag.name"/> &nbsp;
|
||||
</t>
|
||||
</p>
|
||||
|
||||
<div t-field="blog_post.content" class="mt16"/>
|
||||
<hr class="mb32"/>
|
||||
|
@ -102,77 +129,102 @@
|
|||
</template>
|
||||
|
||||
<!-- Options: Blog Post: user can reply -->
|
||||
<template id="view_blog_post_author" inherit_option_id="website_blog.view_blog_post" name="Hide Authors">
|
||||
<template id="opt_blog_post_complete_comment" name="Comment Form"
|
||||
inherit_option_id="website_blog.blog_post_complete" inherit_id="website_blog.blog_post_complete">
|
||||
<xpath expr="//ul[last()]" position="after">
|
||||
<section groups="group_website_blog_reply" class="mb32">
|
||||
<h4>Leave a Comment</h4>
|
||||
<form id="comment" t-attf-action="/blog/#{blog_post.category_id.id}/#{blog_post.id}/post#post"
|
||||
method="POST">
|
||||
<img class="img pull-left img-rounded" t-att-src="'/website/image?model=res.partner&field=image_small&id='+str(user_id.partner_id.id)" style="width: 50px; margin-right: 10px;"/>
|
||||
<div class="pull-left mb32" style="width: 75%%">
|
||||
<textarea rows="3" class="form-control" placeholder="Write a comment..."></textarea>
|
||||
<button type="submit" class="btn btn-danger mt8">Post</button>
|
||||
</div>
|
||||
</form>
|
||||
</section>
|
||||
<section groups="group_website_blog_reply" class="mb32">
|
||||
<h4>Leave a Comment</h4>
|
||||
<form id="comment" t-attf-action="/blog/#{blog_post.id}/post#post"
|
||||
method="POST">
|
||||
<img class="img pull-left img-rounded" t-att-src="'/website/image?model=res.partner&field=image_small&id='+str(user_id.partner_id.id)" style="width: 50px; margin-right: 10px;"/>
|
||||
<div class="pull-left mb32" style="width: 75%%">
|
||||
<textarea rows="3" class="form-control" placeholder="Write a comment..."></textarea>
|
||||
<button type="submit" class="btn btn-danger mt8">Post</button>
|
||||
</div>
|
||||
</form>
|
||||
</section>
|
||||
</xpath>
|
||||
</template>
|
||||
|
||||
<!-- Options: Blog Post: hide author -->
|
||||
<template id="view_blog_post_author" inherit_option_id="website_blog.view_blog_post" name="Hide Authors">
|
||||
<template id="opt_blog_post_complete_author" name="Hide Authors"
|
||||
inherit_option_id="website_blog.blog_post_complete">
|
||||
<xpath expr="//span[@class='icon-user']" position="attributes">
|
||||
<attribute name="class">hidden</attribute>
|
||||
</xpath>
|
||||
</template>
|
||||
|
||||
<!-- Options: Blog Post: show category -->
|
||||
<template id="view_blog_post_show_category" inherit_option_id="website_blog.view_blog_post" name="Show Blog Name">
|
||||
<template id="opt_blog_post_complete_category" name="Blog Name"
|
||||
inherit_option_id="website_blog.blog_post_complete">
|
||||
<xpath expr="//span[@class='icon-user']" position="after">
|
||||
<span class="icon-folder-open"> In <span t-field="blog_post.category_id"/> &nbsp;</span>
|
||||
</xpath>
|
||||
</template>
|
||||
|
||||
<!-- Options: Blog Post: show tags -->
|
||||
<template id="opt_blog_post_complete_tags" name="Tags"
|
||||
inherit_option_id="website_blog.blog_post_complete" inherit_id="website_blog.blog_post_complete">
|
||||
<xpath expr="//p[@name='blog_post_data']" position="after">
|
||||
<p class="post-meta text-muted text-center" t-if="len(blog_post.tag_ids)">
|
||||
<span class="icon-tags"/>
|
||||
<t t-foreach="blog_post.tag_ids" t-as="tag">
|
||||
<a t-attf-href="/blog/tag/#{tag.id}" t-esc="tag.name"/> &nbsp;
|
||||
</t>
|
||||
</p>
|
||||
</xpath>
|
||||
</template>
|
||||
|
||||
<!-- Page -->
|
||||
<template id="index" name="Blog" page="True">
|
||||
<t t-call="website.layout">
|
||||
<t t-set="head">
|
||||
<script type="text/javascript" src="/website_blog/static/src/js/website_blog.js"></script>
|
||||
<link rel='stylesheet' href='/website_blog/static/src/css/website_blog.css'/>
|
||||
</t>
|
||||
<div id="wrap">
|
||||
<div class="container mt16 js_website_blog">
|
||||
<div class="row">
|
||||
<div class="col-lg-8 col-sm-9" t-if="not blog_post">
|
||||
<t t-foreach="blog_posts" t-as="blog_post" data-publish="">
|
||||
<t t-call="website_blog.view_blog_post_short"/>
|
||||
</t>
|
||||
<div class="pull-right" t-call="website.pager"/>
|
||||
</div>
|
||||
<div class="col-md-9 col-lg-8" t-if="blog_post">
|
||||
<t t-call="website_blog.view_blog_post">
|
||||
<t t-set="blog_post" t-value="blog_post"/>
|
||||
</t>
|
||||
<t t-set="head">
|
||||
<script type="text/javascript" src="/website_blog/static/src/js/website_blog.js"></script>
|
||||
<link rel='stylesheet' href='/website_blog/static/src/css/website_blog.css'/>
|
||||
</t>
|
||||
<div id="wrap">
|
||||
<div class="container mt16 js_website_blog">
|
||||
<div class="row">
|
||||
<div class="col-lg-12 col-sm-12" t-if="not blog_post" id="blog_post">
|
||||
<t t-if="category and editable">
|
||||
<div class="row">
|
||||
<a t-attf-href="/blog/#{category.id}/new" class="btn btn-primary pull-right">New Blog Post</a>
|
||||
</div>
|
||||
</t>
|
||||
<t t-foreach="blog_posts" t-as="blog_post" data-publish="">
|
||||
<t t-call="website_blog.blog_post_short"/>
|
||||
</t>
|
||||
<div class="pull-right" t-call="website.pager"/>
|
||||
</div>
|
||||
<div class="col-lg-12 col-sm-12" t-if="blog_post" id="blog_posts_summary">
|
||||
<t t-call="website_blog.blog_post_complete">
|
||||
<t t-set="blog_post" t-value="blog_post"/>
|
||||
</t>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</t>
|
||||
</template>
|
||||
|
||||
<!-- Option: right column -->
|
||||
<template id="blog_right_column" inherit_id="website_blog.index" inherit_option_id="website_blog.index" name="Right Column">
|
||||
<!-- Option: Blog: Right Column -->
|
||||
<template id="blog_right_column" name="Right Column"
|
||||
inherit_option_id="website_blog.index" inherit_id="website_blog.index">
|
||||
<xpath expr="//div[@class='row']" position="inside">
|
||||
<div class="col-sm-3 hidden-xs col-lg-offset-1 mb32" id="right_column">
|
||||
<t t-if="category and editable">
|
||||
<a t-attf-href="/blog/#{category.id}/new" class="btn btn-primary pull-right">New Blog Post</a>
|
||||
</t>
|
||||
<div class="clearfix mb48"/>
|
||||
<div class="col-lg-3 col-sm-3 hidden-xs col-lg-offset-1 mb32" id="right_column">
|
||||
</div>
|
||||
</xpath>
|
||||
<xpath expr="//div[@id='blog_post']" position="attributes">
|
||||
<attribute name="class">col-lg-8 col-sm-8</attribute>
|
||||
</xpath>
|
||||
<xpath expr="//div[@id='blog_posts_summary']" position="attributes">
|
||||
<attribute name="class">col-lg-8 col-sm-8</attribute>
|
||||
</xpath>
|
||||
</template>
|
||||
|
||||
<!-- Option: Right Column: archives -->
|
||||
<template id="blog_history" inherit_id="website_blog.blog_right_column" inherit_option_id="website_blog.blog_right_column" name="Archives">
|
||||
<template id="opt_blog_rc_history" name="Archives"
|
||||
inherit_option_id="website_blog.blog_right_column" inherit_id="website_blog.blog_right_column">
|
||||
<xpath expr="//div[@id='right_column']" position="inside">
|
||||
<section>
|
||||
<h4>Archives</h4>
|
||||
|
@ -194,7 +246,8 @@
|
|||
</template>
|
||||
|
||||
<!-- Option: Right Column: about us -->
|
||||
<template id="blog_aboutus" inherit_option_id="website_blog.blog_right_column" inherit_id="website_blog.blog_right_column" name="About" priority="4">
|
||||
<template id="opt_blog_rc_about_us" name="About Us" priority="4"
|
||||
inherit_option_id="website_blog.blog_right_column" inherit_id="website_blog.blog_right_column">
|
||||
<xpath expr="//div[@id='right_column']" position="inside">
|
||||
<section class="mb16">
|
||||
<h4>About us</h4>
|
||||
|
@ -210,7 +263,8 @@
|
|||
</template>
|
||||
|
||||
<!-- Option: Right Column: follow us -->
|
||||
<template id="blog_followus" inherit_option_id="website_blog.blog_right_column" inherit_id="website_blog.blog_right_column" name="Follow us" priority="2">
|
||||
<template id="opt_blog_rc_follow_us" name="Follow us" priority="2"
|
||||
inherit_option_id="website_blog.blog_right_column" inherit_id="website_blog.blog_right_column">
|
||||
<xpath expr="//div[@id='right_column']" position="inside">
|
||||
<section class="mb16">
|
||||
<h4>Follow us</h4>
|
||||
|
@ -238,8 +292,9 @@
|
|||
</xpath>
|
||||
</template>
|
||||
|
||||
<!-- Option: Right Column: categories + category in blog post -->
|
||||
<template id="blog_categories" inherit_option_id="website_blog.blog_right_column" name="Other Blogs" priority="6">
|
||||
<!-- Option: Right Column: categories -->
|
||||
<template id="opt_blog_rc_categories" name="Other Blogs" priority="6"
|
||||
inherit_option_id="website_blog.blog_right_column">
|
||||
<xpath expr="//div[@id='right_column']" position="inside">
|
||||
<section class="mb16">
|
||||
<h4>Other Blogs</h4>
|
||||
|
@ -256,5 +311,5 @@
|
|||
</xpath>
|
||||
</template>
|
||||
|
||||
</data>
|
||||
</data>
|
||||
</openerp>
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
<openerp>
|
||||
<data>
|
||||
<menuitem name="Knowledge" id="knowledge.menu_document"/>
|
||||
<menuitem name="Pages" id="menu_wiki" parent="knowledge.menu_document" sequence="20" />
|
||||
<menuitem name="Blog Posts" id="menu_wiki" parent="knowledge.menu_document" sequence="20" />
|
||||
|
||||
<!-- Category views -->
|
||||
<record model="ir.ui.view" id="view_blog_category_list">
|
||||
|
@ -23,7 +23,6 @@
|
|||
<group>
|
||||
<field name="name"/>
|
||||
<field name="description"/>
|
||||
<field name="template" widget="html"/>
|
||||
</group>
|
||||
</sheet>
|
||||
<div class="oe_chatter">
|
||||
|
@ -60,14 +59,12 @@
|
|||
<group>
|
||||
<field name="category_id" string="Category"/>
|
||||
</group>
|
||||
<group>
|
||||
<field name="write_uid" groups="base.group_no_one" context="{'default_groups_ref': ['base.group_user', 'base.group_partner_manager', 'base.group_document_user']}"/>
|
||||
<field name="write_date" groups="base.group_no_one"/>
|
||||
<field name="menu_id" groups="base.group_no_one"/>
|
||||
<field name="content" placeholder="e.g. Once upon a time..." widget="html"/>
|
||||
<group string="Technical" groups="base.group_no_one">
|
||||
<field name="write_uid" context="{'default_groups_ref': ['base.group_user', 'base.group_partner_manager', 'base.group_document_user']}"/>
|
||||
<field name="write_date"/>
|
||||
<field name="menu_id"/>
|
||||
</group>
|
||||
<div class="oe_document_page">
|
||||
<field name="content" placeholder="e.g. Once upon a time..." widget="html"/>
|
||||
</div>
|
||||
</sheet>
|
||||
<div class="oe_chatter">
|
||||
<field name="message_follower_ids" widget="mail_followers" groups="base.group_user"/>
|
||||
|
@ -107,7 +104,7 @@
|
|||
</p>
|
||||
</field>
|
||||
</record>
|
||||
<menuitem id="menu_page" parent="menu_wiki" name="Pages" action="action_blog_post" sequence="10"/>
|
||||
<menuitem id="menu_page" parent="menu_wiki" name="Blog Posts" action="action_blog_post" sequence="10"/>
|
||||
|
||||
<record model="ir.actions.act_window" id="action_blog_category">
|
||||
<field name="name">Category</field>
|
|
@ -20,4 +20,4 @@
|
|||
##############################################################################
|
||||
|
||||
import controllers
|
||||
import event
|
||||
import models
|
||||
|
|
|
@ -13,13 +13,14 @@ Online Events
|
|||
'author': 'OpenERP SA',
|
||||
'depends': ['website', 'website_mail', 'event_sale', 'website_sale'],
|
||||
'data': [
|
||||
'event_data.xml',
|
||||
'data/event_data.xml',
|
||||
'views/website_event.xml',
|
||||
'security/ir.model.access.csv',
|
||||
'security/website_event.xml',
|
||||
'event_demo.xml',
|
||||
],
|
||||
'qweb': ['static/src/xml/*.xml'],
|
||||
'demo': [],
|
||||
'demo': [
|
||||
'data/event_demo.xml'
|
||||
],
|
||||
'installable': True,
|
||||
}
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
import event
|
|
@ -19,11 +19,11 @@
|
|||
#
|
||||
##############################################################################
|
||||
|
||||
from openerp.addons.mail.tests.test_mail_base import TestMailBase
|
||||
from openerp.addons.mail.tests.common import TestMail
|
||||
from openerp.tools import mute_logger, email_split
|
||||
|
||||
|
||||
class TestControllers(TestMailBase):
|
||||
class TestControllers(TestMail):
|
||||
|
||||
def test_00(self):
|
||||
cr, uid = self.cr, self.uid
|
||||
|
|
|
@ -20,5 +20,4 @@
|
|||
##############################################################################
|
||||
|
||||
import controllers
|
||||
import mail_message
|
||||
import mail_thread
|
||||
import models
|
||||
|
|
|
@ -0,0 +1,2 @@
|
|||
import mail_message
|
||||
import mail_thread
|
|
@ -19,12 +19,12 @@
|
|||
#
|
||||
##############################################################################
|
||||
|
||||
from openerp.addons.mail.tests.test_mail_base import TestMailBase
|
||||
from openerp.addons.mail.tests.common import TestMail
|
||||
from openerp.addons.website_mail.controllers.main import WebsiteMail
|
||||
from openerp.tools import mute_logger, email_split
|
||||
|
||||
|
||||
class TestControllers(TestMailBase):
|
||||
class TestControllers(TestMail):
|
||||
|
||||
def test_00_subscribe(self):
|
||||
# from openerp.addons.web.http import request
|
||||
|
|
|
@ -3,15 +3,18 @@
|
|||
<data>
|
||||
|
||||
<template id="follow">
|
||||
<a href="#" t-att-data-id="object.id" t-att-data-object="object._name" t-att-data-follow="object.id and object.message_is_follower and 'on' or 'off'" class="pull-right js_follow" t-if="editable" t-ignore="true">
|
||||
<span t-attf-class="label label-success css_follow">Follow</span>
|
||||
<span t-attf-class="label label-danger css_unfollow">Unfollow</span>
|
||||
<span t-attf-class="label label-success css_followed">Following</span>
|
||||
<span t-attf-class="label label-danger css_unfollowed">Not Following</span>
|
||||
</a>
|
||||
<input type="email" name="email" class="js_follow_email css_unfollowed_email"
|
||||
t-att-value="email"
|
||||
t-att-placeholder="email or 'Email Address'"/>
|
||||
<div name="follow">
|
||||
<a href="#" t-att-data-id="object.id" t-att-data-object="object._name" t-att-data-follow="object.id and object.message_is_follower and 'on' or 'off'"
|
||||
class="pull-right js_follow" t-if="editable" t-ignore="true">
|
||||
<span t-attf-class="label label-success css_follow">Follow</span>
|
||||
<span t-attf-class="label label-danger css_unfollow">Unfollow</span>
|
||||
<span t-attf-class="label label-success css_followed">Following</span>
|
||||
<span t-attf-class="label label-danger css_unfollowed">Not Following</span>
|
||||
</a>
|
||||
<input type="email" name="email" class="js_follow_email css_unfollowed_email"
|
||||
t-att-value="email"
|
||||
t-att-placeholder="email or 'Email Address'"/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<template id="website.layout" inherit_id="website.layout">
|
||||
|
|
|
@ -4,6 +4,9 @@ import openerp
|
|||
from openerp.addons.web import http
|
||||
from openerp.addons.web.http import request
|
||||
from openerp.addons.website.models import website
|
||||
from openerp.tools.translate import _
|
||||
|
||||
import urllib
|
||||
|
||||
|
||||
class WebsiteMembership(http.Controller):
|
||||
|
@ -19,21 +22,43 @@ class WebsiteMembership(http.Controller):
|
|||
cr, uid, context = request.cr, request.uid, request.context
|
||||
product_obj = request.registry['product.product']
|
||||
membership_line_obj = request.registry['membership.membership_line']
|
||||
post_name = post.get('search', '')
|
||||
partner_obj = request.registry['res.partner']
|
||||
post_name = post.get('name', '')
|
||||
post_country_id = int(post.get('country_id', '0'))
|
||||
|
||||
# format displayed membership lines domain
|
||||
# base domain for groupby / searches
|
||||
if request.context['is_public_user']:
|
||||
line_domain = [('partner.website_published', '=', True)]
|
||||
base_line_domain = [('partner.website_published', '=', True)]
|
||||
else:
|
||||
line_domain = [(1, '=', 1)]
|
||||
base_line_domain = [(1, '=', 1)]
|
||||
if membership_id:
|
||||
line_domain += [('membership_id', '=', membership_id)]
|
||||
base_line_domain += [('membership_id', '=', membership_id)]
|
||||
membership = product_obj.browse(cr, openerp.SUPERUSER_ID, membership_id, context=context)
|
||||
else:
|
||||
membership = ''
|
||||
if post_name:
|
||||
line_domain += ['|', ('partner.name', 'ilike', "%%%s%%" % post_name), ('partner.website_description', 'ilike', "%%%s%%" % post_name)]
|
||||
base_line_domain += ['|', ('partner.name', 'ilike', "%%%s%%" % post_name), ('partner.website_description', 'ilike', "%%%s%%" % post_name)]
|
||||
|
||||
# group by country, based on all customers (base domain)
|
||||
membership_line_ids = membership_line_obj.search(cr, uid, base_line_domain, context=context)
|
||||
countries = partner_obj.read_group(
|
||||
cr, uid, [('member_lines', 'in', membership_line_ids)], ["id", "country_id"],
|
||||
groupby="country_id", orderby="country_id", context=request.context)
|
||||
countries_total = sum([country_dict['country_id_count'] for country_dict in countries])
|
||||
countries.insert(0, {
|
||||
'country_id_count': countries_total,
|
||||
'country_id': (0, _("All Countries"))
|
||||
})
|
||||
|
||||
# displayed membership lines
|
||||
line_domain = list(base_line_domain)
|
||||
if post_country_id:
|
||||
line_domain += [('partner.country_id', '=', post_country_id)]
|
||||
|
||||
membership_line_ids = membership_line_obj.search(cr, uid, line_domain, context=context)
|
||||
membership_lines = membership_line_obj.browse(cr, uid, membership_line_ids, context=context)
|
||||
google_map_partner_ids = ",".join([str(m.partner.id) for m in membership_lines])
|
||||
partner_ids = [m.partner and m.partner.id for m in membership_lines]
|
||||
google_map_partner_ids = ",".join([str(pid) for pid in partner_ids])
|
||||
|
||||
# format domain for group_by and memberships
|
||||
membership_domain = [('membership', '=', True)]
|
||||
|
@ -44,11 +69,14 @@ class WebsiteMembership(http.Controller):
|
|||
pager = request.website.pager(url="/members/", total=len(membership_line_ids), page=page, step=self._references_per_page, scope=7, url_args=post)
|
||||
|
||||
values = {
|
||||
'membership_line_ids': membership_lines,
|
||||
'membership_ids': memberships,
|
||||
'membership_lines': membership_lines,
|
||||
'memberships': memberships,
|
||||
'membership': membership,
|
||||
'countries': countries,
|
||||
'google_map_partner_ids': google_map_partner_ids,
|
||||
'pager': pager,
|
||||
'name_search': post_name,
|
||||
'post': post,
|
||||
'search': "?%s" % urllib.urlencode(post),
|
||||
}
|
||||
return request.website.render("website_membership.index", values)
|
||||
|
||||
|
|
|
@ -32,44 +32,47 @@
|
|||
Looking for a partner ?<br/>
|
||||
<small>Find an association member</small>
|
||||
</h1>
|
||||
<div class="col-md-4" id="membership_left">
|
||||
<h3>Associations</h3>
|
||||
<ul class="nav">
|
||||
<t t-foreach="membership_ids" t-as="membership_id">
|
||||
<li><a t-href="/members/association/#{ membership_id.id }"><t t-esc="membership_id.name"/></a></li>
|
||||
<div class="col-md-4" id="left_column">
|
||||
<ul class="nav nav-pills nav-stacked mt16">
|
||||
<li class="nav-header"><h3>Associations</h3></li>
|
||||
<li t-att-class="membership and '' or 'active'"><a t-href="/members/">All</a></li>
|
||||
<t t-foreach="memberships" t-as="membership_id">
|
||||
<li t-att-class="membership and membership_id.id == membership.id and 'active' or ''">
|
||||
<a t-href="/members/association/#{ membership_id.id }"><t t-esc="membership_id.name"/></a>
|
||||
</li>
|
||||
</t>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="col-md-8" id="ref_content">
|
||||
<div class='navbar'>
|
||||
<div>
|
||||
<t t-call="website.pager">
|
||||
<t t-set="classname">pull-left</t>
|
||||
</t>
|
||||
<form t-action="/members/" method="get" class="navbar-search pull-right pagination form-inline">
|
||||
<div class="form-group">
|
||||
<input type="text" name="search" class="search-query col-md-2 mt4 form-control" placeholder="Search" t-att-value="name_search"/>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<t t-call="website.pager">
|
||||
<t t-set="classname">pull-left</t>
|
||||
</t>
|
||||
<form t-action="/members/" method="get" class="navbar-search pull-right pagination form-inline">
|
||||
<div class="form-group">
|
||||
<input type="text" name="name" class="search-query col-md-2 mt4 form-control" placeholder="Search" t-att-value="post.get('name', '')"/>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<div>
|
||||
<t t-if="not membership_line_ids">
|
||||
<t t-if="not membership_lines">
|
||||
<p>No result found.</p>
|
||||
</t>
|
||||
<t t-foreach="membership_line_ids" t-as="membership_line_id">
|
||||
<t t-if="membership_id != membership_line_id.membership_id.id">
|
||||
<t t-set="membership_id" t-value="membership_line_id.membership_id.id"/>
|
||||
<t t-foreach="membership_lines" t-as="membership_line_id">
|
||||
<t t-if="current_membership_id != membership_line_id.membership_id.id">
|
||||
<t t-set="current_membership_id" t-value="membership_line_id.membership_id.id"/>
|
||||
<h3 class="text-center"><span t-field="membership_line_id.membership_id"/></h3>
|
||||
</t>
|
||||
<t t-set="partner" t-value="membership_line_id.partner"/>
|
||||
<div class="media thumbnail" data-publish="">
|
||||
<t t-call="website.publish_management"><t t-set="object" t-value="partner"/></t>
|
||||
<div class="media" data-publish="">
|
||||
<t t-call="website.publish_management">
|
||||
<t t-set="object" t-value="partner"/>
|
||||
</t>
|
||||
<a class="pull-left" t-href="/members/#{ partner.id }/">
|
||||
<img class="media-object" t-att-src="partner.img('image_small')"/>
|
||||
</a>
|
||||
<div class="media-body" style="min-height: 64px;">
|
||||
<a class="media-heading" t-href="/members/#{ partner.id }/"><span t-field="partner.parent_id"/> <span t-field="partner.name"/></a> - <span t-field="membership_line_id.membership_id"/>
|
||||
<a class="media-heading" t-href="/members/#{ partner.id }/"><span t-field="partner.parent_id"/> <span t-field="partner.name"/></a>
|
||||
<div t-field="partner.website_short_description"/>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -80,15 +83,34 @@
|
|||
</t>
|
||||
</template>
|
||||
|
||||
<template id="ref_country" inherit_id="website_membership.index" inherit_option_id="website_membership.index" name="Left World Map">
|
||||
<xpath expr="//div[@id='membership_left']/ul" position="after">
|
||||
<div>
|
||||
<h3>World Map</h3>
|
||||
<!-- Option: index: Left Google Map -->
|
||||
<template id="opt_index_country" name="Location"
|
||||
inherit_option_id="website_membership.index" inherit_id="website_membership.index">
|
||||
<xpath expr="//div[@id='left_column']/ul[last()]" position="after">
|
||||
<ul class="nav nav-pills nav-stacked mt16">
|
||||
<li class="nav-header"><h3>Location</h3></li>
|
||||
<t t-foreach="countries">
|
||||
<li t-if="country_id" t-att-class="post.get('country_id', '0') == str(country_id and country_id[0]) and 'active' or ''">
|
||||
<a t-href="/members/#{ search }&country_id=#{ country_id[0] }"><t t-esc="country_id[1]"/>
|
||||
<span class="badge pull-right"><t t-esc="country_id_count"/></span>
|
||||
</a>
|
||||
</li>
|
||||
</t>
|
||||
</ul>
|
||||
</xpath>
|
||||
</template>
|
||||
|
||||
<!-- Option: index: Left Google Map -->
|
||||
<template id="opt_index_google_map" name="Left World Map"
|
||||
inherit_option_id="website_membership.index" inherit_id="website_membership.index">
|
||||
<xpath expr="//div[@id='left_column']/ul[last()]" position="after">
|
||||
<ul class="nav nav-pills nav-stacked mt16">
|
||||
<li class="nav-header"><h3>World Map</h3></li>
|
||||
<ul class="nav">
|
||||
<iframe t-attf-src="/google_map/?width=320&height=240&partner_ids=#{ google_map_partner_ids }&partner_url=/members/"
|
||||
style="width:320px; height:260px; border:0; padding:0; margin:0;"></iframe>
|
||||
</ul>
|
||||
</div>
|
||||
</ul>
|
||||
</xpath>
|
||||
</template>
|
||||
|
||||
|
|
|
@ -1,4 +1,2 @@
|
|||
import controllers
|
||||
import website_styles
|
||||
import product
|
||||
import website_sale
|
||||
import models
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
import website_styles
|
||||
import product
|
||||
import website_sale
|
Before Width: | Height: | Size: 283 KiB |
|
@ -338,15 +338,16 @@
|
|||
<br/>
|
||||
</t>
|
||||
|
||||
<div class="product_price">
|
||||
<b>
|
||||
<div class="product_price mt16">
|
||||
<h4>
|
||||
<b><span class="oe_price" t-esc="product.product_variant_ids[0].price" /> €</b>
|
||||
|
||||
<t t-if="product.product_variant_ids[0].lst_price != product.product_variant_ids[0].price">
|
||||
<span class="text-danger" style="text-decoration: line-through;">
|
||||
&nbsp;&nbsp;<small class="text-danger" style="text-decoration: line-through;">
|
||||
<t t-esc="product.product_variant_ids[0].lst_price" /> €
|
||||
</span>&nbsp;
|
||||
</small>
|
||||
</t>
|
||||
<h4><b><span class="oe_price" t-esc="product.product_variant_ids[0].price" /> €</b></h4>
|
||||
</b>
|
||||
</h4>
|
||||
</div>
|
||||
<button class="btn btn-primary btn-lg mt8">Add to Cart</button>
|
||||
<hr t-if="product.description_sale"/>
|
||||
|
|
|
@ -33,7 +33,7 @@
|
|||
</div>
|
||||
</div>
|
||||
</section>
|
||||
<section data-snippet-id="image-text" class="mt16 mb16">
|
||||
<section data-snippet-id="image-text" class="mt16">
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="col-md-5 col-md-offset-1">
|
||||
|
@ -64,16 +64,34 @@
|
|||
<section data-snippet-id="text-image" class="mt16 mb16">
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="col-md-5 col-md-offset-1 mt64">
|
||||
<h3>Why you'll love an Bose Mini Bluetooth Speaker.</h3>
|
||||
<div class="col-md-5 col-md-offset-1 mt32">
|
||||
<h3>Bose Mini Bluetooth Speaker.</h3>
|
||||
<p>
|
||||
The Bose® SoundLink® mini is Bose's smallest portable Bluetooth speaker. Its ultra-compact size fits in the
|
||||
palm of your hand, yet gives you full, natural sound wirelessly from your iPhone, iPad, or iPod. Grab it and go
|
||||
full-featured. It can do just about everything and
|
||||
experience music just about anywhere.
|
||||
</p>
|
||||
|
||||
<div class="panel panel-default mt48" data-snippet-id="panel">
|
||||
<div class="panel-heading">
|
||||
<h3 class="panel-title">Characteristics</h3>
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
<ul>
|
||||
<li>Sleek, compact design</li>
|
||||
<li>Efficient, high-quality audio</li>
|
||||
<li>Remote control for power, volume, track seek</li>
|
||||
<li>Auxiliary input for portable devices</li>
|
||||
<li>Universal iPod docking station fits most iPod/iPhone models</li>
|
||||
<li>Charges iPod/iPhone</li>
|
||||
<li>Volume control on main system</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div class="col-md-5 mt16 mb16">
|
||||
<div class="col-md-4 mt16 mb16 col-md-offset1">
|
||||
<img class="img img-responsive" src="/website_sale/static/src/img/play_where_you_play.jpg"/>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -82,7 +100,7 @@
|
|||
<section data-snippet-id="text-image" class="mt16 mb16 dark">
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="col-md-5 col-md-offset-1">
|
||||
<div class="col-md-5 col-md-offset-1 mt16">
|
||||
<h2>Plays where you play</h2>
|
||||
<p>
|
||||
The SoundLink® Mini speaker is small and light enough
|
||||
|
@ -94,13 +112,13 @@
|
|||
<p>
|
||||
The rechargeable lithium-ion battery delivers up to seven hours of playtime.
|
||||
And at home, you can listen even longer—the charging cradle lets
|
||||
you listen while it charges. An empty battery usually fully recharges in three hours.
|
||||
you listen while it charges.
|
||||
</p>
|
||||
</div>
|
||||
<div class="col-md-5 col-md-offset-1 mt32">
|
||||
<img class="img img-responsive" src="/website_sale/static/src/img/bluetooth.jpg"/>
|
||||
<img class="img img-responsive" src="/website_sale/static/src/img/more_features.png"/>
|
||||
</div>
|
||||
<div class="col-md-5 col-md-offset-1">
|
||||
<div class="col-md-5 col-md-offset-4 text-center mb16 mt16">
|
||||
<h3>Bluetooth connectivity</h3>
|
||||
<p>
|
||||
The speaker has a range of about 30 feet, so you can enjoy
|
||||
|
@ -116,26 +134,26 @@
|
|||
<section data-snippet-id="text-image" class="mt16 mb16">
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="col-md-5 col-md-offset-1 mt64 mb16">
|
||||
<img class="img img-responsive" src="/website_sale/static/src/img/more_features.png"/>
|
||||
<div class="col-md-5 col-md-offset-1 mt32 mb16">
|
||||
<img class="img img-responsive" src="/website_sale/static/src/img/bluetooth.jpg"/>
|
||||
</div>
|
||||
<div class="col-md-5 mt32">
|
||||
<div class="col-md-5 mt16">
|
||||
<h2>More features.</h2>
|
||||
<p>
|
||||
Charging cradle recharges the battery and serves as a convenient
|
||||
home base for your speaker, and it lets you play while it charges
|
||||
Charging cradle recharges the battery and serves as a convenient
|
||||
home base for your speaker, and it lets you play while it charges.
|
||||
</p>
|
||||
<p>
|
||||
Wall charger can be plugged into the cradle or directly into the speaker
|
||||
Wall charger can be plugged into the cradle or directly into the speaker
|
||||
</p>
|
||||
<p>
|
||||
Auxiliary port lets you connect other audio sources, like an MP3 player
|
||||
Auxiliary port lets you connect other audio sources, like an MP3 player
|
||||
</p>
|
||||
<p>
|
||||
USB port allows for software update to ensure ongoing Bluetooth device compatibility
|
||||
USB port allows for software update to ensure ongoing Bluetooth device compatibility
|
||||
</p>
|
||||
<p>
|
||||
Soft covers are available separately in blue, green or orange. Pick a color to match your style.
|
||||
Soft covers are available separately in blue, green or orange. Pick a color to match your style.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -176,13 +194,13 @@ iOS7
|
|||
</div>
|
||||
</div>
|
||||
</section>
|
||||
<section data-snippet-id="image-text" class="mt16 mb16">
|
||||
<section data-snippet-id="image-text" class="mt16">
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="col-md-5 col-md-offset-1">
|
||||
<img class="img img-responsive" src="/website_sale/static/src/img/mighty.png"/>
|
||||
</div>
|
||||
<div class="col-md-6 mt64">
|
||||
<div class="col-md-6 mt32">
|
||||
<h3>Beautiful 7.9‑inch display.</h3>
|
||||
<h4 class="small text-muted"> A screen worthy of iPad.</h4>
|
||||
<p>
|
||||
|
@ -195,20 +213,20 @@ iOS7
|
|||
</div>
|
||||
</div>
|
||||
</section>
|
||||
<section data-snippet-id="text-image" class="mt16 mb16 dark">
|
||||
<section data-snippet-id="text-image" class="mb16 dark">
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="col-md-5 col-md-offset-1 mt64">
|
||||
<div class="col-md-5 col-md-offset-1 mt32">
|
||||
<h2>Over 375,000 apps.</h2>
|
||||
<h3 class="text-muted">If it's made for iPad, it's made for iPad mini.</h3>
|
||||
<p>
|
||||
Right from the start, apps made for iPad also work with iPad mini.
|
||||
They’re immersive, full-screen apps that let you do almost anything
|
||||
you can imagine. And with automatic updates,
|
||||
you're always getting the best experience possible.
|
||||
Right from the start, apps made for iPad also work with iPad mini.
|
||||
They’re immersive, full-screen apps that let you do almost anything
|
||||
you can imagine. And with automatic updates,
|
||||
you're always getting the best experience possible.
|
||||
</p>
|
||||
</div>
|
||||
<div class="col-md-5 mt16 mb16">
|
||||
<div class="col-md-5 mt16">
|
||||
<img class="img img-responsive" src="/website_sale/static/src/img/apps.png"/>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -260,79 +278,54 @@ iOS7
|
|||
|
||||
<record id="product.product_product_7" model="product.product">
|
||||
<field name="website_published" eval="True"/>
|
||||
<field name="description_sale">Technical Specifications:
|
||||
|
||||
Frequency response: 5Hz to 21kHz
|
||||
Impedance (at 100Hz): 23 ohms
|
||||
Sensitivity (at 100Hz): 109 dB SPL/mW
|
||||
Drivers: Custom two-way balanced armature (woofer and tweeter in each earpiece)
|
||||
|
||||
Length and weight:
|
||||
|
||||
Cable length: 1065 mm from audio jack to splitter; 330 mm to earpiece
|
||||
Weight: 0.4 ounce (10.2 grams)
|
||||
|
||||
Connector:
|
||||
|
||||
Four-conductor 3.5-mm audio jack
|
||||
<field name="description_sale">Frequency: 5Hz to 21kHz
|
||||
Impedance: 23 ohms
|
||||
Sensitivity: 109 dB SPL/mW
|
||||
Drivers: two-way balanced armature
|
||||
Cable length: 1065 mm
|
||||
Weight: 0.4 ounce
|
||||
</field>
|
||||
<field name="website_description" type="html">
|
||||
<section data-snippet-id="text-image" class="mt16 mb16">
|
||||
<section data-snippet-id="text-image" class="mt32">
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="col-md-8 col-md-offset-2">
|
||||
<h1>Apple In-Ear Headphones</h1>
|
||||
<div class="col-md-8 col-md-offset-2 text-center">
|
||||
<h3>Two is better than one.</h3>
|
||||
<p>
|
||||
Unlike many small headphones, each earpiece of the Apple In-Ear Headphones
|
||||
contains two separate high-performance drivers — a woofer to handle bass and
|
||||
mid-range sounds and a tweeter for high-frequency audio. These dedicated
|
||||
drivers help ensure accurate, detailed sound across the entire sonic spectrum.
|
||||
The result: you’re immersed in the music and hear details you never knew existed.
|
||||
Even when listening to an old favorite, you may feel like you’re hearing it for the first time.
|
||||
</p>
|
||||
</div>
|
||||
<div class="col-md-8 col-md-offset-2 dark">
|
||||
<div>
|
||||
<h2>Turns out you haven’t heard everything.</h2>
|
||||
<p>
|
||||
The Apple In-Ear Headphones with Remote and Mic are engineered
|
||||
for superior acoustic accuracy, balance, and clarity. So you hear details
|
||||
you’ve been missing with other, lesser headphones.
|
||||
And the biggest breakthrough? They’re just $79.
|
||||
</p>
|
||||
</div>
|
||||
<div>
|
||||
<h3 class="mt16">Two is better than one.</h3>
|
||||
<p>
|
||||
Unlike many small headphones, each earpiece of the Apple In-Ear Headphones
|
||||
contains two separate high-performance drivers — a woofer to handle bass and
|
||||
mid-range sounds and a tweeter for high-frequency audio. These dedicated
|
||||
drivers help ensure accurate, detailed sound across the entire sonic spectrum.
|
||||
The result: you’re immersed in the music and hear details you never knew existed.
|
||||
Even when listening to an old favorite, you may feel like you’re hearing it for the first time.
|
||||
</p>
|
||||
</div>
|
||||
<div>
|
||||
<div class="col-md-2">
|
||||
<img class="img img-responsive" src="/website_sale/static/src/img/promo_headphones.png"/>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<h3 class="mt16">Hear, hear.</h3>
|
||||
<p>
|
||||
The Apple In-Ear Headphones deliver a truly immersive sound experience by drastically
|
||||
reducing unwanted outside noises. The soft, silicone ear tips fit snugly and comfortably
|
||||
in your ear, creating a seal that isolates your music from your surroundings.
|
||||
Three different sizes of ear tips are included so you can find a perfect fit for each ear.
|
||||
Also included are a convenient carrying case for the ear tips and a cable-control case
|
||||
for the headphones themselves.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mt16">
|
||||
<div class="col-md-6">
|
||||
<h3 class="mt16">Keep it clean.</h3>
|
||||
<p>
|
||||
Inside each earpiece is a stainless steel mesh cap that protects the precision acoustic
|
||||
components from dust and debris. You can remove the caps for cleaning or replace
|
||||
them with an extra set that’s included in the box.
|
||||
</p>
|
||||
</div>
|
||||
<div class="col-md-2">
|
||||
<img class="img img-responsive" src="/website_sale/static/src/img/buds_closeup.png"/>
|
||||
</div>
|
||||
</div>
|
||||
</div><div class="row mt16">
|
||||
<div class="col-md-2 mt16">
|
||||
<img class="img img-responsive" src="/website_sale/static/src/img/promo_headphones.png"/>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<h3 class="mt16">Hear, hear.</h3>
|
||||
<p>
|
||||
The Apple In-Ear Headphones deliver a truly immersive sound experience by drastically
|
||||
reducing unwanted outside noises. The soft, silicone ear tips fit snugly and comfortably
|
||||
in your ear, creating a seal that isolates your music from your surroundings.
|
||||
Three different sizes of ear tips are included so you can find a perfect fit for each ear.
|
||||
Also included are a convenient carrying case for the ear tips and a cable-control case
|
||||
for the headphones themselves.
|
||||
</p>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<h3 class="mt16">Keep it clean.</h3>
|
||||
<p>
|
||||
Inside each earpiece is a stainless steel mesh cap that protects the precision acoustic
|
||||
components from dust and debris. You can remove the caps for cleaning or replace
|
||||
them with an extra set that’s included in the box.
|
||||
</p>
|
||||
</div>
|
||||
</div><div class="row">
|
||||
<div class="col-md-2 col-md-offset-5 mt16">
|
||||
<img class="img img-responsive" src="/website_sale/static/src/img/buds_closeup.png"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -342,41 +335,40 @@ Four-conductor 3.5-mm audio jack
|
|||
|
||||
<record id="product.product_product_8" model="product.product">
|
||||
<field name="website_published" eval="True"/>
|
||||
<field name="description_sale">
|
||||
2.7GHz quad-core Intel Core i5
|
||||
<field name="description_sale">2.7GHz quad-core Intel Core i5
|
||||
Turbo Boost up to 3.2GHz
|
||||
8GB (two 4GB) memory
|
||||
1TB hard drive1
|
||||
Intel Iris Pro graphics
|
||||
</field>
|
||||
<field name="website_description" type="html">
|
||||
<section data-snippet-id="image-text" class="mt16 mb16">
|
||||
<section data-snippet-id="image-text">
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="col-md-5 mt32 col-md-offset-1">
|
||||
<h3>Ultrathin design</h3>
|
||||
<h3 class="text-muted">The desktop. In its most advanced form ever</h3>
|
||||
<p>
|
||||
Creating such a stunningly thin design took some equally stunning feats of technological innovation. We refined,re-imagined,or re-engineered everything about iMac from the inside out. The result is an advanced, elegant all-in-one computer that’s as much a work of art as it is state of the art.
|
||||
Creating such a stunningly thin design took some equally stunning feats of technological innovation. We refined,re-imagined,or re-engineered everything about iMac from the inside out. The result is an advanced, elegant all-in-one computer that’s as much a work of art as it is state of the art.
|
||||
</p>
|
||||
</div>
|
||||
<div class="col-md-5 mt32 mb64">
|
||||
<div class="col-md-5 mt32">
|
||||
<img class="img img-responsive" src="/website_sale/static/src/img/imac1.png"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
<section data-snippet-id="text-image" class="mt16 mb16 dark">
|
||||
<section data-snippet-id="text-image" class="mb16 dark">
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="text-center col-md-8 col-md-offset-2">
|
||||
<h3>Beautiful widescreen display.</h3>
|
||||
<div class="text-center col-md-8 col-md-offset-2 mt16">
|
||||
<h2>Beautiful widescreen display.</h2>
|
||||
<h3 class="text-muted">Brilliance onscreen. And behind it.</h3>
|
||||
<p>
|
||||
How did we make an already gorgeous widescreen display even better? By making it 75 percent less reflective. And by re-architecting the LCD and moving it right up against the cover glass. So you see your photos, games, movies, and everything else in vivid, lifelike detail.
|
||||
</p>
|
||||
</div>
|
||||
<div class="col-md-10 col-md-offset-1 mt16 mb64">
|
||||
<div class="col-md-10 col-md-offset-1">
|
||||
<img class="img img-responsive" src="/website_sale/static/src/img/imac2.png" width="100%"/>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -385,9 +377,11 @@ Four-conductor 3.5-mm audio jack
|
|||
<section data-snippet-id="image-text" class="mt16 mb16">
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="col-md-5 col-md-offset-1 mt32">
|
||||
<p>
|
||||
Powered by fourth-generation Intel Core processors, this iMac is the fastest yet. Every model in the lineup comes standard with a quad-core Intel Core i5 processor, starting at 2.7GHz and topping out at 3.4GHz. And at the Apple Online Store, you can configure your iMac with an even more powerful Intel Core i7 processor, up to 3.5GHz.
|
||||
<div class="col-md-5 col-md-offset-1 mt64">
|
||||
<p class="text-muted">
|
||||
Powered by fourth-generation Intel Core processors, this iMac is the fastest yet. Every model in the lineup comes standard with a quad-core Intel Core i5 processor, starting at 2.7GHz and topping out at 3.4GHz.
|
||||
</p><p class="text-muted">
|
||||
And at the Apple Online Store, you can configure your iMac with an even more powerful Intel Core i7 processor, up to 3.5GHz.
|
||||
</p>
|
||||
</div>
|
||||
<div class="col-md-5 col-md-offset-1 mb32">
|
||||
|
@ -419,14 +413,15 @@ Four-conductor 3.5-mm audio jack
|
|||
<field name="description_sale">The sleek aluminium Apple Wireless Keyboard.
|
||||
</field>
|
||||
<field name="website_description" type="html">
|
||||
<section data-snippet-id="image-text" class="mt16 mb16 dark">
|
||||
<hr/>
|
||||
<section data-snippet-id="image-text" class="mt16 mb16">
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="col-md-8 col-md-offset-2 mt64 mb32">
|
||||
<div class="col-md-10 col-md-offset-1 mt32 mb32">
|
||||
<img class="img img-responsive" src="/website_sale/static/src/img/keyboard.png"/>
|
||||
</div>
|
||||
<div class="col-md-8 col-md-offset-2 mb32">
|
||||
<h3>Apple Wireless Keyboard</h3>
|
||||
<div class="col-md-8 col-md-offset-2 mb32 text-center">
|
||||
<h3>A great Keyboard. Cordless.</h3>
|
||||
<p>
|
||||
The incredibly thin Apple Wireless Keyboard uses Bluetooth technology,
|
||||
which makes it compatible with iPad. And you’re free to type wherever
|
||||
|
@ -441,18 +436,15 @@ Four-conductor 3.5-mm audio jack
|
|||
|
||||
<record id="product.product_product_11" model="product.product">
|
||||
<field name="website_published" eval="True"/>
|
||||
<field name="description_sale">Capacity: 16 GB
|
||||
Height: 3.01 inches (76.5 mm)
|
||||
Width: 1.56 inches (39.6 mm)
|
||||
Depth: 0.21 inch (5.4 mm)
|
||||
Weight: 1.1 ounces (31 grams)1
|
||||
True volume: 0.95 cu. inch (15,537 cu. mm)
|
||||
</field>
|
||||
<field name="description_sale">Height: 3.01 inches
|
||||
Width: 1.56 inches
|
||||
Depth: 0.21 inch
|
||||
Weight: 1.1 ounces</field>
|
||||
<field name="website_description" type="html">
|
||||
<section data-snippet-id="image-text" class="mt16 mb16">
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="col-md-9 col-md-offset-1 mt16 mb64">
|
||||
<div class="col-md-9 col-md-offset-1 mb16">
|
||||
<img class="img img-responsive" src="/website_sale/static/src/img/overview_hero.png"/>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -464,12 +456,13 @@ True volume: 0.95 cu. inch (15,537 cu. mm)
|
|||
<div class="col-md-5 col-md-offset-1 mt64">
|
||||
<h3>Design. The thinnest iPod ever.</h3>
|
||||
<p>
|
||||
About the size of a credit card — and just 5.4 mm thin — iPod nano is the thinnest iPod ever made.
|
||||
The 2.5-inch Multi-Touch display is nearly twice as big as the display on the previous iPod nano,
|
||||
so you can see more of the music, photos, and videos you love.
|
||||
Buttons let you quickly play, pause, change songs, or adjust the volume.
|
||||
The smooth anodized aluminum design makes iPod nano feel as good as it sounds.
|
||||
And iPod nano wouldn’t be iPod nano without gorgeous, hard-to-choose-from color.
|
||||
About the size of a credit card — and just 5.4 mm thin — iPod nano is the thinnest iPod ever made.
|
||||
The 2.5-inch Multi-Touch display is nearly twice as big as the display on the previous iPod nano,
|
||||
so you can see more of the music, photos, and videos you love.
|
||||
</p><p>
|
||||
Buttons let you quickly play, pause, change songs, or adjust the volume.
|
||||
The smooth anodized aluminum design makes iPod nano feel as good as it sounds.
|
||||
And iPod nano wouldn’t be iPod nano without gorgeous, hard-to-choose-from color.
|
||||
</p>
|
||||
</div>
|
||||
<div class="col-md-5">
|
||||
|
@ -481,8 +474,8 @@ True volume: 0.95 cu. inch (15,537 cu. mm)
|
|||
<section data-snippet-id="image-text" class="mt16 mb16">
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="col-md-10 mt32 col-md-offset-1">
|
||||
<h2>Music. It's what beats inside.</h2>
|
||||
<div class="col-md-10 col-md-offset-1">
|
||||
<h2 class="text-center">Music. It's what beats inside.</h2>
|
||||
</div>
|
||||
<div class="col-md-4 mt32 col-md-offset-1">
|
||||
<img class="img img-responsive" src="/website_sale/static/src/img/purple.png"/>
|
||||
|
@ -508,22 +501,20 @@ True volume: 0.95 cu. inch (15,537 cu. mm)
|
|||
</div>
|
||||
</div>
|
||||
</section>
|
||||
<section data-snippet-id="image-text" class="mt16 mb16 dark">
|
||||
<section data-snippet-id="image-text" class="mt16 mb16">
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="col-md-10 mt32 col-md-offset-1">
|
||||
<div class="col-md-12 text-center mb16">
|
||||
<h2>Playlists. The perfect mix for every mood.</h2>
|
||||
</div>
|
||||
<div class="col-md-4 mt32 col-md-offset-1">
|
||||
<img class="img img-responsive" src="/website_sale/static/src/img/plug_playlist.png"/>
|
||||
</div>
|
||||
<div class="col-md-6 mt32">
|
||||
<div class="col-md-4">
|
||||
<h3>Sync to your heart’s content.</h3>
|
||||
<p>
|
||||
iTunes on your Mac or PC makes it easy to load up
|
||||
your iPod. Just choose the playlists, audiobooks,
|
||||
podcasts, and other audio files you want, then sync.
|
||||
</p>
|
||||
</div><div class="col-md-4">
|
||||
<h3>When one playlist isn’t enough.</h3>
|
||||
<p>
|
||||
You probably have multiple playlists in iTunes on your computer.
|
||||
|
@ -532,6 +523,7 @@ True volume: 0.95 cu. inch (15,537 cu. mm)
|
|||
mood strikes you. VoiceOver tells you the name of each playlist,
|
||||
so it’s easy to switch between them and find the one you want without looking.
|
||||
</p>
|
||||
</div><div class="col-md-4">
|
||||
<h3>Have Genius call the tunes.</h3>
|
||||
<p>
|
||||
There’s another way to get a good mix of music on iPod: Let Genius do the work.
|
||||
|
|