合并企业版代码(未测试,先提交到测试分支)

This commit is contained in:
qihao.gong@jikimo.com
2023-04-14 17:42:23 +08:00
parent 7a7b3d7126
commit d28525526a
1300 changed files with 513579 additions and 5426 deletions

View File

@@ -0,0 +1,108 @@
<?xml version="1.0" encoding="UTF-8"?>
<templates xml:space="preserve">
<t t-name="connector_stroke_head" owl="1">
<path d="M2,2 L10,6 L2,10 L6,6 L2,2"
class="o_connector_stroke_head"
t-att="{
'fill': color,
'stroke': color,
}"
t-if="width"
version="1.1"
xmlns="http://www.w3.org/2000/svg"/>
</t>
<t t-name="connector_stroke" owl="1">
<path fill="none"
pointer-events="stroke"
t-att="{
'd': path,
'stroke': color,
'stroke-width': width,
'class': 'o_connector_stroke' + (classNameModifier ? classNameModifier : ''),
'marker-end': markerEnd ? 'url(#' + markerEnd + ')' : false,
'pointer-events': props.inCreation ? 'none' : 'stroke',
}"
t-if="width"/>
</t>
<t t-name="connector" owl="1">
<svg class="o_connector"
pointer-events="none"
version="1.1"
xmlns="http://www.w3.org/2000/svg"
t-att-class="props.hovered ? 'o_connector_hovered' : ''"
t-att-data-id="props.id">
<t t-set="strokeColor"
t-value="props.hovered and !!style.stroke.hoveredColor ? style.stroke.hoveredColor : style.stroke.color"/>
<t t-set="outlineStrokeColor"
t-value="props.hovered and !!style.outlineStroke.hoveredColor ? style.outlineStroke.hoveredColor : style.outlineStroke.color"/>
<defs t-if="style.drawHead">
<marker markerHeight="6"
markerWidth="6"
markerUnits="strokeWidth"
orient="auto"
refX="9"
refY="6"
stroke-linejoin="round"
t-attf-id="o_connector_arrow_head_{{props.id}}"
viewBox="0 0 12 12">
<t t-call="connector_stroke_head">
<t t-set="color" t-value="strokeColor"/>
<t t-set="width" t-value="style.stroke.width"/>
</t>
</marker>
</defs>
<t t-if="hoverEaseWidth > 0" t-call="connector_stroke">
<t t-set="color" t-value="transparent"/>
<t t-set="classNameModifier" t-value="'_hover_ease'"/>
<t t-set="width"
t-value="style.stroke.width + hoverEaseWidth + style.outlineStroke.width"/>
</t>
<t t-if="style.outlineStroke.width > 0" t-call="connector_stroke">
<t t-set="color" t-value="outlineStrokeColor"/>
<t t-set="classNameModifier" t-value="'_outline'"/>
<t t-set="width" t-value="style.stroke.width + style.outlineStroke.width"/>
</t>
<t t-call="connector_stroke">
<t t-set="color" t-value="strokeColor"/>
<t t-set="markerEnd" t-value="'o_connector_arrow_head_' + props.id"/>
<t t-set="width" t-value="style.stroke.width"/>
</t>
<svg class="o_connector_stroke_buttons"
pointer-events="all"
t-att="{
'height': 16,
'width': 48,
'x': removeButtonPosition.left - 24,
'y': removeButtonPosition.top - 8
}"
t-if="props.canBeRemoved and props.hovered"
version="1.1"
viewBox="0 0 1536 512"
xmlns="http://www.w3.org/2000/svg">
<rect fill="transparent" x="0" y="0" width="1536" height="512"/>
<g t-on-click.stop="_onRescheduleSoonerClick" class="o_connector_stroke_button o_connector_stroke_reschedule_button">
<rect fill="white" x="20" y="20" width="472" height="472" rx="236" ry="236"/>
<g pointer-events="none">
<line x1="192" y1="256" x2="320" y2="128" stroke-width="56"/>
<line x1="192" y1="256" x2="320" y2="384" stroke-width="56"/>
</g>
</g>
<g t-on-click.stop="_onRemoveButtonClick" class="o_connector_stroke_button o_connector_stroke_remove_button">
<rect fill="white" x="532" y="20" width="472" height="472" class="o_connector_stroke_button" rx="236" ry="236"/>
<g transform="rotate(45,768,256)" pointer-events="none">
<rect x="740" y="100" fill="rgb(221, 60, 79)" width="56" height="312"/>
<rect x="612" y="228" fill="rgb(221, 60, 79)" width="312" height="56"/>
</g>
</g>
<g t-on-click.stop="_onRescheduleLaterClick" class="o_connector_stroke_button o_connector_stroke_reschedule_button">
<rect fill="white" x="1044" y="20" width="472" height="472" rx="236" ry="236"/>
<g pointer-events="none">
<line x1="1216" y1="128" x2="1344" y2="256" stroke-width="56"/>
<line x1="1216" y1="384" x2="1344" y2="256" stroke-width="56"/>
</g>
</g>
</svg>
</svg>
</t>
</templates>

View File

@@ -0,0 +1,20 @@
<?xml version="1.0" encoding="UTF-8"?>
<templates xml:space="preserve">
<t t-name="connector_container" owl="1">
<div class="o_connector_container"
t-on-mouseover.stop="_onMouseOver"
t-on-mouseout.stop="_onMouseOut">
<t t-foreach="connectors"
t-as="connector"
t-key="connector_value.id">
<Connector t-props="connector_value"
onRemoveButtonClick="props.onRemoveButtonClick"
onRescheduleSoonerButtonClick="props.onRescheduleSoonerButtonClick"
onRescheduleLaterButtonClick="props.onRescheduleLaterButtonClick"
/>
</t>
<Connector t-props="newConnector" t-if="!!newConnector.source &amp;&amp; !!newConnector.target"/>
</div>
</t>
</templates>

View File

@@ -0,0 +1,260 @@
<?xml version="1.0" encoding="UTF-8"?>
<templates>
<div t-name="GanttView.buttons">
<button t-if="widget.is_action_enabled('create')" class="o_gantt_button_add btn btn-primary me-3" title="Add record" data-hotkey="r">
Add
</button>
<div class="d-inline-block me-3">
<button class="o_gantt_button_prev btn btn-primary" title="Previous">
<span class="fa fa-arrow-left"/>
</button>
<button class="o_gantt_button_today btn btn-primary" data-hotkey="t">
Today
</button>
<button class="o_gantt_button_next btn btn-primary" title="Next">
<span class="fa fa-arrow-right"/>
</button>
</div>
<div class="btn-group o_gantt_range">
<t t-call="GanttView.RangeButtons"/>
</div>
<div t-attf-class="btn-group #{displayExpandCollapseButtons ? '' : 'd-none'}">
<button class="o_gantt_button_expand_rows btn btn-secondary" title="Expand rows">
<i class="fa fa-expand"/>
</button>
<button class="o_gantt_button_collapse_rows btn btn-secondary" title="Collapse rows">
<i class="fa fa-compress"/>
</button>
</div>
</div>
<t t-name="GanttView.RangeButtons">
<t t-if="isMobile">
<t t-call="GanttView.RangeButtons.Mobile"/>
</t>
<t t-else="">
<t t-call="GanttView.RangeButtons.Loop"/>
</t>
</t>
<t t-name="GanttView.RangeButtons.Mobile">
<a class="btn btn-link dropdown-toggle" href="#" data-bs-toggle="dropdown" aria-expanded="false">
<t t-esc="SCALES[activateScale].string"/>
</a>
<ul class="dropdown-menu" role="menu">
<t t-call="GanttView.RangeButtons.Loop"/>
</ul>
</t>
<t t-name="GanttView.RangeButtons.Loop">
<t t-foreach="allowedScales" t-as="scale">
<button t-attf-class="o_gantt_button_scale btn btn-secondary #{scale == activateScale ? 'active' : ''} #{isMobile ? 'dropdown-item' : ''}" type="button" t-att-data-value="scale" t-att-data-hotkey="SCALES[scale].hotkey" >
<t t-esc="SCALES[scale].string"/>
</button>
</t>
</t>
<div t-name="GanttView" class="o_gantt_view">
<div class="o_gantt_view_container container-fluid p-0">
<div class="row g-0 o_gantt_header_container position-sticky bg-view">
<div class="col-md-2 col-3 position-relative o_gantt_row_sidebar text-center" t-if="widget.state.groupedBy.length">
<span class="fw-bold" t-esc="widget.string"/>
</div>
<div class="col position-relative o_gantt_header_slots">
<div class="row g-0">
<div class="col text-center p-2 fw-bold">
<t t-esc="widget._getFocusDateFormat()"/>
</div>
</div>
<div class="row g-0 o_gantt_header_scale">
<t t-set="formats" t-value="{'week': 'dddd, Do', 'month': 'DD', 'year': isMobile ? 'MMM' : 'MMMM'}"/>
<t t-foreach="widget.viewInfo.slots" t-as="slot">
<t t-set="isToday" t-value="slot.isSame(new Date(), 'day') &amp;&amp; widget.state.scale !== 'day'"/>
<div t-attf-class="col position-relative o_gantt_header_cell text-center p-2 #{isToday? 'o_gantt_today' : ''} ">
<t t-if="widget.state.scale in formats" t-esc="slot.format(formats[widget.state.scale])"/>
<small t-else="">
<b t-esc="slot.format('k')"/>
<span class="d-block d-xl-inline-block" t-esc="slot.format('a')"/>
</small>
</div>
</t>
</div>
</div>
</div>
<div class="row g-0">
<div class="col position-relative o_gantt_row_container">
</div>
</div>
<div class="row g-0 o_gantt_total position-relative" t-if="widget.totalRow">
<div class="col position-relative o_gantt_total_row_container">
</div>
</div>
</div>
</div>
<div t-name="GanttView.Connector" t-attf-class="invisible o_connector_creator_wrapper o_connector_creator_wrapper_{{vertical_alignment}} {{!widget.options.isGroup ? pill.decorations.join(' ') : ''}} {{'_color' in pill ? 'o_gantt_color_' + pill._color : ''}}">
<div t-attf-class="o_connector_creator o_connector_creator_{{vertical_alignment}} o_connector_creator_{{horizontal_alignment}}">
<div t-att-data-id="pill.id" class="o_connector_creator_bullet">
</div>
</div>
</div>
<t t-name="GanttView.PillsConnectors">
<t t-call="GanttView.Connector" t-if="widget.dependencyEnabled">
<t t-set="vertical_alignment" t-value="'top'"></t>
<t t-set="horizontal_alignment" t-value="'left'"></t>
</t>
<t t-out="0"/>
<t t-call="GanttView.Connector" t-if="widget.dependencyEnabled">
<t t-set="vertical_alignment" t-value="'bottom'"></t>
<t t-set="horizontal_alignment" t-value="'right'"></t>
</t>
</t>
<div t-name="GanttView.Row" t-attf-class="row g-0 o_gantt_row bg-view #{widget.isTotal ? 'o_gantt_row_total' : widget.isGroup ? 'o_gantt_row_group' : 'o_gantt_row_nogroup'} #{widget.isOpen ? 'open' : ''}" t-att-data-from-server="widget.fromServer" t-att-data-row-id="widget.rowId">
<div t-if="!widget.options.hideSidebar" t-attf-class="col-md-2 col-3 o_gantt_row_sidebar position-relative #{!widget.name ? 'o_gantt_row_sidebar_empty' : '' }" t-attf-style="padding-left: #{widget.leftPadding}px;">
<t t-if="widget.progressBar">
<t t-if="widget.progressBar.max_value > 0">
<span t-attf-class="position-absolute o_gantt_progressbar bg-opacity-25 {{ widget.progressBar.ratio > 100 ? 'o_gantt_group_danger text-bg-danger' : 'o_gantt_group_success text-bg-success' }}"
t-att-style="'width: ' + Math.min(widget.progressBar.ratio, 100) + '%;'">
&amp;nbsp;
</span>
<span t-attf-class="position-absolute o_gantt_text_hoverable z-index-1 {{widget.progressBar.ratio > 0 ? (widget.progressBar.ratio > 100 ? 'o_gantt_group_danger text-bg-danger' : 'o_gantt_group_success text-bg-success') : 'o_gantt_group_none' }} {{ widget.isMobile ? 'o_gantt_text_mobile': 'o_gantt_text_hoverable'}}">
<span class="o_gantt_group_hours px-1" t-att-style="widget.cellHeight ? 'line-height: ' + (widget.isMobile ? widget.cellHeight / 2 : widget.cellHeight) + 'px;' : ''">
<t t-esc="widget.progressBar.value_formatted"/> / <t t-esc="widget.progressBar.max_value_formatted"/>
</span>
</span>
</t>
<t t-else="">
<span name="progress_bar_no_max_value" class="position-absolute o_gantt_text_hoverable o_gantt_group_none">
<span name="progress_bar_no_max_value_group" class="o_gantt_group_hours px-1"
t-attf-title="#{widget.progressBar.warning} #{widget.progressBar.value_formatted}."
t-att-style="widget.cellHeight ? 'line-height: ' + (widget.isMobile ? widget.cellHeight / 2 : widget.cellHeight) + 'px;' : ''">
<i class="fa fa-exclamation-triangle"></i>
</span>
</span>
</t>
</t>
<div t-attf-class="o_gantt_row_title text-truncate pe-1 #{widget.isTotal ? 'text-end pe-3 h4 my-0 fw-bold' : ''}" t-att-title="widget.name or ''"
t-att-style="widget.cellHeight ? 'line-height: ' + widget.cellHeight + 'px;' : ''">
<i t-if="!widget.isTotal &amp; widget.isGroup"
t-attf-class="fa small #{widget.isOpen ? 'fa-minus' : 'fa-plus'}"/>
<div t-if="widget.thumbnailUrl and widget.resId"
t-attf-class="o_gantt_row_thumbnail_wrapper d-inline #{!widget.options.isGroup ? 'me-1' : ''}">
<img t-att-src="widget.thumbnailUrl" class="rounded-circle o_gantt_row_thumbnail"/>
</div>
<t t-esc="widget.name"/>
</div>
</div>
<div class="o_gantt_slots_container col position-relative">
<div class="row g-0">
<div t-foreach="widget.slots" t-as="slot"
t-attf-class="col position-relative o_gantt_cell #{slot.isToday ? 'o_gantt_today' : ''} #{slot.hasButtons ? 'o_gantt_hoverable' : ''}"
t-att-data-date="slot.start.format('YYYY-MM-DD HH:mm:ss')"
t-attf-style="height: #{widget.cellHeight}px;#{slot.style ? ' ' + slot.style : ''}">
<!-- plan and add buttons -->
<div t-if="slot.hasButtons" class="o_gantt_cell_buttons justify-content-center">
<div class="position-absolute d-flex">
<i t-if="widget.options.canCreate and widget.options.canCellCreate" title="Create" t-attf-class="o_gantt_cell_add fa fa-plus d-flex justify-content-center #{widget.options.canPlan ? 'pe-1' : ''}"/>
<i t-if="widget.options.canPlan" title="Plan existing" class="o_gantt_cell_plan fa fa-search-plus d-flex justify-content-center"/>
</div>
</div>
<!-- pills -->
<t t-foreach="slot.pills" t-as="pill">
<div t-if="widget.isTotal"
class="o_gantt_pill_wrapper position-absolute d-flex justify-content-center"
t-attf-style="width: #{pill.width}; #{widget.isRTL ? 'right' : 'left'}: #{pill.leftMargin}%;">
<t t-call="GanttView.PillsConnectors">
<div t-att-data-id="pill.id"
t-attf-class="o_gantt_pill o_gantt_consolidated_pill"
t-att-title="pill.display_name"
t-att-style="'height:' + pill.totalHeight + '%;'"/>
</t>
<span class="o_gantt_consolidated_pill_title position-absolute text-truncate px-1" t-esc="pill.display_name"/>
</div>
<div t-elif="pill.consolidated"
t-attf-class="o_gantt_pill_wrapper position-absolute o_gantt_consolidated_wrapper #{widget.options.isGroup ? 'o_gantt_pill_wrapper_group' : ''}"
t-attf-style="width: #{pill.width}; #{widget.isRTL ? 'right' : 'left'}: #{pill.leftMargin}%;">
<t t-call="GanttView.PillsConnectors">
<div
t-att-data-id="pill.id"
t-attf-class="o_gantt_pill o_gantt_consolidated_pill #{pill.status? 'bg-' + pill.status + ' border-' + pill.status : ''} #{!widget.options.isGroup ? pill.decorations.join(' ') : ''}"
t-att-title="pill.display_name"
>
<span
t-if="widget.progressField"
t-attf-class="position-absolute o_gantt_progress"
t-attf-data-progress="#{pill._progress}%;"
t-attf-style="width:#{pill._progress}%;"
>
&amp;nbsp;
</span>
</div>
</t>
<span class="o_gantt_consolidated_pill_title position-relative text-truncate px-1" t-esc="pill.display_name"/>
</div>
<div t-else=""
t-attf-class="o_gantt_pill_wrapper position-absolute #{widget.options.isGroup ? 'o_gantt_pill_wrapper_group' : ''}"
t-attf-style="width: #{pill.width}; margin-top: #{pill.topPadding}px; #{widget.isRTL ? 'right' : 'left'}: #{pill.leftMargin}%;">
<t t-call="GanttView.PillsConnectors">
<div
t-att-data-id="pill.id"
t-attf-class="o_gantt_pill position-relative #{!widget.options.isGroup ? pill.decorations.join(' ') : ''} #{'_color' in pill ? 'o_gantt_color_' + pill._color : ''}"
t-attf-style="#{widget.options.isGroup ? pill.style : ''}"
t-att-title="pill.display_name"
>
<span
t-if="widget.progressField"
t-attf-class="position-absolute o_gantt_progress"
t-attf-data-progress="#{pill._progress}%;"
t-attf-style="width:#{pill._progress}%;"
>
&amp;nbsp;
</span>
<!-- README: be careful when modifying the DOM inside the pill ; @_onMouseMove is strongly dependant of it -->
<p class="text-truncate position-relative mb-0 o_gantt_pill_title" t-esc="pill.label ? pill.label : pill.display_name"/>
</div>
</t>
</div>
</t>
</div>
</div>
</div>
</div>
<t t-name="GanttView.ResizeBadge">
<span t-if="diff === 0" class="o_gantt_pill_resize_badge badge rounded-pill" t-attf-style="#{direction}: 0px;">
<t t-esc="_.str.sprintf('%s %s', diff, time)"/>
</span>
<span t-elif="diff &gt; 0" class="o_gantt_pill_resize_badge badge rounded-pill text-success" t-attf-style="#{direction}: 0px;">
<t t-esc="_.str.sprintf('+%s %s', diff, time)"/>
</span>
<span t-else="diff &lt; 0" class="o_gantt_pill_resize_badge badge rounded-pill text-danger" t-attf-style="#{direction}: 0px;">
<t t-esc="_.str.sprintf('%s %s', diff, time)"/>
</span>
</t>
<!-- Default popover template used if none is defined in the Gantt view arch -->
<div t-name="gantt-popover">
<ul class="p-0 mb-0 list-unstyled d-flex flex-row">
<li class="d-flex flex-column pe-2">
<strong>Name:</strong>
<strong>Start:</strong>
<strong>Stop:</strong>
</li>
<li class="d-flex flex-column">
<span t-esc="display_name"/>
<span t-esc="userTimezoneStartDate.format('DD MMM, LT')"/>
<span t-esc="userTimezoneStopDate.format('DD MMM, LT')"/>
</li>
</ul>
</div>
</templates>