[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:
@@ -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">
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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'">
|
||||
|
||||
Reference in New Issue
Block a user