[IMP] project: get parent task of another project in project sharing
Before this commit, the portal user can see the parent stat button in project sharing form view of task if the parent is in the same project. This button can be clicked and it redirects the user to the parent task form view in the project sharing. This commit improves this button and its visibility in project sharing feature. The button is visible only if the current user has access to the project of the parent task. That is the privacy visibility of the project should be set to 'portal'. If the portal user has access to the project of the parent task and he is not a collaborator of this project, then the current user will be redirected to the classic portal view of the parent task. If it is a collaborator then we display the parent task in the project sharing feature. task-2648955 Closes #82379
This commit is contained in:
@@ -10,8 +10,8 @@ from odoo.addons.project.controllers.portal import CustomerPortal
|
||||
|
||||
class ProjectCustomerPortal(CustomerPortal):
|
||||
|
||||
def _prepare_project_sharing_session_info(self, project):
|
||||
session_info = super()._prepare_project_sharing_session_info(project)
|
||||
def _prepare_project_sharing_session_info(self, project, task=None):
|
||||
session_info = super()._prepare_project_sharing_session_info(project, task)
|
||||
|
||||
company = project.company_id
|
||||
timesheet_encode_uom = company.timesheet_encode_uom_id
|
||||
|
||||
@@ -147,19 +147,22 @@ class ProjectCustomerPortal(CustomerPortal):
|
||||
return request.render("project.portal_my_projects", values)
|
||||
|
||||
@http.route(['/my/project/<int:project_id>'], type='http', auth="public", website=True)
|
||||
def portal_my_project(self, project_id=None, access_token=None, page=1, date_begin=None, date_end=None, sortby=None, search=None, search_in='content', groupby=None, **kw):
|
||||
def portal_my_project(self, project_id=None, access_token=None, page=1, date_begin=None, date_end=None, sortby=None, search=None, search_in='content', groupby=None, task_id=None, **kw):
|
||||
try:
|
||||
project_sudo = self._document_check_access('project.project', project_id, access_token)
|
||||
except (AccessError, MissingError):
|
||||
return request.redirect('/my')
|
||||
if project_sudo.with_user(request.env.user)._check_project_sharing_access():
|
||||
return request.render("project.project_sharing_portal", {'project_id': project_id})
|
||||
values = {'project_id': project_id}
|
||||
if task_id:
|
||||
values['task_id'] = task_id
|
||||
return request.render("project.project_sharing_portal", values)
|
||||
project_sudo = project_sudo if access_token else project_sudo.with_user(request.env.user)
|
||||
values = self._project_get_page_view_values(project_sudo, access_token, page, date_begin, date_end, sortby, search, search_in, groupby, **kw)
|
||||
values['task_url'] = 'project/%s/task' % project_id
|
||||
return request.render("project.portal_my_project", values)
|
||||
|
||||
def _prepare_project_sharing_session_info(self, project):
|
||||
def _prepare_project_sharing_session_info(self, project, task=None):
|
||||
session_info = request.env['ir.http'].session_info()
|
||||
user_context = request.session.get_context() if request.session.uid else {}
|
||||
mods = conf.server_wide_modules or []
|
||||
@@ -188,17 +191,19 @@ class ProjectCustomerPortal(CustomerPortal):
|
||||
# FIXME: See if we prefer to give only the currency that the portal user just need to see the correct information in project sharing
|
||||
currencies=request.env['ir.http'].get_currencies(),
|
||||
)
|
||||
if task:
|
||||
session_info['open_task_action'] = task.action_project_sharing_open_task()
|
||||
return session_info
|
||||
|
||||
@http.route("/my/project/<int:project_id>/project_sharing", type="http", auth="user", methods=['GET'])
|
||||
def render_project_backend_view(self, project_id):
|
||||
def render_project_backend_view(self, project_id, task_id=None):
|
||||
project = request.env['project.project'].sudo().browse(project_id)
|
||||
if not project.exists() or not project.with_user(request.env.user)._check_project_sharing_access():
|
||||
return request.not_found()
|
||||
|
||||
task = task_id and request.env['project.task'].browse(int(task_id))
|
||||
return request.render(
|
||||
'project.project_sharing_embed',
|
||||
{'session_info': self._prepare_project_sharing_session_info(project)},
|
||||
{'session_info': self._prepare_project_sharing_session_info(project, task)},
|
||||
)
|
||||
|
||||
@http.route('/my/project/<int:project_id>/task/<int:task_id>', type='http', auth='public', website=True)
|
||||
|
||||
@@ -44,6 +44,7 @@ PROJECT_TASK_READABLE_FIELDS = {
|
||||
'legend_blocked',
|
||||
'legend_done',
|
||||
'user_ids',
|
||||
'display_parent_task_button',
|
||||
}
|
||||
|
||||
PROJECT_TASK_WRITABLE_FIELDS = {
|
||||
@@ -1038,6 +1039,9 @@ class Task(models.Model):
|
||||
domain="[('allow_task_dependencies', '=', True), ('id', '!=', id)]")
|
||||
dependent_tasks_count = fields.Integer(string="Dependent Tasks", compute='_compute_dependent_tasks_count')
|
||||
|
||||
# Project sharing fields
|
||||
display_parent_task_button = fields.Boolean(compute='_compute_display_parent_task_button', compute_sudo=True)
|
||||
|
||||
# recurrence fields
|
||||
allow_recurring_tasks = fields.Boolean(related='project_id.allow_recurring_tasks')
|
||||
recurring_task = fields.Boolean(string="Recurrent")
|
||||
@@ -1470,6 +1474,11 @@ class Task(models.Model):
|
||||
"""
|
||||
return [('id', 'inselect', (query, [f'%{value}%']))]
|
||||
|
||||
def _compute_display_parent_task_button(self):
|
||||
accessible_parent_tasks = self.parent_id.with_user(self.env.user)._filter_access_rules('read')
|
||||
for task in self:
|
||||
task.display_parent_task_button = task.parent_id in accessible_parent_tasks
|
||||
|
||||
@api.returns('self', lambda value: value.id)
|
||||
def copy(self, default=None):
|
||||
if default is None:
|
||||
@@ -2113,6 +2122,26 @@ class Task(models.Model):
|
||||
'context': self._context
|
||||
}
|
||||
|
||||
def action_project_sharing_view_parent_task(self):
|
||||
if self.parent_id.project_id != self.project_id and self.user_has_groups('base.group_portal'):
|
||||
project = self.parent_id.project_id._filter_access_rules_python('read')
|
||||
if project:
|
||||
url = f"/my/projects/{self.parent_id.project_id.id}/task/{self.parent_id.id}"
|
||||
if project._check_project_sharing_access():
|
||||
url = f"/my/projects/{self.parent_id.project_id.id}?task_id={self.parent_id.id}"
|
||||
return {
|
||||
"name": "Portal Parent Task",
|
||||
"type": "ir.actions.act_url",
|
||||
"url": url,
|
||||
}
|
||||
elif self.display_parent_task_button:
|
||||
return self.parent_id.get_portal_url()
|
||||
# The portal user has no access to the parent task, so normally the button should be invisible.
|
||||
return {}
|
||||
action = self.action_open_parent_task()
|
||||
action['views'] = [(self.env.ref('project.project_sharing_project_task_view_form').id, 'form')]
|
||||
return action
|
||||
|
||||
# ------------
|
||||
# Actions
|
||||
# ------------
|
||||
@@ -2126,6 +2155,11 @@ class Task(models.Model):
|
||||
'context': self._context
|
||||
}
|
||||
|
||||
def action_project_sharing_open_task(self):
|
||||
action = self.action_open_task()
|
||||
action['views'] = [[self.env.ref('project.project_sharing_project_task_view_form').id, 'form']]
|
||||
return action
|
||||
|
||||
def action_dependent_tasks(self):
|
||||
self.ensure_one()
|
||||
action = {
|
||||
|
||||
@@ -43,7 +43,7 @@ export class ProjectSharingWebClient extends Component {
|
||||
}
|
||||
|
||||
async _showView() {
|
||||
const { action_name, project_id } = session;
|
||||
const { action_name, project_id, open_task_action } = session;
|
||||
await this.actionService.doAction(
|
||||
action_name,
|
||||
{
|
||||
@@ -53,6 +53,9 @@ export class ProjectSharingWebClient extends Component {
|
||||
}
|
||||
}
|
||||
);
|
||||
if (open_task_action) {
|
||||
await this.actionService.doAction(open_task_action);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
</template>
|
||||
|
||||
<template id="project_sharing" name="Project Sharing View">
|
||||
<iframe width="100%" height="100%" frameborder="0" t-attf-src="/my/project/{{ project_id }}/project_sharing"/>
|
||||
<iframe width="100%" height="100%" frameborder="0" t-attf-src="/my/project/{{ project_id }}{{ '/' + task_id if task_id else '' }}/project_sharing"/>
|
||||
</template>
|
||||
|
||||
<template id="project_sharing_embed" name="Project Sharing View Embed">
|
||||
|
||||
@@ -159,7 +159,8 @@
|
||||
</header>
|
||||
<sheet string="Task">
|
||||
<div class="oe_button_box" name="button_box">
|
||||
<button name="action_open_parent_task" type="object" special="cancel" class="oe_stat_button o_debounce_disabled" icon="fa-tasks" string="Parent Task" attrs="{'invisible': [('parent_id', '=', False)]}"/>
|
||||
<field name="display_parent_task_button" invisible="1"/>
|
||||
<button name="action_project_sharing_view_parent_task" type="object" class="oe_stat_button" icon="fa-tasks" string="Parent Task" attrs="{'invisible': [('display_parent_task_button', '=', False)]}"/>
|
||||
</div>
|
||||
<widget name="web_ribbon" title="Archived" bg_color="bg-danger" attrs="{'invisible': [('active', '=', True)]}"/>
|
||||
<div class="oe_title pr-0">
|
||||
|
||||
Reference in New Issue
Block a user