commit
4b255b9e4e
|
|
@ -1 +1,2 @@
|
||||||
from . import hr_employee
|
from . import hr_employee
|
||||||
|
from . import hr_leave
|
||||||
|
|
@ -0,0 +1,107 @@
|
||||||
|
from odoo import api, models, _, fields
|
||||||
|
from odoo.exceptions import ValidationError
|
||||||
|
from odoo.tools.misc import format_date
|
||||||
|
from datetime import datetime
|
||||||
|
|
||||||
|
class HRLeave(models.Model):
|
||||||
|
_inherit = "hr.leave"
|
||||||
|
|
||||||
|
def flutter_check_overlap_constrain(self,employee_id, to_date, from_date):
|
||||||
|
if self.env.context.get('leave_skip_date_check', False):
|
||||||
|
return
|
||||||
|
date_from = datetime.fromisoformat(from_date).replace(hour=0, minute=0, second=0)
|
||||||
|
date_to = datetime.fromisoformat(to_date).replace(hour=23, minute=59, second=59)
|
||||||
|
employee_id = int(employee_id)
|
||||||
|
all_leaves = self.search([
|
||||||
|
('date_from', '<', date_to),
|
||||||
|
('date_to', '>', date_from),
|
||||||
|
('employee_id', 'in', [employee_id]),
|
||||||
|
('state', 'not in', ['cancel', 'refuse']),
|
||||||
|
])
|
||||||
|
domain = [
|
||||||
|
('employee_id', '=', employee_id),
|
||||||
|
('date_from', '<', date_to),
|
||||||
|
('date_to', '>', date_from),
|
||||||
|
('state', 'not in', ['cancel', 'refuse']),
|
||||||
|
]
|
||||||
|
conflicting_holidays = all_leaves.filtered_domain(domain)
|
||||||
|
|
||||||
|
if conflicting_holidays:
|
||||||
|
conflicting_holidays_list = []
|
||||||
|
# Do not display the name of the employee if the conflicting holidays have an employee_id.user_id equivalent to the user id
|
||||||
|
holidays_only_have_uid = bool(employee_id)
|
||||||
|
holiday_states = dict(conflicting_holidays.fields_get(allfields=['state'])['state']['selection'])
|
||||||
|
for conflicting_holiday in conflicting_holidays:
|
||||||
|
conflicting_holiday_data = {}
|
||||||
|
conflicting_holiday_data['employee_name'] = conflicting_holiday.employee_id.name
|
||||||
|
conflicting_holiday_data['date_from'] = format_date(self.env,
|
||||||
|
min(conflicting_holiday.mapped('date_from')))
|
||||||
|
conflicting_holiday_data['date_to'] = format_date(self.env,
|
||||||
|
min(conflicting_holiday.mapped('date_to')))
|
||||||
|
conflicting_holiday_data['state'] = holiday_states[conflicting_holiday.state]
|
||||||
|
if conflicting_holiday.employee_id.user_id.id != self.env.uid:
|
||||||
|
holidays_only_have_uid = False
|
||||||
|
if conflicting_holiday_data not in conflicting_holidays_list:
|
||||||
|
conflicting_holidays_list.append(conflicting_holiday_data)
|
||||||
|
if not conflicting_holidays_list:
|
||||||
|
return
|
||||||
|
conflicting_holidays_strings = []
|
||||||
|
if holidays_only_have_uid:
|
||||||
|
for conflicting_holiday_data in conflicting_holidays_list:
|
||||||
|
conflicting_holidays_string = _('from %(date_from)s to %(date_to)s - %(state)s',
|
||||||
|
date_from=conflicting_holiday_data['date_from'],
|
||||||
|
date_to=conflicting_holiday_data['date_to'],
|
||||||
|
state=conflicting_holiday_data['state'])
|
||||||
|
conflicting_holidays_strings.append(conflicting_holidays_string)
|
||||||
|
error = """\
|
||||||
|
You've already booked time off which overlaps with this period:
|
||||||
|
%s
|
||||||
|
Attempting to double-book your time off won't magically make your vacation 2x better!
|
||||||
|
""".join(conflicting_holidays_strings)
|
||||||
|
return error
|
||||||
|
for conflicting_holiday_data in conflicting_holidays_list:
|
||||||
|
conflicting_holidays_string = "\n" + _(
|
||||||
|
'%(employee_name)s - from %(date_from)s to %(date_to)s - %(state)s',
|
||||||
|
employee_name=conflicting_holiday_data['employee_name'],
|
||||||
|
date_from=conflicting_holiday_data['date_from'],
|
||||||
|
date_to=conflicting_holiday_data['date_to'],
|
||||||
|
state=conflicting_holiday_data['state'])
|
||||||
|
conflicting_holidays_strings.append(conflicting_holidays_string)
|
||||||
|
error = "An employee already booked time off which overlaps with this period:%s","".join(conflicting_holidays_strings)
|
||||||
|
return error
|
||||||
|
|
||||||
|
@api.model
|
||||||
|
def calculate_leave_duration(self, date_from, date_to, employee_id):
|
||||||
|
"""
|
||||||
|
Calculate the number of days and hours for the given date range and employee.
|
||||||
|
"""
|
||||||
|
employee = self.env['hr.employee'].browse(employee_id)
|
||||||
|
if not employee:
|
||||||
|
return {'error': 'Employee not found'}
|
||||||
|
|
||||||
|
from_date = datetime.fromisoformat(date_from).replace(hour=0, minute=0, second=0)
|
||||||
|
to_date = datetime.fromisoformat(date_to).replace(hour=23, minute=59, second=59)
|
||||||
|
|
||||||
|
# Define a fake leave record to use _get_durations
|
||||||
|
leave_values = {
|
||||||
|
'employee_id': employee.id,
|
||||||
|
'date_from': fields.Datetime.from_string(from_date),
|
||||||
|
'date_to': fields.Datetime.from_string(to_date),
|
||||||
|
'holiday_status_id': self.env['hr.leave.type'].search([], limit=1).id,
|
||||||
|
# Replace with appropriate leave type ID
|
||||||
|
'resource_calendar_id': employee.resource_calendar_id.id,
|
||||||
|
}
|
||||||
|
leave = self.new(leave_values)
|
||||||
|
durations = leave._get_durations()
|
||||||
|
leave_id = list(durations.keys())[0]
|
||||||
|
days, hours = durations[leave_id]
|
||||||
|
|
||||||
|
return {
|
||||||
|
'days': float(days),
|
||||||
|
'hours': float(hours),
|
||||||
|
}
|
||||||
|
|
||||||
|
@api.model
|
||||||
|
def submit_leave_flutter_odoo(self,leave_request_data):
|
||||||
|
print(leave_request_data)
|
||||||
|
pass
|
||||||
|
|
@ -35,7 +35,7 @@
|
||||||
<field name="max_check_out"/>
|
<field name="max_check_out"/>
|
||||||
<field name="out_time" widget="float_time"/>
|
<field name="out_time" widget="float_time"/>
|
||||||
<field name="worked_hours" widget="float_time"/>
|
<field name="worked_hours" widget="float_time"/>
|
||||||
<!-- <field name="extra_hours"/>-->
|
<!-- <field name="extra_hours"/>-->
|
||||||
<field name="status"/>
|
<field name="status"/>
|
||||||
</list>
|
</list>
|
||||||
</field>
|
</field>
|
||||||
|
|
@ -57,7 +57,7 @@
|
||||||
<field name="max_check_out"/>
|
<field name="max_check_out"/>
|
||||||
<field name="out_time"/>
|
<field name="out_time"/>
|
||||||
<field name="worked_hours"/>
|
<field name="worked_hours"/>
|
||||||
<!-- <field name="extra_hours"/>-->
|
<!-- <field name="extra_hours"/>-->
|
||||||
<field name="status"/>
|
<field name="status"/>
|
||||||
<field name="attendance_id"/>
|
<field name="attendance_id"/>
|
||||||
</list>
|
</list>
|
||||||
|
|
@ -77,11 +77,42 @@
|
||||||
</field>
|
</field>
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
<menuitem id="menu_attendance_attendance" name="Management" parent="hr_attendance.menu_hr_attendance_root"
|
<menuitem id="menu_attendance_attendance" name="Management" parent="hr_attendance.menu_hr_attendance_root"
|
||||||
sequence="6" groups="hr_attendance.group_hr_attendance_officer"/>
|
sequence="6" groups="hr_attendance.group_hr_attendance_officer"/>
|
||||||
|
|
||||||
<!-- Menu for Attendance -->
|
<!-- Menu for Attendance -->
|
||||||
<menuitem id="hr_attendance.menu_hr_attendance_view_attendances_management" name="Attendance" parent="hr_attendance_extended.menu_attendance_attendance" sequence="6" groups="hr_attendance.group_hr_attendance_officer" action="action_attendance_attendance"/>
|
<menuitem id="hr_attendance.menu_hr_attendance_view_attendances_management" name="Attendance"
|
||||||
|
parent="hr_attendance_extended.menu_attendance_attendance" sequence="6"
|
||||||
|
groups="hr_attendance.group_hr_attendance_officer" action="action_attendance_attendance"/>
|
||||||
|
|
||||||
|
|
||||||
|
<record id="hr_attendance_management_view_filter_inherit" model="ir.ui.view">
|
||||||
|
<field name="name">hr_attendance_management_view_filter_inherit</field>
|
||||||
|
<field name="model">hr.attendance</field>
|
||||||
|
<field name="inherit_id" ref="hr_attendance.hr_attendance_management_view_filter"/>
|
||||||
|
<field name="arch" type="xml">
|
||||||
|
<xpath expr="//search" position="inside">
|
||||||
|
<searchpanel>
|
||||||
|
<field name="department_id" icon="fa-users" enable_counters="1"/>
|
||||||
|
</searchpanel>
|
||||||
|
|
||||||
|
</xpath>
|
||||||
|
</field>
|
||||||
|
</record>
|
||||||
|
|
||||||
|
<record id="hr_attendance_view_filter_inherit" model="ir.ui.view">
|
||||||
|
<field name="name">hr_attendance_view_filter_inherit</field>
|
||||||
|
<field name="model">hr.attendance</field>
|
||||||
|
<field name="inherit_id" ref="hr_attendance.hr_attendance_view_filter"/>
|
||||||
|
<field name="arch" type="xml">
|
||||||
|
<xpath expr="//search" position="inside">
|
||||||
|
<searchpanel>
|
||||||
|
<field name="department_id" icon="fa-users" enable_counters="1"/>
|
||||||
|
</searchpanel>
|
||||||
|
|
||||||
|
</xpath>
|
||||||
|
</field>
|
||||||
|
</record>
|
||||||
|
|
||||||
</data>
|
</data>
|
||||||
</odoo>
|
</odoo>
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,8 @@ class AppraisalPeriod(models.Model):
|
||||||
@api.onchange('date_to')
|
@api.onchange('date_to')
|
||||||
def onchange_activation_date(self):
|
def onchange_activation_date(self):
|
||||||
for rec in self:
|
for rec in self:
|
||||||
rec.activation_date = rec.date_to + timedelta(days=1)
|
if rec.date_to:
|
||||||
|
rec.activation_date = rec.date_to + timedelta(days=1)
|
||||||
|
|
||||||
_defaults = {
|
_defaults = {
|
||||||
'color_name': 'red',
|
'color_name': 'red',
|
||||||
|
|
|
||||||
|
|
@ -18,10 +18,11 @@
|
||||||
'version': '0.1',
|
'version': '0.1',
|
||||||
|
|
||||||
# any module necessary for this one to work correctly
|
# any module necessary for this one to work correctly
|
||||||
'depends': ['base','hr'],
|
'depends': ['base','hr','mail'],
|
||||||
|
|
||||||
# always loaded
|
# always loaded
|
||||||
'data': [
|
'data': [
|
||||||
|
'security/security.xml',
|
||||||
'security/ir.model.access.csv',
|
'security/ir.model.access.csv',
|
||||||
'views/hr_employee.xml',
|
'views/hr_employee.xml',
|
||||||
'wizards/work_location_wizard.xml'
|
'wizards/work_location_wizard.xml'
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,9 @@ class HrEmployeeBase(models.AbstractModel):
|
||||||
|
|
||||||
total_exp = fields.Char(string='Total Experience', compute='_compute_total_experience', store=True)
|
total_exp = fields.Char(string='Total Experience', compute='_compute_total_experience', store=True)
|
||||||
|
|
||||||
|
emp_type = fields.Many2one('hr.contract.type', "Employee Type", tracking=True)
|
||||||
|
|
||||||
|
|
||||||
@api.constrains('identification_id')
|
@api.constrains('identification_id')
|
||||||
def _check_identification_id(self):
|
def _check_identification_id(self):
|
||||||
for record in self:
|
for record in self:
|
||||||
|
|
@ -80,3 +83,4 @@ class HrEmployeeBase(models.AbstractModel):
|
||||||
total_years = record.previous_exp // 12
|
total_years = record.previous_exp // 12
|
||||||
total_months = record.previous_exp % 12
|
total_months = record.previous_exp % 12
|
||||||
record.total_exp = f"{total_years} years {total_months} months 0 days"
|
record.total_exp = f"{total_years} years {total_months} months 0 days"
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,22 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8" ?>
|
||||||
|
<odoo>
|
||||||
|
<data>
|
||||||
|
|
||||||
|
<record id="module_internal_user_category" model="ir.module.category">
|
||||||
|
<field name="name">Internal User Category</field>
|
||||||
|
<field name="sequence">17</field>
|
||||||
|
</record>
|
||||||
|
<record id="group_external_user" model="res.groups">
|
||||||
|
<field name="name">External User</field>
|
||||||
|
<field name="category_id" ref="hr_employee_extended.module_internal_user_category"/>
|
||||||
|
</record>
|
||||||
|
|
||||||
|
<record id="group_internal_user" model="res.groups">
|
||||||
|
<field name="name">Internal User</field>
|
||||||
|
<field name="implied_ids" eval="[(4, ref('group_external_user'))]"/>
|
||||||
|
<field name="category_id" ref="hr_employee_extended.module_internal_user_category"/>
|
||||||
|
</record>
|
||||||
|
|
||||||
|
|
||||||
|
</data>
|
||||||
|
</odoo>
|
||||||
|
|
@ -6,8 +6,12 @@
|
||||||
<field name="model">hr.employee</field>
|
<field name="model">hr.employee</field>
|
||||||
<field name="inherit_id" ref="hr.view_employee_form"/>
|
<field name="inherit_id" ref="hr.view_employee_form"/>
|
||||||
<field name="arch" type="xml">
|
<field name="arch" type="xml">
|
||||||
|
<xpath expr="//field[@name='employee_type']" position="attributes">
|
||||||
|
<attribute name="invisible">1</attribute>
|
||||||
|
</xpath>
|
||||||
<xpath expr="//field[@name='work_email']" position="before">
|
<xpath expr="//field[@name='work_email']" position="before">
|
||||||
<field name="employee_id"/>
|
<field name="employee_id"/>
|
||||||
|
<field name="emp_type"/>
|
||||||
</xpath>
|
</xpath>
|
||||||
<xpath expr="//field[@name='work_location_id']" position="after">
|
<xpath expr="//field[@name='work_location_id']" position="after">
|
||||||
<field name="doj"/>
|
<field name="doj"/>
|
||||||
|
|
@ -60,5 +64,13 @@
|
||||||
</field>
|
</field>
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
|
<record id="mail.menu_root_discuss" model="ir.ui.menu">
|
||||||
|
<field name="groups_id" eval="[(3,ref('base.group_user')),(4, ref('hr_employee_extended.group_internal_user'))]"/>
|
||||||
|
</record>
|
||||||
|
|
||||||
|
|
||||||
|
<record id="hr.menu_hr_root" model="ir.ui.menu">
|
||||||
|
<field name="groups_id" eval="[(3,ref('hr.group_hr_manager')),(3,ref('hr.group_hr_user')),(3,ref('base.group_user')),(3,ref('hr_employee_extended.group_external_user')),(4, ref('hr_employee_extended.group_internal_user'))]"/>
|
||||||
|
</record>
|
||||||
</data>
|
</data>
|
||||||
</odoo>
|
</odoo>
|
||||||
|
|
@ -17,6 +17,8 @@ class hrLeaveAccrualLevel(models.Model):
|
||||||
('monthly', 'Monthly'),
|
('monthly', 'Monthly'),
|
||||||
('yearly', 'Yearly'),
|
('yearly', 'Yearly'),
|
||||||
], default='daily', required=True, string="Frequency")
|
], default='daily', required=True, string="Frequency")
|
||||||
|
emp_type = fields.Many2one('hr.contract.type', "Employee Type", tracking=True)
|
||||||
|
|
||||||
|
|
||||||
max_start_count = fields.Integer(
|
max_start_count = fields.Integer(
|
||||||
"Start after",
|
"Start after",
|
||||||
|
|
@ -98,7 +100,11 @@ class hrTimeoffAllocation(models.Model):
|
||||||
# Calculate the current frequency
|
# Calculate the current frequency
|
||||||
run_allocation = self._handel_weekly_frequency(level)
|
run_allocation = self._handel_weekly_frequency(level)
|
||||||
if run_allocation:
|
if run_allocation:
|
||||||
qualified_employees = employees.filtered(lambda emp: self._is_experience_in_range(emp, level))
|
if level.emp_type:
|
||||||
|
level_filtered_employees = employees.filtered(lambda emp: emp.emp_type == level.emp_type)
|
||||||
|
else:
|
||||||
|
level_filtered_employees = employees
|
||||||
|
qualified_employees = level_filtered_employees.filtered(lambda emp: self._emp_filter_by_level(emp, level))
|
||||||
|
|
||||||
# After filtering, we create the leave allocation for each employee
|
# After filtering, we create the leave allocation for each employee
|
||||||
for emp in qualified_employees:
|
for emp in qualified_employees:
|
||||||
|
|
@ -163,7 +169,7 @@ class hrTimeoffAllocation(models.Model):
|
||||||
return fields.date.today() >= start_date
|
return fields.date.today() >= start_date
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def _is_experience_in_range(self, employee, level):
|
def _emp_filter_by_level(self, employee, level):
|
||||||
"""
|
"""
|
||||||
Helper method to check if the employee's total experience (including previous experience) is within the
|
Helper method to check if the employee's total experience (including previous experience) is within the
|
||||||
range defined by the accrual's start and max start counts and types.
|
range defined by the accrual's start and max start counts and types.
|
||||||
|
|
@ -254,3 +260,28 @@ class HRLeave(models.Model):
|
||||||
for rec in self:
|
for rec in self:
|
||||||
if rec.employee_id.leave_manager_id.id != self.env.user.id:
|
if rec.employee_id.leave_manager_id.id != self.env.user.id:
|
||||||
raise ValidationError(_("Only Employees Time Off Approver can approve this "))
|
raise ValidationError(_("Only Employees Time Off Approver can approve this "))
|
||||||
|
|
||||||
|
@api.ondelete(at_uninstall=False)
|
||||||
|
def _unlink_if_correct_states(self):
|
||||||
|
error_message = _('You cannot delete a time off which is in %s state')
|
||||||
|
state_description_values = {elem[0]: elem[1] for elem in self._fields['state']._description_selection(self.env)}
|
||||||
|
now = fields.Datetime.now().date()
|
||||||
|
|
||||||
|
if not self.env.user.has_group('hr_holidays.group_hr_holidays_user'):
|
||||||
|
for hol in self:
|
||||||
|
if hol.state not in ['draft', 'cancel']:
|
||||||
|
raise UserError(error_message % state_description_values.get(self[:1].state))
|
||||||
|
if hol.date_from.date() < now:
|
||||||
|
raise UserError(_('You cannot delete a time off which is in the past'))
|
||||||
|
else:
|
||||||
|
for holiday in self.filtered(lambda holiday: holiday.state not in ['cancel', 'draft']):
|
||||||
|
raise UserError(error_message % (state_description_values.get(holiday.state),))
|
||||||
|
|
||||||
|
|
||||||
|
class HRLeaveType(models.Model):
|
||||||
|
_inherit='hr.leave.type'
|
||||||
|
|
||||||
|
request_unit_type = fields.Selection([
|
||||||
|
('day', 'Day'),
|
||||||
|
('half_day', 'Half Day')], default='day', string='Take Time Off in', required=True)
|
||||||
|
request_unit = fields.Selection(related="request_unit_type",store=True)
|
||||||
|
|
@ -7,6 +7,12 @@
|
||||||
<field name="model">hr.leave.accrual.plan</field>
|
<field name="model">hr.leave.accrual.plan</field>
|
||||||
<field name="inherit_id" ref="hr_holidays.hr_accrual_plan_view_form"/>
|
<field name="inherit_id" ref="hr_holidays.hr_accrual_plan_view_form"/>
|
||||||
<field name="arch" type="xml">
|
<field name="arch" type="xml">
|
||||||
|
<xpath expr="//field[@name='accrued_gain_time']" position="attributes">
|
||||||
|
<attribute name="invisible">1</attribute>
|
||||||
|
</xpath>
|
||||||
|
<xpath expr="//field[@name='transition_mode']" position="attributes">
|
||||||
|
<attribute name="invisible">1</attribute>
|
||||||
|
</xpath>
|
||||||
<xpath expr="//div[@name='carryover']" position="after">
|
<xpath expr="//div[@name='carryover']" position="after">
|
||||||
<field name="time_off_type_id" required="1"/>
|
<field name="time_off_type_id" required="1"/>
|
||||||
<div>
|
<div>
|
||||||
|
|
@ -16,6 +22,9 @@
|
||||||
<strong>after employee joining date</strong>
|
<strong>after employee joining date</strong>
|
||||||
</div>
|
</div>
|
||||||
</xpath>
|
</xpath>
|
||||||
|
<xpath expr="//field[@name='carryover_date']" position="attributes">
|
||||||
|
<attribute name="invisible">1</attribute>
|
||||||
|
</xpath>
|
||||||
<xpath expr="//field[@name='level_ids']/kanban" position="replace">
|
<xpath expr="//field[@name='level_ids']/kanban" position="replace">
|
||||||
<kanban default_order="sequence">
|
<kanban default_order="sequence">
|
||||||
<field name="sequence"/>
|
<field name="sequence"/>
|
||||||
|
|
@ -212,6 +221,15 @@
|
||||||
Experience is required
|
Experience is required
|
||||||
</div>
|
</div>
|
||||||
</group>
|
</group>
|
||||||
|
<group name="emp_types">
|
||||||
|
<div class="o_td_label">
|
||||||
|
<label for="emp_type" string="Employee Type"/>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<field name="emp_type" style="width: 4" required="max_start_count > 0 or max_start_type != False"/>
|
||||||
|
</div>
|
||||||
|
</group>
|
||||||
|
|
||||||
|
|
||||||
</xpath>
|
</xpath>
|
||||||
</field>
|
</field>
|
||||||
|
|
@ -229,5 +247,20 @@
|
||||||
|
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
|
|
||||||
|
<record model="ir.ui.view" id="hr_holidays_edit_holiday_status_form_inherit">
|
||||||
|
<field name="name">hr_holidays.edit_holiday_status_form.inherit</field>
|
||||||
|
<field name="model">hr.leave.type</field>
|
||||||
|
<field name="inherit_id" ref="hr_holidays.edit_holiday_status_form"/>
|
||||||
|
<field name="arch" type="xml">
|
||||||
|
<xpath expr="//field[@name='request_unit']" position="attributes">
|
||||||
|
<attribute name="invisible">1</attribute>
|
||||||
|
</xpath>
|
||||||
|
<xpath expr="//field[@name='request_unit']" position="after">
|
||||||
|
<field name="request_unit_type"/>
|
||||||
|
</xpath>
|
||||||
|
</field>
|
||||||
|
</record>
|
||||||
|
|
||||||
</data>
|
</data>
|
||||||
</odoo>
|
</odoo>
|
||||||
|
|
@ -1,89 +1,85 @@
|
||||||
.mk_apps_sidebar_panel {
|
.mk_apps_sidebar_panel {
|
||||||
@include mk-disable-scrollbar();
|
@include mk-disable-scrollbar();
|
||||||
background-color: $mk-appbar-background;
|
background-color: $mk-appbar-background;
|
||||||
width: var(--mk-sidebar-width, 0);
|
width: var(--mk-sidebar-collapsed-width, 40px); /* Collapsed width: Icons only */
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
|
transition: width 300ms ease; /* Smooth transition for width */
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
width: var(--mk-sidebar-expanded-width, 150px); /* Expanded width: Fits names */
|
||||||
|
}
|
||||||
|
|
||||||
.mk_apps_sidebar {
|
.mk_apps_sidebar {
|
||||||
height: 100%;
|
height: 100%;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
.mk_apps_sidebar_menu {
|
|
||||||
padding: 0;
|
.mk_apps_sidebar_menu {
|
||||||
> li > a {
|
padding: 0;
|
||||||
cursor: pointer;
|
|
||||||
font-size: 13px;
|
> li > a {
|
||||||
font-weight: 300;
|
cursor: pointer;
|
||||||
overflow: hidden;
|
font-size: 13px;
|
||||||
padding: 8px 11px;
|
font-weight: 300;
|
||||||
text-decoration: none;
|
overflow: hidden;
|
||||||
color: $mk-appbar-color;
|
padding: 8px 11px;
|
||||||
text-overflow: ellipsis;
|
text-decoration: none;
|
||||||
.mk_apps_sidebar_icon {
|
color: $mk-appbar-color;
|
||||||
width: 22px;
|
text-overflow: ellipsis;
|
||||||
height: 22px;
|
|
||||||
margin-right: 5px;
|
.mk_apps_sidebar_icon {
|
||||||
}
|
width: 22px;
|
||||||
}
|
height: 22px;
|
||||||
> li.active > a {
|
margin-right: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mk_apps_sidebar_name {
|
||||||
|
opacity: 0;
|
||||||
|
display: inline-block; /* Name stays inline with the icon */
|
||||||
|
margin-left: 5px; /* Spacing between icon and name */
|
||||||
|
transition: opacity 300ms ease;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
> li.active > a {
|
||||||
background: $mk-appbar-active;
|
background: $mk-appbar-active;
|
||||||
}
|
}
|
||||||
> li:hover > a {
|
> li:hover > a {
|
||||||
background: $mk-appbar-active;
|
background: $mk-appbar-active;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
> li > a .mk_apps_sidebar_name {
|
||||||
|
opacity: 1; /* All names visible on hover of the entire sidebar */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.mk_sidebar_type_large {
|
.mk_sidebar_type_large {
|
||||||
--mk-sidebar-width: #{$mk-sidebar-large-width};
|
--mk-sidebar-collapsed-width: 40px;
|
||||||
|
--mk-sidebar-expanded-width: 150px; /* Adjust this to match the names' width */
|
||||||
}
|
}
|
||||||
|
|
||||||
.mk_sidebar_type_small {
|
.mk_sidebar_type_small {
|
||||||
--mk-sidebar-width: #{$mk-sidebar-small-width};
|
--mk-sidebar-collapsed-width: 50px;
|
||||||
.mk_apps_sidebar_name {
|
--mk-sidebar-expanded-width: 150px; /* Adjust if needed */
|
||||||
display: none;
|
|
||||||
}
|
.mk_apps_sidebar_name {
|
||||||
.mk_apps_sidebar_icon {
|
display: none;
|
||||||
margin-right: 0 !important;
|
}
|
||||||
}
|
|
||||||
.mk_apps_sidebar_logo {
|
.mk_apps_sidebar_icon {
|
||||||
display: none;
|
margin-right: 0 !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.mk_apps_sidebar_logo {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.mk_sidebar_type_invisible {
|
.mk_sidebar_type_invisible {
|
||||||
--mk-sidebar-width: 0;
|
--mk-sidebar-collapsed-width: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.editor_has_snippets_hide_backend_navbar,
|
|
||||||
.o_home_menu_background,
|
|
||||||
.o_fullscreen {
|
|
||||||
--mk-sidebar-width: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.editor_has_snippets_hide_backend_navbar .mk_apps_sidebar_panel {
|
|
||||||
transition: width 300ms;
|
|
||||||
}
|
|
||||||
|
|
||||||
@include media-breakpoint-only(md) {
|
|
||||||
.mk_sidebar_type_large {
|
|
||||||
--mk-sidebar-width: #{$mk-sidebar-small-width};
|
|
||||||
.mk_apps_sidebar_name {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
.mk_apps_sidebar_icon {
|
|
||||||
margin-right: 0 !important;
|
|
||||||
}
|
|
||||||
.mk_apps_sidebar_logo {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@include media-breakpoint-down(md) {
|
|
||||||
.mk_sidebar_type_large, .mk_sidebar_type_small {
|
|
||||||
--mk-sidebar-width: 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue