Initial commit: Hr packages
|
After Width: | Height: | Size: 6.3 KiB |
|
|
@ -0,0 +1,24 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="70" height="70" viewBox="0 0 70 70">
|
||||
<defs>
|
||||
<path id="icon-a" d="M4,5.35309892e-14 C36.4160122,9.87060235e-15 58.0836068,-3.97961823e-14 65,5.07020818e-14 C69,6.733808e-14 70,1 70,5 C70,43.0488877 70,62.4235458 70,65 C70,69 69,70 65,70 C61,70 9,70 4,70 C1,70 7.10542736e-15,69 7.10542736e-15,65 C7.25721566e-15,62.4676575 3.83358709e-14,41.8005206 3.60818146e-14,5 C-1.13686838e-13,1 1,5.75716207e-14 4,5.35309892e-14 Z"/>
|
||||
<linearGradient id="icon-c" x1="100%" x2="0%" y1="0%" y2="100%">
|
||||
<stop offset="0%" stop-color="#CDC484"/>
|
||||
<stop offset="100%" stop-color="#B5AA59"/>
|
||||
</linearGradient>
|
||||
<path id="icon-d" d="M27.2777778,16.2348485 C32.4714536,16.2348485 36.681713,20.506348 36.681713,25.7755682 C36.681713,31.0447884 32.4714536,35.3162879 27.2777778,35.3162879 C22.0841019,35.3162879 17.8738426,31.0447884 17.8738426,25.7755682 C17.8738426,20.506348 22.0841019,16.2348485 27.2777778,16.2348485 Z M32,36 C32,35.5868456 24.1175854,37.5736818 20.6967864,35.0773525 L16.5053937,36.1404272 C13.9936026,36.7775087 12.2314815,39.0671622 12.2314815,41.6939608 L12.2314815,43.9029356 C12.2314815,45.4837136 13.4945475,46.7651515 15.052662,46.7651515 C25.363233,46.7651515 30.5185185,46.7651515 30.5185185,46.7651515 C28.6666667,40.4242424 32,36.4131544 32,36 Z M48.5116455,29.4292211 L49.8821338,32.7804044 C50.108418,33.3336802 50.7775488,33.5511019 51.2858154,33.2365172 L54.3643115,31.3309087 C55.1962939,30.8159288 56.2338818,31.569761 56.0011523,32.5201752 L55.140166,36.0368953 C54.9979932,36.61751 55.4115674,37.186738 56.0077051,37.230942 L59.6183691,37.4987982 C60.5941357,37.5712005 60.9904688,38.790921 60.2436182,39.4230444 L57.4800293,41.7619923 C57.0237549,42.1481736 57.0237549,42.8517324 57.4800293,43.2379137 L60.2436719,45.5769153 C60.9905762,46.2090387 60.5942432,47.4287592 59.6184229,47.5011615 L56.0077588,47.7690177 C55.4116211,47.8132217 54.9980469,48.3824497 55.1402197,48.9630644 L56.0012061,52.4797846 C56.2338818,53.4301987 55.1962939,54.1840309 54.3643652,53.669051 L51.2858691,51.7634425 C50.7776025,51.4488041 50.108418,51.6662258 49.8821875,52.2195553 L48.5116992,55.5707386 C48.1413086,56.4764115 46.8587988,56.4764115 46.4884082,55.5707386 L45.1179199,52.2195553 C44.8916357,51.6662795 44.2225049,51.4488578 43.7142383,51.7634425 L40.6356885,53.669051 C39.8037061,54.1840309 38.7661182,53.4301987 38.9988477,52.4797846 L39.859834,48.9630644 C40.0020068,48.3824497 39.5884326,47.8132217 38.9922949,47.7690177 L35.3816309,47.5011615 C34.4058643,47.4287592 34.0095313,46.2090387 34.7563818,45.5769153 L37.5199707,43.2379674 C37.9762451,42.8517862 37.9762451,42.1482273 37.5199707,41.762046 L34.7563281,39.4230444 C34.0094238,38.790921 34.4057568,37.5712005 35.3815771,37.4987982 L38.9922412,37.230942 C39.5883789,37.186738 40.0019531,36.61751 39.8597803,36.0368953 L38.9987939,32.5201752 C38.7661182,31.569761 39.8037061,30.8159288 40.6356348,31.3309087 L43.7141846,33.2365172 C44.2224512,33.5511556 44.891582,33.3337339 45.1178662,32.7804044 L46.4883545,29.4292211 C46.8587451,28.5236019 48.1412549,28.5236019 48.5116455,29.4292211 Z M54.8046875,42.4999799 C54.8046875,38.4721469 51.5277832,35.1952995 47.5,35.1952995 C43.4721631,35.1952995 40.1953125,38.4721469 40.1953125,42.4999799 C40.1953125,46.5278128 43.4721631,49.8046602 47.5,49.8046602 C51.5277832,49.8046602 54.8046875,46.5278128 54.8046875,42.4999799 Z M53.0859375,42.4999799 C53.0859375,45.5800843 50.5801074,48.0859119 47.5,48.0859119 C44.4198926,48.0859119 41.9140625,45.5800843 41.9140625,42.4999799 C41.9140625,39.4198754 44.4198926,36.9140478 47.5,36.9140478 C50.5801074,36.9140478 53.0859375,39.4198754 53.0859375,42.4999799 Z"/>
|
||||
<path id="icon-e" d="M27.2777778,14.2348485 C32.4714536,14.2348485 36.681713,18.506348 36.681713,23.7755682 C36.681713,29.0447884 32.4714536,33.3162879 27.2777778,33.3162879 C22.0841019,33.3162879 17.8738426,29.0447884 17.8738426,23.7755682 C17.8738426,18.506348 22.0841019,14.2348485 27.2777778,14.2348485 Z M32,34 C32,33.5868456 24.1175854,35.5736818 20.6967864,33.0773525 L16.5053937,34.1404272 C13.9936026,34.7775087 12.2314815,37.0671622 12.2314815,39.6939608 L12.2314815,41.9029356 C12.2314815,43.4837136 13.4945475,44.7651515 15.052662,44.7651515 C25.363233,44.7651515 30.5185185,44.7651515 30.5185185,44.7651515 C28.6666667,38.4242424 32,34.4131544 32,34 Z M48.5116455,27.4292211 L49.8821338,30.7804044 C50.108418,31.3336802 50.7775488,31.5511019 51.2858154,31.2365172 L54.3643115,29.3309087 C55.1962939,28.8159288 56.2338818,29.569761 56.0011523,30.5201752 L55.140166,34.0368953 C54.9979932,34.61751 55.4115674,35.186738 56.0077051,35.230942 L59.6183691,35.4987982 C60.5941357,35.5712005 60.9904688,36.790921 60.2436182,37.4230444 L57.4800293,39.7619923 C57.0237549,40.1481736 57.0237549,40.8517324 57.4800293,41.2379137 L60.2436719,43.5769153 C60.9905762,44.2090387 60.5942432,45.4287592 59.6184229,45.5011615 L56.0077588,45.7690177 C55.4116211,45.8132217 54.9980469,46.3824497 55.1402197,46.9630644 L56.0012061,50.4797846 C56.2338818,51.4301987 55.1962939,52.1840309 54.3643652,51.669051 L51.2858691,49.7634425 C50.7776025,49.4488041 50.108418,49.6662258 49.8821875,50.2195553 L48.5116992,53.5707386 C48.1413086,54.4764115 46.8587988,54.4764115 46.4884082,53.5707386 L45.1179199,50.2195553 C44.8916357,49.6662795 44.2225049,49.4488578 43.7142383,49.7634425 L40.6356885,51.669051 C39.8037061,52.1840309 38.7661182,51.4301987 38.9988477,50.4797846 L39.859834,46.9630644 C40.0020068,46.3824497 39.5884326,45.8132217 38.9922949,45.7690177 L35.3816309,45.5011615 C34.4058643,45.4287592 34.0095313,44.2090387 34.7563818,43.5769153 L37.5199707,41.2379674 C37.9762451,40.8517862 37.9762451,40.1482273 37.5199707,39.762046 L34.7563281,37.4230444 C34.0094238,36.790921 34.4057568,35.5712005 35.3815771,35.4987982 L38.9922412,35.230942 C39.5883789,35.186738 40.0019531,34.61751 39.8597803,34.0368953 L38.9987939,30.5201752 C38.7661182,29.569761 39.8037061,28.8159288 40.6356348,29.3309087 L43.7141846,31.2365172 C44.2224512,31.5511556 44.891582,31.3337339 45.1178662,30.7804044 L46.4883545,27.4292211 C46.8587451,26.5236019 48.1412549,26.5236019 48.5116455,27.4292211 Z M54.8046875,40.4999799 C54.8046875,36.4721469 51.5277832,33.1952995 47.5,33.1952995 C43.4721631,33.1952995 40.1953125,36.4721469 40.1953125,40.4999799 C40.1953125,44.5278128 43.4721631,47.8046602 47.5,47.8046602 C51.5277832,47.8046602 54.8046875,44.5278128 54.8046875,40.4999799 Z M53.0859375,40.4999799 C53.0859375,43.5800843 50.5801074,46.0859119 47.5,46.0859119 C44.4198926,46.0859119 41.9140625,43.5800843 41.9140625,40.4999799 C41.9140625,37.4198754 44.4198926,34.9140478 47.5,34.9140478 C50.5801074,34.9140478 53.0859375,37.4198754 53.0859375,40.4999799 Z"/>
|
||||
</defs>
|
||||
<g fill="none" fill-rule="evenodd">
|
||||
<mask id="icon-b" fill="#fff">
|
||||
<use xlink:href="#icon-a"/>
|
||||
</mask>
|
||||
<g mask="url(#icon-b)">
|
||||
<rect width="70" height="70" fill="url(#icon-c)"/>
|
||||
<path fill="#FFF" fill-opacity=".383" d="M4,1.8 L65,1.8 C67.6666667,1.8 69.3333333,1.13333333 70,-0.2 C70,2.46666667 70,3.46666667 70,2.8 L1.10547097e-14,2.8 C-1.65952376e-14,3.46666667 -2.9161925e-14,2.46666667 -2.66453526e-14,-0.2 C0.666666667,1.13333333 2,1.8 4,1.8 Z" transform="matrix(1 0 0 -1 0 2.8)"/>
|
||||
<path fill="#393939" d="M43.6444444,52 L4,52 C2,52 -7.10542736e-15,51.8514286 0,47.84 L2.21121142e-16,23.3197384 L20,0 L36,9.36 L30.6694253,16.3853185 L31.9690606,16.0436983 L28.4526012,19.3069352 L28.4526012,24.5134324 L39.2011791,11.8378465 L42.1902641,14.2434656 L46.8367307,9.36 L51,14.56 L60.3723121,27.0292074 L43.6444444,52 Z" opacity=".324" transform="translate(0 18)"/>
|
||||
<path fill="#000" fill-opacity=".383" d="M4,4 L65,4 C67.6666667,4 69.3333333,3 70,1 C70,3.66666667 70,5 70,5 L1.77635684e-15,5 C1.77635684e-15,5 1.77635684e-15,3.66666667 1.77635684e-15,1 C0.666666667,3 2,4 4,4 Z" transform="translate(0 65)"/>
|
||||
<use fill="#000" fill-rule="nonzero" opacity=".3" xlink:href="#icon-d"/>
|
||||
<use fill="#FFF" fill-rule="nonzero" xlink:href="#icon-e"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 8 KiB |
|
|
@ -0,0 +1,16 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<templates xml:space="preserve">
|
||||
<t t-inherit="mail.PersonaImStatusIcon" t-inherit-mode="extension">
|
||||
<xpath expr="//*[@name='root']" position="inside">
|
||||
<t t-if="personaImStatusIconView.persona.im_status === 'leave_online'">
|
||||
<i class="o_PersonaImStatusIcon_icon o-online fa fa-plane fa-stack-1x text-primary" title="Online" role="img" aria-label="User is online"/>
|
||||
</t>
|
||||
<t t-if="personaImStatusIconView.persona.im_status === 'leave_away'">
|
||||
<i class="o_PersonaImStatusIcon_icon o-away fa fa-plane fa-stack-1x text-warning" title="Away" role="img" aria-label="User is away"/>
|
||||
</t>
|
||||
<t t-if="personaImStatusIconView.persona.im_status === 'leave_offline'">
|
||||
<i class="o_PersonaImStatusIcon_icon o-offline fa fa-plane fa-stack-1x text-700" title="Out of office" role="img" aria-label="User is out of office"/>
|
||||
</t>
|
||||
</xpath>
|
||||
</t>
|
||||
</templates>
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<templates xml:space="preserve">
|
||||
<t t-inherit="mail.ThreadIcon" t-inherit-mode="extension">
|
||||
<xpath expr="//*[@name='noImStatusCondition']" position="before">
|
||||
<t t-elif="thread.channel.correspondent.im_status === 'leave_online'">
|
||||
<div class="o_ThreadIcon_online fa fa-fw fa-plane" title="Online"/>
|
||||
</t>
|
||||
<t t-elif="thread.channel.correspondent.im_status === 'leave_away'">
|
||||
<div class="o_ThreadIcon_away fa fa-fw fa-plane text-warning" title="Away"/>
|
||||
</t>
|
||||
<t t-elif="thread.channel.correspondent.im_status === 'leave_offline'">
|
||||
<div class="o_ThreadIcon_offline fa fa-fw fa-plane" title="Out of office"/>
|
||||
</t>
|
||||
</xpath>
|
||||
</t>
|
||||
</templates>
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
// -----------------------------------------------------------------------------
|
||||
// Layout
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
.o_ThreadView_outOfOffice {
|
||||
margin-top: 0;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<templates xml:space="preserve">
|
||||
<t t-inherit="mail.ThreadView" t-inherit-mode="extension">
|
||||
<xpath expr="//*[@name='loadingCondition']" position="before">
|
||||
<t t-if="threadView.thread.channel and threadView.thread.channel.correspondent and threadView.thread.channel.correspondent.outOfOfficeText">
|
||||
<div class="o_ThreadView_outOfOffice alert alert-primary" t-esc="threadView.thread.channel.correspondent.outOfOfficeText" role="alert"/>
|
||||
</t>
|
||||
</xpath>
|
||||
</t>
|
||||
</templates>
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
// = HR Holidays
|
||||
// ============================================================================
|
||||
// No CSS hacks, variables overrides only
|
||||
.o_timeoff_card, .o_time_off_icon_types {
|
||||
--timeOffCard-icon-filter: invert(1) brightness(2);
|
||||
}
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
/* @odoo-module */
|
||||
|
||||
import Popover from "web.Popover";
|
||||
|
||||
const { Component } = owl;
|
||||
|
||||
export class TimeOffCardPopover extends Component {}
|
||||
TimeOffCardPopover.components = { Popover };
|
||||
|
||||
TimeOffCardPopover.template = 'hr_holidays.TimeOffCardPopover';
|
||||
TimeOffCardPopover.props = ['allocated', 'approved', 'planned', 'left', 'usable'];
|
||||
|
||||
export class TimeOffCard extends Component {}
|
||||
|
||||
TimeOffCard.components = { TimeOffCardPopover };
|
||||
TimeOffCard.template = 'hr_holidays.TimeOffCard';
|
||||
TimeOffCard.props = ['name', 'id', 'data', 'requires_allocation'];
|
||||
|
||||
export class TimeOffCardMobile extends TimeOffCard {}
|
||||
|
||||
TimeOffCardMobile.template = 'hr_holidays.TimeOffCardMobile';
|
||||
|
|
@ -0,0 +1,74 @@
|
|||
.o_timeoff_card {
|
||||
flex-direction: column;
|
||||
flex-grow: 1;
|
||||
display: flex;
|
||||
text-align: center;
|
||||
|
||||
&:not(:last-child) {
|
||||
border-right: 2px solid $border-color;
|
||||
}
|
||||
|
||||
span {
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
.o_timeoff_name {
|
||||
color: $body-color;
|
||||
font-size: 15px;
|
||||
margin-bottom: 3px;
|
||||
}
|
||||
|
||||
.o_timeoff_duration {
|
||||
font-size: 30px;
|
||||
font-weight: bold;
|
||||
|
||||
img {
|
||||
height: 30px;
|
||||
filter: var(--timeOffCard-icon-filter);
|
||||
}
|
||||
}
|
||||
|
||||
.o_timeoff_validity {
|
||||
font-size: 10px;
|
||||
}
|
||||
|
||||
.o_timeoff_info {
|
||||
display: inline-block;
|
||||
margin-right: -10px;
|
||||
|
||||
span {
|
||||
cursor: pointer;
|
||||
padding-right: 10px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.o_timeoff_card_mobile {
|
||||
.o_timeoff_green {
|
||||
color: $o-enterprise-primary-color;
|
||||
}
|
||||
}
|
||||
|
||||
.o_timeoff_popover {
|
||||
background-color: $o-view-background-color;
|
||||
font-size: 12px;
|
||||
|
||||
ul {
|
||||
list-style-type: none;
|
||||
margin-bottom: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
li {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
|
||||
span {
|
||||
padding-left: 3px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.o_time_off_icon_types img {
|
||||
filter: var(--timeOffCard-icon-filter);
|
||||
}
|
||||
|
|
@ -0,0 +1,74 @@
|
|||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<templates xml:space="preserve">
|
||||
<div t-name="hr_holidays.TimeOffCard" owl="1" class="o_timeoff_card py-3 text-odoo">
|
||||
<t t-set="data" t-value="props.data"/>
|
||||
<t t-set="duration" t-value="props.requires_allocation ? data.virtual_remaining_leaves : data.virtual_leaves_taken"/>
|
||||
<t t-set="show_popover" t-value="true"/>
|
||||
|
||||
<strong class="o_timeoff_name"><t t-esc="props.name"/></strong>
|
||||
<span class="o_timeoff_duration">
|
||||
<t t-if="data and data.icon">
|
||||
<img t-att-src="data.icon" />
|
||||
</t>
|
||||
<t t-esc="duration"/>
|
||||
</span>
|
||||
<div class="text-uppercase">
|
||||
<t t-if="data.request_unit == 'hour'" name="duration_unit">hours</t>
|
||||
<t t-else="">days</t>
|
||||
<t t-if="props.requires_allocation" name="duration_type">
|
||||
available
|
||||
</t>
|
||||
<t t-else="">
|
||||
taken
|
||||
</t>
|
||||
<t t-if="show_popover">
|
||||
<TimeOffCardPopover
|
||||
allocated="data.max_leaves"
|
||||
approved="data.leaves_approved"
|
||||
planned="data.leaves_requested"
|
||||
left="data.virtual_remaining_leaves"
|
||||
usable="data.usable_remaining_leaves" />
|
||||
</t>
|
||||
</div>
|
||||
<span t-if="props.requires_allocation and data.closest_allocation_expire !== false" class="text-uppercase o_timeoff_validity">
|
||||
<t t-if="data.closest_allocation_remaining != data.virtual_remaining_leaves">
|
||||
(<t t-esc="data.closest_allocation_remaining"/> <t t-if="data.request_unit == 'hour'">hours</t><t t-else="">days</t>
|
||||
valid until <span t-esc="data.closest_allocation_expire"/>)
|
||||
</t>
|
||||
<t t-else="">
|
||||
(valid until <span t-esc="data.closest_allocation_expire"/>)
|
||||
</t>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<t t-name="hr_holidays.TimeOffCardMobile" owl="1">
|
||||
<t t-set="data" t-value="props.data"/>
|
||||
<t t-set="duration" t-value="props.requires_allocation ? data.virtual_remaining_leaves : data.virtual_leaves_taken" />
|
||||
|
||||
<span class="float-end o_timeoff_card_mobile">
|
||||
<t t-if="props.requires_allocation" name="duration_type">
|
||||
<strong t-esc="duration" class="o_timeoff_green"/> / <span t-esc="data.max_leaves"/> <t t-if="data.request_unit == 'hour'">Hours</t><t t-else="">Days</t> <span class="o_timeoff_green">Available</span>
|
||||
</t>
|
||||
<t t-else="">
|
||||
<strong t-esc="duration"/> <t t-if="data.request_unit == 'hour'">Hours</t><t t-else="">Days</t> <span class="text-odoo">Taken</span>
|
||||
</t>
|
||||
</span>
|
||||
</t>
|
||||
|
||||
<t t-name="hr_holidays.TimeOffCardPopover" owl="1">
|
||||
<div class="o_timeoff_info">
|
||||
<Popover position="'right'" popoverClass="'o_timeoff_popover'">
|
||||
<span class="fa fa-question-circle-o"/>
|
||||
<t t-set-slot="opened">
|
||||
<ul>
|
||||
<li>Allocated: <span t-esc="props.allocated"/></li>
|
||||
<li>Approved: <span t-esc="props.approved"/></li>
|
||||
<li style="border-bottom: 1px solid gray;">Planned: <span t-esc="props.planned"/></li>
|
||||
<li>Left: <span t-esc="props.left"/></li>
|
||||
<li t-if="props.left != props.usable">Usable: <span t-esc="props.usable"/></li>
|
||||
</ul>
|
||||
</t>
|
||||
</Popover>
|
||||
</div>
|
||||
</t>
|
||||
</templates>
|
||||
|
|
@ -0,0 +1,42 @@
|
|||
/* @odoo-module */
|
||||
|
||||
import { TimeOffCard } from './time_off_card';
|
||||
import { useBus, useService } from "@web/core/utils/hooks";
|
||||
|
||||
const { Component, useState, onWillStart } = owl;
|
||||
|
||||
export class TimeOffDashboard extends Component {
|
||||
setup() {
|
||||
this.orm = useService("orm");
|
||||
this.state = useState({
|
||||
holidays: [],
|
||||
});
|
||||
useBus(this.env.timeOffBus, 'update_dashboard', async () => {
|
||||
await this.loadDashboardData()
|
||||
});
|
||||
|
||||
onWillStart(async () => {
|
||||
await this.loadDashboardData();
|
||||
});
|
||||
}
|
||||
|
||||
async loadDashboardData() {
|
||||
const context = {};
|
||||
if (this.props.employeeId !== null) {
|
||||
context['employee_id'] = this.props.employeeId;
|
||||
}
|
||||
|
||||
this.state.holidays = await this.orm.call(
|
||||
'hr.leave.type',
|
||||
'get_days_all_request',
|
||||
[],
|
||||
{
|
||||
context: context
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
TimeOffDashboard.components = { TimeOffCard };
|
||||
TimeOffDashboard.template = 'hr_holidays.TimeOffDashboard';
|
||||
TimeOffDashboard.props = ['employeeId'];
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
.o_timeoff_dashboard {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
|
||||
height: auto;
|
||||
box-shadow: inset 0 -1px 0 $border-color;
|
||||
position: sticky;
|
||||
top: 0;
|
||||
z-index: 100;
|
||||
background-color: $o-webclient-background-color;
|
||||
}
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<templates xml:space="preserve">
|
||||
<div t-name="hr_holidays.TimeOffDashboard" owl="1" class="o_timeoff_dashboard">
|
||||
<t t-foreach="state.holidays" t-as="holiday" t-key="holiday[3]">
|
||||
<TimeOffCard name="holiday[0]" data="holiday[1]" requires_allocation="holiday[2] == 'yes'" id="holiday[3]"/>
|
||||
</t>
|
||||
</div>
|
||||
</templates>
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100">
|
||||
<g id="Annual_Time_Off" data-name="Annual Time Off">
|
||||
<g>
|
||||
<rect x="13.34" y="24.39" width="73.32" height="59.4" rx="6.37" stroke-width="5" stroke="#875b7b" stroke-linecap="round" stroke-linejoin="round" fill="none"/>
|
||||
<g>
|
||||
<path d="M30.5,32.12V16.21a2.5,2.5,0,0,0-5,0V32.12a2.5,2.5,0,0,0,5,0Z" fill="#875b7b"/>
|
||||
<path d="M52.5,32.12V16.21a2.5,2.5,0,0,0-5,0V32.12a2.5,2.5,0,1,0,5,0Z" fill="#875b7b"/>
|
||||
<path d="M74.5,32.12V16.21a2.5,2.5,0,0,0-5,0V32.12a2.5,2.5,0,1,0,5,0Z" fill="#875b7b"/>
|
||||
</g>
|
||||
<path d="M13.35,43.32h73.3c3.22,0,3.22-5,0-5H13.35c-3.22,0-3.22,5,0,5Z" fill="#875b7b"/>
|
||||
<g>
|
||||
<polyline points="28.57 55.08 36.01 55.08 36.01 69.96 28.56 69.96" fill="none" stroke="#875b7b" stroke-linecap="round" stroke-linejoin="round" stroke-width="4"/>
|
||||
<g>
|
||||
<line x1="28.56" y1="62.47" x2="35.54" y2="62.47" fill="none" stroke="#875b7b" stroke-linecap="round" stroke-linejoin="round" stroke-width="4"/>
|
||||
<polyline points="46.29 62.47 53.73 62.47 53.73 69.96 46.29 69.96 46.29 55.08 53.74 55.08" fill="none" stroke="#875b7b" stroke-linecap="round" stroke-linejoin="round" stroke-width="4"/>
|
||||
<polyline points="71.44 55.08 64 55.08 64 62.47 71.44 62.47 71.44 69.96 64 69.96" fill="none" stroke="#875b7b" stroke-linecap="round" stroke-linejoin="round" stroke-width="4"/>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.4 KiB |
|
|
@ -0,0 +1,16 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100">
|
||||
<g id="Annual_Time_Off" data-name="Annual Time Off">
|
||||
<g>
|
||||
<rect x="13.34" y="24.39" width="73.32" height="59.4" rx="6.37" stroke-width="5" stroke="#875b7b" stroke-linecap="round" stroke-linejoin="round" fill="none"/>
|
||||
<g>
|
||||
<path d="M30.5,32.12V16.21a2.5,2.5,0,0,0-5,0V32.12a2.5,2.5,0,0,0,5,0Z" fill="#875b7b"/>
|
||||
<path d="M52.5,32.12V16.21a2.5,2.5,0,0,0-5,0V32.12a2.5,2.5,0,1,0,5,0Z" fill="#875b7b"/>
|
||||
<path d="M74.5,32.12V16.21a2.5,2.5,0,0,0-5,0V32.12a2.5,2.5,0,1,0,5,0Z" fill="#875b7b"/>
|
||||
</g>
|
||||
<g>
|
||||
<path d="M86.65,40.82H13.35v36.6l3.32,6.21,63.63.16,7.62-3.5ZM38,70a2,2,0,0,1-2,2H28.56a2,2,0,0,1,0-4H34V64.47H28.56a2,2,0,0,1,0-4H34V57.08H28.57a2,2,0,0,1,0-4H36a2,2,0,0,1,2,2Zm15.72-9.49a2,2,0,0,1,2,2V70a2,2,0,0,1-2,2H46.29a2,2,0,0,1-2-2V55.08a2,2,0,0,1,2-2h7.45a2,2,0,0,1,0,4H48.29v3.39Zm17.71,0a2,2,0,0,1,2,2V70a2,2,0,0,1-2,2H64a2,2,0,1,1,0-4h5.44V64.47H64a2,2,0,0,1-2-2V55.08a2,2,0,0,1,2-2h7.44a2,2,0,0,1,0,4H66v3.39Z" fill="#875b7b"/>
|
||||
<rect x="48.29" y="64.47" width="3.44" height="3.49" fill="#875b7b"/>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.1 KiB |
|
|
@ -0,0 +1,20 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100">
|
||||
<g id="Annual_Time_Off" data-name="Annual Time Off">
|
||||
<g>
|
||||
<g>
|
||||
<path d="M30.5,32.12V16.21a2.5,2.5,0,0,0-5,0V32.12a2.5,2.5,0,0,0,5,0Z" fill="#875b7b"/>
|
||||
<path d="M52.5,32.12V16.21a2.5,2.5,0,0,0-5,0V32.12a2.5,2.5,0,1,0,5,0Z" fill="#875b7b"/>
|
||||
<path d="M74.5,32.12V16.21a2.5,2.5,0,0,0-5,0V32.12a2.5,2.5,0,1,0,5,0Z" fill="#875b7b"/>
|
||||
</g>
|
||||
<g>
|
||||
<path d="M36,72H28.56a2,2,0,0,1,0-4H34V57.08H28.57a2,2,0,0,1,0-4H36a2,2,0,0,1,2,2V70A2,2,0,0,1,36,72Z" fill="#875b7b"/>
|
||||
<g>
|
||||
<path d="M35.54,64.47h-7a2,2,0,0,1,0-4h7a2,2,0,0,1,0,4Z" fill="#875b7b"/>
|
||||
<path d="M53.73,72H46.29a2,2,0,0,1-2-2V55.08a2,2,0,0,1,2-2h7.45a2,2,0,0,1,0,4H48.29v3.39h5.44a2,2,0,0,1,2,2V70A2,2,0,0,1,53.73,72Zm-5.44-4h3.44V64.47H48.29Z" fill="#875b7b"/>
|
||||
<path d="M71.44,72H64a2,2,0,1,1,0-4h5.44V64.47H64a2,2,0,0,1-2-2V55.08a2,2,0,0,1,2-2h7.44a2,2,0,0,1,0,4H66v3.39h5.44a2,2,0,0,1,2,2V70A2,2,0,0,1,71.44,72Z" fill="#875b7b"/>
|
||||
</g>
|
||||
</g>
|
||||
<path d="M80.29,21.89H79.5V32.12a7.53,7.53,0,0,1-7.27,7.49h-.32a7.56,7.56,0,0,1-7.41-7.5V21.89h-7V32.12a7.53,7.53,0,0,1-7.27,7.49h-.32a7.56,7.56,0,0,1-7.41-7.5V21.89h-7V32.12a7.53,7.53,0,0,1-7.27,7.49h-.32a7.56,7.56,0,0,1-7.41-7.5V21.89h-.79a8.88,8.88,0,0,0-8.87,8.87V77.42a8.88,8.88,0,0,0,8.87,8.87H80.29a8.88,8.88,0,0,0,8.87-8.87V30.76A8.88,8.88,0,0,0,80.29,21.89Zm3.87,55.53a3.87,3.87,0,0,1-3.87,3.87H19.71a3.87,3.87,0,0,1-3.87-3.87V43.32H84.16Z" fill="#875b7b"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.5 KiB |
|
|
@ -0,0 +1,15 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100">
|
||||
<g id="Compensatory_Time_Off" data-name="Compensatory Time Off">
|
||||
<g>
|
||||
<line x1="23.12" y1="26.88" x2="76.88" y2="26.88" fill="none" stroke="#875b7b" stroke-linecap="round" stroke-linejoin="round" stroke-width="5"/>
|
||||
<line x1="23.12" y1="84.74" x2="76.88" y2="84.74" fill="none" stroke="#875b7b" stroke-linecap="round" stroke-linejoin="round" stroke-width="5"/>
|
||||
<line x1="50" y1="15.26" x2="50" y2="84.66" fill="none" stroke="#875b7b" stroke-linecap="round" stroke-linejoin="round" stroke-width="5"/>
|
||||
<line x1="23.45" y1="27.4" x2="11.73" y2="58.24" fill="none" stroke="#875b7b" stroke-linecap="round" stroke-linejoin="round" stroke-width="5"/>
|
||||
<line x1="35.24" y1="57.87" x2="23.52" y2="27.03" fill="none" stroke="#875b7b" stroke-linecap="round" stroke-linejoin="round" stroke-width="5"/>
|
||||
<path d="M23.92,75.75a16.87,16.87,0,0,0,16.55-13.6,2.67,2.67,0,0,0-2.6-3.2H10a2.67,2.67,0,0,0-2.6,3.2A16.87,16.87,0,0,0,23.92,75.75Z" fill="none" stroke="#875b7b" stroke-miterlimit="10" stroke-width="5"/>
|
||||
<line x1="75.62" y1="27.4" x2="63.9" y2="58.24" fill="none" stroke="#875b7b" stroke-linecap="round" stroke-linejoin="round" stroke-width="5"/>
|
||||
<line x1="87.41" y1="57.87" x2="75.69" y2="27.03" fill="none" stroke="#875b7b" stroke-linecap="round" stroke-linejoin="round" stroke-width="5"/>
|
||||
<path d="M76.08,75.75a16.87,16.87,0,0,0,16.56-13.6A2.67,2.67,0,0,0,90,59H62.13a2.67,2.67,0,0,0-2.6,3.2A16.87,16.87,0,0,0,76.08,75.75Z" fill="none" stroke="#875b7b" stroke-miterlimit="10" stroke-width="5"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.6 KiB |
|
|
@ -0,0 +1,15 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100">
|
||||
<g id="Compensatory_Time_Off" data-name="Compensatory Time Off">
|
||||
<g>
|
||||
<line x1="23.12" y1="26.88" x2="76.88" y2="26.88" fill="none" stroke="#875b7b" stroke-linecap="round" stroke-linejoin="round" stroke-width="5"/>
|
||||
<line x1="23.12" y1="84.74" x2="76.88" y2="84.74" fill="none" stroke="#875b7b" stroke-linecap="round" stroke-linejoin="round" stroke-width="5"/>
|
||||
<line x1="50" y1="15.26" x2="50" y2="84.66" fill="none" stroke="#875b7b" stroke-linecap="round" stroke-linejoin="round" stroke-width="5"/>
|
||||
<line x1="23.45" y1="27.4" x2="11.73" y2="61.24" fill="none" stroke="#875b7b" stroke-linecap="round" stroke-linejoin="round" stroke-width="5"/>
|
||||
<line x1="35.24" y1="60.87" x2="23.52" y2="27.03" fill="none" stroke="#875b7b" stroke-linecap="round" stroke-linejoin="round" stroke-width="5"/>
|
||||
<path d="M23.92,75.75a16.87,16.87,0,0,0,16.55-13.6,2.67,2.67,0,0,0-2.6-3.2H10a2.67,2.67,0,0,0-2.6,3.2A16.87,16.87,0,0,0,23.92,75.75Z" fill="#875b7b"/>
|
||||
<line x1="75.62" y1="27.4" x2="63.9" y2="61.24" fill="none" stroke="#875b7b" stroke-linecap="round" stroke-linejoin="round" stroke-width="5"/>
|
||||
<line x1="87.41" y1="60.87" x2="75.69" y2="27.03" fill="none" stroke="#875b7b" stroke-linecap="round" stroke-linejoin="round" stroke-width="5"/>
|
||||
<path d="M76.08,75.75a16.87,16.87,0,0,0,16.56-13.6A2.67,2.67,0,0,0,90,59H62.13a2.67,2.67,0,0,0-2.6,3.2A16.87,16.87,0,0,0,76.08,75.75Z" fill="#875b7b"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.5 KiB |
|
|
@ -0,0 +1,11 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100">
|
||||
<g id="Compensatory_Time_Off" data-name="Compensatory Time Off">
|
||||
<g>
|
||||
<polyline points="23.12 66.91 23.12 29.88 76.88 19.88 76.88 59.29" fill="none" stroke="#875b7b" stroke-linecap="round" stroke-linejoin="round" stroke-width="5"/>
|
||||
<line x1="23.12" y1="84.74" x2="76.88" y2="84.74" fill="none" stroke="#875b7b" stroke-linecap="round" stroke-linejoin="round" stroke-width="5"/>
|
||||
<line x1="50" y1="15.26" x2="50" y2="84.66" fill="none" stroke="#875b7b" stroke-linecap="round" stroke-linejoin="round" stroke-width="5"/>
|
||||
<path d="M23.92,75.75a16.87,16.87,0,0,0,16.55-13.6,2.67,2.67,0,0,0-2.6-3.2H10a2.67,2.67,0,0,0-2.6,3.2A16.87,16.87,0,0,0,23.92,75.75Z" fill="#875b7b"/>
|
||||
<path d="M76.08,65.75a16.87,16.87,0,0,0,16.56-13.6A2.67,2.67,0,0,0,90,49H62.13a2.67,2.67,0,0,0-2.6,3.2A16.87,16.87,0,0,0,76.08,65.75Z" fill="#875b7b"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 940 B |
|
|
@ -0,0 +1,11 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100">
|
||||
<g id="Credit_Time" data-name="Credit Time">
|
||||
<g>
|
||||
<path d="M50,88.84A36.55,36.55,0,1,1,86.55,52.29,36.59,36.59,0,0,1,50,88.84Zm0-68.09A31.55,31.55,0,1,0,81.55,52.29,31.59,31.59,0,0,0,50,20.75Z" fill="#875b7b"/>
|
||||
<path d="M41.35,16.66h17.3a2.5,2.5,0,0,0,0-5H41.35a2.5,2.5,0,0,0,0,5Z" fill="#875b7b"/>
|
||||
<path d="M41.35,13.66h17.3a2.5,2.5,0,0,0,0-5H41.35a2.5,2.5,0,0,0,0,5Z" fill="#875b7b"/>
|
||||
<path d="M70.66,22.86l2.23,2.23a1.92,1.92,0,0,0,.8.52,2.32,2.32,0,0,0,1.93,0,2,2,0,0,0,.81-.52l.39-.51a2.5,2.5,0,0,0,.34-1.26l-.09-.66a2.5,2.5,0,0,0-.64-1.1l-2.24-2.24a1.83,1.83,0,0,0-.8-.51,2.23,2.23,0,0,0-1.93,0,1.83,1.83,0,0,0-.8.51l-.39.51a2.43,2.43,0,0,0-.34,1.26l.08.67a2.52,2.52,0,0,0,.65,1.1Z" fill="#875b7b"/>
|
||||
<path d="M60.78,36.56a13.49,13.49,0,0,0-8.6-3.94V29.87c0-3.21-5-3.22-5,0V33A11.57,11.57,0,0,0,38.43,43.3a11.44,11.44,0,0,0,8.75,11.9V68.42a8.48,8.48,0,0,1-4.42-2.36,2.18,2.18,0,0,1-.64-1.55V61.46A2.5,2.5,0,0,0,39.64,59h0a2.51,2.51,0,0,0-2.5,2.49v3a7.25,7.25,0,0,0,2.1,5.11,13.49,13.49,0,0,0,8,3.87v1.24c0,3.22,5,3.22,5,0V73.34a11.59,11.59,0,0,0,9.39-10.49,11.46,11.46,0,0,0-9.39-12V37.64a8.5,8.5,0,0,1,5.06,2.45,2.15,2.15,0,0,1,.64,1.55v3a2.49,2.49,0,0,0,2.49,2.51h0a2.51,2.51,0,0,0,2.5-2.49V41.66A7.21,7.21,0,0,0,60.78,36.56ZM45.16,48.49a6.4,6.4,0,0,1,2-10.24V50A6.52,6.52,0,0,1,45.16,48.49Zm11.42,14a6.5,6.5,0,0,1-4.4,5.63V56a6.49,6.49,0,0,1,4.4,6.58Z" fill="#875b7b"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.5 KiB |
|
|
@ -0,0 +1,13 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100">
|
||||
<g id="Credit_Time" data-name="Credit Time">
|
||||
<path d="M50,88.84A36.55,36.55,0,1,1,86.55,52.29,36.59,36.59,0,0,1,50,88.84Zm0-68.09A31.55,31.55,0,1,0,81.55,52.29,31.59,31.59,0,0,0,50,20.75Z" fill="#875b7b"/>
|
||||
<path d="M41.35,16.66h17.3a2.5,2.5,0,0,0,0-5H41.35a2.5,2.5,0,0,0,0,5Z" fill="#875b7b"/>
|
||||
<path d="M41.35,13.66h17.3a2.5,2.5,0,0,0,0-5H41.35a2.5,2.5,0,0,0,0,5Z" fill="#875b7b"/>
|
||||
<path d="M70.66,22.86l2.23,2.23a1.92,1.92,0,0,0,.8.52,2.32,2.32,0,0,0,1.93,0,2,2,0,0,0,.81-.52l.39-.51a2.5,2.5,0,0,0,.34-1.26l-.09-.66a2.5,2.5,0,0,0-.64-1.1l-2.24-2.24a1.83,1.83,0,0,0-.8-.51,2.23,2.23,0,0,0-1.93,0,1.83,1.83,0,0,0-.8.51l-.39.51a2.43,2.43,0,0,0-.34,1.26l.08.67a2.52,2.52,0,0,0,.65,1.1Z" fill="#875b7b"/>
|
||||
<g>
|
||||
<path d="M43.42,43.62A6.5,6.5,0,0,0,47.18,50V38.25A6.47,6.47,0,0,0,43.42,43.62Z" fill="#875b7b"/>
|
||||
<path d="M52.18,68.16a6.44,6.44,0,0,0,0-12.21Z" fill="#875b7b"/>
|
||||
<path d="M50,24.51A27.49,27.49,0,1,0,77.49,52,27.49,27.49,0,0,0,50,24.51Zm12.87,20.2a2.51,2.51,0,0,1-2.5,2.49h0a2.49,2.49,0,0,1-2.49-2.51v-3a2.15,2.15,0,0,0-.64-1.55,8.5,8.5,0,0,0-5.06-2.45V50.81a11.45,11.45,0,0,1,0,22.53v1.37c0,3.22-5,3.22-5,0V73.47a13.49,13.49,0,0,1-8-3.87,7.25,7.25,0,0,1-2.1-5.11v-3A2.51,2.51,0,0,1,39.63,59h0a2.5,2.5,0,0,1,2.49,2.51v3.05a2.18,2.18,0,0,0,.64,1.55,8.48,8.48,0,0,0,4.42,2.36V55.2a11.43,11.43,0,0,1,0-22.23v-3.1c0-3.22,5-3.21,5,0v2.75a13.49,13.49,0,0,1,8.6,3.94,7.21,7.21,0,0,1,2.1,5.1Z" fill="#875b7b"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.5 KiB |
|
|
@ -0,0 +1,14 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100">
|
||||
<g id="Extra_Time_Off" data-name="Extra Time Off">
|
||||
<g>
|
||||
<path d="M56.9,12.07a2.73,2.73,0,0,1,2.79,2.63l.46,9.13A2.77,2.77,0,0,0,64.5,26L72,20.75a2.71,2.71,0,0,1,1.58-.52A2.78,2.78,0,0,1,76,24.28l-4.16,8.13a2.77,2.77,0,0,0,2.45,4h.24l9.11-.76.26,0a2.77,2.77,0,0,1,1.47,5.1l-7.67,5a2.77,2.77,0,0,0,.33,4.83l8.26,3.89a2.76,2.76,0,0,1-1,5.26l-9.13.46A2.77,2.77,0,0,0,74,64.5L79.25,72A2.78,2.78,0,0,1,77,76.36,2.82,2.82,0,0,1,75.72,76l-8.13-4.16a2.82,2.82,0,0,0-1.26-.31,2.77,2.77,0,0,0-2.76,3l.76,9.11a2.74,2.74,0,0,1-2.79,3,2.67,2.67,0,0,1-2.29-1.27l-5-7.67A2.72,2.72,0,0,0,52,76.48a2.75,2.75,0,0,0-2.51,1.59l-3.89,8.26a2.66,2.66,0,0,1-2.47,1.6,2.73,2.73,0,0,1-2.79-2.63l-.46-9.13A2.77,2.77,0,0,0,35.5,74L28,79.25a2.71,2.71,0,0,1-1.58.52,2.78,2.78,0,0,1-2.46-4l4.16-8.13a2.77,2.77,0,0,0-2.45-4h-.24l-9.11.76-.26,0a2.77,2.77,0,0,1-1.47-5.1l7.67-5a2.77,2.77,0,0,0-.33-4.83l-8.26-3.89a2.76,2.76,0,0,1,1-5.26l9.13-.46A2.77,2.77,0,0,0,26,35.5L20.75,28A2.78,2.78,0,0,1,23,23.64a2.82,2.82,0,0,1,1.28.32l8.13,4.16a2.76,2.76,0,0,0,4-2.69l-.76-9.11a2.74,2.74,0,0,1,2.79-3,2.67,2.67,0,0,1,2.29,1.27l5,7.67A2.72,2.72,0,0,0,48,23.52a2.75,2.75,0,0,0,2.51-1.59l3.89-8.26a2.66,2.66,0,0,1,2.47-1.6m0-4h0A6.67,6.67,0,0,0,50.81,12l-3,6.26L44.1,12.41a6.69,6.69,0,0,0-5.64-3.09,6.88,6.88,0,0,0-5.05,2.2,6.67,6.67,0,0,0-1.73,5.14l.58,6.89L26.1,20.4a6.67,6.67,0,0,0-3.1-.76,6.78,6.78,0,0,0-6,3.67,6.65,6.65,0,0,0,.46,7L21.41,36l-6.91.35A6.77,6.77,0,0,0,12,49.19l6.26,3L12.41,55.9a6.77,6.77,0,0,0,3.65,12.45l.6,0,6.89-.58L20.4,73.9a6.68,6.68,0,0,0,.22,6.58,6.85,6.85,0,0,0,5.8,3.29,6.75,6.75,0,0,0,3.86-1.23l5.68-4,.35,6.91A6.76,6.76,0,0,0,49.19,88l3-6.26,3.76,5.81a6.69,6.69,0,0,0,5.64,3.09,6.88,6.88,0,0,0,5.05-2.2,6.68,6.68,0,0,0,1.73-5.14l-.58-6.89L73.9,79.6a6.67,6.67,0,0,0,3.1.76,6.78,6.78,0,0,0,6-3.67,6.65,6.65,0,0,0-.46-7l-4-5.68,6.91-.35A6.77,6.77,0,0,0,88,50.81l-6.26-3,5.81-3.76a6.77,6.77,0,0,0-3.65-12.45l-.6,0-6.89.58L79.6,26.1a6.68,6.68,0,0,0-.22-6.58,6.85,6.85,0,0,0-5.8-3.29,6.75,6.75,0,0,0-3.86,1.23L64,21.41l-.35-6.91A6.71,6.71,0,0,0,56.9,8.07Z" fill="#875b7b"/>
|
||||
<g>
|
||||
<path d="M34.89,56.11a1.26,1.26,0,0,0,.35-1.73A1.28,1.28,0,0,0,33.5,54l-2.75,1.84a1.23,1.23,0,0,0-.41.49,1.08,1.08,0,0,0-.06,1,1,1,0,0,0,.11.2s0,0,0,0l5.13,7.64a1.17,1.17,0,0,0,1.61.37,1.73,1.73,0,0,0,.24-.1L40,63.75a1.25,1.25,0,0,0-1.39-2.08l-1.72,1.15L35.66,61l1.69-1.13A1.25,1.25,0,0,0,36,57.75l-1.68,1.13-1.09-1.62Z" fill="#875b7b"/>
|
||||
<path d="M41.05,49.06a1.51,1.51,0,0,0-1,1.85v0h0a1.5,1.5,0,0,0-1.84,2.36l3.22,2.52,1.1,3.93a1.5,1.5,0,0,0,1.85,1,1.48,1.48,0,0,0,1-1.85h0a1.5,1.5,0,0,0,1.76.06,1.32,1.32,0,0,0,.35-.32,1.51,1.51,0,0,0-.26-2.11L44,54,42.9,50.1A1.51,1.51,0,0,0,41.05,49.06Z" fill="#875b7b"/>
|
||||
<path d="M48.13,44.21l-2.79,1.87A1.26,1.26,0,0,0,45,47.81a1.28,1.28,0,0,0,1.74.35l.31-.22,4.46,6.65a1.25,1.25,0,0,0,2.08-1.39l-4.46-6.65.39-.26a1.25,1.25,0,0,0-1.39-2.08Z" fill="#875b7b"/>
|
||||
<path d="M58.44,45.63l.82-.55a1.29,1.29,0,0,0,.53-.8,1.25,1.25,0,0,0-.19-.94l-.07-.07-2.36-3.51a1.26,1.26,0,0,0-1.73-.34l-2.58,1.73a1.22,1.22,0,0,0-.63,1.63s0,0,0,0l.08.15,5.11,7.61a1.25,1.25,0,0,0,2.08-1.39l-.42-.63,1.74.65a1.23,1.23,0,0,0,1.6-.74,1.23,1.23,0,0,0-.73-1.6Zm-1.63-1.92-.67.45-1-1.52.66-.45Z" fill="#875b7b"/>
|
||||
<path d="M62.5,34.6l-2.58,1.73a1.27,1.27,0,0,0-.48.66,1,1,0,0,0,0,.62.44.44,0,0,0,0,.1.76.76,0,0,0,0,.11.85.85,0,0,0,.13.25l5.1,7.6a1.25,1.25,0,0,0,2.08-1.39L64.83,41.4l.72-.49,2,2.93a1.25,1.25,0,0,0,2.08-1.4l-5.17-7.7A1.21,1.21,0,0,0,62.5,34.6Zm.93,4.72-1.08-1.61.73-.49,1.08,1.62Z" fill="#875b7b"/>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 3.6 KiB |
|
|
@ -0,0 +1,9 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100">
|
||||
<g id="Extra_Time_Off" data-name="Extra Time Off">
|
||||
<g>
|
||||
<path d="M62.35,37.71l1.08,1.61.73-.48-1.08-1.62Z" fill="#875b7b"/>
|
||||
<path d="M55.13,42.64c.34.5.68,1,1,1.52l.67-.45-1-1.52Z" fill="#875b7b"/>
|
||||
<path d="M86.33,54.43l-8.26-3.89a2.77,2.77,0,0,1-.33-4.83l7.67-5a2.76,2.76,0,0,0-1.73-5.08l-9.11.76a2.77,2.77,0,0,1-2.69-4L76,24.28a2.77,2.77,0,0,0-4-3.53L64.5,26a2.77,2.77,0,0,1-4.35-2.13l-.46-9.13a2.76,2.76,0,0,0-5.26-1l-3.89,8.26a2.77,2.77,0,0,1-4.83.33l-5-7.67a2.76,2.76,0,0,0-5.08,1.73l.76,9.11a2.77,2.77,0,0,1-4,2.69L24.28,24a2.77,2.77,0,0,0-3.53,4L26,35.5a2.77,2.77,0,0,1-2.13,4.35l-9.13.46a2.76,2.76,0,0,0-1,5.26l8.26,3.89a2.77,2.77,0,0,1,.33,4.83l-7.67,5a2.76,2.76,0,0,0,1.73,5.08l9.11-.76a2.77,2.77,0,0,1,2.69,4L24,75.72a2.77,2.77,0,0,0,4,3.53L35.5,74a2.77,2.77,0,0,1,4.35,2.13l.46,9.13a2.76,2.76,0,0,0,5.26,1l3.89-8.26a2.77,2.77,0,0,1,4.83-.33l5,7.67a2.76,2.76,0,0,0,5.08-1.73l-.76-9.11a2.77,2.77,0,0,1,4-2.69L75.72,76a2.77,2.77,0,0,0,3.53-4L74,64.5a2.77,2.77,0,0,1,2.13-4.35l9.13-.46A2.76,2.76,0,0,0,86.33,54.43ZM40,63.75l-2.64,1.77a1.73,1.73,0,0,1-.24.1,1.17,1.17,0,0,1-1.61-.37L30.4,57.61s0,0,0,0a1,1,0,0,1-.11-.2,1.08,1.08,0,0,1,.06-1,1.23,1.23,0,0,1,.41-.49L33.5,54a1.28,1.28,0,0,1,1.74.34,1.26,1.26,0,0,1-.35,1.73l-1.71,1.15,1.09,1.62L36,57.75a1.25,1.25,0,0,1,1.4,2.08L35.66,61l1.25,1.86,1.72-1.15A1.25,1.25,0,0,1,40,63.75Zm7.47-5.09a1.52,1.52,0,0,1-2.11.26h0a1.5,1.5,0,1,1-2.89.81l-1.1-3.93-3.22-2.52A1.5,1.5,0,0,1,40,50.92h0v0a1.5,1.5,0,1,1,2.89-.81L44,54l3.23,2.51A1.51,1.51,0,0,1,47.49,58.66Zm4-4.07c-1.49-2.21-3-4.43-4.46-6.65l-.31.22A1.28,1.28,0,0,1,45,47.81a1.26,1.26,0,0,1,.34-1.73l2.79-1.87a1.25,1.25,0,0,1,1.39,2.08l-.39.26c1.48,2.22,3,4.43,4.46,6.65A1.25,1.25,0,0,1,51.51,54.59Zm10.92-6.14a1.23,1.23,0,0,1-1.6.74l-1.74-.65.42.63a1.25,1.25,0,0,1-2.08,1.39L52.32,43l-.08-.15v0a1.22,1.22,0,0,1,.63-1.63l2.58-1.73a1.26,1.26,0,0,1,1.73.34l2.36,3.51.07.07a1.25,1.25,0,0,1,.19.94,1.29,1.29,0,0,1-.53.8l-.82.55,3.26,1.22A1.23,1.23,0,0,1,62.43,48.45Zm5.08-4.61-2-2.93-.72.49,1.93,2.88a1.25,1.25,0,0,1-2.08,1.39l-5.1-7.6a.85.85,0,0,1-.13-.25.76.76,0,0,1,0-.11.44.44,0,0,1,0-.1,1,1,0,0,1,0-.62,1.27,1.27,0,0,1,.48-.66L62.5,34.6a1.21,1.21,0,0,1,1.92.14l5.17,7.7A1.25,1.25,0,0,1,67.51,43.84Z" fill="#875b7b"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 2.3 KiB |
|
|
@ -0,0 +1,17 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100">
|
||||
<g id="Maternity_Time_Off" data-name="Maternity Time Off">
|
||||
<g>
|
||||
<g>
|
||||
<path d="M63,11.81H53.58V38.42H20.75v2.35a24,24,0,0,0,24,24H63a24,24,0,0,0,24-24v-5A24,24,0,0,0,63,11.81Z" fill="none" stroke="#875b7b" stroke-linecap="round" stroke-linejoin="round" stroke-width="5"/>
|
||||
<path d="M46.1,40.92H86.75c3.21,0,3.22-5,0-5H46.1c-3.22,0-3.23,5,0,5Z" fill="#875b7b"/>
|
||||
<path d="M23.25,38.52V23.4a2.53,2.53,0,0,0-2.5-2.5H13a2.5,2.5,0,0,0,0,5h7.71l-2.5-2.5V38.52a2.5,2.5,0,0,0,5,0Z" fill="#875b7b"/>
|
||||
<circle cx="28.65" cy="79.82" r="8.37" fill="none" stroke="#875b7b" stroke-linecap="round" stroke-linejoin="round" stroke-width="5"/>
|
||||
<circle cx="78.1" cy="79.82" r="8.37" fill="none" stroke="#875b7b" stroke-linecap="round" stroke-linejoin="round" stroke-width="5"/>
|
||||
<path d="M80.64,71.45V59.26a2.5,2.5,0,0,0-5,0V71.45a2.5,2.5,0,0,0,5,0Z" fill="#875b7b"/>
|
||||
<path d="M31.25,71.45V59.68a2.5,2.5,0,0,0-5,0V71.45a2.5,2.5,0,0,0,5,0Z" fill="#875b7b"/>
|
||||
</g>
|
||||
<path d="M28.66,82.27c3.22,0,3.22-5,0-5s-3.22,5,0,5Z" fill="#875b7b"/>
|
||||
<path d="M78.08,82.27c3.21,0,3.22-5,0-5s-3.23,5,0,5Z" fill="#875b7b"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.2 KiB |
|
|
@ -0,0 +1,12 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100">
|
||||
<g id="Maternity_Time_Off" data-name="Maternity Time Off">
|
||||
<g>
|
||||
<path d="M89.46,40.77v-5A26.51,26.51,0,0,0,63,9.31H53.58a2.5,2.5,0,0,0-2.5,2.5V35.92H23.25V23.4a2.53,2.53,0,0,0-2.5-2.5H13a2.5,2.5,0,0,0,0,5h5.21V40.77a26.41,26.41,0,0,0,8,18.94v9.51a10.89,10.89,0,1,0,5,0V63.55a26.38,26.38,0,0,0,13.48,3.7H63A26.25,26.25,0,0,0,75.64,64v5.22a10.87,10.87,0,1,0,5,0V60.48A26.41,26.41,0,0,0,89.46,40.77ZM63,14.31A21.49,21.49,0,0,1,84.46,35.79v.13H56.08V14.31ZM44.73,62.25A21.5,21.5,0,0,1,23.25,40.92h61.2a21.39,21.39,0,0,1-7.64,16.26,2.89,2.89,0,0,0-.47.38A21.33,21.33,0,0,1,63,62.25Z" fill="#875b7b"/>
|
||||
<polygon points="21.36 39.59 22.89 51.45 32.66 62.33 55.54 65.12 78.42 60.8 86.94 47.4 86.94 37.63 21.36 39.59" fill="#875b7b"/>
|
||||
<line x1="54.7" y1="36.38" x2="69.77" y2="13.5" fill="#875b7b" stroke="#875b7b" stroke-miterlimit="10" stroke-width="5"/>
|
||||
<path d="M28.66,82.27c3.22,0,3.22-5,0-5s-3.22,5,0,5Z" fill="#875b7b"/>
|
||||
<path d="M78.08,82.27c3.21,0,3.22-5,0-5s-3.23,5,0,5Z" fill="#875b7b"/>
|
||||
</g>
|
||||
<line x1="85.12" y1="24.8" x2="54.7" y2="36.38" fill="#875b7b" stroke="#875b7b" stroke-miterlimit="10" stroke-width="5"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.2 KiB |
|
|
@ -0,0 +1,19 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100">
|
||||
<g id="Maternity_Time_Off" data-name="Maternity Time Off">
|
||||
<g>
|
||||
<g>
|
||||
<path d="M23.25,38.52V23.4a2.53,2.53,0,0,0-2.5-2.5H13a2.5,2.5,0,0,0,0,5h7.71l-2.5-2.5V38.52a2.5,2.5,0,0,0,5,0Z" fill="#875b7b"/>
|
||||
<path d="M28.65,90.69A10.87,10.87,0,1,1,39.53,79.82,10.89,10.89,0,0,1,28.65,90.69Zm0-16.74a5.87,5.87,0,1,0,5.88,5.87A5.87,5.87,0,0,0,28.65,74Z" fill="#875b7b"/>
|
||||
<path d="M78.1,90.69A10.87,10.87,0,1,1,89,79.82,10.89,10.89,0,0,1,78.1,90.69ZM78.1,74A5.87,5.87,0,1,0,84,79.82,5.88,5.88,0,0,0,78.1,74Z" fill="#875b7b"/>
|
||||
<path d="M80.64,71.45V59.26a2.5,2.5,0,0,0-5,0V71.45a2.5,2.5,0,0,0,5,0Z" fill="#875b7b"/>
|
||||
<path d="M31.25,71.45V59.68a2.5,2.5,0,0,0-5,0V71.45a2.5,2.5,0,0,0,5,0Z" fill="#875b7b"/>
|
||||
<g>
|
||||
<path d="M63,14.31H56.08V35.92H84.46v-.13A21.49,21.49,0,0,0,63,14.31Z" fill="none"/>
|
||||
<path d="M89.46,35.79A26.51,26.51,0,0,0,63,9.31H53.58a2.5,2.5,0,0,0-2.5,2.5V35.92H20.75a2.5,2.5,0,0,0-2.5,2.5v2.35a26.36,26.36,0,0,0,4.39,14.59,7.65,7.65,0,0,1,5.88-3.17h.32a7.55,7.55,0,0,1,7.41,7.5v6.17a26.41,26.41,0,0,0,8.48,1.4H63a26.13,26.13,0,0,0,7.65-1.14V59.26a7.54,7.54,0,0,1,7.28-7.49h.32a7.49,7.49,0,0,1,6.53,4,26.31,26.31,0,0,0,4.69-15Zm-5,.13H56.08V14.31H63A21.49,21.49,0,0,1,84.46,35.79Z" fill="#875b7b"/>
|
||||
</g>
|
||||
</g>
|
||||
<path d="M28.66,82.27c3.22,0,3.22-5,0-5s-3.22,5,0,5Z" fill="#875b7b"/>
|
||||
<path d="M78.08,82.27c3.21,0,3.22-5,0-5s-3.23,5,0,5Z" fill="#875b7b"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.5 KiB |
|
|
@ -0,0 +1,15 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100">
|
||||
<g id="Paid_Time_Off" data-name="Paid Time Off">
|
||||
<g>
|
||||
<path d="M21.46,61.83a3,3,0,0,1,4.24-.27L39.5,73.7H78.9a3,3,0,0,1,0,6H74.37v4.81a3,3,0,0,1-6,0V79.7H45.48v4.81a3,3,0,0,1-6,0V79.7H38.37a3,3,0,0,1-2-.75L21.73,66.07A3,3,0,0,1,21.46,61.83Z" fill="#875b7b"/>
|
||||
<g>
|
||||
<rect x="46.5" y="67.63" width="6" height="0.07" fill="#875b7b"/>
|
||||
<path d="M78.87,41.86c0-.18-.09-.36-.09-.54,0-32.94-58-32.94-58,0a5.58,5.58,0,0,1-.1.59c-.2,2.4,2.94,3.29,4.29,1.3,2.45-3.62,10.12-3.71,12.86-.29.57.71,1.84.95,2.26.14,1.88-3.62,17.81-3.54,18.69,0,.21.88,1.66.59,2.23-.11,2.83-3.48,10.92-3.39,13.51.24C76,45.18,79.12,44.25,78.87,41.86Z" fill="none" stroke="#875b7b" stroke-miterlimit="10" stroke-width="5"/>
|
||||
<path d="M46.5,40.62v27h6v-27A23.17,23.17,0,0,0,46.5,40.62Z" fill="#875b7b"/>
|
||||
<path d="M52.5,11.6a3.08,3.08,0,0,0-2.41-3.06,3,3,0,0,0-3.59,3v3h6Z" fill="#875b7b"/>
|
||||
</g>
|
||||
</g>
|
||||
<path d="M40.13,43.06c-4.26-10.68,0-19.27,9.55-26.59" fill="none" stroke="#875b7b" stroke-miterlimit="10" stroke-width="5"/>
|
||||
<path d="M59.57,43.33c4.26-10.67,0-19.26-9.55-26.58" fill="none" stroke="#875b7b" stroke-miterlimit="10" stroke-width="5"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.2 KiB |
|
|
@ -0,0 +1,15 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100">
|
||||
<g id="Paid_Time_Off" data-name="Paid Time Off">
|
||||
<g>
|
||||
<path d="M21.46,61.83a3,3,0,0,1,4.24-.27L39.5,73.7H78.9a3,3,0,0,1,0,6H74.37v4.81a3,3,0,0,1-6,0V79.7H45.48v4.81a3,3,0,0,1-6,0V79.7H38.37a3,3,0,0,1-2-.75L21.73,66.07A3,3,0,0,1,21.46,61.83Z" fill="#875b7b"/>
|
||||
<g>
|
||||
<rect x="46.5" y="67.63" width="6" height="0.07" fill="#875b7b"/>
|
||||
<path d="M78.87,41.86c0-.18-.09-.36-.09-.54,0-32.94-58-32.94-58,0a5.58,5.58,0,0,1-.1.59c-.2,2.4,2.94,3.29,4.29,1.3,2.45-3.62,10.12-3.71,12.86-.29.57.71,1.84.95,2.26.14,1.88-3.62,17.81-3.54,18.69,0,.21.88,1.66.59,2.23-.11,2.83-3.48,10.92-3.39,13.51.24C76,45.18,79.12,44.25,78.87,41.86Z" fill="none" stroke="#875b7b" stroke-miterlimit="10" stroke-width="5"/>
|
||||
<path d="M46.5,40.62v27h6v-27A23.17,23.17,0,0,0,46.5,40.62Z" fill="#875b7b"/>
|
||||
<path d="M52.5,11.6a3.08,3.08,0,0,0-2.41-3.06,3,3,0,0,0-3.59,3v3h6Z" fill="#875b7b"/>
|
||||
</g>
|
||||
</g>
|
||||
<path d="M21.77,43.82c-3.22-18.89,18.49-25.37,27.4-24.71C43.73,22.74,39,25.49,39,40.56,29.28,37.67,26.2,40.61,21.77,43.82Z" fill="#875b7b"/>
|
||||
<path d="M76,43.91c3.32-19.85-17.83-26.36-26.84-24.8,5.44,3.63,9.12,7.5,9.12,22.57C65.64,39.83,69.39,41.65,76,43.91Z" fill="#875b7b"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.3 KiB |
|
|
@ -0,0 +1,12 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100">
|
||||
<g id="Paid_Time_Off" data-name="Paid Time Off">
|
||||
<g>
|
||||
<path d="M21.46,61.83a3,3,0,0,1,4.24-.27L39.5,73.7H78.9a3,3,0,0,1,0,6H74.37v4.81a3,3,0,0,1-6,0V79.7H45.48v4.81a3,3,0,0,1-6,0V79.7H38.37a3,3,0,0,1-2-.75L21.73,66.07A3,3,0,0,1,21.46,61.83Z" fill="#875b7b"/>
|
||||
<g>
|
||||
<rect x="46.5" y="67.63" width="6" height="0.07" fill="#875b7b"/>
|
||||
<path d="M78.78,41.32A29.93,29.93,0,0,0,52.5,19V15.6a3.08,3.08,0,0,0-2.41-3.06,3,3,0,0,0-3.59,3V19A29.92,29.92,0,0,0,20.82,41.32a4.28,4.28,0,0,0-.1.59c-.2,2.4,2.94,3.29,4.29,1.3,2.45-3.62,10.12-3.71,12.86-.29a1.53,1.53,0,0,0,2.26.14c3.79-3.52,14.93-3.52,18.69,0A1.5,1.5,0,0,0,61.05,43c2.83-3.48,10.92-3.39,13.51.24,1.39,2,4.56,1,4.31-1.35A3.38,3.38,0,0,0,78.78,41.32Z" fill="#875b7b"/>
|
||||
<rect x="46.5" y="38.79" width="6" height="28.84" fill="#875b7b"/>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 920 B |
|
|
@ -0,0 +1,5 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100">
|
||||
<g id="Parental_Time_Off" data-name="Parental Time Off">
|
||||
<path d="M94.89,52.33,87.17,34.94a3.76,3.76,0,0,0-3.86-2.2,5.87,5.87,0,1,0-7.52.21,3.76,3.76,0,0,0-3.11.75,2,2,0,0,0-1.05,1L58.9,47.42A3.74,3.74,0,0,0,58,49.07l-4,1.81A3.74,3.74,0,0,0,52.19,50a4.28,4.28,0,1,0-5.52,0,3.8,3.8,0,0,0-1.89.72l-2.86-2a3.91,3.91,0,0,0-.82-1.22L27.65,34a3.75,3.75,0,0,0-2.81-1.09l-.19-.05a5.88,5.88,0,1,0-7.64,0,3.77,3.77,0,0,0-4.18,2.16L5.11,52.33A3.77,3.77,0,0,0,12,55.38l.4-.89A5.12,5.12,0,0,0,13,56.62V73.69a3.77,3.77,0,0,0,3.77,3.77h0a3.77,3.77,0,0,0,3.77-3.77V59.29h.15V73.67a3.77,3.77,0,1,0,7.54,0V56.41a5.19,5.19,0,0,0,.54-2.26V45.76l7,7a3.74,3.74,0,0,0,3.74.93l3.75,2.67v9.2a3.69,3.69,0,0,0,.48,1.8v7.44a2.75,2.75,0,1,0,5.49,0v-5.5h.11v5.49a2.75,2.75,0,0,0,5.49,0V67.19a3.64,3.64,0,0,0,.4-1.64V56.34l5.6-2.55a3.75,3.75,0,0,0,3.38-1l8.64-8.64.74,4.59a1.61,1.61,0,0,1-.2,1.07L65.7,63.28a1.86,1.86,0,0,0,1.89,2.65h4v7.76a3.77,3.77,0,0,0,7.54,0V65.93h.15v7.74a3.77,3.77,0,0,0,7.54,0V65.93h3.43a1.85,1.85,0,0,0,1.88-2.65l-5.47-9.66a3.78,3.78,0,0,0-.9-1.57l-1.21-2.14a1.62,1.62,0,0,1-.18-1.14l.22-1.07L88,55.38a3.77,3.77,0,0,0,6.89-3.05Z" fill="none" stroke="#875b7b" stroke-linejoin="round" stroke-width="3"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.3 KiB |
|
|
@ -0,0 +1,5 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100">
|
||||
<g id="Parental_Time_Off" data-name="Parental Time Off">
|
||||
<path d="M94.89,52.33,87.17,34.94a3.76,3.76,0,0,0-3.86-2.2,5.87,5.87,0,1,0-7.52.21,3.76,3.76,0,0,0-3.11.75,2,2,0,0,0-1.05,1L58.9,47.42A3.74,3.74,0,0,0,58,49.07l-4,1.81A3.74,3.74,0,0,0,52.19,50a4.28,4.28,0,1,0-5.52,0,3.8,3.8,0,0,0-1.89.72l-2.86-2a3.91,3.91,0,0,0-.82-1.22L27.65,34a3.75,3.75,0,0,0-2.81-1.09l-.19-.05a5.88,5.88,0,1,0-7.64,0,3.77,3.77,0,0,0-4.18,2.16L5.11,52.33A3.77,3.77,0,0,0,12,55.38l.4-.89A5.12,5.12,0,0,0,13,56.62V73.69a3.77,3.77,0,0,0,3.77,3.77h0a3.77,3.77,0,0,0,3.77-3.77V59.29h.15V73.67a3.77,3.77,0,1,0,7.54,0V56.41a5.19,5.19,0,0,0,.54-2.26V45.76l7,7a3.74,3.74,0,0,0,3.74.93l3.75,2.67v9.2a3.69,3.69,0,0,0,.48,1.8v7.44a2.75,2.75,0,1,0,5.49,0v-5.5h.11v5.49a2.75,2.75,0,0,0,5.49,0V67.19a3.64,3.64,0,0,0,.4-1.64V56.34l5.6-2.55a3.75,3.75,0,0,0,3.38-1l8.64-8.64.74,4.59a1.61,1.61,0,0,1-.2,1.07L65.7,63.28a1.86,1.86,0,0,0,1.89,2.65h4v7.76a3.77,3.77,0,0,0,7.54,0V65.93h.15v7.74a3.77,3.77,0,0,0,7.54,0V65.93h3.43a1.85,1.85,0,0,0,1.88-2.65l-5.47-9.66a3.78,3.78,0,0,0-.9-1.57l-1.21-2.14a1.62,1.62,0,0,1-.18-1.14l.22-1.07L88,55.38a3.77,3.77,0,0,0,6.89-3.05Z" fill="#875b7b"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.2 KiB |
|
|
@ -0,0 +1,14 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100">
|
||||
<g id="Recovery_Bank_Holiday" data-name="Recovery Bank Holiday">
|
||||
<g>
|
||||
<g>
|
||||
<path d="M57.46,55.29V43.75a2.5,2.5,0,0,0-5,0V55.29a2.5,2.5,0,0,0,5,0Z" fill="#875b7b"/>
|
||||
<path d="M54.78,53.33l-14.85-.08a2.5,2.5,0,0,0,0,5l14.85.08a2.5,2.5,0,0,0,0-5Z" fill="#875b7b"/>
|
||||
</g>
|
||||
<g>
|
||||
<path d="M40.52,24.65A30.41,30.41,0,1,1,19.6,53.55c0-.36,0-.72,0-1.07" fill="none" stroke="#875b7b" stroke-linecap="round" stroke-linejoin="round" stroke-width="5"/>
|
||||
<path d="M47.38,14.28l-8.52,8.61a2.53,2.53,0,0,0,.51,3.92l9.37,6.05a2.52,2.52,0,0,0,3.42-.9,2.56,2.56,0,0,0-.9-3.42l-9.37-6,.5,3.92,8.53-8.6a2.5,2.5,0,1,0-3.54-3.54Z" fill="#875b7b"/>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 771 B |
|
|
@ -0,0 +1,8 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100">
|
||||
<g id="Recovery_Bank_Holiday" data-name="Recovery Bank Holiday">
|
||||
<g>
|
||||
<path d="M20,45a7.48,7.48,0,0,1,7.23,7.76c0,.27,0,.53,0,.8A22.91,22.91,0,1,0,57.55,31.86a7.74,7.74,0,0,1-.81,2.43,7.52,7.52,0,0,1-6.62,3.9,7.19,7.19,0,0,1-3.93-1.14l-8.87-5.72a7.44,7.44,0,0,1-4.07-7.59A34.22,34.22,0,0,0,16.93,45.55,7.42,7.42,0,0,1,19.79,45ZM40.1,53.24l12.52.07V43.74a2.5,2.5,0,0,1,5,0V55.28a2.34,2.34,0,0,1-.21,1,2.56,2.56,0,0,1-2.46,2L40.1,58.24a2.5,2.5,0,0,1,0-5Z" fill="#875b7b"/>
|
||||
<path d="M50.16,20.63c-.65,0-1.3,0-1.95.08,1-1,1.92-1.93,2.87-2.9a2.5,2.5,0,1,0-3.53-3.53l-8.16,8.23a2.48,2.48,0,0,0,.35,4.43l9.16,5.91a2.52,2.52,0,0,0,3.42-.9,2.56,2.56,0,0,0-.89-3.42L47.2,25.81a26.57,26.57,0,0,1,3-.18,27.91,27.91,0,1,1-27.9,27.91c0-.33,0-.65,0-1A2.49,2.49,0,0,0,19.87,50a2.52,2.52,0,0,0-2.59,2.4c0,.39,0,.77,0,1.16a32.91,32.91,0,1,0,32.9-32.91Z" fill="#875b7b"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 956 B |
|
|
@ -0,0 +1,12 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100">
|
||||
<g id="Sick_Time_Off" data-name="Sick Time Off">
|
||||
<g>
|
||||
<path d="M44.38,10.28h6.89a3.1,3.1,0,0,1,3.1,3.1V38.33A21.07,21.07,0,0,1,33.3,59.4h0A21.08,21.08,0,0,1,12.23,38.33V13.39a3.1,3.1,0,0,1,3.11-3.1l6.6,0" fill="none" stroke="#875b7b" stroke-linecap="round" stroke-linejoin="round" stroke-width="5"/>
|
||||
<path d="M32.63,59.93v7.84c0,29.27,44.79,29.27,44.79,0V57.82" fill="none" stroke="#875b7b" stroke-linecap="round" stroke-linejoin="round" stroke-width="5"/>
|
||||
<g>
|
||||
<circle cx="77.16" cy="45.77" r="10.6" fill="none" stroke="#875b7b" stroke-linecap="round" stroke-linejoin="round" stroke-width="5"/>
|
||||
<path d="M77.19,48.27c3.21,0,3.22-5,0-5s-3.23,5,0,5Z" fill="#875b7b"/>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 802 B |
|
|
@ -0,0 +1,12 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100">
|
||||
<g id="Sick_Time_Off" data-name="Sick Time Off">
|
||||
<g>
|
||||
<path d="M44.38,10.28h6.89a3.1,3.1,0,0,1,3.1,3.1V38.33A21.07,21.07,0,0,1,33.3,59.4h0A21.08,21.08,0,0,1,12.23,38.33V13.39a3.1,3.1,0,0,1,3.11-3.1l6.6,0" fill="none" stroke="#875b7b" stroke-linecap="round" stroke-linejoin="round" stroke-width="5"/>
|
||||
<path d="M32.63,59.93v7.84c0,29.27,44.79,29.27,44.79,0V57.82" fill="none" stroke="#875b7b" stroke-linecap="round" stroke-linejoin="round" stroke-width="5"/>
|
||||
<g>
|
||||
<circle cx="77.16" cy="45.77" r="10.6" fill="#875b7b" stroke="#875b7b" stroke-linecap="round" stroke-linejoin="round" stroke-width="5"/>
|
||||
<path d="M77.19,48.27c3.21,0,3.22-5,0-5s-3.23,5,0,5Z" fill="#875b7b"/>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 805 B |
|
|
@ -0,0 +1,10 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100">
|
||||
<g id="Small_Unemployement" data-name="Small Unemployement">
|
||||
<path d="M50,86.88A36.88,36.88,0,1,1,86.88,50,36.93,36.93,0,0,1,50,86.88Zm0-68.76A31.88,31.88,0,1,0,81.88,50,31.91,31.91,0,0,0,50,18.12Z" fill="#875b7b"/>
|
||||
<g>
|
||||
<path d="M34.9,64.53a2.14,2.14,0,0,1-2.14-2.14V54a49.9,49.9,0,0,0,13.75,3l-7.53-5a45.14,45.14,0,0,1-6.22-2V48l-4-2.63v17a6.14,6.14,0,0,0,6.14,6.14H64l-6.08-4Z" fill="#875b7b"/>
|
||||
<path d="M45.37,35.47h9.26v3.38H46.16L52.49,43H65.1a2.14,2.14,0,0,1,2.14,2.14V50c-.89.33-1.8.63-2.71.91l6.71,4.41V45.15A6.14,6.14,0,0,0,65.1,39H58.63V33.47a2,2,0,0,0-2-2H43.37a2,2,0,0,0-2,2V35.7l4,2.63Z" fill="#875b7b"/>
|
||||
</g>
|
||||
<path d="M78.42,71.53a2.46,2.46,0,0,1-1.37-.41L20.59,34a2.5,2.5,0,0,1,2.74-4.18L79.8,66.94a2.5,2.5,0,0,1-1.38,4.59Z" fill="#875b7b"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 864 B |
|
|
@ -0,0 +1,10 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100">
|
||||
<g id="Small_Unemployement" data-name="Small Unemployement">
|
||||
<path d="M50,86.88A36.88,36.88,0,1,1,86.88,50,36.92,36.92,0,0,1,50,86.88Zm0-68.76A31.88,31.88,0,1,0,81.88,50,31.91,31.91,0,0,0,50,18.12Z" fill="#875b7b"/>
|
||||
<g>
|
||||
<path d="M71.74,45.15a6.65,6.65,0,0,0-6.64-6.64h-6v-5a2.5,2.5,0,0,0-2.5-2.5H43.37a2.5,2.5,0,0,0-2.5,2.5v1.9L71.74,55.66Zm-17.61-6.8H45.87V36h8.26Z" fill="#875b7b"/>
|
||||
<path d="M28.26,45.15V62.39A6.65,6.65,0,0,0,34.9,69H64.77L28.26,45Z" fill="#875b7b"/>
|
||||
</g>
|
||||
<path d="M78.42,71.53a2.46,2.46,0,0,1-1.37-.41L20.59,34a2.5,2.5,0,0,1,2.74-4.18L79.8,66.94a2.5,2.5,0,0,1-1.38,4.59Z" fill="#875b7b"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 717 B |
|
|
@ -0,0 +1,11 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100">
|
||||
<g id="Small_Unemployement" data-name="Small Unemployement">
|
||||
<g>
|
||||
<g>
|
||||
<path d="M76.31,41.83a8.05,8.05,0,0,0-8-8H61.05v-6.1a3,3,0,0,0-3-3H42a3,3,0,0,0-3,3v6.1h-.74l38.1,25ZM55,33.6H45V30.72H55Z" fill="#875b7b"/>
|
||||
<path d="M23.69,62.69a8,8,0,0,0,8,8H65.67l-42-27.59Z" fill="#875b7b"/>
|
||||
</g>
|
||||
<path d="M82.64,75.33a2.89,2.89,0,0,1-1.59-.47L15.77,31.94A2.89,2.89,0,1,1,19,27.11L84.23,70a2.89,2.89,0,0,1-1.59,5.3Z" fill="#875b7b"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 549 B |
|
|
@ -0,0 +1,10 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100">
|
||||
<g id="Training_Time_Off" data-name="Training Time Off">
|
||||
<g>
|
||||
<path d="M47,42.25,8.09,29.61,47.66,17a8.69,8.69,0,0,1,5.22,0l39,12.15L52.44,42.23A8.59,8.59,0,0,1,47,42.25Z" fill="none" stroke="#875b7b" stroke-linecap="round" stroke-linejoin="round" stroke-width="5"/>
|
||||
<path d="M24.23,37.5v7.42c0,15.69,51.54,15.69,51.54,0V37.31" fill="none" stroke="#875b7b" stroke-linecap="round" stroke-linejoin="round" stroke-width="5"/>
|
||||
<line x1="35.89" y1="38.87" x2="35.89" y2="71.8" fill="none" stroke="#875b7b" stroke-linecap="round" stroke-linejoin="round" stroke-width="5"/>
|
||||
<circle cx="35.94" cy="77.78" r="5.68" fill="none" stroke="#875b7b" stroke-linecap="round" stroke-linejoin="round" stroke-width="5"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 816 B |
|
|
@ -0,0 +1,11 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100">
|
||||
<g id="Training_Time_Off" data-name="Training Time Off">
|
||||
<g>
|
||||
<g>
|
||||
<path d="M21.73,41.93v3c0,2.84,1.25,6.66,6.66,9.72V44.09Z" fill="#875b7b"/>
|
||||
<path d="M49.7,50.18a16.43,16.43,0,0,1-5-.79L43.39,49v9.88a64.34,64.34,0,0,0,6.61.35c14.07,0,28.27-4.41,28.27-14.27V41.53L54.81,49.35A16.23,16.23,0,0,1,49.7,50.18Z" fill="#875b7b"/>
|
||||
</g>
|
||||
<path d="M92.65,26.69l-39-12.14a11.12,11.12,0,0,0-6.73,0L7.33,27.23a2.5,2.5,0,0,0,0,4.76l26.07,8.47V70a8.16,8.16,0,1,0,5,0V42.08l7.86,2.55a11.06,11.06,0,0,0,7,0L92.7,31.45a2.5,2.5,0,0,0,0-4.76Z" fill="#875b7b"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 666 B |
|
|
@ -0,0 +1,10 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100">
|
||||
<g id="Unpaid_Time_Off" data-name="Unpaid Time Off">
|
||||
<path d="M50,86.55A36.55,36.55,0,1,1,86.55,50,36.6,36.6,0,0,1,50,86.55Zm0-68.1A31.55,31.55,0,1,0,81.55,50,31.59,31.59,0,0,0,50,18.45Z" fill="#875b7b"/>
|
||||
<path d="M60.78,34.26a13.53,13.53,0,0,0-8.6-3.93V27.58c0-3.22-5-3.22-5,0v3.09A11.57,11.57,0,0,0,38.43,41a11.4,11.4,0,0,0,3.08,8.61,11.55,11.55,0,0,0,5.67,3.29V66.13a8.48,8.48,0,0,1-4.42-2.36,2.2,2.2,0,0,1-.64-1.55v-3a2.5,2.5,0,0,0-2.49-2.51h0a2.51,2.51,0,0,0-2.5,2.49V62.2a7.25,7.25,0,0,0,2.1,5.11,13.55,13.55,0,0,0,8,3.87v1.24c0,3.22,5,3.22,5,0V71.05a11.6,11.6,0,0,0,9.39-10.49,11.46,11.46,0,0,0-9.39-12V35.35a8.5,8.5,0,0,1,5.06,2.45,2.15,2.15,0,0,1,.64,1.55v3a2.49,2.49,0,0,0,2.49,2.51h0a2.51,2.51,0,0,0,2.5-2.49V39.37A7.25,7.25,0,0,0,60.78,34.26ZM45.16,46.2a6.4,6.4,0,0,1,2-10.24v11.7A6.68,6.68,0,0,1,45.16,46.2Zm11.42,14a6.5,6.5,0,0,1-4.4,5.63V53.66a6.38,6.38,0,0,1,2.66,1.71A6.46,6.46,0,0,1,56.58,60.24Z" fill="#875b7b"/>
|
||||
<g>
|
||||
<path d="M33.44,40.68a16.67,16.67,0,0,1,.74-3.87L23,29.43a2.49,2.49,0,1,0-2.75,4.15l13.13,8.69C33.4,41.74,33.41,41.21,33.44,40.68Z" fill="#875b7b"/>
|
||||
<path d="M78.88,66.42,66.5,58.22a16.83,16.83,0,0,1,.06,2.66,15.9,15.9,0,0,1-.5,3l10.08,6.67a2.48,2.48,0,1,0,2.74-4.14Z" fill="#875b7b"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.3 KiB |
|
|
@ -0,0 +1,15 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100">
|
||||
<g id="Unpaid_Time_Off" data-name="Unpaid Time Off">
|
||||
<g>
|
||||
<path d="M61.24,34.26a13.53,13.53,0,0,0-8.6-3.93V27.58c0-3.22-5-3.22-5,0v3.09A11.57,11.57,0,0,0,38.89,41a11.44,11.44,0,0,0,8.75,11.9V66.13a8.5,8.5,0,0,1-4.43-2.36,2.19,2.19,0,0,1-.63-1.55v-3a2.5,2.5,0,0,0-2.49-2.51h0a2.5,2.5,0,0,0-2.5,2.49V62.2a7.21,7.21,0,0,0,2.1,5.11,13.52,13.52,0,0,0,8,3.87v1.24c0,3.22,5,3.22,5,0V71.05A11.58,11.58,0,0,0,62,60.56a11.46,11.46,0,0,0-9.38-12V35.35A8.5,8.5,0,0,1,57.7,37.8a2.2,2.2,0,0,1,.64,1.55v3a2.49,2.49,0,0,0,2.48,2.51h0a2.51,2.51,0,0,0,2.5-2.49V39.37A7.25,7.25,0,0,0,61.24,34.26Zm-13.6,13.4a6.56,6.56,0,0,1-2-1.46,6.4,6.4,0,0,1,2-10.24Zm7.66,7.71a6.42,6.42,0,0,1-2.66,10.5V53.66A6.38,6.38,0,0,1,55.3,55.37Z" fill="#875b7b"/>
|
||||
<g>
|
||||
<path d="M80.8,64,66.12,54.35A16.47,16.47,0,0,1,67,60.88a15.83,15.83,0,0,1-1.24,5.22l9.53,6.27a4.93,4.93,0,0,0,2.74.82A5,5,0,0,0,80.8,64Z" fill="#875b7b"/>
|
||||
<path d="M33.9,40.68a16.07,16.07,0,0,1,1.78-6.37L24.42,26.9a5,5,0,0,0-5.5,8.35L34.25,45.34A16.79,16.79,0,0,1,33.9,40.68Z" fill="#875b7b"/>
|
||||
</g>
|
||||
<g>
|
||||
<line x1="78.33" y1="31.08" x2="21.67" y2="68.47" fill="#875b7b"/>
|
||||
<path d="M21.68,73.47a5,5,0,0,1-2.76-9.17L75.57,26.9a5,5,0,0,1,5.51,8.35L24.43,72.64A5,5,0,0,1,21.68,73.47Z" fill="#875b7b"/>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.3 KiB |
|
|
@ -0,0 +1,5 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100">
|
||||
<g id="Credit_Time" data-name="Credit Time">
|
||||
<path d="M90.13,38.78a5.33,5.33,0,0,0-.28-1.44,1,1,0,0,0,0-.16c-.06-.18-.13-.35-.2-.51a6,6,0,0,0-.3-.56L89.21,36a4.82,4.82,0,0,0-4.15-2.26l-.43.06a4.3,4.3,0,0,0-.62,0H71a5,5,0,0,0,0,10H72.3L61.63,54.44,51.26,44.21s-.08-.06-.12-.1l-9-8.88a4.84,4.84,0,0,0-1.78-1.1,4.94,4.94,0,0,0-5.63.93L19.94,49.85v-2.7a5,5,0,0,0-10,0v13.1a3.93,3.93,0,0,0-.07,1,5.33,5.33,0,0,0,.28,1.44,1.09,1.09,0,0,0,0,.17c.06.17.13.34.2.5a6,6,0,0,0,.3.56l.09.14a4.82,4.82,0,0,0,4.15,2.26l.43-.06a4.3,4.3,0,0,0,.62,0H29a5,5,0,0,0,0-10H27.7L38.37,45.56,48.74,55.79s.08.06.12.1l9,8.88a4.84,4.84,0,0,0,1.78,1.1,4.94,4.94,0,0,0,5.63-.93L80.06,50.15v2.7a5,5,0,0,0,10,0V39.75A3.93,3.93,0,0,0,90.13,38.78Z" fill="none" stroke="#875b7b" stroke-miterlimit="10" stroke-width="5"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 869 B |
|
|
@ -0,0 +1,5 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100">
|
||||
<g id="Credit_Time" data-name="Credit Time">
|
||||
<path d="M90.13,38.78a5.33,5.33,0,0,0-.28-1.44,1,1,0,0,0,0-.16c-.06-.18-.13-.35-.2-.51a6,6,0,0,0-.3-.56L89.21,36a4.82,4.82,0,0,0-4.15-2.26l-.43.06a4.3,4.3,0,0,0-.62,0H71a5,5,0,0,0,0,10H72.3L61.63,54.44,51.26,44.21s-.08-.06-.12-.1l-9-8.88a4.84,4.84,0,0,0-1.78-1.1,4.94,4.94,0,0,0-5.63.93L19.94,49.85v-2.7a5,5,0,0,0-10,0v13.1a3.93,3.93,0,0,0-.07,1,5.33,5.33,0,0,0,.28,1.44,1.09,1.09,0,0,0,0,.17c.06.17.13.34.2.5a6,6,0,0,0,.3.56l.09.14a4.82,4.82,0,0,0,4.15,2.26l.43-.06a4.3,4.3,0,0,0,.62,0H29a5,5,0,0,0,0-10H27.7L38.37,45.56,48.74,55.79s.08.06.12.1l9,8.88a4.84,4.84,0,0,0,1.78,1.1,4.94,4.94,0,0,0,5.63-.93L80.06,50.15v2.7a5,5,0,0,0,10,0V39.75A3.93,3.93,0,0,0,90.13,38.78Z" fill="#875b7b"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 815 B |
|
|
@ -0,0 +1,11 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100">
|
||||
<g id="Work_Accident_Time_Off" data-name="Work Accident Time Off">
|
||||
<g>
|
||||
<path d="M39,44.17H61A20.59,20.59,0,0,1,81.63,64.75V89.91a0,0,0,0,1,0,0H27.2a8.82,8.82,0,0,1-8.82-8.82V64.75A20.59,20.59,0,0,1,39,44.17Z" fill="none" stroke="#875b7b" stroke-linecap="round" stroke-linejoin="round" stroke-width="5"/>
|
||||
<circle cx="50" cy="27.11" r="17.02" fill="none" stroke="#875b7b" stroke-linecap="round" stroke-linejoin="round" stroke-width="5"/>
|
||||
<path d="M63.63,89.8c11.79,0,11.79-16.12,0-16.12H58.5" fill="none" stroke="#875b7b" stroke-linecap="round" stroke-linejoin="round" stroke-width="5"/>
|
||||
<line x1="26.87" y1="48.15" x2="37.68" y2="88.75" fill="none" stroke="#875b7b" stroke-linecap="round" stroke-linejoin="round" stroke-width="5"/>
|
||||
<line x1="38.96" y1="44.17" x2="67.63" y2="89.68" fill="none" stroke="#875b7b" stroke-linecap="round" stroke-linejoin="round" stroke-width="5"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 998 B |
|
|
@ -0,0 +1,10 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100">
|
||||
<g id="Work_Accident_Time_Off" data-name="Work Accident Time Off">
|
||||
<g>
|
||||
<path d="M39,44.17H61A20.59,20.59,0,0,1,81.63,64.75V89.91a0,0,0,0,1,0,0H27.2a8.82,8.82,0,0,1-8.82-8.82V64.75A20.59,20.59,0,0,1,39,44.17Z" fill="none" stroke="#875b7b" stroke-linecap="round" stroke-linejoin="round" stroke-width="5"/>
|
||||
<circle cx="50" cy="27.11" r="17.02" fill="none" stroke="#875b7b" stroke-linecap="round" stroke-linejoin="round" stroke-width="5"/>
|
||||
<path d="M34,73.68H63.63c11.79,0,11.79,16.12,0,16.12" fill="none" stroke="#875b7b" stroke-linecap="round" stroke-linejoin="round" stroke-width="5"/>
|
||||
<polygon points="37.68 88.75 26.87 48.15 38.96 44.17 67.64 89.68 37.68 88.75" fill="#875b7b" stroke="#875b7b" stroke-linecap="round" stroke-linejoin="round" stroke-width="5"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 877 B |
|
|
@ -0,0 +1,17 @@
|
|||
/** @odoo-module **/
|
||||
import FieldRegistry from 'web.field_registry';
|
||||
import basic_fields from 'web.basic_fields';
|
||||
|
||||
var FieldFloat = basic_fields.FieldFloat;
|
||||
|
||||
var FloatWithoutTrailingZeros = FieldFloat.extend({
|
||||
_renderReadonly: function () {
|
||||
var value = this._formatValue(this.value);
|
||||
var parsed_value = parseFloat(value);
|
||||
value = parsed_value.toString().replace(/\.0+$/, '');
|
||||
this.$el.text(value);
|
||||
}
|
||||
});
|
||||
|
||||
FieldRegistry.add('float_without_trailing_zeros', FloatWithoutTrailingZeros);
|
||||
|
||||
|
|
@ -0,0 +1,105 @@
|
|||
/* @odoo-module */
|
||||
|
||||
import { useService } from '@web/core/utils/hooks';
|
||||
import { registry } from '@web/core/registry'
|
||||
|
||||
import { formatDate } from "@web/core/l10n/dates";
|
||||
|
||||
const { Component, useState, onWillStart, onWillUpdateProps } = owl;
|
||||
const { DateTime } = luxon;
|
||||
|
||||
export class LeaveStatsComponent extends Component {
|
||||
setup() {
|
||||
this.orm = useService('orm');
|
||||
|
||||
this.state = useState({
|
||||
leaves: [],
|
||||
departmentLeaves: [],
|
||||
});
|
||||
|
||||
this.date = this.props.record.data.date_from || DateTime.now();
|
||||
this.department = this.props.record.data.department_id;
|
||||
this.employee = this.props.record.data.employee_id;
|
||||
|
||||
onWillStart(async () => {
|
||||
await this.loadLeaves(this.date, this.employee);
|
||||
await this.loadDepartmentLeaves(this.date, this.department, this.employee);
|
||||
});
|
||||
onWillUpdateProps(async (nextProps) => {
|
||||
const dateFrom = nextProps.record.data.date_from || DateTime.now();
|
||||
const dateChanged = this.date !== dateFrom;
|
||||
const employee = nextProps.record.data.employee_id;
|
||||
const department = nextProps.record.data.department_id;
|
||||
|
||||
if (dateChanged || employee && (this.employee && this.employee[0]) !== employee[0]) {
|
||||
await this.loadLeaves(dateFrom, employee);
|
||||
}
|
||||
|
||||
if (dateChanged || department && (this.department && this.department[0]) !== department[0]) {
|
||||
await this.loadDepartmentLeaves(dateFrom, department, employee);
|
||||
}
|
||||
|
||||
this.date = dateFrom;
|
||||
this.employee = employee;
|
||||
this.department = department;
|
||||
})
|
||||
}
|
||||
|
||||
get thisYear() {
|
||||
return this.date.toFormat('yyyy');
|
||||
}
|
||||
|
||||
async loadDepartmentLeaves(date, department, employee) {
|
||||
if (!(department && employee && date)) {
|
||||
this.state.departmentLeaves = [];
|
||||
return;
|
||||
}
|
||||
|
||||
const dateFrom = date.startOf('month');
|
||||
const dateTo = date.endOf('month');
|
||||
|
||||
const departmentLeaves = await this.orm.searchRead(
|
||||
'hr.leave',
|
||||
[
|
||||
['department_id', '=', department[0]],
|
||||
['state', '=', 'validate'],
|
||||
['holiday_type', '=', 'employee'],
|
||||
['date_from', '<=', dateTo],
|
||||
['date_to', '>=', dateFrom],
|
||||
],
|
||||
['employee_id', 'date_from', 'date_to', 'number_of_days'],
|
||||
);
|
||||
|
||||
this.state.departmentLeaves = departmentLeaves.map((leave) => {
|
||||
return Object.assign({}, leave, {
|
||||
dateFrom: formatDate(DateTime.fromSQL(leave.date_from, { zone: 'utc' }).toLocal()),
|
||||
dateTo: formatDate(DateTime.fromSQL(leave.date_to, { zone: 'utc' }).toLocal()),
|
||||
sameEmployee: leave.employee_id[0] === employee[0],
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
async loadLeaves(date, employee) {
|
||||
if (!(employee && date)) {
|
||||
this.state.leaves = [];
|
||||
return;
|
||||
}
|
||||
|
||||
const dateFrom = date.startOf('year');
|
||||
const dateTo = date.endOf('year');
|
||||
this.state.leaves = await this.orm.readGroup(
|
||||
'hr.leave',
|
||||
[
|
||||
['employee_id', '=', employee[0]],
|
||||
['state', '=', 'validate'],
|
||||
['date_from', '<=', dateTo],
|
||||
['date_to', '>=', dateFrom]
|
||||
],
|
||||
['holiday_status_id', 'number_of_days:sum'],
|
||||
['holiday_status_id'],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
LeaveStatsComponent.template = 'hr_holidays.LeaveStatsComponent';
|
||||
registry.category('view_widgets').add('hr_leave_stats', LeaveStatsComponent);
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<templates xml:space="preserve">
|
||||
<div t-name="hr_holidays.LeaveStatsComponent" owl="1" class="o_leave_stats">
|
||||
<div t-if="employee" id="o_leave_stats_employee">
|
||||
<div class="o_hr_leave_subtitle">
|
||||
<t t-esc="employee[1]"/> in <t t-esc="thisYear"/>
|
||||
</div>
|
||||
<div t-if="state.leaves.length === 0">
|
||||
None
|
||||
</div>
|
||||
<div t-foreach="state.leaves" t-as="leave" t-key="leave_index" class="d-flex flex-row justify-content-between">
|
||||
<span t-esc="leave.holiday_status_id[1]"/>
|
||||
<span><t t-esc="leave.number_of_days"/> day(s)</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div t-if="department" id="o_leave_stats_department">
|
||||
<div class="o_horizontal_separator o_hr_leave_subtitle">
|
||||
<t t-esc="department[1]"/>
|
||||
</div>
|
||||
<div t-if="state.departmentLeaves.length === 0">
|
||||
None
|
||||
</div>
|
||||
<div t-foreach="state.departmentLeaves" t-as="leave" t-key="leave_index" t-attf-class="d-flex flex-row justify-content-between {{leave.sameEmployee ? 'fw-bold': ''}}">
|
||||
<span><t t-esc="leave.employee_id[1]"/>: <t t-esc="leave.number_of_days"/> day(s)</span>
|
||||
<span><t t-esc="leave.dateFrom"/> - <t t-esc="leave.dateTo"/></span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</templates>
|
||||
|
|
@ -0,0 +1,52 @@
|
|||
/** @odoo-module **/
|
||||
|
||||
import { registerPatch } from '@mail/model/model_core';
|
||||
import { attr } from '@mail/model/model_field';
|
||||
import { clear } from '@mail/model/model_field_command';
|
||||
|
||||
import { str_to_date } from 'web.time';
|
||||
|
||||
registerPatch({
|
||||
name: 'Partner',
|
||||
fields: {
|
||||
isOnline: {
|
||||
compute() {
|
||||
if (['leave_online', 'leave_away'].includes(this.im_status)) {
|
||||
return true;
|
||||
}
|
||||
return this._super();
|
||||
},
|
||||
},
|
||||
/**
|
||||
* Date of end of the out of office period of the partner as string.
|
||||
* String is expected to use Odoo's date string format
|
||||
* (examples: '2011-12-01' or '2011-12-01').
|
||||
*/
|
||||
out_of_office_date_end: attr(),
|
||||
/**
|
||||
* Text shown when partner is out of office.
|
||||
*/
|
||||
outOfOfficeText: attr({
|
||||
compute() {
|
||||
if (!this.out_of_office_date_end) {
|
||||
return clear();
|
||||
}
|
||||
if (!this.messaging.locale || !this.messaging.locale.language) {
|
||||
return clear();
|
||||
}
|
||||
const currentDate = new Date();
|
||||
const date = str_to_date(this.out_of_office_date_end);
|
||||
const options = { day: 'numeric', month: 'short' };
|
||||
if (currentDate.getFullYear() !== date.getFullYear()) {
|
||||
options.year = 'numeric';
|
||||
}
|
||||
let localeCode = this.messaging.locale.language.replace(/_/g, '-');
|
||||
if (localeCode === "sr@latin") {
|
||||
localeCode = "sr-Latn-RS";
|
||||
}
|
||||
const formattedDate = date.toLocaleDateString(localeCode, options);
|
||||
return _.str.sprintf(this.env._t("Out of office until %s"), formattedDate);
|
||||
},
|
||||
}),
|
||||
},
|
||||
});
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
/** @odoo-module **/
|
||||
|
||||
import { registry } from "@web/core/registry";
|
||||
import { RadioField, preloadRadio } from "@web/views/fields/radio/radio_field";
|
||||
|
||||
class RadioImageField extends RadioField {}
|
||||
RadioImageField.template = "hr_holidays.RadioImageField";
|
||||
|
||||
registry.category("fields").add("hr_holidays_radio_image", RadioImageField);
|
||||
|
||||
registry.category("preloadedData").add("hr_holidays_radio_image", {
|
||||
loadOnTypes: ["many2one"],
|
||||
preload: preloadRadio,
|
||||
});
|
||||
|
|
@ -0,0 +1,36 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<templates id="template" xml:space="preserve">
|
||||
|
||||
<t t-name="hr_holidays.RadioImageField" owl="1">
|
||||
<div role="radiogroup" class="d-flex flex-wrap" t-att-aria-label="string">
|
||||
<t t-if="props.readonly">
|
||||
<t t-if="value !== false">
|
||||
<div>
|
||||
<img t-attf-src="/hr_holidays/static/src/img/icons/{{items.find((item) => item[0] === value)[1]}}" width="48" height="48" />
|
||||
</div>
|
||||
</t>
|
||||
</t>
|
||||
<t t-else="">
|
||||
<t t-foreach="items" t-as="item" t-key="item[0]">
|
||||
<div class="form-check o_radio_item" aria-atomic="true">
|
||||
<input
|
||||
type="radio"
|
||||
class="form-check-input o_radio_input"
|
||||
t-att-checked="item[0] === value"
|
||||
t-att-disabled="props.readonly"
|
||||
t-att-name="id"
|
||||
t-att-data-value="item[0]"
|
||||
t-att-data-index="item_index"
|
||||
t-att-id="`${id}_${item[0]}`"
|
||||
t-on-change="() => this.onChange(item)"
|
||||
/>
|
||||
<label class="form-check-label o_form_label" t-att-for="`${id}_${item[0]}`">
|
||||
<img t-attf-src="/hr_holidays/static/src/img/icons/{{item[1]}}" width="48" height="48" />
|
||||
</label>
|
||||
</div>
|
||||
</t>
|
||||
</t>
|
||||
</div>
|
||||
</t>
|
||||
|
||||
</templates>
|
||||
|
|
@ -0,0 +1,115 @@
|
|||
$o-hr-holidays-border-color: map-get($grays, '300');
|
||||
|
||||
.o_hr_holidays_hierarchy {
|
||||
margin-left: -$o-horizontal-padding;
|
||||
margin-right: -$o-horizontal-padding;
|
||||
@include media-breakpoint-up(lg, $o-extra-grid-breakpoints) {
|
||||
margin-left: -$o-horizontal-padding*2;
|
||||
margin-right: -$o-horizontal-padding*2;
|
||||
}
|
||||
margin-bottom:-24px;
|
||||
padding: 10px 0px 24px 16px;
|
||||
background-color: rgba(128, 128, 128, 0.15);
|
||||
box-shadow: 0px 1px 1px rgba(17, 17, 17, 0.23);
|
||||
overflow-x: auto;
|
||||
.o_hr_holidays_title {
|
||||
padding: 0px 0px 0px 86px;
|
||||
font-size: 18px;
|
||||
}
|
||||
|
||||
.o_hr_holidays_hierarchy_readonly {
|
||||
padding: 40px 0px 0px 40px;
|
||||
}
|
||||
|
||||
.o_hr_holidays_plan_level_container {
|
||||
counter-reset: o-hr-holidays-accrual-plan-level-counter;
|
||||
|
||||
.o-kanban-button-new {
|
||||
padding: 2px 12px;
|
||||
margin: 0px 0px 0px 44px;
|
||||
border-radius: 25px;
|
||||
}
|
||||
|
||||
.o_legacy_kanban_view.o_kanban_ungrouped .o_kanban_record,
|
||||
.o_kanban_renderer.o_kanban_ungrouped .o_kanban_record {
|
||||
counter-increment: o-hr-holidays-accrual-plan-level-counter;
|
||||
display: flex;
|
||||
flex: 0 0 100%;
|
||||
border: 0px;
|
||||
padding: 0px 0px 0px 100px;
|
||||
margin: 0px 0px 0px 0px;
|
||||
background-color: transparent;
|
||||
|
||||
// Timeline Border
|
||||
&:before {
|
||||
content: '';
|
||||
display: block;
|
||||
@include o-position-absolute;
|
||||
height: 100%;
|
||||
margin-left: 8px;
|
||||
border-left: 1px dashed darken($o-hr-holidays-border-color, 10%);
|
||||
}
|
||||
|
||||
.o_hr_holidays_plan_level_level::before {
|
||||
content: counter(o-hr-holidays-accrual-plan-level-counter);
|
||||
}
|
||||
|
||||
// Whole record
|
||||
.o_hr_holidays_body {
|
||||
margin-left: 8px;
|
||||
padding-top: 20px;
|
||||
|
||||
// Left side 'Level'
|
||||
.o_hr_holidays_timeline {
|
||||
@include o-position-absolute($top: 32px, $left: 6px);
|
||||
width: 90px;
|
||||
padding: 3px 0px;
|
||||
border-radius: 3px;
|
||||
background-color: $o-btn-secondary-bg;
|
||||
box-shadow: 0 1px 2px rgba(0,0,0,.1);
|
||||
}
|
||||
|
||||
// Actual kanban card
|
||||
.o_hr_holidays_card {
|
||||
position: relative;
|
||||
margin-left: 22px;
|
||||
margin-right: 2px;
|
||||
width: 500px;
|
||||
border-radius: 3px;
|
||||
background-color: $o-btn-secondary-bg;
|
||||
box-shadow: 0 1px 2px rgba(0,0,0,.1);
|
||||
|
||||
// Triangle
|
||||
&:before {
|
||||
content: '';
|
||||
@include o-position-absolute($top: 12px, $left: -17px);
|
||||
margin-left: 10px;
|
||||
width: 14px;
|
||||
height: 14px;
|
||||
background-color: $o-btn-secondary-bg;
|
||||
border-bottom: 1px solid $o-hr-holidays-border-color;
|
||||
transform: rotate(45deg);
|
||||
}
|
||||
|
||||
// Circle
|
||||
&:after {
|
||||
content: '';
|
||||
@include o-position-absolute($top: 14px, $left: -36px);
|
||||
width: 12px;
|
||||
height: 12px;
|
||||
border: 2px solid $o-brand-primary;
|
||||
border-radius: 10px;
|
||||
background: $o-btn-secondary-bg;
|
||||
}
|
||||
|
||||
.content {
|
||||
position: relative;
|
||||
background-color: $o-btn-secondary-bg;
|
||||
padding: 5px 7px;
|
||||
font-size: 14px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,50 @@
|
|||
.o_hr_leave_form {
|
||||
.o_form_sheet {
|
||||
padding: 0!important;
|
||||
overflow: hidden;
|
||||
.ribbon-top-right {
|
||||
top: 16px;
|
||||
right: -8px;
|
||||
}
|
||||
}
|
||||
.o_hr_leave_content {
|
||||
margin: 0;
|
||||
.o_group {
|
||||
margin: 0;
|
||||
}
|
||||
.o_hr_leave_title, .o_hr_leave_subtitle {
|
||||
line-height: 1.2;
|
||||
font-weight: 500;
|
||||
margin-bottom: 8px;
|
||||
* {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
}
|
||||
.o_hr_leave_title {
|
||||
font-size: 1.8rem;
|
||||
}
|
||||
.o_hr_leave_subtitle {
|
||||
font-size: 1.2rem;
|
||||
}
|
||||
.o_hr_leave_column {
|
||||
padding: 16px;
|
||||
}
|
||||
.col_right {
|
||||
background-color: map-get($grays, '200');
|
||||
padding-top: 28px;
|
||||
}
|
||||
.o_hr_leave_date {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
@include media-breakpoint-down(lg) {
|
||||
flex-direction: column;
|
||||
}
|
||||
@include media-breakpoint-down(md) {
|
||||
flex-direction: row;
|
||||
}
|
||||
}
|
||||
.o_leave_stats {
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,89 @@
|
|||
/** @odoo-module **/
|
||||
import tour from 'web_tour.tour';
|
||||
import { _t } from 'web.core';
|
||||
|
||||
const leaveType = "NotLimitedHR";
|
||||
const leaveDateFrom = "01/17/2022";
|
||||
const leaveDateTo = "01/17/2022";
|
||||
const description = 'Days off';
|
||||
|
||||
tour.register('hr_holidays_tour', {
|
||||
url: '/web',
|
||||
rainbowManMessage: _t("Congrats, we can see that your request has been validated."),
|
||||
test: false
|
||||
}, [
|
||||
tour.stepUtils.showAppsMenuItem(),
|
||||
{
|
||||
trigger: '.o_app[data-menu-xmlid="hr_holidays.menu_hr_holidays_root"]',
|
||||
content: _t("Let's discover the Time Off application"),
|
||||
position: 'bottom',
|
||||
},
|
||||
{
|
||||
trigger: 'button.btn-time-off',
|
||||
content: _t("Click on any date or on this button to request a time-off"),
|
||||
position: 'bottom',
|
||||
},
|
||||
{
|
||||
trigger: 'div[name="holiday_status_id"] input',
|
||||
content: _t("Let's try to create a Sick Time Off, select it in the list"),
|
||||
run: `text ${leaveType}`,
|
||||
},
|
||||
{
|
||||
trigger: `.ui-autocomplete .ui-menu-item a:contains("${leaveType}")`,
|
||||
run: "click",
|
||||
auto: true,
|
||||
in_modal: false,
|
||||
},
|
||||
{
|
||||
trigger: '.o_field_widget[name="request_date_from"] input',
|
||||
content: _t("You can select the period you need to take off, from start date to end date"),
|
||||
position: 'right',
|
||||
run: `text ${leaveDateFrom}`,
|
||||
},
|
||||
{
|
||||
trigger: '.o_field_widget[name="request_date_to"] input',
|
||||
content: _t("You can select the period you need to take off, from start date to end date"),
|
||||
position: 'right',
|
||||
run: `text ${leaveDateTo}`,
|
||||
},
|
||||
{
|
||||
trigger: 'div[name="name"] textarea',
|
||||
content: _t("Add some description for the people that will validate it"),
|
||||
run: `text ${description}`,
|
||||
position: 'right'
|
||||
},
|
||||
{
|
||||
trigger: `button:contains(${_t('Save')})`,
|
||||
content: _t("Submit your request"),
|
||||
position: 'bottom',
|
||||
},
|
||||
{
|
||||
trigger: 'button[data-menu-xmlid="hr_holidays.menu_hr_holidays_approvals"]',
|
||||
content: _t("Let's go validate it"),
|
||||
position: 'bottom'
|
||||
},
|
||||
{
|
||||
trigger: 'a[data-menu-xmlid="hr_holidays.menu_open_department_leave_approve"]',
|
||||
content: _t("Select Time Off"),
|
||||
position: 'right'
|
||||
},
|
||||
{
|
||||
trigger: 'table.o_list_table',
|
||||
content: _t("Select the request you just created"),
|
||||
position: 'bottom',
|
||||
run: function(actions) {
|
||||
const rows = this.$anchor.find('tr.o_data_row');
|
||||
actions.click(rows[0]);
|
||||
}
|
||||
},
|
||||
{
|
||||
trigger: 'button[name="action_approve"]',
|
||||
content: _t("Let's approve it"),
|
||||
position: 'bottom'
|
||||
},
|
||||
{
|
||||
trigger: 'a[data-menu-xmlid="hr_holidays.menu_hr_holidays_root"]',
|
||||
content: _t("State is now confirmed. We can go back to the calendar"),
|
||||
position: 'bottom'
|
||||
}
|
||||
]);
|
||||
|
|
@ -0,0 +1,124 @@
|
|||
/** @odoo-module */
|
||||
|
||||
import { ConfirmationDialog } from "@web/core/confirmation_dialog/confirmation_dialog";
|
||||
import { CalendarController } from '@web/views/calendar/calendar_controller';
|
||||
import { FormViewDialog } from '@web/views/view_dialogs/form_view_dialog';
|
||||
|
||||
import { serializeDate } from "@web/core/l10n/dates";
|
||||
|
||||
import { TimeOffCalendarFilterPanel } from './filter_panel/calendar_filter_panel';
|
||||
import { TimeOffFormViewDialog } from '../view_dialog/form_view_dialog';
|
||||
import { useLeaveCancelWizard } from '../hooks';
|
||||
|
||||
const { EventBus, useSubEnv } = owl;
|
||||
|
||||
export class TimeOffCalendarController extends CalendarController {
|
||||
setup() {
|
||||
super.setup();
|
||||
useSubEnv({
|
||||
timeOffBus: new EventBus(),
|
||||
});
|
||||
this.leaveCancelWizard = useLeaveCancelWizard();
|
||||
}
|
||||
|
||||
get employeeId() {
|
||||
return this.model.employeeId;
|
||||
}
|
||||
|
||||
get filterPanelProps() {
|
||||
return {
|
||||
...super.filterPanelProps,
|
||||
employee_id: this.employeeId,
|
||||
};
|
||||
}
|
||||
|
||||
newTimeOffRequest() {
|
||||
const context = {};
|
||||
if (this.employeeId) {
|
||||
context['default_employee_id'] = this.employeeId;
|
||||
}
|
||||
if (this.model.meta.scale == 'day') {
|
||||
context['default_date_from'] = serializeDate(
|
||||
this.model.data.range.start.set({ hours: 7 }), "datetime"
|
||||
);
|
||||
context['default_date_to'] = serializeDate(
|
||||
this.model.data.range.end.set({ hours: 19 }), "datetime"
|
||||
);
|
||||
}
|
||||
|
||||
this.displayDialog(FormViewDialog, {
|
||||
resModel: 'hr.leave',
|
||||
title: this.env._t('New Time Off'),
|
||||
viewId: this.model.formViewId,
|
||||
onRecordSaved: () => {
|
||||
this.model.load();
|
||||
this.env.timeOffBus.trigger('update_dashboard');
|
||||
},
|
||||
context: context,
|
||||
});
|
||||
}
|
||||
|
||||
newAllocationRequest() {
|
||||
const context = {
|
||||
'form_view_ref': 'hr_holidays.hr_leave_allocation_view_form_dashboard',
|
||||
};
|
||||
if (this.employeeId) {
|
||||
context['default_employee_id'] = this.employeeId;
|
||||
context['default_employee_ids'] = [this.employeeId];
|
||||
context['form_view_ref'] = 'hr_holidays.hr_leave_allocation_view_form_manager_dashboard';
|
||||
}
|
||||
|
||||
this.displayDialog(FormViewDialog, {
|
||||
resModel: 'hr.leave.allocation',
|
||||
title: this.env._t('New Allocation'),
|
||||
context: context,
|
||||
});
|
||||
}
|
||||
|
||||
deleteRecord(record) {
|
||||
if (!record.can_cancel) {
|
||||
this.displayDialog(ConfirmationDialog, {
|
||||
title: this.env._t("Confirmation"),
|
||||
body: this.env._t("Are you sure you want to delete this record ?"),
|
||||
confirm: async () => {
|
||||
await this.model.unlinkRecord(record.id);
|
||||
this.env.timeOffBus.trigger('update_dashboard');
|
||||
},
|
||||
cancel: () => {},
|
||||
});
|
||||
} else {
|
||||
this.leaveCancelWizard(record.id, () => {
|
||||
this.model.load();
|
||||
this.env.timeOffBus.trigger('update_dashboard');
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
async editRecord(record, context = {}, shouldFetchFormViewId = true) {
|
||||
const onDialogClosed = () => {
|
||||
this.model.load();
|
||||
this.env.timeOffBus.trigger('update_dashboard');
|
||||
};
|
||||
|
||||
return new Promise((resolve) => {
|
||||
this.displayDialog(
|
||||
TimeOffFormViewDialog, {
|
||||
resModel: this.model.resModel,
|
||||
resId: record.id || false,
|
||||
context,
|
||||
title: this.env._t("Time Off Request"),
|
||||
viewId: this.model.formViewId,
|
||||
onRecordSaved: onDialogClosed,
|
||||
onRecordDeleted: (record) => this.deleteRecord(record),
|
||||
onLeaveCancelled: onDialogClosed,
|
||||
},
|
||||
{ onClose: () => resolve() }
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
||||
TimeOffCalendarController.template = "hr_holidays.CalendarController";
|
||||
TimeOffCalendarController.components = {
|
||||
...TimeOffCalendarController.components,
|
||||
FilterPanel: TimeOffCalendarFilterPanel,
|
||||
}
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<templates xml:space="preserve">
|
||||
|
||||
<t t-name="hr_holidays.CalendarController" t-inherit="web.CalendarController" t-inherit-mode="primary" owl="1">
|
||||
<xpath expr="//DatePicker" position="replace"/>
|
||||
</t>
|
||||
|
||||
<t t-name="hr_holidays.CalendarController.controlButtons" t-inherit="web.CalendarController.controlButtons" t-inherit-mode="primary" owl="1">
|
||||
<xpath expr="//span[hasclass('o_calendar_scale_buttons')]" position="after">
|
||||
<span class="o_timeoff_buttons">
|
||||
<button class="btn btn-primary btn-time-off mx-1" t-on-click="newTimeOffRequest" type="button">
|
||||
New Time Off
|
||||
</button>
|
||||
<button class="btn btn-secondary" t-on-click="newAllocationRequest" type="button">
|
||||
<t t-if="employeeId">New</t> Allocation Request
|
||||
</button>
|
||||
</span>
|
||||
</xpath>
|
||||
</t>
|
||||
|
||||
</templates>
|
||||
|
|
@ -0,0 +1,75 @@
|
|||
/** @odoo-module */
|
||||
|
||||
import { CalendarModel } from '@web/views/calendar/calendar_model';
|
||||
import { deserializeDateTime, serializeDate, serializeDateTime } from "@web/core/l10n/dates";
|
||||
|
||||
export class TimeOffCalendarModel extends CalendarModel {
|
||||
setup(params, services) {
|
||||
super.setup(params, services);
|
||||
|
||||
this.data.stressDays = {};
|
||||
if (this.env.isSmall) {
|
||||
this.meta.scale = 'month';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
normalizeRecord(rawRecord) {
|
||||
let result = super.normalizeRecord(...arguments);
|
||||
if (rawRecord.employee_id) {
|
||||
const employee = rawRecord.employee_id[1];
|
||||
result.title = [employee, result.title].join(' ');
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
makeContextDefaults(record) {
|
||||
const { scale } = this.meta;
|
||||
const context = super.makeContextDefaults(record);
|
||||
if (this.employeeId) {
|
||||
context['default_employee_id'] = this.employeeId;
|
||||
}
|
||||
|
||||
if(['day', 'week'].includes(scale)) {
|
||||
if ('default_date_from' in context) {
|
||||
context['default_date_from'] = serializeDateTime(deserializeDateTime(context['default_date_from']).set({ hours: 7 }));
|
||||
}
|
||||
if ('default_date_to' in context) {
|
||||
context['default_date_to'] = serializeDateTime(deserializeDateTime(context['default_date_from']).set({ hours: 19 }));
|
||||
}
|
||||
}
|
||||
return context;
|
||||
}
|
||||
|
||||
async updateData(data) {
|
||||
await super.updateData(data);
|
||||
data.stressDays = await this.fetchStressDays(data);
|
||||
}
|
||||
|
||||
async fetchStressDays(data) {
|
||||
return this.orm.call("hr.employee", "get_stress_days", [
|
||||
this.employeeId,
|
||||
serializeDate(data.range.start, "datetime"),
|
||||
serializeDate(data.range.end, "datetime"),
|
||||
]);
|
||||
}
|
||||
|
||||
get stressDays() {
|
||||
return this.data.stressDays;
|
||||
}
|
||||
|
||||
get employeeId() {
|
||||
return this.meta.context.employee_id && this.meta.context.employee_id[0] || null;
|
||||
}
|
||||
|
||||
fetchRecords(data) {
|
||||
const { fieldNames, resModel } = this.meta;
|
||||
const context = {};
|
||||
if (!this.employeeId) {
|
||||
context['short_name'] = 1;
|
||||
}
|
||||
return this.orm.searchRead(resModel, this.computeDomain(data), fieldNames, { context });
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
/** @odoo-module */
|
||||
|
||||
import { CalendarRenderer } from '@web/views/calendar/calendar_renderer';
|
||||
|
||||
import { TimeOffCalendarCommonRenderer } from './common/calendar_common_renderer';
|
||||
import { TimeOffCalendarYearRenderer } from './year/calendar_year_renderer';
|
||||
|
||||
import { TimeOffDashboard } from '../../dashboard/time_off_dashboard';
|
||||
|
||||
export class TimeOffCalendarRenderer extends CalendarRenderer {
|
||||
get employeeId() {
|
||||
return this.props.model.employeeId;
|
||||
}
|
||||
|
||||
get showDashboard() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
TimeOffCalendarRenderer.template = 'hr_holidays.CalendarRenderer';
|
||||
TimeOffCalendarRenderer.components = {
|
||||
...TimeOffCalendarRenderer.components,
|
||||
day: TimeOffCalendarCommonRenderer,
|
||||
week: TimeOffCalendarCommonRenderer,
|
||||
month: TimeOffCalendarCommonRenderer,
|
||||
year: TimeOffCalendarYearRenderer,
|
||||
TimeOffDashboard,
|
||||
};
|
||||
|
||||
export class TimeOffDashboardCalendarRenderer extends TimeOffCalendarRenderer {
|
||||
get showDashboard() {
|
||||
return !this.env.isSmall;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
.o_timeoff_calendar {
|
||||
.o_calendar_renderer {
|
||||
height: unset;
|
||||
|
||||
@for $size from 1 through length($o-colors) {
|
||||
.o_calendar_widget {
|
||||
.hr_stress_day_top_#{$size - 1}:not(.fc-disabled-day) {
|
||||
.fc-day-number {
|
||||
color: nth($o-colors, $size) !important;
|
||||
font-weight: 600;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.fc-bgevent {
|
||||
border-radius: 25px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<templates xml:space="preserve">
|
||||
|
||||
<t t-name="hr_holidays.CalendarRenderer" owl="1">
|
||||
<div class="o_timeoff_calendar">
|
||||
<TimeOffDashboard t-if="showDashboard" employeeId="employeeId"/>
|
||||
<t t-call="web.CalendarRenderer"/>
|
||||
</div>
|
||||
</t>
|
||||
|
||||
</templates>
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
/** @odoo-module */
|
||||
|
||||
import { calendarView } from '@web/views/calendar/calendar_view';
|
||||
|
||||
import { TimeOffCalendarController } from './calendar_controller';
|
||||
import { TimeOffCalendarModel } from './calendar_model';
|
||||
import { TimeOffCalendarRenderer, TimeOffDashboardCalendarRenderer } from './calendar_renderer';
|
||||
|
||||
import { registry } from '@web/core/registry';
|
||||
|
||||
const TimeOffCalendarView = {
|
||||
...calendarView,
|
||||
|
||||
Controller: TimeOffCalendarController,
|
||||
Renderer: TimeOffCalendarRenderer,
|
||||
Model: TimeOffCalendarModel,
|
||||
|
||||
buttonTemplate: "hr_holidays.CalendarController.controlButtons",
|
||||
}
|
||||
|
||||
registry.category('views').add('time_off_calendar', TimeOffCalendarView);
|
||||
registry.category('views').add('time_off_calendar_dashboard', {
|
||||
...TimeOffCalendarView,
|
||||
Renderer: TimeOffDashboardCalendarRenderer,
|
||||
});
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
/** @odoo-module */
|
||||
|
||||
import { CalendarCommonPopover } from "@web/views/calendar/calendar_common/calendar_common_popover";
|
||||
|
||||
import { useService } from "@web/core/utils/hooks";
|
||||
|
||||
export class TimeOffCalendarCommonPopover extends CalendarCommonPopover {
|
||||
setup() {
|
||||
super.setup();
|
||||
|
||||
this.dialog = useService('dialog');
|
||||
this.action = useService('action');
|
||||
}
|
||||
|
||||
get isEventDeletable() {
|
||||
const record = this.props.record.rawRecord;
|
||||
const state = record.state;
|
||||
return record.can_cancel || state && !['validate', 'refuse'].includes(state);
|
||||
}
|
||||
|
||||
get isEventEditable() {
|
||||
const state = this.props.record.rawRecord.state;
|
||||
return state !== undefined;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
/** @odoo-module */
|
||||
|
||||
import { CalendarCommonRenderer } from '@web/views/calendar/calendar_common/calendar_common_renderer';
|
||||
|
||||
import { useStressDays } from '../../hooks';
|
||||
import { TimeOffCalendarCommonPopover } from './calendar_common_popover';
|
||||
|
||||
|
||||
export class TimeOffCalendarCommonRenderer extends CalendarCommonRenderer {
|
||||
setup() {
|
||||
super.setup();
|
||||
this.stressDays = useStressDays(this.props);
|
||||
}
|
||||
|
||||
onDayRender(info) {
|
||||
super.onDayRender(info);
|
||||
this.stressDays(info);
|
||||
}
|
||||
}
|
||||
TimeOffCalendarCommonRenderer.components = {
|
||||
...TimeOffCalendarCommonRenderer,
|
||||
Popover: TimeOffCalendarCommonPopover,
|
||||
}
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
// = HR Holidays
|
||||
// ============================================================================
|
||||
// No CSS hacks, variables overrides only
|
||||
.o_calendar_filter {
|
||||
--calendarFilter-icon--plain: url("/hr/static/src/img/icons/plain_dark.svg");
|
||||
--calendarFilter-icon--hatched: url("/hr/static/src/img/icons/hatched_dark.svg");
|
||||
--calendarFilter-icon--line: url("/hr/static/src/img/icons/line_dark.svg");
|
||||
}
|
||||
|
|
@ -0,0 +1,79 @@
|
|||
/** @odoo-module */
|
||||
|
||||
import { CalendarFilterPanel } from "@web/views/calendar/filter_panel/calendar_filter_panel";
|
||||
import { TimeOffCardMobile } from "../../../dashboard/time_off_card";
|
||||
import { getFormattedDateSpan } from '@web/views/calendar/utils';
|
||||
|
||||
import { useService } from "@web/core/utils/hooks";
|
||||
import { serializeDate } from "@web/core/l10n/dates";
|
||||
|
||||
const { useState, onWillStart, onWillUpdateProps } = owl;
|
||||
|
||||
export class TimeOffCalendarFilterPanel extends CalendarFilterPanel {
|
||||
setup() {
|
||||
super.setup();
|
||||
|
||||
this.orm = useService('orm');
|
||||
this.getFormattedDateSpan = getFormattedDateSpan;
|
||||
this.leaveState = useState({
|
||||
holidays: [],
|
||||
stressDays: [],
|
||||
bankHolidays: [],
|
||||
});
|
||||
|
||||
onWillStart(async () => {
|
||||
await this.loadFilterData();
|
||||
await this.updateSpecialDays();
|
||||
});
|
||||
onWillUpdateProps(this.updateSpecialDays);
|
||||
}
|
||||
|
||||
async updateSpecialDays() {
|
||||
const context = {
|
||||
'employee_id': this.props.employee_id,
|
||||
}
|
||||
const specialDays = await this.orm.call(
|
||||
'hr.employee', 'get_special_days_data', [
|
||||
serializeDate(this.props.model.rangeStart, "datetime"),
|
||||
serializeDate(this.props.model.rangeEnd, "datetime"),
|
||||
],
|
||||
{
|
||||
'context': context,
|
||||
},
|
||||
);
|
||||
specialDays['bankHolidays'].forEach(bankHoliday => {
|
||||
bankHoliday.start = luxon.DateTime.fromISO(bankHoliday.start)
|
||||
bankHoliday.end = luxon.DateTime.fromISO(bankHoliday.end)
|
||||
});
|
||||
specialDays['stressDays'].forEach(stressDay => {
|
||||
stressDay.start = luxon.DateTime.fromISO(stressDay.start)
|
||||
stressDay.end = luxon.DateTime.fromISO(stressDay.end)
|
||||
});
|
||||
this.leaveState.bankHolidays = specialDays['bankHolidays'];
|
||||
this.leaveState.stressDays = specialDays['stressDays'];
|
||||
}
|
||||
|
||||
async loadFilterData() {
|
||||
if(!this.env.isSmall) {
|
||||
return;
|
||||
}
|
||||
|
||||
const filterData = {};
|
||||
const data = await this.orm.call(
|
||||
'hr.leave.type', 'get_days_all_request', [],
|
||||
);
|
||||
|
||||
data.forEach((leave) => {
|
||||
filterData[leave[3]] = leave;
|
||||
});
|
||||
this.leaveState.holidays = filterData;
|
||||
}
|
||||
}
|
||||
TimeOffCalendarFilterPanel.template = 'hr_holidays.CalendarFilterPanel';
|
||||
TimeOffCalendarFilterPanel.components = {
|
||||
...TimeOffCalendarFilterPanel.components,
|
||||
TimeOffCardMobile,
|
||||
}
|
||||
TimeOffCalendarFilterPanel.subTemplates = {
|
||||
filter: "hr_holidays.CalendarFilterPanel.filter",
|
||||
}
|
||||
|
|
@ -0,0 +1,45 @@
|
|||
.o_calendar_filter {
|
||||
span {
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
& img {
|
||||
width:30px;
|
||||
|
||||
&.o_calendar_filter_plain {
|
||||
content:var(--calendarFilter-icon--plain);
|
||||
}
|
||||
|
||||
&.o_calendar_filter_hatched {
|
||||
content:var(--calendarFilter-icon--hatched);
|
||||
}
|
||||
|
||||
&.o_calendar_filter_line {
|
||||
content:var(--calendarFilter-icon--line);
|
||||
}
|
||||
}
|
||||
|
||||
.o_timeoff_legend {
|
||||
display: inline-block;
|
||||
width: 24px;
|
||||
height: 30px;
|
||||
margin: 0 3px;
|
||||
padding: 3px 0;
|
||||
text-align: center;
|
||||
|
||||
&_bankholiday {
|
||||
background-color: $gray-200;
|
||||
}
|
||||
|
||||
&_stressday {
|
||||
font-weight: 600;
|
||||
}
|
||||
}
|
||||
|
||||
@for $size from 1 through length($o-colors) {
|
||||
.hr_stress_day_#{$size - 1}:not(.fc-disabled-day) {
|
||||
color: nth($o-colors, $size) !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,56 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<templates xml:space="preserve">
|
||||
|
||||
<t t-name="hr_holidays.CalendarFilterPanel" t-inherit="web.CalendarFilterPanel" t-inherit-mode="primary" owl="1">
|
||||
<xpath expr="//t[@t-foreach='props.model.filterSections']" position="after">
|
||||
<div class="o_calendar_filter">
|
||||
<h5>Legend</h5>
|
||||
|
||||
<div class="d-flex flex-column">
|
||||
<span><img class="o_calendar_filter_plain" src="/hr/static/src/img/icons/plain.svg"/> Validated</span>
|
||||
<span><img class="o_calendar_filter_hatched" src="/hr/static/src/img/icons/hatched.svg"/> To Approve</span>
|
||||
<span><img class="o_calendar_filter_line" src="/hr/static/src/img/icons/line.svg"/> Refused</span>
|
||||
<span><span class="o_timeoff_legend o_timeoff_legend_bankholiday">13</span> Public Holiday</span>
|
||||
<span><span class="o_timeoff_legend o_timeoff_legend_stressday text-odoo">13</span> Stress Day</span>
|
||||
</div>
|
||||
|
||||
<div class="d-flex flex-column mt-4" t-if="leaveState.stressDays.length">
|
||||
<h5>Stress Days</h5>
|
||||
<ul class="ps-2">
|
||||
<li t-foreach="leaveState.stressDays" t-as="stressDay" t-key="stressDay.id" class="mt-2 list-unstyled">
|
||||
<strong
|
||||
t-esc="getFormattedDateSpan(stressDay.start, stressDay.end)"
|
||||
t-att-class="'hr_stress_day_'+stressDay.colorIndex"/>
|
||||
: <t t-esc="stressDay.title"/>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="d-flex flex-column mt-4" t-if="leaveState.bankHolidays.length">
|
||||
<h5>Public Holidays</h5>
|
||||
<ul class="ps-2">
|
||||
<li t-foreach="leaveState.bankHolidays" t-as="bankHoliday" t-key="bankHoliday.id" class="mt-2 list-unstyled">
|
||||
<strong
|
||||
t-esc="getFormattedDateSpan(bankHoliday.start, bankHoliday.end)"/>
|
||||
: <t t-esc="bankHoliday.title"/>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</xpath>
|
||||
</t>
|
||||
|
||||
|
||||
<t t-name="hr_holidays.CalendarFilterPanel.filter" t-inherit="web.CalendarFilterPanel.filter" t-inherit-mode="primary" owl="1">
|
||||
<xpath expr="//span[@t-esc='filter.label']" position="replace">
|
||||
<span class="o_cw_filter_title text-truncate flex-grow">
|
||||
<t t-esc="filter.label"/>
|
||||
|
||||
<t t-if="env.isSmall">
|
||||
<t t-set="holiday" t-value="leaveState.holidays[filter.value]"/>
|
||||
<TimeOffCardMobile t-if="holiday" name="holiday[0]" id="holiday[3]" data="holiday[1]" requires_allocation="holiday[2] === 'yes'" />
|
||||
</t>
|
||||
</span>
|
||||
</xpath>
|
||||
</t>
|
||||
</templates>
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
/** @odoo-module **/
|
||||
|
||||
import { Dialog } from "@web/core/dialog/dialog";
|
||||
|
||||
import { CalendarYearPopover } from "@web/views/calendar/calendar_year/calendar_year_popover";
|
||||
|
||||
export class TimeOffCalendarYearPopover extends CalendarYearPopover {}
|
||||
TimeOffCalendarYearPopover.components = { Dialog };
|
||||
TimeOffCalendarYearPopover.template = "web.CalendarYearPopover";
|
||||
TimeOffCalendarYearPopover.subTemplates = {
|
||||
...CalendarYearPopover.subTemplates,
|
||||
body: "hr_holidays.StressDayCalendarYearPopover.body",
|
||||
};
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<templates xml:space="preserve">
|
||||
<t t-name="hr_holidays.StressDayCalendarYearPopover.body" owl="1">
|
||||
<t t-foreach="recordGroups" t-as="recordGroup" t-key="recordGroup.title">
|
||||
<div class="fw-bold mt-2" t-esc="recordGroup.title" />
|
||||
<t t-foreach="recordGroup.records" t-as="record" t-key="record.id">
|
||||
<t t-if="record.id < 0">
|
||||
<p class="">
|
||||
<t t-if="record.startHour"><t t-esc="record.startHour" /> </t>
|
||||
<t t-esc="record.title"/>
|
||||
</p>
|
||||
</t>
|
||||
<t t-else="">
|
||||
<t t-call="{{ constructor.subTemplates.record }}" />
|
||||
</t>
|
||||
</t>
|
||||
</t>
|
||||
</t>
|
||||
</templates>
|
||||
|
|
@ -0,0 +1,71 @@
|
|||
/** @odoo-module */
|
||||
|
||||
import { CalendarYearRenderer } from '@web/views/calendar/calendar_year/calendar_year_renderer';
|
||||
|
||||
import { useService } from "@web/core/utils/hooks";
|
||||
import { useStressDays } from '../../hooks';
|
||||
import { useCalendarPopover } from '@web/views/calendar/hooks';
|
||||
import { TimeOffCalendarYearPopover } from './calendar_year_popover';
|
||||
|
||||
const { useEffect } = owl;
|
||||
|
||||
export class TimeOffCalendarYearRenderer extends CalendarYearRenderer {
|
||||
setup() {
|
||||
super.setup();
|
||||
this.orm = useService("orm");
|
||||
this.stressDays = useStressDays(this.props);
|
||||
this.stressDaysList = [];
|
||||
this.stressDayPopover = useCalendarPopover(TimeOffCalendarYearPopover);
|
||||
|
||||
useEffect((el) => {
|
||||
for (const week of el) {
|
||||
const row = week.parentElement;
|
||||
|
||||
// Remove the week number if the week is empty.
|
||||
// FullCalendar always displays 6 weeks even when empty.
|
||||
if (!row.children[1].classList.length &&
|
||||
!row.children[row.children.length - 1].classList.length) {
|
||||
row.remove();
|
||||
}
|
||||
}
|
||||
}, () => [this.rootRef.el && this.rootRef.el.querySelectorAll('.fc-content-skeleton td.fc-week-number')]);
|
||||
}
|
||||
|
||||
get options() {
|
||||
return Object.assign(super.options, {
|
||||
weekNumbers: true,
|
||||
weekNumbersWithinDays: false,
|
||||
weekLabel: this.env._t('Week'),
|
||||
});
|
||||
}
|
||||
|
||||
/** @override **/
|
||||
async onDateClick(info) {
|
||||
const is_stress_day = [...info.dayEl.classList].some(elClass => elClass.startsWith('hr_stress_day_'))
|
||||
this.stressDayPopover.close();
|
||||
if (is_stress_day && !this.env.isSmall) {
|
||||
this.popover.close();
|
||||
const date = luxon.DateTime.fromISO(info.dateStr);
|
||||
const target = info.dayEl;
|
||||
const stress_days_data = await this.orm.call("hr.employee", "get_stress_days_data", [date, date]);
|
||||
stress_days_data.forEach(stress_day_data => {
|
||||
stress_day_data['start'] = luxon.DateTime.fromISO(stress_day_data['start'])
|
||||
stress_day_data['end'] = luxon.DateTime.fromISO(stress_day_data['end'])
|
||||
});
|
||||
const records = Object.values(this.props.model.records).filter((r) =>
|
||||
luxon.Interval.fromDateTimes(r.start.startOf("day"), r.end.endOf("day")).contains(date)
|
||||
);
|
||||
const props = this.getPopoverProps(date, records)
|
||||
props['records'] = stress_days_data.concat(props['records'])
|
||||
this.stressDayPopover.open(target, props, "o_cw_popover");
|
||||
}
|
||||
else {
|
||||
super.onDateClick(info);
|
||||
}
|
||||
}
|
||||
|
||||
onDayRender(info) {
|
||||
super.onDayRender(info);
|
||||
this.stressDaysList = this.stressDays(info);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
.o_timeoff_calendar {
|
||||
.o_calendar_widget {
|
||||
.fc-dayGridYear-view {
|
||||
.fc-week-number {
|
||||
color: #adb5bd;
|
||||
font-size: 0.85rem;
|
||||
cursor: default;
|
||||
vertical-align: middle;
|
||||
|
||||
line-height: unset;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,43 @@
|
|||
/** @odoo-module */
|
||||
|
||||
import { useService } from "@web/core/utils/hooks";
|
||||
|
||||
const { useEnv } = owl;
|
||||
|
||||
export function useStressDays(props) {
|
||||
return (info) => {
|
||||
const date = luxon.DateTime.fromJSDate(info.date).toISODate();
|
||||
const stressDay = props.model.stressDays[date];
|
||||
if (stressDay) {
|
||||
const dayNumberElTop = info.view.el.querySelector(`.fc-day-top[data-date="${info.el.dataset.date }"]`)
|
||||
const dayNumberEl = info.view.el.querySelector(`.fc-day[data-date="${info.el.dataset.date }"]`)
|
||||
if (dayNumberElTop) {
|
||||
dayNumberElTop.classList.add(`hr_stress_day_top_${stressDay}`);
|
||||
}
|
||||
if (dayNumberEl) {
|
||||
dayNumberEl.classList.add(`hr_stress_day_${stressDay}`);
|
||||
}
|
||||
}
|
||||
return props.model.stressDays;
|
||||
}
|
||||
}
|
||||
|
||||
export function useLeaveCancelWizard() {
|
||||
const action = useService('action');
|
||||
const env = useEnv();
|
||||
|
||||
return (leaveId, callback) => {
|
||||
action.doAction({
|
||||
name: env._t('Delete Confirmation'),
|
||||
type: "ir.actions.act_window",
|
||||
res_model: "hr.holidays.cancel.leave",
|
||||
target: "new",
|
||||
views: [[false, "form"]],
|
||||
context: {
|
||||
default_leave_id: leaveId,
|
||||
}
|
||||
}, {
|
||||
onClose: callback,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,70 @@
|
|||
/** @odoo-module */
|
||||
|
||||
import { FormViewDialog } from "@web/views/view_dialogs/form_view_dialog";
|
||||
|
||||
import { registry } from '@web/core/registry';
|
||||
|
||||
import { formView } from '@web/views/form/form_view';
|
||||
import { FormController } from '@web/views/form/form_controller';
|
||||
|
||||
import { useLeaveCancelWizard } from '../hooks';
|
||||
|
||||
export class TimeOffDialogFormController extends FormController {
|
||||
setup() {
|
||||
super.setup();
|
||||
this.leaveCancelWizard = useLeaveCancelWizard();
|
||||
}
|
||||
|
||||
deleteRecord() {
|
||||
const record = this.model.root.data
|
||||
|
||||
this.props.onRecordDeleted(record)
|
||||
this.props.onCancelLeave();
|
||||
if (record.can_cancel) {
|
||||
this.leaveCancelWizard(record.id, () => {
|
||||
this.props.onLeaveCancelled();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
get canDelete() {
|
||||
const record = this.model.root.data;
|
||||
return !this.model.root.isNew && (record.can_cancel || record.state && ['confirm', 'validate', 'validate1'].includes(record.state));
|
||||
}
|
||||
}
|
||||
|
||||
TimeOffDialogFormController.props = {
|
||||
...FormController.props,
|
||||
onCancelLeave: Function,
|
||||
onRecordDeleted: Function,
|
||||
onLeaveCancelled: Function,
|
||||
}
|
||||
|
||||
registry.category('views').add('timeoff_dialog_form', {
|
||||
...formView,
|
||||
Controller: TimeOffDialogFormController,
|
||||
});
|
||||
|
||||
|
||||
export class TimeOffFormViewDialog extends FormViewDialog {
|
||||
setup() {
|
||||
super.setup();
|
||||
|
||||
this.viewProps = Object.assign(this.viewProps, {
|
||||
type: "timeoff_dialog_form",
|
||||
buttonTemplate: 'hr_holidays.FormViewDialog.buttons',
|
||||
onCancelLeave: () => {
|
||||
this.props.close();
|
||||
},
|
||||
onRecordDeleted: (record) => {
|
||||
this.props.onRecordDeleted(record)
|
||||
},
|
||||
onLeaveCancelled: this.props.onLeaveCancelled.bind(this),
|
||||
})
|
||||
}
|
||||
}
|
||||
TimeOffFormViewDialog.props = {
|
||||
...TimeOffFormViewDialog.props,
|
||||
onRecordDeleted: Function,
|
||||
onLeaveCancelled: Function,
|
||||
}
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<templates xml:space="preserve">
|
||||
|
||||
<t t-name="hr_holidays.FormViewDialog.buttons" t-inherit="web.FormViewDialog.ToOne.buttons" owl="1">
|
||||
<xpath expr="//button[contains(@class, 'o_form_button_save')]" position="replace">
|
||||
<button class="btn btn-primary o_form_button_save" t-on-click="saveButtonClicked" data-hotkey="c">Save</button>
|
||||
</xpath>
|
||||
|
||||
<xpath expr="//button[contains(@class, 'o_form_button_cancel')]" position="after">
|
||||
<button class="btn btn-secondary" t-if="canDelete" t-on-click="deleteRecord" data-hotkey="x">Delete</button>
|
||||
</xpath>
|
||||
</t>
|
||||
|
||||
</templates>
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
/** @odoo-module **/
|
||||
|
||||
import '@mail/../tests/helpers/mock_server'; // ensure mail overrides are applied first
|
||||
|
||||
import { patch } from "@web/core/utils/patch";
|
||||
import { MockServer } from "@web/../tests/helpers/mock_server";
|
||||
|
||||
patch(MockServer.prototype, 'hr_holidays', {
|
||||
/**
|
||||
* Overrides to add out of office to employees.
|
||||
*
|
||||
* @override
|
||||
*/
|
||||
_mockResPartnerMailPartnerFormat(ids) {
|
||||
const partnerFormats = this._super(...arguments);
|
||||
const partners = this.getRecords(
|
||||
'res.partner',
|
||||
[['id', 'in', ids]],
|
||||
{ active_test: false },
|
||||
);
|
||||
for (const partner of partners) {
|
||||
// Not a real field but ease the testing
|
||||
partnerFormats.get(partner.id).out_of_office_date_end = partner.out_of_office_date_end;
|
||||
}
|
||||
return partnerFormats;
|
||||
},
|
||||
});
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
/** @odoo-module **/
|
||||
|
||||
import { insertModelFields } from '@bus/../tests/helpers/model_definitions_helpers';
|
||||
|
||||
insertModelFields('res.partner', {
|
||||
out_of_office_date_end: { type: 'date' },
|
||||
});
|
||||
|
|
@ -0,0 +1,114 @@
|
|||
/** @odoo-module **/
|
||||
|
||||
import { UPDATE_BUS_PRESENCE_DELAY } from '@bus/im_status_service';
|
||||
|
||||
import { start, startServer } from '@mail/../tests/helpers/test_utils';
|
||||
|
||||
QUnit.module('hr_holidays', {}, function () {
|
||||
QUnit.module('components', {}, function () {
|
||||
QUnit.module('persona_im_status_icon_tests.js');
|
||||
|
||||
QUnit.test('on leave & online', async function (assert) {
|
||||
assert.expect(2);
|
||||
|
||||
const pyEnv = await startServer();
|
||||
const partnerId = pyEnv['res.partner'].create({ im_status: 'leave_online' });
|
||||
const mailChannelId = pyEnv['mail.channel'].create({});
|
||||
pyEnv['mail.message'].create({
|
||||
author_id: partnerId,
|
||||
body: 'not empty',
|
||||
model: 'mail.channel',
|
||||
res_id: mailChannelId,
|
||||
});
|
||||
const { advanceTime, afterNextRender, openDiscuss } = await start({
|
||||
discuss: {
|
||||
params: {
|
||||
default_active_id: mailChannelId,
|
||||
},
|
||||
},
|
||||
hasTimeControl: true,
|
||||
});
|
||||
await openDiscuss();
|
||||
await afterNextRender(() => advanceTime(UPDATE_BUS_PRESENCE_DELAY));
|
||||
assert.hasClass(
|
||||
document.querySelector('.o_PersonaImStatusIcon_icon'),
|
||||
'o-online',
|
||||
"persona IM status icon should have online status rendering"
|
||||
);
|
||||
assert.hasClass(
|
||||
document.querySelector('.o_PersonaImStatusIcon_icon'),
|
||||
'fa-plane',
|
||||
"persona IM status icon should have leave status rendering"
|
||||
);
|
||||
});
|
||||
|
||||
QUnit.test('on leave & away', async function (assert) {
|
||||
assert.expect(2);
|
||||
|
||||
const pyEnv = await startServer();
|
||||
const partnerId = pyEnv['res.partner'].create({ im_status: 'leave_away' });
|
||||
const mailChannelId = pyEnv['mail.channel'].create({});
|
||||
pyEnv['mail.message'].create({
|
||||
author_id: partnerId,
|
||||
body: 'not empty',
|
||||
model: 'mail.channel',
|
||||
res_id: mailChannelId,
|
||||
});
|
||||
const { advanceTime, afterNextRender, openDiscuss } = await start({
|
||||
discuss: {
|
||||
params: {
|
||||
default_active_id: mailChannelId,
|
||||
},
|
||||
},
|
||||
hasTimeControl: true,
|
||||
});
|
||||
await openDiscuss();
|
||||
await afterNextRender(() => advanceTime(UPDATE_BUS_PRESENCE_DELAY));
|
||||
assert.hasClass(
|
||||
document.querySelector('.o_PersonaImStatusIcon_icon'),
|
||||
'o-away',
|
||||
"persona IM status icon should have away status rendering"
|
||||
);
|
||||
assert.hasClass(
|
||||
document.querySelector('.o_PersonaImStatusIcon_icon'),
|
||||
'fa-plane',
|
||||
"persona IM status icon should have leave status rendering"
|
||||
);
|
||||
});
|
||||
|
||||
QUnit.test('on leave & offline', async function (assert) {
|
||||
assert.expect(2);
|
||||
|
||||
const pyEnv = await startServer();
|
||||
const partnerId = pyEnv['res.partner'].create({ im_status: 'leave_offline' });
|
||||
const mailChannelId = pyEnv['mail.channel'].create({});
|
||||
pyEnv['mail.message'].create({
|
||||
author_id: partnerId,
|
||||
body: 'not empty',
|
||||
model: 'mail.channel',
|
||||
res_id: mailChannelId,
|
||||
});
|
||||
const { advanceTime, afterNextRender, openDiscuss } = await start({
|
||||
discuss: {
|
||||
params: {
|
||||
default_active_id: mailChannelId,
|
||||
},
|
||||
},
|
||||
hasTimeControl: true,
|
||||
});
|
||||
await openDiscuss();
|
||||
await afterNextRender(() => advanceTime(UPDATE_BUS_PRESENCE_DELAY));
|
||||
assert.hasClass(
|
||||
document.querySelector('.o_PersonaImStatusIcon_icon'),
|
||||
'o-offline',
|
||||
"persona IM status icon should have offline status rendering"
|
||||
);
|
||||
assert.hasClass(
|
||||
document.querySelector('.o_PersonaImStatusIcon_icon'),
|
||||
'fa-plane',
|
||||
"persona IM status icon should have leave status rendering"
|
||||
);
|
||||
});
|
||||
|
||||
});
|
||||
});
|
||||
|
|
@ -0,0 +1,103 @@
|
|||
/** @odoo-module **/
|
||||
|
||||
import {
|
||||
start,
|
||||
startServer,
|
||||
} from '@mail/../tests/helpers/test_utils';
|
||||
|
||||
QUnit.module('mail', {}, function () {
|
||||
QUnit.module('components', {}, function () {
|
||||
QUnit.module('thread_icon_tests.js');
|
||||
|
||||
QUnit.test('thread icon of a chat when correspondent is on leave & online', async function (assert) {
|
||||
assert.expect(2);
|
||||
|
||||
const pyEnv = await startServer();
|
||||
const resPartnerId1 = pyEnv['res.partner'].create({
|
||||
im_status: 'leave_online',
|
||||
name: 'Demo',
|
||||
});
|
||||
pyEnv['mail.channel'].create({
|
||||
channel_member_ids: [
|
||||
[0, 0, { partner_id: pyEnv.currentPartnerId }],
|
||||
[0, 0, { partner_id: resPartnerId1 }],
|
||||
],
|
||||
channel_type: 'chat',
|
||||
});
|
||||
const { openDiscuss } = await start();
|
||||
await openDiscuss();
|
||||
|
||||
assert.containsOnce(
|
||||
document.body,
|
||||
'.o_ThreadIcon_online',
|
||||
"thread icon should have online status rendering"
|
||||
);
|
||||
assert.hasClass(
|
||||
document.querySelector('.o_ThreadIcon_online'),
|
||||
'fa-plane',
|
||||
"thread icon should have leave status rendering"
|
||||
);
|
||||
});
|
||||
|
||||
QUnit.test('thread icon of a chat when correspondent is on leave & away', async function (assert) {
|
||||
assert.expect(2);
|
||||
|
||||
const pyEnv = await startServer();
|
||||
const resPartnerId1 = pyEnv['res.partner'].create({
|
||||
im_status: 'leave_away',
|
||||
name: 'Demo',
|
||||
});
|
||||
pyEnv['mail.channel'].create({
|
||||
channel_member_ids: [
|
||||
[0, 0, { partner_id: pyEnv.currentPartnerId }],
|
||||
[0, 0, { partner_id: resPartnerId1 }],
|
||||
],
|
||||
channel_type: 'chat',
|
||||
});
|
||||
const { openDiscuss } = await start();
|
||||
await openDiscuss();
|
||||
|
||||
assert.containsOnce(
|
||||
document.body,
|
||||
'.o_ThreadIcon_away',
|
||||
"thread icon should have away status rendering"
|
||||
);
|
||||
assert.hasClass(
|
||||
document.querySelector('.o_ThreadIcon_away'),
|
||||
'fa-plane',
|
||||
"thread icon should have leave status rendering"
|
||||
);
|
||||
});
|
||||
|
||||
QUnit.test('thread icon of a chat when correspondent is on leave & offline', async function (assert) {
|
||||
assert.expect(2);
|
||||
|
||||
const pyEnv = await startServer();
|
||||
const resPartnerId1 = pyEnv['res.partner'].create({
|
||||
im_status: 'leave_offline',
|
||||
name: 'Demo',
|
||||
});
|
||||
pyEnv['mail.channel'].create({
|
||||
channel_member_ids: [
|
||||
[0, 0, { partner_id: pyEnv.currentPartnerId }],
|
||||
[0, 0, { partner_id: resPartnerId1 }],
|
||||
],
|
||||
channel_type: 'chat',
|
||||
});
|
||||
const { openDiscuss } = await start();
|
||||
await openDiscuss();
|
||||
|
||||
assert.containsOnce(
|
||||
document.body,
|
||||
'.o_ThreadIcon_offline',
|
||||
"thread icon should have offline status rendering"
|
||||
);
|
||||
assert.hasClass(
|
||||
document.querySelector('.o_ThreadIcon_offline'),
|
||||
'fa-plane',
|
||||
"thread icon should have leave status rendering"
|
||||
);
|
||||
});
|
||||
|
||||
});
|
||||
});
|
||||
|
|
@ -0,0 +1,51 @@
|
|||
/** @odoo-module **/
|
||||
|
||||
import { start, startServer } from '@mail/../tests/helpers/test_utils';
|
||||
|
||||
QUnit.module('hr_holidays', {}, function () {
|
||||
QUnit.module('components', {}, function () {
|
||||
QUnit.module('thread_view_tests.js');
|
||||
|
||||
QUnit.test('out of office message on direct chat with out of office partner', async function (assert) {
|
||||
assert.expect(2);
|
||||
|
||||
// Returning date of the out of office partner, simulates he'll be back in a month
|
||||
const returningDate = moment.utc().add(1, 'month');
|
||||
const pyEnv = await startServer();
|
||||
// Needed partner & user to allow simulation of message reception
|
||||
const resPartnerId1 = pyEnv['res.partner'].create({
|
||||
name: "Foreigner partner",
|
||||
out_of_office_date_end: returningDate.format("YYYY-MM-DD"),
|
||||
});
|
||||
const mailChannelId1 = pyEnv['mail.channel'].create({
|
||||
channel_member_ids: [
|
||||
[0, 0, { partner_id: pyEnv.currentPartnerId }],
|
||||
[0, 0, { partner_id: resPartnerId1 }],
|
||||
],
|
||||
channel_type: 'chat',
|
||||
});
|
||||
const { openDiscuss, messaging } = await start({
|
||||
discuss: {
|
||||
params: {
|
||||
default_active_id: `mail.channel_${mailChannelId1}`,
|
||||
},
|
||||
},
|
||||
});
|
||||
await openDiscuss();
|
||||
assert.containsOnce(
|
||||
document.body,
|
||||
'.o_ThreadView_outOfOffice',
|
||||
"should have an out of office alert on thread view"
|
||||
);
|
||||
const formattedDate = returningDate.toDate().toLocaleDateString(
|
||||
messaging.locale.language.replace(/_/g, '-'),
|
||||
{ day: 'numeric', month: 'short' }
|
||||
);
|
||||
assert.ok(
|
||||
document.querySelector('.o_ThreadView_outOfOffice').textContent.includes(formattedDate),
|
||||
"out of office message should mention the returning date"
|
||||
);
|
||||
});
|
||||
|
||||
});
|
||||
});
|
||||
|
|
@ -0,0 +1,59 @@
|
|||
/** @odoo-module **/
|
||||
|
||||
import { click, clickSave, getFixture } from "@web/../tests/helpers/utils";
|
||||
import { makeView, setupViewRegistries } from "@web/../tests/views/helpers";
|
||||
|
||||
let serverData;
|
||||
let target;
|
||||
|
||||
QUnit.module("Fields", (hooks) => {
|
||||
hooks.beforeEach(() => {
|
||||
serverData = {
|
||||
models: {
|
||||
partner: {
|
||||
fields: {
|
||||
product_id: { string: "Product", type: "many2one", relation: "product" },
|
||||
},
|
||||
records: [{ id: 1, product_id: false }],
|
||||
},
|
||||
product: {
|
||||
fields: {
|
||||
name: { string: "Product Name", type: "char" },
|
||||
},
|
||||
records: [
|
||||
{ id: 1, display_name: "a" },
|
||||
{ id: 2, display_name: "b" },
|
||||
{ id: 3, display_name: "c" },
|
||||
],
|
||||
},
|
||||
},
|
||||
};
|
||||
target = getFixture();
|
||||
setupViewRegistries();
|
||||
});
|
||||
|
||||
QUnit.module("RadioImageField");
|
||||
|
||||
QUnit.test("field is correctly renderered", async function (assert) {
|
||||
await makeView({
|
||||
type: "form",
|
||||
resModel: "partner",
|
||||
resId: 1,
|
||||
serverData,
|
||||
arch: '<form><field name="product_id" widget="hr_holidays_radio_image"/></form>',
|
||||
});
|
||||
|
||||
assert.containsOnce(target, ".o_field_widget.o_field_hr_holidays_radio_image");
|
||||
assert.containsN(target, ".o_radio_input", 3);
|
||||
assert.containsNone(target, ".o_radio_input:checked");
|
||||
assert.containsN(target, "img", 3);
|
||||
|
||||
await click(target.querySelector("img"));
|
||||
assert.containsOnce(target, ".o_radio_input:checked");
|
||||
|
||||
await clickSave(target);
|
||||
assert.containsOnce(target, ".o_field_widget.o_field_hr_holidays_radio_image");
|
||||
assert.containsN(target, ".o_radio_input", 3);
|
||||
assert.containsN(target, "img", 3);
|
||||
});
|
||||
});
|
||||
|
|
@ -0,0 +1,159 @@
|
|||
/** @odoo-module */
|
||||
|
||||
import { selectDropdownItem, editInput, getFixture } from '@web/../tests/helpers/utils';
|
||||
import { makeView, setupViewRegistries } from "@web/../tests/views/helpers";
|
||||
|
||||
|
||||
let serverData;
|
||||
let target;
|
||||
|
||||
QUnit.module('leave_stats_widget', (hooks) => {
|
||||
hooks.beforeEach(() => {
|
||||
setupViewRegistries();
|
||||
|
||||
target = getFixture();
|
||||
serverData = {
|
||||
models: {
|
||||
department: {
|
||||
fields: {
|
||||
name: { string: "Name", type: "char" },
|
||||
},
|
||||
records: [{id:11, name: "R&D"}],
|
||||
},
|
||||
employee: {
|
||||
fields: {
|
||||
name: { string: "Name", type: "char" },
|
||||
department_id: { string: "Department", type: "many2one", relation: 'department' },
|
||||
},
|
||||
records: [{
|
||||
id: 100,
|
||||
name: "Richard",
|
||||
department_id: 11,
|
||||
},{
|
||||
id: 200,
|
||||
name: "Jesus",
|
||||
department_id: 11,
|
||||
}],
|
||||
},
|
||||
'hr.leave.type': {
|
||||
fields: {
|
||||
name: { string: "Name", type: "char" }
|
||||
},
|
||||
records: [{
|
||||
id: 55,
|
||||
name: "Legal Leave",
|
||||
}]
|
||||
},
|
||||
'hr.leave': {
|
||||
fields: {
|
||||
employee_id: { string: "Employee", type: "many2one", relation: 'employee' },
|
||||
department_id: { string: "Department", type: "many2one", relation: 'department' },
|
||||
date_from: { string: "From", type: "datetime" },
|
||||
date_to: { string: "To", type: "datetime" },
|
||||
holiday_status_id: { string: "Leave type", type: "many2one", relation: 'hr.leave.type' },
|
||||
state: { string: "State", type: "char" },
|
||||
holiday_type: { string: "Holiday Type", type: "char" },
|
||||
number_of_days: { string: "State", type: "integer" },
|
||||
},
|
||||
records: [{
|
||||
id: 12,
|
||||
employee_id: 100,
|
||||
department_id: 11,
|
||||
date_from: "2016-10-20 09:00:00",
|
||||
date_to: "2016-10-25 18:00:00",
|
||||
holiday_status_id: 55,
|
||||
state: 'validate',
|
||||
number_of_days: 5,
|
||||
holiday_type: 'employee',
|
||||
},{
|
||||
id: 13,
|
||||
employee_id: 100,
|
||||
department_id: 11,
|
||||
date_from: "2016-10-02 09:00:00",
|
||||
date_to: "2016-10-02 18:00:00",
|
||||
holiday_status_id: 55,
|
||||
state: 'validate',
|
||||
number_of_days: 1,
|
||||
holiday_type: 'employee',
|
||||
},{
|
||||
id: 14,
|
||||
employee_id: 200,
|
||||
department_id: 11,
|
||||
date_from: "2016-10-15 09:00:00",
|
||||
date_to: "2016-10-20 18:00:00",
|
||||
holiday_status_id: 55,
|
||||
state: 'validate',
|
||||
number_of_days: 8,
|
||||
holiday_type: 'employee',
|
||||
}]
|
||||
}
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
QUnit.test('leave stats renders correctly', async (assert) => {
|
||||
assert.expect(5);
|
||||
await makeView({
|
||||
serverData,
|
||||
type: "form",
|
||||
resModel: 'hr.leave',
|
||||
arch: '<form string="Leave">' +
|
||||
'<field name="employee_id"/>' +
|
||||
'<field name="department_id"/>' +
|
||||
'<field name="date_from"/>' +
|
||||
'<widget name="hr_leave_stats"/>' +
|
||||
'</form>',
|
||||
resId: 12,
|
||||
mockRPC(route, args) {
|
||||
if (args.model === 'hr.leave' && args.method === 'search') {
|
||||
return Promise.resolve(this.data['hr.leave'].records.map(function (record) { return record.id; }));
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
const $leaveTypeBody = target.querySelector('.o_leave_stats #o_leave_stats_employee');
|
||||
const $leavesDepartmentBody = target.querySelector('.o_leave_stats #o_leave_stats_department');
|
||||
|
||||
assert.containsOnce($leaveTypeBody, 'span:contains(Legal Leave)', "it should have leave type");
|
||||
assert.containsOnce($leaveTypeBody, 'span:contains(6)', "it should have 6 days");
|
||||
|
||||
assert.containsN($leavesDepartmentBody, 'span:contains(Richard)', 2, "it should have 2 leaves for Richard");
|
||||
assert.containsOnce($leavesDepartmentBody, 'span:contains(Jesus)', "it should have 1 leaves for Jesus");
|
||||
assert.containsOnce($leavesDepartmentBody, 'div.o_horizontal_separator:contains(R&D)', "it should have R&D title");
|
||||
});
|
||||
QUnit.test('leave stats reload when employee/department changes', async (assert) => {
|
||||
assert.expect(3);
|
||||
await makeView({
|
||||
serverData,
|
||||
type: "form",
|
||||
resModel: 'hr.leave',
|
||||
mode: 'edit',
|
||||
arch: '<form string="Leave">' +
|
||||
'<field name="employee_id"/>' +
|
||||
'<field name="department_id"/>' +
|
||||
'<field name="date_from"/>' +
|
||||
'<widget name="hr_leave_stats"/>' +
|
||||
'</form>',
|
||||
mockRPC(route, args) {
|
||||
if (args.model === 'hr.leave' && args.method === 'search_read') {
|
||||
assert.ok(_.some(args.kwargs.domain, _.matcher(['department_id', '=', 11])), "It should load department's leaves data");
|
||||
}
|
||||
if (args.model === 'hr.leave' && args.method === 'read_group') {
|
||||
assert.ok(_.some(args.kwargs.domain, _.matcher(['employee_id', '=', 200])), "It should load employee's leaves data");
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
// Set date => shouldn't load data yet (no employee nor department defined)
|
||||
await editInput(
|
||||
target,
|
||||
"div[name='date_from'] .o_datepicker_input",
|
||||
"2016-10-12 09:00:00"
|
||||
);
|
||||
|
||||
// Set employee => should load employee's date
|
||||
await selectDropdownItem(target, "employee_id", "Jesus");
|
||||
// Set department => should load department's data
|
||||
await selectDropdownItem(target, "department_id", "R&D");
|
||||
});
|
||||
});
|
||||
|
|
@ -0,0 +1,47 @@
|
|||
odoo.define('hr_holidays.tour_time_off_request_calendar_view', function (require) {
|
||||
'use strict';
|
||||
|
||||
var tour = require('web_tour.tour');
|
||||
|
||||
tour.register('time_off_request_calendar_view', {
|
||||
test: true,
|
||||
url: '/web',
|
||||
},
|
||||
[
|
||||
tour.stepUtils.showAppsMenuItem(),
|
||||
{
|
||||
content: "Open Time Off app",
|
||||
trigger: '.o_app[data-menu-xmlid="hr_holidays.menu_hr_holidays_root"]',
|
||||
},
|
||||
{
|
||||
content: "Click on the first Thursday of the year",
|
||||
trigger: '.fc-day-top.fc-thu',
|
||||
run: () => {
|
||||
const el = document.querySelector('.fc-day-top.fc-thu').firstChild;
|
||||
el.scrollIntoView();
|
||||
|
||||
const fromPosition = el.getBoundingClientRect();
|
||||
fromPosition.x += el.offsetWidth / 2;
|
||||
fromPosition.y += el.offsetHeight / 2;
|
||||
|
||||
el.dispatchEvent(new MouseEvent("mousedown", {
|
||||
bubbles: true,
|
||||
which: 1,
|
||||
button: 0,
|
||||
clientX: fromPosition.x,
|
||||
clientY: fromPosition.y}));
|
||||
el.dispatchEvent(new MouseEvent("mouseup", {
|
||||
bubbles: true,
|
||||
which: 1,
|
||||
button: 0,
|
||||
clientX: fromPosition.x,
|
||||
clientY: fromPosition.y }));
|
||||
}
|
||||
},
|
||||
{
|
||||
content: "Save the leave",
|
||||
trigger: '.btn:contains("Save")',
|
||||
run: 'click',
|
||||
}
|
||||
]);
|
||||
});
|
||||