[IMP] website_*: generic filter and sort mecanism for portal documents

website portal now provide mecanism to sort and filter the
paginated document on the portal pages.
All portal module now use this mecanism, like they do for
'archive document' and 'pager'.

A generic template was added in website_portal. To use
it, renaming variables in method controller was required
to make it as generic as possible.

Some style cleaning was also done to make portal pages
consistent.
This commit is contained in:
Vipul Bhatt
2016-11-09 09:36:01 +01:00
committed by Jérome Maes
parent 78dfb01942
commit 1cc8252a95
10 changed files with 208 additions and 176 deletions
@@ -39,18 +39,21 @@ class WebsiteAccount(website_account):
return response
@http.route(['/my/leads', '/my/leads/page/<int:page>'], type='http', auth="user", website=True)
def portal_my_leads(self, page=1, date_begin=None, date_end=None, lead=None, sortby=None, **kw):
def portal_my_leads(self, page=1, date_begin=None, date_end=None, sortby=None, **kw):
values = self._prepare_portal_layout_values()
CrmLead = request.env['crm.lead']
domain = self.get_domain_my_lead(request.env.user)
sortings = {
searchbar_sortings = {
'date': {'label': _('Newest'), 'order': 'create_date desc'},
'name': {'label': _('Name'), 'order': 'name'},
'contact_name': {'label': _('Contact Name'), 'order': 'contact_name'},
}
order = sortings.get(sortby, sortings['date'])['order']
# default sort by value
if not sortby:
sortby = 'date'
order = searchbar_sortings[sortby]['order']
# archive groups - Default Group By 'create_date'
archive_groups = self._get_archive_groups('crm.lead', domain)
@@ -60,7 +63,7 @@ class WebsiteAccount(website_account):
lead_count = CrmLead.search_count(domain)
pager = request.website.pager(
url="/my/leads",
url_args={'date_begin': date_begin, 'date_end': date_end, 'sortby': sortby, 'lead': lead},
url_args={'date_begin': date_begin, 'date_end': date_end, 'sortby': sortby},
total=lead_count,
page=page,
step=self._items_per_page
@@ -72,17 +75,16 @@ class WebsiteAccount(website_account):
'date': date_begin,
'leads': leads,
'page_name': 'lead',
'lead': lead,
'sortings': sortings,
'sortby': sortby,
'archive_groups': archive_groups,
'default_url': '/my/leads',
'pager': pager
'pager': pager,
'searchbar_sortings': searchbar_sortings,
'sortby': sortby,
})
return request.render("website_crm_partner_assign.portal_my_leads", values)
@http.route(['/my/opportunities', '/my/opportunities/page/<int:page>'], type='http', auth="user", website=True)
def portal_my_opportunities(self, page=1, date_begin=None, date_end=None, opportunity=None, sortby=None, **kw):
def portal_my_opportunities(self, page=1, date_begin=None, date_end=None, sortby=None, filterby=None, **kw):
values = self._prepare_portal_layout_values()
CrmLead = request.env['crm.lead']
domain = self.get_domain_my_opp(request.env.user)
@@ -90,7 +92,7 @@ class WebsiteAccount(website_account):
today = fields.Date.today()
this_week_end_date = fields.Date.to_string(fields.Date.from_string(today) + datetime.timedelta(days=7))
filters = {
searchbar_filters = {
'all': {'label': _('All'), 'domain': []},
'today': {'label': _('Today Activities'), 'domain': [('date_action', '=', today)]},
'week': {'label': _('This Week Activities'),
@@ -99,8 +101,7 @@ class WebsiteAccount(website_account):
'won': {'label': _('Won'), 'domain': [('stage_id.probability', '=', 100), ('stage_id.fold', '=', True)]},
'lost': {'label': _('Lost'), 'domain': [('active', '=', False)]},
}
sortings = {
searchbar_sortings = {
'date': {'label': _('Newest'), 'order': 'create_date desc'},
'name': {'label': _('Name'), 'order': 'name'},
'contact_name': {'label': _('Contact Name'), 'order': 'contact_name'},
@@ -109,8 +110,14 @@ class WebsiteAccount(website_account):
'stage': {'label': _('Stage'), 'order': 'stage_id'},
}
domain += filters.get(opportunity, filters['all'])['domain']
order = sortings.get(sortby, sortings['date'])['order']
# default sort by value
if not sortby:
sortby = 'date'
order = searchbar_sortings[sortby]['order']
# default filter by value
if not filterby:
filterby = 'all'
domain += searchbar_filters[filterby]['domain']
# archive groups - Default Group By 'create_date'
archive_groups = self._get_archive_groups('crm.lead', domain)
@@ -120,7 +127,7 @@ class WebsiteAccount(website_account):
opp_count = CrmLead.search_count(domain)
pager = request.website.pager(
url="/my/opportunities",
url_args={'date_begin': date_begin, 'date_end': date_end, 'sortby': sortby, 'opportunity': opportunity},
url_args={'date_begin': date_begin, 'date_end': date_end, 'sortby': sortby, 'filterby': filterby},
total=opp_count,
page=page,
step=self._items_per_page
@@ -132,13 +139,13 @@ class WebsiteAccount(website_account):
'date': date_begin,
'opportunities': opportunities,
'page_name': 'opportunity',
'filters': OrderedDict(sorted(filters.items())),
'opportunity': opportunity,
'sortings': sortings,
'sortby': sortby,
'archive_groups': archive_groups,
'default_url': '/my/opportunities',
'pager': pager
'pager': pager,
'searchbar_sortings': searchbar_sortings,
'sortby': sortby,
'searchbar_filters': OrderedDict(sorted(searchbar_filters.items())),
'filterby': filterby,
})
return request.render("website_crm_partner_assign.portal_my_opportunities", values)
@@ -240,17 +240,7 @@
<t t-call="website_portal.portal_layout">
<h3 class="page-header">
Your Leads
<div class="dropdown pull-right mr8">
<button id="sortby" class="btn btn-default" type="button" data-toggle="dropdown">
<span class="fa fa-sort fa-lg" /> <span t-esc="sortings.get(sortby, {}).get('label', 'Newest')"/>
<span class="caret"></span>
</button>
<ul class="dropdown-menu" aria-labelledby="sortby">
<li t-foreach="sortings" t-as="option" t-att-class="sortby == option and 'active'">
<a t-att-href="default_url + '?' + keep_query('date_begin', 'date_end', 'lead', sortby=option)"><span t-esc="sortings.get(option).get('label')"/></a>
</li>
</ul>
</div>
<t t-call="website_portal.portal_searchbar"/>
</h3>
<div t-if="not leads" class="alert alert-warning mt8" role="alert">
There are no leads.
@@ -285,36 +275,13 @@
<t t-call="website_portal.portal_layout">
<h3 class="page-header">
Your Opportunities
<div class="dropdown pull-right mr8">
<button id="sortby" class="btn btn-default" type="button" data-toggle="dropdown">
<span class="fa fa-sort fa-lg" /> <span t-esc="sortings.get(sortby, {}).get('label', 'Newest')"/>
<span class="caret"></span>
</button>
<ul class="dropdown-menu" aria-labelledby="sortby">
<li t-foreach="sortings" t-as="option" t-att-class="sortby == option and 'active'">
<a t-att-href="default_url + '?' + keep_query('date_begin', 'date_end', 'opportunity', sortby=option)"><span t-esc="sortings.get(option).get('label')"/></a>
</li>
</ul>
</div>
<div class="dropdown pull-right mr8">
<button id="filters" class="btn btn-default" type="button" data-toggle="dropdown">
<span class="fa fa-filter fa-lg" /> <span t-esc="filters.get(opportunity, {}).get('label', 'All')"/>
<span class="caret"></span>
</button>
<ul class="dropdown-menu" aria-labelledby="filters">
<li t-foreach="filters" t-as="option" t-att-class="opportunity == option and 'active'">
<a t-att-href="default_url + '?' + keep_query('date_begin', 'date_end', 'sortby', opportunity=option)"><span t-esc="filters.get(option).get('label')"/></a>
</li>
</ul>
</div>
<t t-call="website_portal.portal_searchbar"/>
</h3>
<div class="panel panel-default">
<t t-if="not opportunities">
<div class="alert alert-warning mt8" role="alert">
There are no opportunities.
</div>
</t>
<table t-if="opportunities" class="table table-hover">
<div t-if="not opportunities" class="alert alert-warning mt8" role="alert">
There are no opportunities.
</div>
<div t-if="opportunities" class="panel panel-default">
<table class="table table-hover">
<thead>
<tr class="active">
<th class="col-xs-2">Date</th>
@@ -26,6 +26,50 @@
</ul>
</template>
<!--
The search bar is composed of 2 buttons : a "filter by" and a "sort by". Changing the 'sortby'
criteria will keep the number of page, query params, ... Changing the 'filterby' param will
redirect the user to the beginning of document list, keeping query parameters.
:param dict searchbar_sortings : containing the sort criteria like
{'date': {'label': _('Newest'), 'order': 'create_date desc'}}
:param string sortby : name of the sort criteria
:param dict searchbar_filters : containing the filter criteria like
{'open': {'label': _('In Progress'), 'domain': [('state', '=', 'open')]}}
:param string filterby : name of the filter criteria
:param default_url : the base url of the pages (like '/my/orders')
-->
<template id="portal_searchbar" name="Portal Search Bar">
<div t-if="searchbar_sortings" class="dropdown pull-right mr8">
<button id="portal_searchbar_sortby" class="btn btn-default" type="button" data-toggle="dropdown">
<span class="fa fa-sort fa-lg" />
<span t-esc="searchbar_sortings[sortby].get('label', 'Newest')"/>
<span class="caret"></span>
</button>
<ul class="dropdown-menu" aria-labelledby="portal_searchbar_sortby">
<li t-foreach="searchbar_sortings" t-as="option" t-attf-class="#{sortby == option and 'active'}">
<a t-att-href="request.httprequest.path + '?' + keep_query('*', sortby=option)">
<span t-esc="searchbar_sortings[option].get('label')"/>
</a>
</li>
</ul>
</div>
<div t-if="searchbar_filters" class="dropdown pull-right mr8">
<button id="portal_searchbar_filters" class="btn btn-default" type="button" data-toggle="dropdown">
<span class="fa fa-filter fa-lg" />
<span t-esc="searchbar_filters[filterby].get('label', 'All')"/>
<span class="caret"></span>
</button>
<ul class="dropdown-menu" aria-labelledby="portal_searchbar_filters">
<li t-foreach="searchbar_filters" t-as="option" t-att-class="filterby == option and 'active'">
<a t-att-href="default_url + '?' + keep_query('*', filterby=option)">
<span t-esc="searchbar_filters[option].get('label')"/>
</a>
</li>
</ul>
</div>
</template>
<template id="portal_layout" name="Portal Layout">
<t t-call="website.layout">
<div class="container mt16">
+47 -9
View File
@@ -43,7 +43,7 @@ class website_account(website_account):
#
@http.route(['/my/quotes', '/my/quotes/page/<int:page>'], type='http', auth="user", website=True)
def portal_my_quotes(self, page=1, date_begin=None, date_end=None, **kw):
def portal_my_quotes(self, page=1, date_begin=None, date_end=None, sortby=None, **kw):
values = self._prepare_portal_layout_values()
partner = request.env.user.partner_id
SaleOrder = request.env['sale.order']
@@ -53,6 +53,16 @@ class website_account(website_account):
('state', 'in', ['sent', 'cancel'])
]
searchbar_sortings = {
'date': {'label': _('Order Date'), 'order': 'date_order desc'},
'name': {'label': _('Name'), 'order': 'name'},
}
# default sortby order
if not sortby:
sortby = 'date'
sort_order = searchbar_sortings[sortby]['order']
archive_groups = self._get_archive_groups('sale.order', domain)
if date_begin and date_end:
domain += [('create_date', '>', date_begin), ('create_date', '<=', date_end)]
@@ -62,13 +72,13 @@ class website_account(website_account):
# make pager
pager = request.website.pager(
url="/my/quotes",
url_args={'date_begin': date_begin, 'date_end': date_end},
url_args={'date_begin': date_begin, 'date_end': date_end, 'sortby': sortby},
total=quotation_count,
page=page,
step=self._items_per_page
)
# search the count to display, according to the pager data
quotations = SaleOrder.search(domain, limit=self._items_per_page, offset=pager['offset'])
quotations = SaleOrder.search(domain, order=sort_order, limit=self._items_per_page, offset=pager['offset'])
values.update({
'date': date_begin,
@@ -76,11 +86,13 @@ class website_account(website_account):
'pager': pager,
'archive_groups': archive_groups,
'default_url': '/my/quotes',
'searchbar_sortings': searchbar_sortings,
'sortby': sortby,
})
return request.render("website_portal_sale.portal_my_quotations", values)
@http.route(['/my/orders', '/my/orders/page/<int:page>'], type='http', auth="user", website=True)
def portal_my_orders(self, page=1, date_begin=None, date_end=None, **kw):
def portal_my_orders(self, page=1, date_begin=None, date_end=None, sortby=None, **kw):
values = self._prepare_portal_layout_values()
partner = request.env.user.partner_id
SaleOrder = request.env['sale.order']
@@ -89,6 +101,16 @@ class website_account(website_account):
('message_partner_ids', 'child_of', [partner.commercial_partner_id.id]),
('state', 'in', ['sale', 'done'])
]
searchbar_sortings = {
'date': {'label': _('Order Date'), 'order': 'date_order desc'},
'name': {'label': _('Name'), 'order': 'name'},
}
# default sortby order
if not sortby:
sortby = 'date'
sort_order = searchbar_sortings[sortby]['order']
archive_groups = self._get_archive_groups('sale.order', domain)
if date_begin and date_end:
domain += [('create_date', '>', date_begin), ('create_date', '<=', date_end)]
@@ -98,13 +120,13 @@ class website_account(website_account):
# pager
pager = request.website.pager(
url="/my/orders",
url_args={'date_begin': date_begin, 'date_end': date_end},
url_args={'date_begin': date_begin, 'date_end': date_end, 'sortby': sortby},
total=order_count,
page=page,
step=self._items_per_page
)
# content according to pager and archive selected
orders = SaleOrder.search(domain, limit=self._items_per_page, offset=pager['offset'])
orders = SaleOrder.search(domain, order=sort_order, limit=self._items_per_page, offset=pager['offset'])
values.update({
'date': date_begin,
@@ -113,6 +135,8 @@ class website_account(website_account):
'pager': pager,
'archive_groups': archive_groups,
'default_url': '/my/orders',
'searchbar_sortings': searchbar_sortings,
'sortby': sortby,
})
return request.render("website_portal_sale.portal_my_orders", values)
@@ -135,7 +159,7 @@ class website_account(website_account):
#
@http.route(['/my/invoices', '/my/invoices/page/<int:page>'], type='http', auth="user", website=True)
def portal_my_invoices(self, page=1, date_begin=None, date_end=None, **kw):
def portal_my_invoices(self, page=1, date_begin=None, date_end=None, sortby=None, **kw):
values = self._prepare_portal_layout_values()
partner = request.env.user.partner_id
AccountInvoice = request.env['account.invoice']
@@ -144,6 +168,18 @@ class website_account(website_account):
('message_partner_ids', 'child_of', [partner.commercial_partner_id.id]),
('state', 'in', ['open', 'paid', 'cancelled'])
]
searchbar_sortings = {
'date': {'label': _('Invoice Date'), 'order': 'date_invoice desc'},
'duedate': {'label': _('Due Date'), 'order': 'date_due desc'},
'name': {'label': _('Name'), 'order': 'name desc'},
'state': {'label': _('Status'), 'order': 'state'},
}
# default sort by order
if not sortby:
sortby = 'date'
order = searchbar_sortings[sortby]['order']
archive_groups = self._get_archive_groups('account.invoice', domain)
if date_begin and date_end:
domain += [('create_date', '>', date_begin), ('create_date', '<=', date_end)]
@@ -153,13 +189,13 @@ class website_account(website_account):
# pager
pager = request.website.pager(
url="/my/invoices",
url_args={'date_begin': date_begin, 'date_end': date_end},
url_args={'date_begin': date_begin, 'date_end': date_end, 'sortby': sortby},
total=invoice_count,
page=page,
step=self._items_per_page
)
# content according to pager and archive selected
invoices = AccountInvoice.search(domain, limit=self._items_per_page, offset=pager['offset'])
invoices = AccountInvoice.search(domain, order=order, limit=self._items_per_page, offset=pager['offset'])
values.update({
'date': date_begin,
'invoices': invoices,
@@ -167,6 +203,8 @@ class website_account(website_account):
'pager': pager,
'archive_groups': archive_groups,
'default_url': '/my/invoices',
'searchbar_sortings': searchbar_sortings,
'sortby': sortby,
})
return request.render("website_portal_sale.portal_my_invoices", values)
@@ -63,7 +63,10 @@
<template id="portal_my_quotations" name="My Quotations">
<t t-call="website_portal.portal_layout">
<h3 class="page-header">Your Quotes</h3>
<div class="page-header">
<span class="h3">Your Quotes</span>
<t t-call="website_portal.portal_searchbar"/>
</div>
<t t-if="not quotations">
<p>There are currently no quotes for your account.</p>
</t>
@@ -72,6 +75,7 @@
<thead>
<tr class="active">
<th>Quotation #</th>
<th>Order Date</th>
<th>Valid Until</th>
<th></th>
<th>Total</th>
@@ -82,6 +86,7 @@
<td>
<a t-attf-href="/my/orders/#{quotation.id}?#{keep_query()}"><t t-esc="quotation.name"/></a>
</td>
<td><span t-field="quotation.date_order"/></td>
<td><span t-field="quotation.validity_date"/></td>
<td>
<t t-if="quotation.state == 'cancel'">
@@ -105,7 +110,10 @@
<template id="portal_my_orders" name="My Sales Orders">
<t t-call="website_portal.portal_layout">
<h3 class="page-header">Your Orders</h3>
<div class="page-header">
<span class="h3">Your Orders</span>
<t t-call="website_portal.portal_searchbar"/>
</div>
<t t-if="not orders">
<p>There are currently no orders for your account.</p>
</t>
@@ -149,7 +157,10 @@
<template id="portal_my_invoices" name="My Invoices and Payments">
<t t-call="website_portal.portal_layout">
<h3 class="page-header">Your Invoices and Payments</h3>
<div class="page-header">
<span class="h3">Your Invoices and Payments</span>
<t t-call="website_portal.portal_searchbar"/>
</div>
<t t-if="not invoices">
<p>There are currently no invoices for your account.</p>
</t>
+35 -26
View File
@@ -25,24 +25,27 @@ class WebsiteAccount(website_account):
def my_projects(self, page=1, date_begin=None, date_end=None, sortby=None, **kw):
values = self._prepare_portal_layout_values()
Project = request.env['project.project']
domain = [('privacy_visibility', '=', 'portal')]
sortings = {
searchbar_sortings = {
'date': {'label': _('Newest'), 'order': 'create_date desc'},
'name': {'label': _('Name'), 'order': 'name'},
}
domain = [('privacy_visibility','=','portal')]
order = sortings.get(sortby, sortings['date'])['order']
if not sortby:
sortby = 'date'
order = searchbar_sortings[sortby]['order']
# archive groups - Default Group By 'create_date'
archive_groups = self._get_archive_groups('project.project', domain)
if date_begin and date_end:
domain += [('create_date', '>', date_begin), ('create_date', '<=', date_end)]
# projects count
project_count = Project.search_count(domain)
# pager
pager = request.website.pager(
url="/my/projects",
url_args={'date_begin': date_begin, 'date_end': date_end, 'sortby': sortby},
total=values['project_count'],
total=project_count,
page=page,
step=self._items_per_page
)
@@ -53,13 +56,13 @@ class WebsiteAccount(website_account):
values.update({
'date': date_begin,
'date_end': date_end,
'sortings': sortings,
'sortby': sortby,
'projects': projects,
'page_name': 'project',
'archive_groups': archive_groups,
'default_url': '/my/projects',
'pager': pager
'pager': pager,
'searchbar_sortings': searchbar_sortings,
'sortby': sortby
})
return request.render("website_project.my_projects", values)
@@ -68,41 +71,47 @@ class WebsiteAccount(website_account):
return request.render("website_project.my_project", {'project': project})
@http.route(['/my/tasks', '/my/tasks/page/<int:page>'], type='http', auth="user", website=True)
def my_tasks(self, page=1, date_begin=None, date_end=None, project=None, sortby=None, **kw):
def my_tasks(self, page=1, date_begin=None, date_end=None, sortby=None, filterby=None, **kw):
values = self._prepare_portal_layout_values()
domain = [('project_id.privacy_visibility', '=', 'portal')]
sortings = {
searchbar_sortings = {
'date': {'label': _('Newest'), 'order': 'create_date desc'},
'name': {'label': _('Name'), 'order': 'name'},
'stage': {'label': _('Stage'), 'order': 'stage_id'},
'update': {'label': _('Last Stage Update'), 'order': 'date_last_stage_update desc'},
}
projects = request.env['project.project'].search([('privacy_visibility', '=', 'portal')])
project_filters = {
searchbar_filters = {
'all': {'label': _('All'), 'domain': []},
}
# extends filterby criteria with project (criteria name is the project id)
projects = request.env['project.project'].search([('privacy_visibility', '=', 'portal')])
for proj in projects:
project_filters.update({
searchbar_filters.update({
str(proj.id): {'label': proj.name, 'domain': [('project_id', '=', proj.id)]}
})
domain = [('project_id.privacy_visibility', '=', 'portal')]
domain += project_filters.get(project, project_filters['all'])['domain']
order = sortings.get(sortby, sortings['date'])['order']
# default sort by value
if not sortby:
sortby = 'date'
order = searchbar_sortings[sortby]['order']
# default filter by value
if not filterby:
filterby = 'all'
domain += searchbar_filters[filterby]['domain']
# archive groups - Default Group By 'create_date'
archive_groups = self._get_archive_groups('project.task', domain)
if date_begin and date_end:
domain += [('create_date', '>', date_begin), ('create_date', '<=', date_end)]
# task count
task_count = request.env['project.task'].search_count(domain)
# pager
pager = request.website.pager(
url="/my/tasks",
url_args={'date_begin': date_begin, 'date_end': date_end, 'sortby': sortby, 'project': project},
total=values['task_count'],
url_args={'date_begin': date_begin, 'date_end': date_end, 'sortby': sortby, 'filterby': filterby},
total=task_count,
page=page,
step=self._items_per_page
)
@@ -112,16 +121,16 @@ class WebsiteAccount(website_account):
values.update({
'date': date_begin,
'date_end': date_end,
'project_filters': OrderedDict(sorted(project_filters.items())),
'projects': projects,
'project': project,
'sortings': sortings,
'sortby': sortby,
'tasks': tasks,
'page_name': 'task',
'archive_groups': archive_groups,
'default_url': '/my/tasks',
'pager': pager
'pager': pager,
'searchbar_sortings': searchbar_sortings,
'sortby': sortby,
'searchbar_filters': OrderedDict(sorted(searchbar_filters.items())),
'filterby': filterby,
})
return request.render("website_project.my_tasks", values)
@@ -35,17 +35,7 @@
<div class="row">
<h3 class="page-header">
Your Projects
<div class="dropdown pull-right mr8">
<button id="sortby" class="btn btn-default" type="button" data-toggle="dropdown">
<span class="fa fa-sort fa-lg" /> <span t-esc="sortings.get(sortby, {}).get('label', 'Newest')"/>
<span class="caret"></span>
</button>
<ul class="dropdown-menu" aria-labelledby="sortby">
<li t-foreach="sortings" t-as="option" t-attf-class="#{sortby == option and 'active'}">
<a t-att-href="default_url + '?' + keep_query('date_begin', 'date_end', sortby=option)"><span t-esc="sortings.get(option).get('label')"/></a>
</li>
</ul>
</div>
<t t-call="website_portal.portal_searchbar"/>
</h3>
</div>
<div class="panel panel-default">
@@ -67,7 +57,7 @@
<a t-attf-href="/my/project/#{project.id}?{{ keep_query() }}"><span t-field="project.name"/></a>
</td>
<td>
<a t-if="project.use_tasks" t-attf-href="/my/tasks?project=#{project.id}">
<a t-if="project.use_tasks" t-attf-href="/my/tasks?filterby=#{project.id}">
<t t-esc="project.task_count" />
<t t-esc="project.label_tasks" />
</a>
@@ -126,7 +116,7 @@
</div>
<div class="col-md-6">
<div class="pull-right">
<a t-attf-href="/my/tasks?project=#{project.id}" class="btn btn-default btn-lg">
<a t-attf-href="/my/tasks?filterby=#{project.id}" class="btn btn-default btn-lg">
<span class="fa fa-tasks" />
<span t-esc="project.task_count" />
<span t-field="project.label_tasks" />
@@ -157,28 +147,7 @@
<t t-call="website_portal.portal_layout">
<h3 class="page-header">
Your Tasks
<div class="dropdown pull-right mr8">
<button id="sortby" class="btn btn-default" type="button" data-toggle="dropdown">
<span class="fa fa-sort fa-lg" /> <span t-esc="sortings.get(sortby, {}).get('label', 'Newest')"/>
<span class="caret"></span>
</button>
<ul class="dropdown-menu" aria-labelledby="sortby">
<li t-foreach="sortings" t-as="option" t-att-class="sortby == option and 'active'">
<a t-attf-href="/my/tasks?{{ keep_query('date_begin', 'date_end', 'project', sortby=option) }}"><span t-esc="sortings.get(option).get('label')"/></a>
</li>
</ul>
</div>
<div class="dropdown pull-right mr8">
<button id="project_filters" class="btn btn-default" type="button" data-toggle="dropdown">
Projects: <span t-esc="project_filters.get(project, {}).get('label', 'All')"/>
<span class="caret"></span>
</button>
<ul class="dropdown-menu" aria-labelledby="project_filters">
<li t-foreach="project_filters" t-as="option" t-att-class="project == option and 'active'">
<a t-attf-href="/my/tasks?{{ keep_query('date_begin', 'date_end', 'sortby', project=option) }}"><span t-esc="project_filters.get(option).get('label')"/></a>
</li>
</ul>
</div>
<t t-call="website_portal.portal_searchbar"/>
</h3>
<div class="panel panel-default">
<t t-if="not tasks">
@@ -22,42 +22,49 @@ class WebsiteAccount(website_account):
return values
@http.route(['/my/issues', '/my/issues/page/<int:page>'], type='http', auth="user", website=True)
def my_issues(self, page=1, date_begin=None, date_end=None, project=None, sortby=None, **kw):
def my_issues(self, page=1, date_begin=None, date_end=None, sortby=None, filterby=None, **kw):
values = self._prepare_portal_layout_values()
# portal users can't see the privacy_visibility, fetch the domain for them in sudo
portal_projects = request.env['project.project'].sudo().search([('privacy_visibility', '=', 'portal')])
domain = [('project_id', 'in', portal_projects.ids)]
sortings = {
searchbar_sortings = {
'date': {'label': _('Newest'), 'order': 'create_date desc'},
'name': {'label': _('Name'), 'order': 'name'},
'stage': {'label': _('Stage'), 'order': 'stage_id'},
'update': {'label': _('Last Stage Update'), 'order': 'date_last_stage_update desc'},
}
projects = request.env['project.project'].search([('privacy_visibility','=','portal')])
project_filters = {
searchbar_filters = {
'all': {'label': _('All'), 'domain': []},
}
# extends filterby criteria with project (criteria name is the project id)
projects = request.env['project.project'].search([('privacy_visibility', '=', 'portal')])
for proj in projects:
project_filters.update({
searchbar_filters.update({
str(proj.id): {'label': proj.name, 'domain': [('project_id', '=', proj.id)]}
})
# portal users can't see the privacy_visibility, fetch the domain for them in sudo
portal_projects = request.env['project.project'].sudo().search([('privacy_visibility', '=', 'portal')])
domain = [('project_id', 'in', portal_projects.ids)]
domain += project_filters.get(project, project_filters['all'])['domain']
order = sortings.get(sortby, sortings['date'])['order']
# default sort by value
if not sortby:
sortby = 'date'
order = searchbar_sortings[sortby]['order']
# default filter by value
if not filterby:
filterby = 'all'
domain += searchbar_filters[filterby]['domain']
# archive groups - Default Group By 'create_date'
archive_groups = self._get_archive_groups('project.issue', domain)
if date_begin and date_end:
domain += [('create_date', '>', date_begin), ('create_date', '<=', date_end)]
# issue count
issue_count = request.env['project.issue'].search_count(domain)
# pager
pager = request.website.pager(
url="/my/issues",
url_args={'date_begin': date_begin, 'date_end': date_end},
total=values['issue_count'],
total=issue_count,
page=page,
step=self._items_per_page
)
@@ -67,16 +74,16 @@ class WebsiteAccount(website_account):
values.update({
'date': date_begin,
'date_end': date_end,
'project_filters': OrderedDict(sorted(project_filters.items())),
'projects': projects,
'project': project,
'sortings': sortings,
'sortby': sortby,
'issues': project_issues,
'page_name': 'issue',
'archive_groups': archive_groups,
'default_url': '/my/issues',
'pager': pager
'pager': pager,
'searchbar_sortings': searchbar_sortings,
'sortby': sortby,
'searchbar_filters': OrderedDict(sorted(searchbar_filters.items())),
'filterby': filterby,
})
return request.render("website_project_issue.my_issues", values)
@@ -30,28 +30,7 @@
<t t-call="website_portal.portal_layout">
<h3 class="page-header">
Your Issues
<div class="dropdown pull-right mr8">
<button id="sortby" class="btn btn-default" type="button" data-toggle="dropdown">
<span class="fa fa-sort" /> <span t-esc="sortings.get(sortby, {}).get('label', 'Newest')"/>
<span class="caret"></span>
</button>
<ul class="dropdown-menu" aria-labelledby="sortby">
<li t-foreach="sortings" t-as="option" t-att-class="sortby == option and 'active'">
<a t-att-href="default_url + '?' + keep_query('date_begin', 'date_end', 'project', sortby=option)"><span t-esc="sortings.get(option).get('label')"/></a>
</li>
</ul>
</div>
<div class="dropdown pull-right mr8">
<button id="project_filters" class="btn btn-default" type="button" data-toggle="dropdown">
Projects: <span t-esc="project_filters.get(project, {}).get('label', 'All')"/>
<span class="caret"></span>
</button>
<ul class="dropdown-menu" aria-labelledby="project_filters">
<li t-foreach="project_filters" t-as="option" t-att-class="project == option and 'active'">
<a t-att-href="default_url + '?' + keep_query('date_begin', 'date_end', 'sortby', project=option)"><span t-esc="project_filters.get(option).get('label')"/></a>
</li>
</ul>
</div>
<t t-call="website_portal.portal_searchbar"/>
</h3>
<div class="panel panel-default">
<t t-if="not issues">
@@ -163,7 +142,7 @@
</xpath>
<xpath expr="//table/tbody/tr/td[last()]" position="after">
<td>
<a t-if="project.use_issues" t-attf-href="/my/issues?project=#{project.id}">
<a t-if="project.use_issues" t-attf-href="/my/issues?filterby=#{project.id}">
<t t-esc="project.issue_count" />
<t t-esc="project.label_issues" />
</a>
@@ -173,7 +152,7 @@
<template id="my_project" inherit_id="website_project.my_project">
<xpath expr="//div[@class='panel-body']/div[@class='row']/div[@class='col-md-6'][last()]/div[@class='pull-right']" position="before">
<a t-attf-href="/my/issues?project=#{project.id}" class="btn btn-default btn-lg pull-right ml8">
<a t-attf-href="/my/issues?filterby=#{project.id}" class="btn btn-default btn-lg pull-right ml8">
<span class="fa fa-bug" />
<span t-esc="project.issue_count" />
<span t-field="project.label_issues" />
@@ -708,6 +708,7 @@
<a t-attf-href="/quote/#{quotation.id}?#{keep_query()}"><t t-esc="quotation.name"/></a>
</t>
</td>
<td><span t-field="quotation.date_order"/></td>
<td><span t-field="quotation.validity_date"/></td>
<td>
<t t-if="quotation.state == 'cancel'">