@odoo/o-spreadsheet 16.4.11 → 16.4.13

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,3982 @@
1
+ <odoo>
2
+ <t t-name="o-spreadsheet-ActionButton" owl="1">
3
+ <span
4
+ t-if="isVisible"
5
+ class="o-menu-item-button"
6
+ t-att-title="title"
7
+ t-att-class="{'o-disabled': !isEnabled, active: isActive}"
8
+ t-attf-class="{{props.class}}"
9
+ t-on-click="onClick">
10
+ <span t-if="iconTitle" t-att-style="buttonStyle">
11
+ <t t-call="{{iconTitle}}"/>
12
+ </span>
13
+ <t t-if="props.hasTriangleDownIcon">
14
+ <t t-call="o-spreadsheet-Icon.TRIANGLE_DOWN"/>
15
+ </t>
16
+ </span>
17
+ </t>
18
+
19
+ <t t-name="o-spreadsheet-Ripple" owl="1">
20
+ <div
21
+ class="o-ripple-container position-relative"
22
+ t-att-class="props.class"
23
+ t-on-click="onClick">
24
+ <div class="position-absolute w-100 h-100">
25
+ <t t-foreach="state.ripples" t-as="ripple" t-key="ripple.id">
26
+ <RippleEffect t-props="getRippleEffectProps(ripple.id)"/>
27
+ </t>
28
+ </div>
29
+ <div class="position-relative" t-ref="childContainer">
30
+ <t t-slot="default"/>
31
+ </div>
32
+ </div>
33
+ </t>
34
+
35
+ <t t-name="o-spreadsheet-RippleEffect" owl="1">
36
+ <div
37
+ class="position-absolute"
38
+ t-att-class="{ 'overflow-hidden': !props.allowOverflow }"
39
+ t-att-style="props.style">
40
+ <div class="o-ripple position-relative pe-none" t-ref="ripple" t-att-style="rippleStyle"/>
41
+ </div>
42
+ </t>
43
+
44
+ <t t-name="o-spreadsheet-Autofill" owl="1">
45
+ <div class="o-autofill" t-att-style="style"/>
46
+ <div
47
+ class="o-autofill-handler"
48
+ t-att-style="handlerStyle"
49
+ t-on-mousedown="onMouseDown"
50
+ t-on-dblclick="onDblClick"
51
+ />
52
+ <t t-set="tooltip" t-value="getTooltip()"/>
53
+ <div t-if="tooltip" class="o-autofill-nextvalue" t-att-style="styleNextValue">
54
+ <t t-component="tooltip.component" t-props="tooltip.props"/>
55
+ </div>
56
+ </t>
57
+
58
+ <t t-name="o-spreadsheet-BorderEditor" owl="1">
59
+ <Popover t-props="popoverProps">
60
+ <div
61
+ class="d-flex o-border-selector"
62
+ t-on-click.stop=""
63
+ t-att-class="props.class ? props.class : ''">
64
+ <div class="o-border-selector-section">
65
+ <div
66
+ t-foreach="BORDER_POSITIONS"
67
+ t-as="borderPositionsRow"
68
+ t-key="borderPositionsRow"
69
+ class="d-flex o-dropdown-button o-dropdown-line">
70
+ <span
71
+ t-foreach="borderPositionsRow"
72
+ t-as="borderPosition"
73
+ t-key="borderPosition"
74
+ class="o-line-item o-hoverable-button"
75
+ t-att-class="{active:props.currentBorderPosition === borderPosition[0]}"
76
+ t-att-name="borderPosition[0]"
77
+ t-on-click.stop="() => this.setBorderPosition(borderPosition[0])">
78
+ <t t-call="{{borderPosition[1]}}"/>
79
+ </span>
80
+ </div>
81
+ </div>
82
+ <div class="o-divider"/>
83
+ <div class="o-border-selector-section">
84
+ <div
85
+ class="m-0 p-0 d-flex align-items-center justify-content-center o-with-color o-hoverable-button"
86
+ title="Border color"
87
+ t-on-click.stop="(ev) => this.toggleDropdownTool('borderColorTool')">
88
+ <ColorPickerWidget
89
+ currentColor="props.currentBorderColor"
90
+ toggleColorPicker="(ev) => this.toggleDropdownTool('borderColorTool')"
91
+ showColorPicker="state.activeTool === 'borderColorTool'"
92
+ onColorPicked="(color) => this.setBorderColor(color)"
93
+ title="env._t('Border Color')"
94
+ icon="props.currentBorderColor === '' ? 'o-spreadsheet-Icon.BORDER_NO_COLOR' : 'o-spreadsheet-Icon.BORDER_COLOR'"
95
+ dropdownMaxHeight="this.props.dropdownMaxHeight"
96
+ class="'o-dropdown-button o-border-picker-button'"
97
+ />
98
+ <t t-call="o-spreadsheet-Icon.TRIANGLE_DOWN"/>
99
+ </div>
100
+ <div
101
+ class="o-border-style-tool d-flex align-items-center justify-content-center o-hoverable-button"
102
+ title="Line style"
103
+ t-ref="lineStyleButton"
104
+ t-on-click.stop="(ev) => this.toggleDropdownTool('borderTypeTool')">
105
+ <t t-call="o-spreadsheet-Icon.BORDER_TYPE"/>
106
+ <t t-call="o-spreadsheet-Icon.TRIANGLE_DOWN"/>
107
+ <Popover
108
+ t-props="lineStylePickerPopoverProps"
109
+ t-if="state.activeTool === 'borderTypeTool'">
110
+ <div class="o-border-style-dropdown">
111
+ <t t-foreach="borderStyles" t-as="borderStyle" t-key="borderStyle">
112
+ <div
113
+ t-att-title="borderStyle"
114
+ t-on-click.stop="() => this.setBorderStyle(borderStyle)">
115
+ <div class="d-flex o-dropdown-border-type">
116
+ <div class="o-dropdown-border-check">
117
+ <t
118
+ t-if="props.currentBorderStyle === borderStyle"
119
+ t-call="o-spreadsheet-Icon.CHECK"
120
+ />
121
+ </div>
122
+ <div t-attf-class="o-style-preview o-style-{{borderStyle}}"/>
123
+ </div>
124
+ </div>
125
+ </t>
126
+ </div>
127
+ </Popover>
128
+ </div>
129
+ </div>
130
+ </div>
131
+ </Popover>
132
+ </t>
133
+
134
+ <t t-name="o-spreadsheet-BorderEditorWidget" owl="1">
135
+ <div class="d-flex position-relative" title="Borders">
136
+ <span
137
+ t-ref="borderEditorButton"
138
+ t-on-click.stop="props.toggleBorderEditor"
139
+ t-att-class="props.class ? props.class : ''"
140
+ t-att-disabled="props.disabled">
141
+ <span t-att-style="iconStyle">
142
+ <t t-call="o-spreadsheet-Icon.BORDERS"/>
143
+ </span>
144
+ </span>
145
+ <BorderEditor
146
+ t-if="props.showBorderEditor"
147
+ onBorderColorPicked.bind="onBorderColorPicked"
148
+ onBorderStylePicked.bind="onBorderStylePicked"
149
+ onBorderPositionPicked.bind="onBorderPositionPicked"
150
+ currentBorderColor="state.currentColor"
151
+ currentBorderStyle="state.currentStyle"
152
+ currentBorderPosition="state.currentPosition"
153
+ maxHeight="props.dropdownMaxHeight"
154
+ anchorRect="borderEditorAnchorRect"
155
+ />
156
+ </div>
157
+ </t>
158
+
159
+ <t t-name="o-spreadsheet-BottomBar" owl="1">
160
+ <div
161
+ class="o-spreadsheet-bottom-bar o-two-columns d-flex align-items-center overflow-hidden"
162
+ t-on-click="props.onClick"
163
+ t-ref="bottomBar"
164
+ t-on-contextmenu.prevent="">
165
+ <Ripple>
166
+ <div
167
+ class="o-sheet-item o-add-sheet me-2 p-1"
168
+ t-if="!env.model.getters.isReadonly()"
169
+ t-on-click="clickAddSheet">
170
+ <t t-call="o-spreadsheet-Icon.PLUS"/>
171
+ </div>
172
+ </Ripple>
173
+ <Ripple>
174
+ <div class="o-sheet-item o-list-sheets me-2 p-1" t-on-click="clickListSheets">
175
+ <t t-call="o-spreadsheet-Icon.LIST"/>
176
+ </div>
177
+ </Ripple>
178
+ <div class="o-all-sheets position-relative flex-shrink-0 d-flex h-100 me-3">
179
+ <div
180
+ class="o-bottom-bar-fade-in position-absolute h-100 w-100 pe-none"
181
+ t-if="state.isSheetListScrollableLeft"
182
+ />
183
+ <div
184
+ class="o-sheet-list d-flex w-100 overflow-hidden px-1"
185
+ t-ref="sheetList"
186
+ t-on-wheel="onWheel"
187
+ t-on-scroll="onScroll">
188
+ <t t-foreach="getSheets()" t-as="sheet" t-key="sheet.id">
189
+ <BottomBarSheet
190
+ style="getSheetStyle(sheet.id)"
191
+ sheetId="sheet.id"
192
+ openContextMenu="(registry, ev) => this.onSheetContextMenu(sheet.id, registry, ev)"
193
+ onMouseDown="(ev) => this.onSheetMouseDown(sheet.id, ev)"
194
+ />
195
+ </t>
196
+ </div>
197
+ <div
198
+ class="o-bottom-bar-fade-out position-absolute h-100 w-100 pe-none"
199
+ t-if="state.isSheetListScrollableRight"
200
+ />
201
+ </div>
202
+ <div
203
+ class="o-bottom-bar-arrows d-flex h-100 me-5 align-items-center"
204
+ t-if="state.isSheetListScrollableLeft || state.isSheetListScrollableRight">
205
+ <Ripple
206
+ ignoreClickPosition="true"
207
+ width="20"
208
+ height="20"
209
+ offsetX="1"
210
+ allowOverflow="true"
211
+ enabled="state.isSheetListScrollableLeft">
212
+ <div
213
+ class="o-bottom-bar-arrow o-bottom-bar-arrow-left d-flex align-items-center me-2"
214
+ t-att-class="{'o-disabled': !state.isSheetListScrollableLeft}"
215
+ t-on-click="onArrowLeft">
216
+ <t t-call="o-spreadsheet-Icon.CARET_LEFT"/>
217
+ </div>
218
+ </Ripple>
219
+ <Ripple
220
+ ignoreClickPosition="true"
221
+ width="20"
222
+ height="20"
223
+ offsetX="-1"
224
+ allowOverflow="true"
225
+ enabled="state.isSheetListScrollableRight">
226
+ <div
227
+ class="o-bottom-bar-arrow o-bottom-bar-arrow-right d-flex align-items-center me-4"
228
+ t-att-class="{'o-disabled': !state.isSheetListScrollableRight}"
229
+ t-on-click="onArrowRight">
230
+ <t t-call="o-spreadsheet-Icon.CARET_RIGHT"/>
231
+ </div>
232
+ </Ripple>
233
+ </div>
234
+
235
+ <BottomBarStatistic
236
+ openContextMenu="(x, y, registry) => this.openContextMenu(x, y, 'listSelectionStatistics', registry)"
237
+ closeContextMenu="() => this.closeContextMenuWithId('listSelectionStatistics')"
238
+ />
239
+
240
+ <Menu
241
+ t-if="menuState.isOpen"
242
+ position="menuState.position"
243
+ menuItems="menuState.menuItems"
244
+ maxHeight="menuMaxHeight"
245
+ onClose="() => this.closeMenu()"
246
+ menuId="menuState.menuId"
247
+ />
248
+ </div>
249
+ </t>
250
+
251
+ <t t-name="o-spreadsheet-BottomBarSheet" owl="1">
252
+ <Ripple>
253
+ <div
254
+ class="o-sheet d-flex align-items-center user-select-none text-nowrap "
255
+ t-on-mousedown="(ev) => this.onMouseDown(ev)"
256
+ t-on-contextmenu.prevent="(ev) => this.onContextMenu(ev)"
257
+ t-ref="sheetDiv"
258
+ t-att-style="props.style"
259
+ t-att-title="sheetName"
260
+ t-att-data-id="props.sheetId"
261
+ t-att-class="{active: isSheetActive}">
262
+ <span
263
+ class="o-sheet-name"
264
+ t-att-class="{'o-sheet-name-editable': state.isEditing }"
265
+ t-ref="sheetNameSpan"
266
+ t-esc="sheetName"
267
+ t-on-click="(ev) => this.onClickSheetName(ev)"
268
+ t-on-dblclick="() => this.onDblClick()"
269
+ t-on-focusout="() => this.onFocusOut()"
270
+ t-on-keydown="(ev) => this.onKeyDown(ev)"
271
+ t-att-contenteditable="state.isEditing.toString()"
272
+ />
273
+ <span class="o-sheet-icon ms-1" t-on-click.stop="(ev) => this.onIconClick(ev)">
274
+ <t t-call="o-spreadsheet-Icon.TRIANGLE_DOWN"/>
275
+ </span>
276
+ </div>
277
+ </Ripple>
278
+ </t>
279
+
280
+ <t t-name="o-spreadsheet-BottomBarStatisic" owl="1">
281
+ <t t-set="selectedStatistic" t-value="getSelectedStatistic()"/>
282
+ <Ripple class="'ms-auto'" t-if="selectedStatistic !== undefined">
283
+ <div
284
+ class="o-selection-statistic text-truncate user-select-none me-4 bg-white rounded shadow"
285
+ t-on-click="listSelectionStatistics">
286
+ <t t-esc="selectedStatistic"/>
287
+ <span class="ms-2">
288
+ <t t-call="o-spreadsheet-Icon.TRIANGLE_DOWN"/>
289
+ </span>
290
+ </div>
291
+ </Ripple>
292
+ </t>
293
+
294
+ <t t-name="o-spreadsheet-ClientTag" owl="1">
295
+ <div>
296
+ <div class="o-client-tag" t-att-style="tagStyle" t-esc="props.name"/>
297
+ </div>
298
+ </t>
299
+
300
+ <t t-name="o-spreadsheet-ColorPicker" owl="1">
301
+ <Popover t-props="popoverProps">
302
+ <div class="o-color-picker" t-on-click.stop="" t-att-style="colorPickerStyle">
303
+ <div class="o-color-picker-section-name">Standard</div>
304
+ <div class="colors-grid">
305
+ <div
306
+ t-foreach="COLORS"
307
+ t-as="color"
308
+ t-key="color"
309
+ class="o-color-picker-line-item"
310
+ t-att-data-color="color"
311
+ t-on-click="() => this.onColorClick(color)"
312
+ t-attf-style="background-color:{{color}};">
313
+ <div
314
+ t-if="isSameColor(props.currentColor, color)"
315
+ align="center"
316
+ t-attf-style="color:{{checkmarkColor}}">
317
+ ✓
318
+ </div>
319
+ </div>
320
+ </div>
321
+ <div class="o-separator"/>
322
+ <div
323
+ class="o-color-picker-section-name o-color-picker-toggler"
324
+ t-on-click="toggleColorPicker">
325
+ <span>Custom</span>
326
+ </div>
327
+ <div class="colors-grid o-color-picker-toggler" t-on-click.stop="toggleColorPicker">
328
+ <div class="o-color-picker-line-item o-color-picker-toggler-button">
329
+ <div class="o-color-picker-toggler-sign">
330
+ <t t-call="o-spreadsheet-Icon.PLUS"/>
331
+ </div>
332
+ </div>
333
+ <div
334
+ t-foreach="env.model.getters.getCustomColors()"
335
+ t-as="color"
336
+ t-key="color"
337
+ class="o-color-picker-line-item"
338
+ t-att-data-color="color"
339
+ t-attf-style="background-color:{{color}};"
340
+ t-on-click="() => this.onColorClick(color)">
341
+ <div
342
+ t-if="isSameColor(props.currentColor, color)"
343
+ align="center"
344
+ t-attf-style="color:{{checkmarkColor}}">
345
+ ✓
346
+ </div>
347
+ </div>
348
+ </div>
349
+ <div t-if="state.showGradient" class="o-custom-selector">
350
+ <div
351
+ class="o-gradient"
352
+ t-on-click.stop=""
353
+ t-on-mousedown="dragGradientPointer"
354
+ t-att-style="gradientHueStyle">
355
+ <div class="saturation w-100 h-100 position-absolute pe-none"/>
356
+ <div class="lightness w-100 h-100 position-absolute pe-none"/>
357
+ <div class="magnifier pe-none" t-att-style="pointerStyle"/>
358
+ </div>
359
+ <div class="o-hue-container" t-on-mousedown="dragHuePointer">
360
+ <div class="o-hue-picker" t-on-click.stop=""/>
361
+ <div class="o-hue-slider pe-none" t-att-style="sliderStyle">
362
+ <t t-call="o-spreadsheet-Icon.TRIANGLE_UP"/>
363
+ </div>
364
+ </div>
365
+ <div class="o-custom-input-preview">
366
+ <input
367
+ type="text"
368
+ t-att-class="{'o-wrong-color': !isHexColorInputValid }"
369
+ t-on-click.stop=""
370
+ t-att-value="state.customHexColor"
371
+ t-on-input="setHexColor"
372
+ maxlength="7"
373
+ />
374
+ <div class="o-color-preview" t-att-style="colorPreviewStyle"/>
375
+ </div>
376
+ <div class="o-custom-input-buttons">
377
+ <button
378
+ class="o-add-button"
379
+ t-att-class="{'o-disabled': !state.customHexColor or !isHexColorInputValid}"
380
+ t-on-click.stop="addCustomColor">
381
+ Add
382
+ </button>
383
+ </div>
384
+ </div>
385
+ <div class="o-separator"/>
386
+ <div class="o-buttons">
387
+ <button t-on-click="resetColor" class="o-cancel">No Color</button>
388
+ </div>
389
+ </div>
390
+ </Popover>
391
+ </t>
392
+
393
+ <t t-name="o-spreadsheet-ColorPickerWidget" owl="1">
394
+ <div class="o-color-picker-widget">
395
+ <span
396
+ class="o-color-picker-button"
397
+ t-ref="colorPickerButton"
398
+ t-on-click.stop="props.toggleColorPicker"
399
+ t-att-title="props.title"
400
+ t-att-class="props.class ? props.class : 'o-color-picker-button-style'"
401
+ t-att-disabled="props.disabled">
402
+ <span t-att-style="iconStyle">
403
+ <t t-call="{{props.icon}}"/>
404
+ </span>
405
+ </span>
406
+ <ColorPicker
407
+ t-if="props.showColorPicker"
408
+ anchorRect="colorPickerAnchorRect"
409
+ onColorPicked="props.onColorPicked"
410
+ currentColor="props.currentColor"
411
+ maxHeight="props.dropdownMaxHeight"
412
+ />
413
+ </div>
414
+ </t>
415
+
416
+ <t t-name="o-spreadsheet-TextValueProvider" owl="1">
417
+ <div
418
+ t-att-class="{
419
+ 'o-autocomplete-dropdown':props.values.length,
420
+ 'shadow':props.values.length}">
421
+ <t t-foreach="props.values" t-as="v" t-key="v.text">
422
+ <div
423
+ class="d-flex flex-column"
424
+ t-att-class="{'o-autocomplete-value-focus': props.selectedIndex === v_index}"
425
+ t-on-click="() => this.props.onValueSelected(v.text)">
426
+ <div class="o-autocomplete-value" t-esc="v.text"/>
427
+ <div
428
+ class="o-autocomplete-description text-truncate"
429
+ t-esc="v.description"
430
+ t-if="props.selectedIndex === v_index"
431
+ />
432
+ </div>
433
+ </t>
434
+ </div>
435
+ </t>
436
+
437
+ <t t-name="o-spreadsheet-Composer" owl="1">
438
+ <div class="o-composer-container w-100 h-100">
439
+ <div
440
+ class="o-composer w-100 text-start"
441
+ t-att-class="{ 'text-muted': env.model.getters.isReadonly(), 'active': props.focus !== 'inactive' }"
442
+ t-att-style="props.inputStyle"
443
+ t-ref="o_composer"
444
+ tabindex="1"
445
+ t-att-contenteditable="env.model.getters.isReadonly() ? 'false' : 'true'"
446
+ spellcheck="false"
447
+ t-on-keydown="onKeydown"
448
+ t-on-mousewheel.stop=""
449
+ t-on-input="onInput"
450
+ t-on-mousedown="onMousedown"
451
+ t-on-click="onClick"
452
+ t-on-keyup="onKeyup"
453
+ t-on-paste.stop=""
454
+ t-on-compositionstart="onCompositionStart"
455
+ t-on-compositionend="onCompositionEnd"
456
+ t-on-dblclick="onDblClick"
457
+ />
458
+
459
+ <div
460
+ t-if="props.focus !== 'inactive' and (autoCompleteState.showProvider or functionDescriptionState.showDescription)"
461
+ class="o-composer-assistant"
462
+ t-att-style="assistantStyle"
463
+ t-on-mousedown.prevent.stop=""
464
+ t-on-click.prevent.stop=""
465
+ t-on-mouseup.prevent.stop="">
466
+ <TextValueProvider
467
+ t-if="autoCompleteState.showProvider"
468
+ values="autoCompleteState.values"
469
+ selectedIndex="autoCompleteState.selectedIndex"
470
+ onValueSelected.bind="this.autoComplete"
471
+ />
472
+ <FunctionDescriptionProvider
473
+ t-if="functionDescriptionState.showDescription"
474
+ functionName="functionDescriptionState.functionName"
475
+ functionDescription="functionDescriptionState.functionDescription"
476
+ argToFocus="functionDescriptionState.argToFocus"
477
+ />
478
+ </div>
479
+ </div>
480
+ </t>
481
+
482
+ <t t-name="o-spreadsheet-FunctionDescriptionProvider" owl="1">
483
+ <div
484
+ class="o-formula-assistant-container user-select-none shadow"
485
+ t-att-class="{
486
+ 'pe-none': assistantState.allowCellSelectionBehind,
487
+ 'pe-auto': !assistantState.allowCellSelectionBehind
488
+ }">
489
+ <t t-set="context" t-value="getContext()"/>
490
+ <div
491
+ class="o-formula-assistant bg-white"
492
+ t-if="context.functionName"
493
+ t-on-mousemove="onMouseMove"
494
+ t-att-class="{'opacity-25': assistantState.allowCellSelectionBehind}">
495
+ <div class="o-formula-assistant-head">
496
+ <span t-esc="context.functionName"/>
497
+ (
498
+ <t t-foreach="context.functionDescription.args" t-as="arg" t-key="arg.name">
499
+ <span t-if="arg_index > '0'">,&#xA0;</span>
500
+ <span t-att-class="{ 'o-formula-assistant-focus': context.argToFocus === arg_index }">
501
+ <span>
502
+ <span t-if="arg.optional || arg.repeating || arg.default">[</span>
503
+ <span t-esc="arg.name"/>
504
+ <span t-if="arg.repeating">, ...</span>
505
+ <span t-if="arg.optional || arg.repeating || arg.default">]</span>
506
+ </span>
507
+ </span>
508
+ </t>
509
+ )
510
+ </div>
511
+
512
+ <div class="o-formula-assistant-core pb-3 m-3">
513
+ <div class="o-formula-assistant-gray">ABOUT</div>
514
+ <div t-esc="context.functionDescription.description"/>
515
+ </div>
516
+
517
+ <t t-foreach="context.functionDescription.args" t-as="arg" t-key="arg.name">
518
+ <div
519
+ class="o-formula-assistant-arg p-3 pt-0 display-flex flex-column"
520
+ t-att-class="{
521
+ 'o-formula-assistant-gray': context.argToFocus >= '0',
522
+ 'o-formula-assistant-focus': context.argToFocus === arg_index,
523
+ }">
524
+ <div>
525
+ <span t-esc="arg.name"/>
526
+ <span
527
+ t-if="arg.optional || arg.repeating || arg.default ">&#xA0;- [optional]&#xA0;</span>
528
+ <span t-if="arg.default">
529
+ <span>default:&#xA0;</span>
530
+ <t t-esc="arg.defaultValue"/>
531
+ </span>
532
+ <span t-if="arg.repeating">repeatable</span>
533
+ </div>
534
+ <div class="o-formula-assistant-arg-description" t-esc="arg.description"/>
535
+ </div>
536
+ </t>
537
+ </div>
538
+ </div>
539
+ </t>
540
+
541
+ <t t-name="o-spreadsheet-GridComposer" owl="1">
542
+ <div
543
+ class="o-cell-reference"
544
+ t-if="shouldDisplayCellReference"
545
+ t-att-style="cellReferenceStyle"
546
+ t-esc="cellReference"
547
+ />
548
+ <div class="o-grid-composer" t-att-style="containerStyle" t-ref="gridComposer">
549
+ <Composer
550
+ focus="props.focus"
551
+ inputStyle="composerStyle"
552
+ rect="composerState.rect"
553
+ delimitation="composerState.delimitation"
554
+ onComposerUnmounted="props.onComposerUnmounted"
555
+ onComposerContentFocused="props.onComposerContentFocused"
556
+ />
557
+ </div>
558
+ </t>
559
+
560
+ <t t-name="o-spreadsheet-TopBarComposer" owl="1">
561
+ <div
562
+ class="o-topbar-composer bg-white user-select-text"
563
+ t-on-click.stop=""
564
+ t-att-style="containerStyle">
565
+ <Composer
566
+ focus="props.focus"
567
+ inputStyle="composerStyle"
568
+ onComposerContentFocused="props.onComposerContentFocused"
569
+ />
570
+ </div>
571
+ </t>
572
+
573
+ <t t-name="o-spreadsheet-SpreadsheetDashboard" owl="1">
574
+ <div
575
+ class="o-grid o-two-columns"
576
+ tabindex="-1"
577
+ t-on-wheel="onMouseWheel"
578
+ t-on-click="onClosePopover">
579
+ <div class="mx-auto h-100 position-relative" t-ref="grid" t-att-style="gridContainer">
580
+ <GridOverlay
581
+ onCellHovered.bind="onCellHovered"
582
+ onGridResized.bind="onGridResized"
583
+ onGridMoved.bind="moveCanvas"
584
+ gridOverlayDimensions="gridOverlayDimensions"
585
+ />
586
+ <canvas t-ref="canvas"/>
587
+ <GridPopover
588
+ hoveredCell="hoveredCell"
589
+ gridRect="getGridRect()"
590
+ onMouseWheel.bind="onMouseWheel"
591
+ onClosePopover.bind="onClosePopover"
592
+ />
593
+ <div
594
+ t-foreach="getClickableCells()"
595
+ t-as="clickableCell"
596
+ t-key="clickableCell.tKey"
597
+ class="o-dashboard-clickable-cell"
598
+ t-on-click="() => this.selectClickableCell(clickableCell)"
599
+ t-on-contextmenu.prevent=""
600
+ t-att-style="getCellClickableStyle(clickableCell.coordinates)"
601
+ />
602
+ <FilterIconsOverlay/>
603
+ </div>
604
+ <VerticalScrollBar/>
605
+ <HorizontalScrollBar/>
606
+ <div class="o-scrollbar corner"/>
607
+ </div>
608
+ </t>
609
+
610
+ <t t-name="o-spreadsheet-ErrorToolTip" owl="1">
611
+ <div class="o-error-tooltip">
612
+ <t t-esc="props.text"/>
613
+ </div>
614
+ </t>
615
+
616
+ <t t-name="o-spreadsheet-ChartJsComponent" owl="1">
617
+ <canvas class="o-figure-canvas w-100 h-100" t-att-style="canvasStyle" t-ref="graphContainer"/>
618
+ </t>
619
+
620
+ <t t-name="o-spreadsheet-ScorecardChart" owl="1">
621
+ <div class="o-scorecard w-100 h-100" t-att-style="chartStyle" t-ref="chart">
622
+ <t t-set="textStyles" t-value="getTextStyles()"/>
623
+ <div t-if="title" class="o-title-text" t-esc="title" t-att-style="textStyles.titleStyle"/>
624
+ <div class="o-scorecard-content" t-att-style="chartContentStyle">
625
+ <div class="o-key-text" t-if="keyValue" t-esc="keyValue" t-att-style="textStyles.keyStyle"/>
626
+ <t t-if="baseline || baselineDescr">
627
+ <div class="o-baseline-text" t-att-style="textStyles.baselineStyle">
628
+ <t t-if="baseline">
629
+ <t t-if="baselineArrowDirection === 'up'">
630
+ <t t-call="o-spreadsheet-Icon.ARROW_UP">
631
+ <t t-set="color" t-value="'fill : ' + runtime.baselineColor"/>
632
+ </t>
633
+ </t>
634
+ <t t-if="baselineArrowDirection === 'down'">
635
+ <t t-call="o-spreadsheet-Icon.ARROW_DOWN">
636
+ <t t-set="color" t-value="'fill : ' + runtime.baselineColor"/>
637
+ </t>
638
+ </t>
639
+ <span t-att-style="textStyles.baselineValueStyle" class="o-baseline-text-value">
640
+ <t t-esc="baseline"/>
641
+ </span>
642
+ </t>
643
+ <span t-att-style="textStyles.baselineDescrStyle" class="o-baseline-text-description">
644
+ <t t-esc="env._t(baselineDescr)"/>
645
+ </span>
646
+ </div>
647
+ </t>
648
+ </div>
649
+ </div>
650
+ </t>
651
+
652
+ <t t-name="o-spreadsheet-FigureComponent" owl="1">
653
+ <div class="o-figure-wrapper pe-auto" t-att-style="wrapperStyle">
654
+ <div
655
+ class="o-figure w-100 h-100"
656
+ t-on-mousedown.stop="(ev) => this.onMouseDown(ev)"
657
+ t-on-contextmenu.prevent.stop="(ev) => !env.model.getters.isReadonly() and this.onContextMenu(ev)"
658
+ t-ref="figure"
659
+ t-att-style="props.style"
660
+ t-att-data-id="props.figure.id"
661
+ tabindex="0"
662
+ t-on-keydown="(ev) => this.onKeyDown(ev)"
663
+ t-on-keyup.stop="">
664
+ <t
665
+ t-component="figureRegistry.get(props.figure.tag).Component"
666
+ t-key="props.figure.id"
667
+ onFigureDeleted="props.onFigureDeleted"
668
+ figure="props.figure"
669
+ />
670
+ <div class="o-figure-menu position-absolute m-2" t-if="!env.isDashboard()">
671
+ <div
672
+ class="o-figure-menu-item"
673
+ t-if="!env.model.getters.isReadonly()"
674
+ t-on-click="showMenu"
675
+ t-ref="menuButton"
676
+ t-on-contextmenu.prevent.stop="showMenu">
677
+ <t t-call="o-spreadsheet-Icon.LIST"/>
678
+ </div>
679
+ <Menu
680
+ t-if="menuState.isOpen"
681
+ position="menuState.position"
682
+ menuItems="menuState.menuItems"
683
+ onClose="() => this.menuState.isOpen=false"
684
+ />
685
+ </div>
686
+ </div>
687
+ <div class="o-figure-border w-100 h-100 position-absolute pe-none" t-att-style="borderStyle"/>
688
+ <t t-if="isSelected">
689
+ <div
690
+ class="o-fig-anchor o-top"
691
+ t-att-style="this.getResizerPosition('top')"
692
+ t-on-mousedown="(ev) => this.clickAnchor(0,-1, ev)"
693
+ />
694
+ <div
695
+ class="o-fig-anchor o-topRight"
696
+ t-att-style="this.getResizerPosition('top right')"
697
+ t-on-mousedown="(ev) => this.clickAnchor(1,-1, ev)"
698
+ />
699
+ <div
700
+ class="o-fig-anchor o-right"
701
+ t-att-style="this.getResizerPosition('right')"
702
+ t-on-mousedown="(ev) => this.clickAnchor(1,0, ev)"
703
+ />
704
+ <div
705
+ class="o-fig-anchor o-bottomRight"
706
+ t-att-style="this.getResizerPosition('bottom right')"
707
+ t-on-mousedown="(ev) => this.clickAnchor(1,1, ev)"
708
+ />
709
+ <div
710
+ class="o-fig-anchor o-bottom"
711
+ t-att-style="this.getResizerPosition('bottom')"
712
+ t-on-mousedown="(ev) => this.clickAnchor(0,1, ev)"
713
+ />
714
+ <div
715
+ class="o-fig-anchor o-bottomLeft"
716
+ t-att-style="this.getResizerPosition('bottom left')"
717
+ t-on-mousedown="(ev) => this.clickAnchor(-1,1, ev)"
718
+ />
719
+ <div
720
+ class="o-fig-anchor o-left"
721
+ t-att-style="this.getResizerPosition('left')"
722
+ t-on-mousedown="(ev) => this.clickAnchor(-1,0, ev)"
723
+ />
724
+ <div
725
+ class="o-fig-anchor o-topLeft"
726
+ t-att-style="this.getResizerPosition('top left')"
727
+ t-on-mousedown="(ev) => this.clickAnchor(-1,-1, ev)"
728
+ />
729
+ </t>
730
+ </div>
731
+ </t>
732
+
733
+ <t t-name="o-spreadsheet-ChartFigure" owl="1">
734
+ <div class="o-chart-container w-100 h-100" t-on-dblclick="onDoubleClick">
735
+ <t
736
+ t-component="chartComponent"
737
+ figure="this.props.figure"
738
+ t-key="this.props.figure.id + '-' + chartType"
739
+ />
740
+ </div>
741
+ </t>
742
+
743
+ <t t-name="o-spreadsheet-FiguresContainer" owl="1">
744
+ <div>
745
+ <t t-foreach="containers" t-as="container" t-key="container.type">
746
+ <div
747
+ class="o-figure-container position-absolute pe-none overflow-hidden"
748
+ t-att-style="container.style"
749
+ t-att-data-id="container.type + 'Container'">
750
+ <div
751
+ class="o-figure-viewport-inverse w-0 h-0 overflow-visible position-absolute"
752
+ t-att-style="container.inverseViewportStyle">
753
+ <t t-foreach="container.figures" t-as="figure" t-key="figure.id">
754
+ <FigureComponent
755
+ onFigureDeleted="this.props.onFigureDeleted"
756
+ figure="figure"
757
+ style="getFigureStyle(figure)"
758
+ onMouseDown="(ev) => this.startDraggingFigure(figure, ev)"
759
+ onClickAnchor="(dirX, dirY, ev) => this.startResize(figure, dirX, dirY, ev)"
760
+ />
761
+ </t>
762
+ </div>
763
+ </div>
764
+ </t>
765
+ </div>
766
+ <div
767
+ class="o-figure-container position-absolute pe-none overflow-hidden"
768
+ t-if="dnd.horizontalSnap"
769
+ t-att-style="dnd.horizontalSnap.containerStyle"
770
+ t-att-data-id="'HorizontalSnapContainer'">
771
+ <div class="o-figure-snap-line horizontal" t-att-style="dnd.horizontalSnap.lineStyle"/>
772
+ </div>
773
+ <div
774
+ class="o-figure-container position-absolute pe-none overflow-hidden"
775
+ t-if="dnd.verticalSnap"
776
+ t-att-style="dnd.verticalSnap.containerStyle"
777
+ t-att-data-id="'VerticalSnapContainer'">
778
+ <div class="o-figure-snap-line vertical" t-att-style="dnd.verticalSnap.lineStyle"/>
779
+ </div>
780
+ </t>
781
+
782
+ <t t-name="o-spreadsheet-ImageFigure" owl="1">
783
+ <img t-att-src="getImagePath" class="w-100 h-100"/>
784
+ </t>
785
+
786
+ <t t-name="o-spreadsheet-FilterIcon" owl="1">
787
+ <div class="o-filter-icon" t-att-style="style" t-on-click.stop="props.onClick">
788
+ <t t-if="props.isActive" t-call="o-spreadsheet-Icon.FILTER_ICON_ACTIVE"/>
789
+ <t t-else="" t-call="o-spreadsheet-Icon.FILTER_ICON"/>
790
+ </div>
791
+ </t>
792
+
793
+ <t t-name="o-spreadsheet-FilterIconsOverlay" owl="1">
794
+ <t
795
+ t-foreach="getVisibleFilterHeaders()"
796
+ t-as="header"
797
+ t-key="'filter'+header.col + '_' + header.row">
798
+ <FilterIcon
799
+ position="getFilterHeaderPosition(header)"
800
+ isActive="isFilterActive(header)"
801
+ t-key="'icon_'+header.col + '_' + header.row"
802
+ onClick="() => this.toggleFilterMenu(header)"
803
+ />
804
+ </t>
805
+ </t>
806
+
807
+ <t t-name="o-spreadsheet-FilterMenu" owl="1">
808
+ <div class="o-filter-menu d-flex flex-column bg-white" t-on-wheel.stop="">
809
+ <div t-if="!isReadonly">
810
+ <div class="o-filter-menu-item" t-on-click="() => this.sortFilterZone('ascending')">
811
+ Sort ascending (A ⟶ Z)
812
+ </div>
813
+ <div class="o-filter-menu-item" t-on-click="() => this.sortFilterZone('descending')">
814
+ Sort descending (Z ⟶ A)
815
+ </div>
816
+ </div>
817
+ <div class="o-separator" t-if="!isReadonly"/>
818
+ <div class="o-filter-menu-actions">
819
+ <div class="o-filter-menu-action-text" t-on-click="selectAll">Select all</div>
820
+ <div class="o-filter-menu-action-text" t-on-click="clearAll">Clear</div>
821
+ </div>
822
+ <div class="position-relative">
823
+ <input
824
+ class="w-100"
825
+ t-ref="filterMenuSearchBar"
826
+ type="text"
827
+ t-model="state.textFilter"
828
+ placeholder="Search..."
829
+ t-on-keydown="onKeyDown"
830
+ />
831
+ <i class="o-search-icon position-absolute">
832
+ <t t-call="o-spreadsheet-Icon.SEARCH"/>
833
+ </i>
834
+ </div>
835
+ <div
836
+ class="o-filter-menu-list d-flex flex-column rounded"
837
+ t-ref="filterValueList"
838
+ t-on-click="this.clearScrolledToValue"
839
+ t-on-scroll="this.clearScrolledToValue">
840
+ <t t-foreach="displayedValues" t-as="value" t-key="value.string">
841
+ <FilterMenuValueItem
842
+ onClick="() => this.checkValue(value)"
843
+ onMouseMove="() => this.onMouseMove(value)"
844
+ value="value.string"
845
+ isChecked="value.checked"
846
+ isSelected="value.string === state.selectedValue"
847
+ scrolledTo="value.scrolledTo"
848
+ />
849
+ </t>
850
+ <div
851
+ t-if="displayedValues.length === 0"
852
+ class="o-filter-menu-no-values d-flex align-items-center justify-content-center w-100 h-100 ">
853
+ No results
854
+ </div>
855
+ </div>
856
+ <div class="o-filter-menu-buttons d-flex justify-content-end">
857
+ <div class="o-filter-menu-button o-filter-menu-button-cancel" t-on-click="cancel">
858
+ Cancel
859
+ </div>
860
+ <div class="o-filter-menu-button o-filter-menu-button-primary" t-on-click="confirm">
861
+ Confirm
862
+ </div>
863
+ </div>
864
+ </div>
865
+ </t>
866
+
867
+ <t t-name="o-spreadsheet-FilterMenuValueItem" owl="1">
868
+ <div
869
+ t-on-click="this.props.onClick"
870
+ t-on-mousemove="this.props.onMouseMove"
871
+ class="o-filter-menu-item o-filter-menu-value"
872
+ t-ref="menuValueItem"
873
+ t-att-class="{'selected': this.props.isSelected}">
874
+ <div>
875
+ <div class="o-filter-menu-value-checked">
876
+ <span t-if="this.props.isChecked">✓</span>
877
+ </div>
878
+ </div>
879
+ <div class="o-filter-menu-value-text text-truncate">
880
+ <t t-if="this.props.value === ''">(Blanks)</t>
881
+ <t t-else="" t-esc="this.props.value"/>
882
+ </div>
883
+ </div>
884
+ </t>
885
+
886
+ <t t-name="o-spreadsheet-FontSizeEditor" owl="1">
887
+ <div class="o-dropdown" t-ref="FontSizeEditor">
888
+ <div
889
+ class=" o-font-size-editor d-flex align-items-center"
890
+ t-att-class="props.class"
891
+ title="Font Size"
892
+ t-on-click="this.toggleFontList">
893
+ <input
894
+ type="number"
895
+ min="1"
896
+ max="400"
897
+ class="o-font-size bg-transparent border-0"
898
+ t-on-keydown="onInputKeydown"
899
+ t-on-click.stop=""
900
+ t-on-focus.stop="onInputFocused"
901
+ t-att-value="currentFontSize"
902
+ t-on-change="setSizeFromInput"
903
+ t-ref="inputFontSize"
904
+ />
905
+ <span>
906
+ <t t-call="o-spreadsheet-Icon.TRIANGLE_DOWN"/>
907
+ </span>
908
+ </div>
909
+ <div
910
+ class="o-dropdown-content o-text-options"
911
+ t-if="dropdown.isOpen"
912
+ t-on-click.stop=""
913
+ t-att-style="props.dropdownStyle">
914
+ <t t-foreach="fontSizes" t-as="fontSize" t-key="fontSize">
915
+ <div
916
+ t-esc="fontSize"
917
+ t-att-data-size="fontSize"
918
+ t-on-click="() => this.setSizeFromList(fontSize)"
919
+ />
920
+ </t>
921
+ </div>
922
+ </div>
923
+ </t>
924
+
925
+ <t t-name="o-spreadsheet-Grid" owl="1">
926
+ <div
927
+ class="o-grid"
928
+ tabindex="-1"
929
+ t-att-class="{'o-two-columns': !props.sidePanelIsOpen}"
930
+ t-on-click="focus"
931
+ t-on-keydown="onKeydown"
932
+ t-on-wheel="onMouseWheel"
933
+ t-ref="grid">
934
+ <GridOverlay
935
+ onCellClicked.bind="onCellClicked"
936
+ onCellDoubleClicked.bind="onCellDoubleClicked"
937
+ onCellRightClicked.bind="onCellRightClicked"
938
+ onCellHovered.bind="onCellHovered"
939
+ onGridResized.bind="onGridResized"
940
+ onGridMoved.bind="moveCanvas"
941
+ gridOverlayDimensions="gridOverlayDimensions"
942
+ onFigureDeleted.bind="focus"
943
+ />
944
+ <HeadersOverlay onOpenContextMenu="(type, x, y) => this.toggleContextMenu(type, x, y)"/>
945
+
946
+ <t t-if="env.model.getters.getEditionMode() !== 'inactive'">
947
+ <GridComposer
948
+ onComposerUnmounted="() => this.focus()"
949
+ onComposerContentFocused="props.onComposerContentFocused"
950
+ focus="props.focusComposer"
951
+ gridDims="env.model.getters.getSheetViewDimensionWithHeaders()"
952
+ />
953
+ </t>
954
+ <t else="1">
955
+ <input
956
+ class="position-absolute"
957
+ style="z-index:-1000;"
958
+ t-on-input="onInput"
959
+ t-on-contextmenu="onInputContextMenu"
960
+ t-ref="hiddenInput"
961
+ />
962
+ </t>
963
+ <canvas t-ref="canvas"/>
964
+ <t
965
+ t-foreach="env.model.getters.getClientsToDisplay()"
966
+ t-as="client"
967
+ t-key="getClientPositionKey(client)">
968
+ <ClientTag
969
+ name="client.name"
970
+ color="client.color"
971
+ col="client.position.col"
972
+ row="client.position.row"
973
+ active="isCellHovered(client.position.col, client.position.row)"
974
+ />
975
+ </t>
976
+ <GridPopover
977
+ t-if="!menuState.isOpen"
978
+ hoveredCell="hoveredCell"
979
+ gridRect="getGridRect()"
980
+ onMouseWheel.bind="onMouseWheel"
981
+ onClosePopover.bind="onClosePopover"
982
+ />
983
+ <t t-if="env.model.getters.getEditionMode() === 'inactive'">
984
+ <Autofill position="getAutofillPosition()" isVisible="isAutofillVisible"/>
985
+ </t>
986
+ <t t-if="env.model.getters.getEditionMode() !== 'inactive'">
987
+ <t t-foreach="env.model.getters.getHighlights()" t-as="highlight" t-key="highlight_index">
988
+ <t t-if="highlight.sheetId === env.model.getters.getActiveSheetId()">
989
+ <Highlight zone="highlight.zone" color="highlight.color"/>
990
+ </t>
991
+ </t>
992
+ </t>
993
+ <Menu
994
+ t-if="menuState.isOpen"
995
+ menuItems="menuState.menuItems"
996
+ position="menuState.position"
997
+ onClose="() => this.closeMenu()"
998
+ />
999
+ <FilterIconsOverlay gridPosition="{ x: HEADER_WIDTH, y : HEADER_HEIGHT }"/>
1000
+ <VerticalScrollBar topOffset="HEADER_HEIGHT"/>
1001
+ <HorizontalScrollBar leftOffset="HEADER_WIDTH"/>
1002
+ <div class="o-scrollbar corner"/>
1003
+ </div>
1004
+ </t>
1005
+
1006
+ <t t-name="o-spreadsheet-GridOverlay" owl="1">
1007
+ <div
1008
+ t-ref="gridOverlay"
1009
+ class="o-grid-overlay overflow-hidden"
1010
+ t-att-class="{'o-paint-format-cursor': isPaintingFormat}"
1011
+ t-att-style="style"
1012
+ t-on-mousedown="onMouseDown"
1013
+ t-on-dblclick.self="onDoubleClick"
1014
+ t-on-contextmenu="onContextMenu">
1015
+ <FiguresContainer onFigureDeleted="props.onFigureDeleted"/>
1016
+ </div>
1017
+ </t>
1018
+
1019
+ <t t-name="o-spreadsheet-GridPopover" owl="1">
1020
+ <Popover
1021
+ t-if="cellPopover.isOpen"
1022
+ positioning="cellPopover.cellCorner"
1023
+ maxHeight="cellPopover.Component.size and cellPopover.Component.size.maxHeight"
1024
+ maxWidth="cellPopover.Component.size and cellPopover.Component.size.maxHidth"
1025
+ anchorRect="cellPopover.anchorRect"
1026
+ containerRect="env.getPopoverContainerRect()"
1027
+ onMouseWheel="props.onMouseWheel"
1028
+ zIndex="zIndex">
1029
+ <t
1030
+ t-component="cellPopover.Component"
1031
+ t-props="{...cellPopover.props, onClosed : () => props.onClosePopover()}"
1032
+ />
1033
+ </Popover>
1034
+ </t>
1035
+
1036
+ <t t-name="o-spreadsheet-HeadersOverlay" owl="1">
1037
+ <div class="o-overlay">
1038
+ <ColResizer onOpenContextMenu="props.onOpenContextMenu"/>
1039
+ <RowResizer onOpenContextMenu="props.onOpenContextMenu"/>
1040
+ <div class="all" t-on-mousedown.self="selectAll"/>
1041
+ </div>
1042
+ </t>
1043
+
1044
+ <t t-name="o-spreadsheet-RowResizer" owl="1">
1045
+ <div
1046
+ class="o-row-resizer"
1047
+ t-on-mousemove.self="onMouseMove"
1048
+ t-on-mouseleave="onMouseLeave"
1049
+ t-on-mousedown.self.prevent="select"
1050
+ t-ref="rowResizer"
1051
+ t-on-mouseup.self="onMouseUp"
1052
+ t-on-contextmenu.self="onContextMenu"
1053
+ t-att-class="{'o-grab': state.waitingForMove, 'o-dragging': state.isMoving}">
1054
+ <div
1055
+ t-if="state.isMoving"
1056
+ class="dragging-row-line"
1057
+ t-attf-style="top:{{state.draggerLinePosition}}px;"
1058
+ />
1059
+ <div
1060
+ t-if="state.isMoving"
1061
+ class="dragging-row-shadow"
1062
+ t-attf-style="top:{{state.draggerShadowPosition}}px; height:{{state.draggerShadowThickness}}px;"
1063
+ />
1064
+ <t t-if="state.resizerIsActive">
1065
+ <div
1066
+ class="o-handle"
1067
+ t-on-mousedown="onMouseDown"
1068
+ t-on-dblclick="onDblClick"
1069
+ t-on-contextmenu.prevent=""
1070
+ t-attf-style="top:{{state.draggerLinePosition - 2}}px;">
1071
+ <div class="dragging-resizer" t-if="state.isResizing"/>
1072
+ </div>
1073
+ </t>
1074
+ <t
1075
+ t-foreach="env.model.getters.getHiddenRowsGroups(env.model.getters.getActiveSheetId())"
1076
+ t-as="hiddenItem"
1077
+ t-key="hiddenItem_index">
1078
+ <t t-if="!hiddenItem.includes(0)">
1079
+ <div
1080
+ class="o-unhide"
1081
+ t-att-data-index="hiddenItem_index"
1082
+ t-attf-style="top:{{unhideStyleValue(hiddenItem[0]) - 17}}px;"
1083
+ t-on-click="() => this.unhide(hiddenItem)">
1084
+ <t t-call="o-spreadsheet-Icon.TRIANGLE_UP"/>
1085
+ </div>
1086
+ </t>
1087
+ <t
1088
+ t-if="!hiddenItem.includes(env.model.getters.getNumberRows(env.model.getters.getActiveSheetId())-1)">
1089
+ <div
1090
+ class="o-unhide"
1091
+ t-att-data-index="hiddenItem_index"
1092
+ t-attf-style="top:{{unhideStyleValue(hiddenItem[0]) + 3}}px;"
1093
+ t-on-click="() => this.unhide(hiddenItem)">
1094
+ <t t-call="o-spreadsheet-Icon.TRIANGLE_DOWN"/>
1095
+ </div>
1096
+ </t>
1097
+ </t>
1098
+ </div>
1099
+ </t>
1100
+
1101
+ <t t-name="o-spreadsheet-ColResizer" owl="1">
1102
+ <div
1103
+ class="o-col-resizer"
1104
+ t-on-mousemove.self="onMouseMove"
1105
+ t-on-mouseleave="onMouseLeave"
1106
+ t-on-mousedown.self.prevent="select"
1107
+ t-ref="colResizer"
1108
+ t-on-mouseup.self="onMouseUp"
1109
+ t-on-contextmenu.self="onContextMenu"
1110
+ t-att-class="{'o-grab': state.waitingForMove, 'o-dragging': state.isMoving, }">
1111
+ <div
1112
+ t-if="state.isMoving"
1113
+ class="dragging-col-line"
1114
+ t-attf-style="left:{{state.draggerLinePosition}}px;"
1115
+ />
1116
+ <div
1117
+ t-if="state.isMoving"
1118
+ class="dragging-col-shadow"
1119
+ t-attf-style="left:{{state.draggerShadowPosition}}px; width:{{state.draggerShadowThickness}}px"
1120
+ />
1121
+ <t t-if="state.resizerIsActive">
1122
+ <div
1123
+ class="o-handle"
1124
+ t-on-mousedown="onMouseDown"
1125
+ t-on-dblclick="onDblClick"
1126
+ t-on-contextmenu.prevent=""
1127
+ t-attf-style="left:{{state.draggerLinePosition - 2}}px;">
1128
+ <div class="dragging-resizer" t-if="state.isResizing"/>
1129
+ </div>
1130
+ </t>
1131
+ <t
1132
+ t-foreach="env.model.getters.getHiddenColsGroups(env.model.getters.getActiveSheetId())"
1133
+ t-as="hiddenItem"
1134
+ t-key="hiddenItem_index">
1135
+ <t t-if="!hiddenItem.includes(0)">
1136
+ <div
1137
+ class="o-unhide"
1138
+ t-att-data-index="hiddenItem_index"
1139
+ t-attf-style="left:{{unhideStyleValue(hiddenItem[0]) - 17}}px; margin-right:6px;"
1140
+ t-on-click="() => this.unhide(hiddenItem)">
1141
+ <t t-call="o-spreadsheet-Icon.TRIANGLE_LEFT"/>
1142
+ </div>
1143
+ </t>
1144
+ <t
1145
+ t-if="!hiddenItem.includes(env.model.getters.getNumberCols(env.model.getters.getActiveSheetId())-1)">
1146
+ <div
1147
+ class="o-unhide"
1148
+ t-att-data-index="hiddenItem_index"
1149
+ t-attf-style="left:{{unhideStyleValue(hiddenItem[0]) + 3}}px;"
1150
+ t-on-click="() => this.unhide(hiddenItem)">
1151
+ <t t-call="o-spreadsheet-Icon.TRIANGLE_RIGHT"/>
1152
+ </div>
1153
+ </t>
1154
+ </t>
1155
+ </div>
1156
+ </t>
1157
+
1158
+ <t t-name="o-spreadsheet-Border" owl="1">
1159
+ <div
1160
+ class="o-border"
1161
+ t-on-mousedown.prevent="onMouseDown"
1162
+ t-att-style="style"
1163
+ t-att-class="{
1164
+ 'o-moving': props.isMoving,
1165
+ 'o-border-n': props.orientation === 'n',
1166
+ 'o-border-s': props.orientation === 's',
1167
+ 'o-border-w': props.orientation === 'w',
1168
+ 'o-border-e': props.orientation === 'e',
1169
+ }"
1170
+ />
1171
+ </t>
1172
+
1173
+ <t t-name="o-spreadsheet-Corner" owl="1">
1174
+ <div
1175
+ class="o-corner"
1176
+ t-on-mousedown.prevent="onMouseDown"
1177
+ t-att-style="style"
1178
+ t-att-class="{
1179
+ 'o-resizing': props.isResizing,
1180
+ 'o-corner-nw': props.orientation === 'nw',
1181
+ 'o-corner-ne': props.orientation === 'ne',
1182
+ 'o-corner-sw': props.orientation === 'sw',
1183
+ 'o-corner-se': props.orientation === 'se',
1184
+ }"
1185
+ />
1186
+ </t>
1187
+
1188
+ <t t-name="o-spreadsheet-Highlight" owl="1">
1189
+ <div class="o-highlight" t-ref="highlight">
1190
+ <t t-foreach="['n', 's', 'w', 'e']" t-as="orientation" t-key="orientation">
1191
+ <Border
1192
+ onMoveHighlight="(x, y) => this.onMoveHighlight(x,y)"
1193
+ isMoving='highlightState.shiftingMode === "isMoving"'
1194
+ orientation="orientation"
1195
+ zone="props.zone"
1196
+ />
1197
+ </t>
1198
+ <t t-foreach="['nw', 'ne', 'sw', 'se']" t-as="orientation" t-key="orientation">
1199
+ <Corner
1200
+ onResizeHighlight="(isLeft, isTop) => this.onResizeHighlight(isLeft, isTop)"
1201
+ isResizing='highlightState.shiftingMode === "isResizing"'
1202
+ orientation="orientation"
1203
+ zone="props.zone"
1204
+ color="props.color"
1205
+ />
1206
+ </t>
1207
+ </div>
1208
+ </t>
1209
+
1210
+ <t t-name="o-spreadsheet-IconPicker" owl="1">
1211
+ <div class="o-icon-picker">
1212
+ <t t-foreach="iconSets" t-as="iconSet" t-key="iconSet">
1213
+ <div class="o-cf-icon-line">
1214
+ <div
1215
+ class="o-icon-picker-item"
1216
+ t-on-click="() => this.onIconClick(iconSets[iconSet].good)">
1217
+ <t t-call="o-spreadsheet-Icon.{{icons[iconSets[iconSet].good].template}}"/>
1218
+ </div>
1219
+ <div
1220
+ class="o-icon-picker-item"
1221
+ t-on-click="() => this.onIconClick(iconSets[iconSet].neutral)">
1222
+ <t t-call="o-spreadsheet-Icon.{{icons[iconSets[iconSet].neutral].template}}"/>
1223
+ </div>
1224
+ <div
1225
+ class="o-icon-picker-item"
1226
+ t-on-click="() => this.onIconClick(iconSets[iconSet].bad)">
1227
+ <t t-call="o-spreadsheet-Icon.{{icons[iconSets[iconSet].bad].template}}"/>
1228
+ </div>
1229
+ </div>
1230
+ </t>
1231
+ </div>
1232
+ </t>
1233
+
1234
+ <t t-name="o-spreadsheet-Icon.CLEAR_AND_RELOAD" owl="1">
1235
+ <svg class="o-icon">
1236
+ <path
1237
+ fill="currentColor"
1238
+ d="M14 15H4V3h6v3h4M4 1.5A1.5 1.5 0 0 0 2.5 3v12a1.5 1.5 0 0 0 1.4 1.5h10a1.5 1.5 0 0 0 1.5-1.5V5l-3.5-3.5
1239
+ "
1240
+ />
1241
+ </svg>
1242
+ </t>
1243
+ <t t-name="o-spreadsheet-Icon.EXPORT_XLSX" owl="1">
1244
+ <svg class="o-icon">
1245
+ <path
1246
+ fill="currentColor"
1247
+ d="M0 1a1 1 0 0 1 1-1h7a1 1 0 0 1 1 1v7a1 1 0 0 1-1 1H1a1 1 0 0 1-1-1m4-4V1H1v3m7 0V1H5v3M4 8V5H1v3m7 0V5H5v3m-3.5 2h2v4h3v-1.5l3 2.5-3 2.5V16h-5m9.5-6h6a1 1 0 0 1 1 1v6a1 1 0 0 1-1 1h-6a1 1 0 0 1-1-1v-6a1 1 0 0 1 1-1m1.7 7 1.3-2 1.3 2h2l-2-3 2-3h-2L14 13l-1.3-2h-2l2 3-2 3"
1248
+ />
1249
+ </svg>
1250
+ </t>
1251
+ <t t-name="o-spreadsheet-Icon.OPEN_READ_ONLY" owl="1">
1252
+ <svg class="o-icon">
1253
+ <path
1254
+ fill="currentColor"
1255
+ d="M13 7V5c0-2.5-2-4-4-4S5 2.5 5 5v2h-.5C3.5 7 3 7.5 3 8.5v7c0 1 .5 1.5 1.5 1.5h9c1 0 1.5-.5 1.5-1.5v-7c0-1-.5-1.5-1.5-1.5m-7-2c0-1.5 1-2.5 2.5-2.5s2.5 1 2.5 2.5v2h-5V5m1 7a1.5 1.5 0 0 1 3 0 1.5 1.5 0 0 1-3 0"
1256
+ />
1257
+ </svg>
1258
+ </t>
1259
+ <t t-name="o-spreadsheet-Icon.OPEN_DASHBOARD" owl="1">
1260
+ <svg class="o-icon">
1261
+ <path
1262
+ fill="currentColor"
1263
+ d="M13 2.07A8 8 0 1 0 15.93 5L14.2 6A6 6 0 1 1 12 3.8m-2 3.47a2 2 0 1 0 .73.73l5.5-5.5-.6-.6M9.3 3.8a.6.6 0 1 1-.01-.01m1.81.51a.6.6 0 1 1-.01-.01M7.5 4.3a.6.6 0 1 1-.01-.01M5.9 5.4a.6.6 0 1 1-.01-.01M4.8 6.9a.6.6 0 1 1-.01-.01m8.71.61a.6.6 0 1 0-.01 0"
1264
+ />
1265
+ </svg>
1266
+ </t>
1267
+ <t t-name="o-spreadsheet-Icon.OPEN_READ_WRITE" owl="1">
1268
+ <svg class="o-icon">
1269
+ <path
1270
+ fill="currentColor"
1271
+ d="M13 7V5a4 4 0 0 0-8 0v2h-.5C3.5 7 3 7.5 3 8.5v7c0 1 .5 1.5 1.5 1.5h9c1 0 1.5-.5 1.5-1.5v-7c0-1-.5-1.5-1.5-1.5m-7-2a2 2 0 0 1 5 0v2h-5m1 5a1.5 1.5 0 0 1 3 0 1.5 1.5 0 0 1-3 0m6 3.5h-9v-7h9"
1272
+ />
1273
+ </svg>
1274
+ </t>
1275
+ <t t-name="o-spreadsheet-Icon.IMPORT_XLSX" owl="1">
1276
+ <svg class="o-icon">
1277
+ <path
1278
+ fill="currentColor"
1279
+ d="M9 10a1 1 0 0 1 1-1h7a1 1 0 0 1 1 1v7a1 1 0 0 1-1 1h-7a1 1 0 0 1-1-1m4-4v-3h-3v3m7 0v-3h-3v3m-1 4v-3h-3v3m7 0v-3h-3v3M.5 9h2v4h3v-1.5l3 2.5-3 2.5V15h-5M1 0h6a1 1 0 0 1 1 1v6a1 1 0 0 1-1 1H1a1 1 0 0 1-1-1V1a1 1 0 0 1 1-1m1.7 7L4 5l1.3 2h2l-2-3 2-3h-2L4 3 2.7 1h-2l2 3-2 3"
1280
+ />
1281
+ </svg>
1282
+ </t>
1283
+ <t t-name="o-spreadsheet-Icon.UNDO" owl="1">
1284
+ <svg class="o-icon">
1285
+ <path
1286
+ fill="currentColor"
1287
+ d="M5.43 9.43 8 12H1V5l2.96 2.958A8.29 8.29 0 0 1 9.32 6c3.46 0 6.42 2.11 7.68 5l-2 1c-.94-2.39-3.13-3.92-5.68-4a6.57 6.57 0 0 0-3.89 1.43"
1288
+ />
1289
+ </svg>
1290
+ </t>
1291
+ <t t-name="o-spreadsheet-Icon.REDO" owl="1">
1292
+ <svg class="o-icon">
1293
+ <path
1294
+ fill="currentColor"
1295
+ d="M12.57 9.43 10 12h7V5l-2.96 2.96A8.29 8.29 0 0 0 8.68 6C5.22 6 2.26 8.11 1 11l2 1c.94-2.39 3.13-3.92 5.68-4a6.58 6.58 0 0 1 3.89 1.43"
1296
+ />
1297
+ </svg>
1298
+ </t>
1299
+ <t t-name="o-spreadsheet-Icon.COPY" owl="1">
1300
+ <svg class="o-icon">
1301
+ <path
1302
+ fill="currentColor"
1303
+ d="M14.5 15.23v1.5H3a1 1 0 0 1-1-1V3.23h1.5v11a1 1 0 0 0 1 1h10m0-3.5a1 1 0 0 1-1 1H7a1 1 0 0 1-1-1v-8a1 1 0 0 1 1-1h6.5a1 1 0 0 1 1 1m-9-2.5a1 1 0 0 0-1 1v11a1 1 0 0 0 1 1H15a1 1 0 0 0 1-1v-11a1 1 0 0 0-1-1"
1304
+ />
1305
+ </svg>
1306
+ </t>
1307
+ <t t-name="o-spreadsheet-Icon.CUT" owl="1">
1308
+ <svg class="o-icon">
1309
+ <path
1310
+ fill="currentColor"
1311
+ d="M3 2v2l4.5 5-1.2 1.3c-.4-.2-.8-.3-1.3-.3-1.7 0-3 1.3-3 3s1.3 3 3 3 3-1.3 3-3c0-.5-.1-.9-.3-1.3L9 10.4l1.3 1.3c-.2.4-.3.8-.3 1.3 0 1.7 1.3 3 3 3s3-1.3 3-3-1.3-3-3-3c-.5 0-.9.1-1.3.3L10.4 9 15 4.4V2h-.4L9 7.6 3.4 2H3Zm2 12.5c-.8 0-1.5-.7-1.5-1.5s.7-1.5 1.5-1.5 1.5.7 1.5 1.5-.7 1.5-1.5 1.5Zm9.5-1.5c0 .8-.7 1.5-1.5 1.5s-1.5-.7-1.5-1.5.7-1.5 1.5-1.5 1.5.7 1.5 1.5ZM9 8.5c.3 0 .5.2.5.5s-.2.5-.5.5-.5-.2-.5-.5.2-.5.5-.5"
1312
+ />
1313
+ </svg>
1314
+ </t>
1315
+ <t t-name="o-spreadsheet-Icon.PASTE" owl="1">
1316
+ <svg class="o-icon">
1317
+ <path
1318
+ fill="currentColor"
1319
+ d="M14.5 2.5H11C10.7 1.6 10 1 9 1s-1.5.5-2 1.5H3.5C2.5 2.5 2 3 2 4v11c0 1 .5 1.5 1.5 1.5h11c1 0 1.5-.5 1.5-1.5V4c0-1-.5-1.5-1.5-1.5Zm-4.75.75c0 .5-.34.75-.75.75s-.75-.34-.75-.75.34-.75.75-.75.75.34.75.75ZM14.5 15h-11V4H5v2.5h8V4h1.5v11"
1320
+ />
1321
+ </svg>
1322
+ </t>
1323
+ <t t-name="o-spreadsheet-Icon.FIND_AND_REPLACE" owl="1">
1324
+ <svg class="o-icon">
1325
+ <path
1326
+ fill="currentColor"
1327
+ d="M10.75 11.25c-1 .75-2.25 1.25-3.5 1.25-3 0-5.5-2.5-5.5-5.5s2.5-5.5 5.5-5.5 5.5 2.5 5.5 5.5c0 1.25-.5 2.5-1.25 3.5l.25.25h.75l4 4-1.5 1.5-4-4v-.75l-.25-.25ZM7.25 11c2.25 0 4-1.75 4-4s-1.75-4-4-4-4 1.75-4 4 1.75 4 4 4"
1328
+ />
1329
+ </svg>
1330
+ </t>
1331
+ <t t-name="o-spreadsheet-Icon.DELETE" owl="1">
1332
+ <svg class="o-icon">
1333
+ <path
1334
+ fill="currentColor"
1335
+ d="M12 1.75v-1H6v1H1.5v2h1v12a1.5 1.5 0 0 0 1.5 1.5h10a1.5 1.5 0 0 0 1.5-1.5v-12h1v-2M4 15.75v-12h10v12Zm2-10.5h2v9H6Zm4 0h2v9h-2"
1336
+ />
1337
+ </svg>
1338
+ </t>
1339
+ <t t-name="o-spreadsheet-Icon.CLEAR" owl="1">
1340
+ <svg class="o-icon">
1341
+ <path
1342
+ fill="currentColor"
1343
+ d="M1.5 15a.75.75 0 0 0 0 1.5h15a.75.75 0 0 0 0-1.5M5.3 12.75c.1.1.3.2.5.2h4c.2 0 .4-.1.5-.2l5.5-5.5c.2-.3.2-.6 0-.8l-4.4-4.4c-.3-.2-.6-.2-.8 0l-4.8 4.8c-2.7 2.9-3.1 2.8-2.4 4M7 7.25l3.6 3.6-1 1-3.6.1-1.8-1.9"
1344
+ />
1345
+ </svg>
1346
+ </t>
1347
+ <t t-name="o-spreadsheet-Icon.FREEZE" owl="1">
1348
+ <svg class="o-icon">
1349
+ <path
1350
+ fill="currentColor"
1351
+ d="M.5 17.5h16a1 1 0 0 0 1-1v-15a1 1 0 0 0-1-1h-15a1 1 0 0 0-1 1v15a1 1 0 0 0 1 1m9-10.5v4.5H6V7m0 9v-3.5h4.5V16M5 16H3.5L5 14.5M5 13l-3 3v-1.5l3-3M2 13v-2l3-3v2m-3-.5v-2l3-3v2M2 6V4l2-2h1v1m11 13h-4.5v-3.5H16m0-1h-4.5V7H16m0-5v4h-4.5V2m-1 4H6V2h4.5"
1352
+ />
1353
+ </svg>
1354
+ </t>
1355
+ <t t-name="o-spreadsheet-Icon.UNFREEZE" owl="1">
1356
+ <svg class="o-icon">
1357
+ <path
1358
+ fill="currentColor"
1359
+ d="M.5 17.5h16a1 1 0 0 0 1-1v-15a1 1 0 0 0-1-1h-15a1 1 0 0 0-1 1v15a1 1 0 0 0 1 1M5 6H2V2h3m0 9.5H2V7h3m0 9H2v-3.5h3M10.5 7v4.5H6V7m0 9v-3.5h4.5V16m5.5 0h-4.5v-3.5H16m0-1h-4.5V7H16m0-5v4h-4.5V2m-1 4H6V2h4.5"
1360
+ />
1361
+ </svg>
1362
+ </t>
1363
+ <t t-name="o-spreadsheet-Icon.SHOW_HIDE_GRID" owl="1">
1364
+ <svg class="o-icon">
1365
+ <path
1366
+ fill="currentColor"
1367
+ d="M.5 2A1.5 1.5 0 0 1 2 .5h14A1.5 1.5 0 0 1 17.5 2v7H11V7H7v4s-.5 0-1.5 1h-1v5h-3a1.5 1.5 0 0 1-1-1M6 6V2H2v4m9 0V2H7v4m9 0V2h-4v4m-6 5V7H2v4m14-2V7h-4v2m-7.5 6.5V12H2v3.5 M14 10.5c1 0 1 .5 1 1-1.5 2.5-3.5 4.5-5 6.5-.5 0-1-.5-1-1-1-.5-1.5-1-2.5-2 0 0-.5-.5 0-1 1.5-2 4-3 7-3m-1 1.5C13.5 12 4 14 10 16c0 0-1.5-2 2.5-3.5m5 1.5c.5.5.5 1 .5 1-1.5 2-3.5 3-6 2.5.5-.5.5-1 1-1s5.5-1 2-3.5l1-1"
1368
+ />
1369
+ </svg>
1370
+ </t>
1371
+ <t t-name="o-spreadsheet-Icon.SHOW_HIDE_FORMULA" owl="1">
1372
+ <svg class="o-icon">
1373
+ <path
1374
+ fill="currentColor"
1375
+ d="M7 14.25q-.25.75-.75 1.25T5 16q-.75 0-1.5-.5Q3 15 3 14.25q0-.5.25-.75t.75-.25q.25 0 .25.75v.5H5q.5 0 .5-.5l1.25-6.5H5V6h2l.5-2.25q.25-.75.75-1.25T9.5 2q1 0 1.5.5t.5 1q0 .5-.25.75t-.5.25q-.5 0-.75-.25t-.25-.5V3H9.5q-.25 0-.5.5L8.5 6H10v1.5H8.25m1.25 1H15v1h-4l2 2-2 2h4v1H9V14l2.5-2.5L9 9"
1376
+ />
1377
+ </svg>
1378
+ </t>
1379
+ <t t-name="o-spreadsheet-Icon.HIDE_ROW" owl="1">
1380
+ <svg class="o-icon">
1381
+ <path
1382
+ fill="currentColor"
1383
+ d="M.5 2A1.5 1.5 0 0 1 2 .5h14A1.5 1.5 0 0 1 17.5 2v14a1.5 1.5 0 0 1-1.5 1.5H2A1.5 1.5 0 0 1 .5 16V2H2v3.5h14V2H2v9h14V7H2v9h14v-3.5H2M1 12l4-5h2l-4 5m2 0 4-5h2l-4 5m2 0 4-5h2l-4 5m2 0 4-5v4"
1384
+ />
1385
+ </svg>
1386
+ </t>
1387
+ <t t-name="o-spreadsheet-Icon.HIDE_COL" owl="1">
1388
+ <svg class="o-icon">
1389
+ <path
1390
+ fill="currentColor"
1391
+ d="M16 .5A1.5 1.5 0 0 1 17.5 2v14a1.5 1.5 0 0 1-1.5 1.5H2A1.5 1.5 0 0 1 .5 16V2A1.5 1.5 0 0 1 2 .5h14V2h-3.5v14H16V2H7v14h4V2H2v14h3.5V2M6 1l5 4v2L6 3m0 2 5 4v2L6 7m0 2 5 4v2l-5-4m0 2 5 4H"
1392
+ />
1393
+ </svg>
1394
+ </t>
1395
+ <t t-name="o-spreadsheet-Icon.INSERT_ROW" owl="1">
1396
+ <svg class="o-icon">
1397
+ <path
1398
+ fill="currentColor"
1399
+ d="M.5 2A1.5 1.5 0 0 1 2 .5h14A1.5 1.5 0 0 1 17.5 2v14a1.5 1.5 0 0 1-1.5 1.5H2A1.5 1.5 0 0 1 .5 16V2H2v3.5h14V2H2v9h14V7H2v9h14v-3.5H2"
1400
+ />
1401
+ </svg>
1402
+ </t>
1403
+ <t t-name="o-spreadsheet-Icon.INSERT_ROW_BEFORE" owl="1">
1404
+ <svg class="o-icon">
1405
+ <path
1406
+ fill="currentColor"
1407
+ d="M3.5 14.5A1.5 1.5 0 0 0 5 16h10a1.5 1.5 0 0 0 1.5-1.5v-7h-3V5h3V1.5A1.5 1.5 0 0 0 15 0H5a1.5 1.5 0 0 0-1.5 1.5v2h-3V9h3M15 12.5v2H5v-2M15 9v2H5V9m10-7.5v2H5v-2M12 5v2.5H2V5"
1408
+ />
1409
+ </svg>
1410
+ </t>
1411
+ <t t-name="o-spreadsheet-Icon.INSERT_ROW_AFTER" owl="1">
1412
+ <svg class="o-icon">
1413
+ <path
1414
+ fill="currentColor"
1415
+ d="M3.5 1.5A1.5 1.5 0 0 1 5 0h10a1.5 1.5 0 0 1 1.5 1.5v7h-3V11h3v3.5A1.5 1.5 0 0 1 15 16H5a1.5 1.5 0 0 1-1.5-1.5v-2h-3V7h3M15 3.5v-2H5v2M15 7V5H5v2m10 7.5v-2H5v2m7-3.5V8.5H2V11"
1416
+ />
1417
+ </svg>
1418
+ </t>
1419
+ <t t-name="o-spreadsheet-Icon.INSERT_COL" owl="1">
1420
+ <svg class="o-icon">
1421
+ <path
1422
+ fill="currentColor"
1423
+ d="M.5 2A1.5 1.5 0 0 1 2 .5h14A1.5 1.5 0 0 1 17.5 2v14a1.5 1.5 0 0 1-1.5 1.5H2A1.5 1.5 0 0 1 .5 16V2H2v14h3.5V2H2h5v14h4V2H2h10.5v14H16V2H2"
1424
+ />
1425
+ </svg>
1426
+ </t>
1427
+ <t t-name="o-spreadsheet-Icon.INSERT_COL_AFTER" owl="1">
1428
+ <svg class="o-icon">
1429
+ <path
1430
+ fill="currentColor"
1431
+ d="M2.5 3A1.5 1.5 0 0 0 1 4.5v10A1.5 1.5 0 0 0 2.5 16h7v-3H12v3h3.5a1.5 1.5 0 0 0 1.5-1.5v-10A1.5 1.5 0 0 0 15.5 3h-2V0H8v3M4.5 14.5h-2v-10h2m3.5 10H6v-10h2m7.5 10h-2v-10h2m-3.5 7H9.5v-10H12"
1432
+ />
1433
+ </svg>
1434
+ </t>
1435
+ <t t-name="o-spreadsheet-Icon.INSERT_COL_BEFORE" owl="1">
1436
+ <svg class="o-icon">
1437
+ <path
1438
+ fill="currentColor"
1439
+ d="M15.5 3A1.5 1.5 0 0 1 17 4.5v10a1.5 1.5 0 0 1-1.5 1.5h-7v-3H6v3H2.5A1.5 1.5 0 0 1 1 14.5v-10A1.5 1.5 0 0 1 2.5 3h2V0H10v3m3.5 11.5h2v-10h-2m-3.5 10h2v-10h-2m-7.5 10h2v-10h-2m3.5 7h2.5v-10H6"
1440
+ />
1441
+ </svg>
1442
+ </t>
1443
+ <t t-name="o-spreadsheet-Icon.INSERT_CELL" owl="1">
1444
+ <svg class="o-icon">
1445
+ <path
1446
+ fill="currentColor"
1447
+ d="M.5 2A1.5 1.5 0 0 1 2 .5h14A1.5 1.5 0 0 1 17.5 2v14a1.5 1.5 0 0 1-1.5 1.5H2A1.5 1.5 0 0 1 .5 16V2H2v14h14V2H2"
1448
+ />
1449
+ </svg>
1450
+ </t>
1451
+ <t t-name="o-spreadsheet-Icon.INSERT_CELL_SHIFT_DOWN" owl="1">
1452
+ <svg class="o-icon">
1453
+ <path
1454
+ fill="currentColor"
1455
+ d="M5 2.5A1.5 1.5 0 0 1 6.5 1h10A1.5 1.5 0 0 1 18 2.5v13a1.5 1.5 0 0 1-1.5 1.5h-10A1.5 1.5 0 0 1 5 15.5v-5h5.25v-3H5m11.5-2v-3h-4.75v3m-1.5 0v-3H6.5v3m10 5v-3h-4.75v3m-1.5 5v-3H6.5v3m10 0v-3h-4.75v3M0 12.5l2.5 4 2.5-4H3.25v-6h-1.5v6"
1456
+ />
1457
+ </svg>
1458
+ </t>
1459
+ <t t-name="o-spreadsheet-Icon.INSERT_CELL_SHIFT_RIGHT" owl="1">
1460
+ <svg class="o-icon">
1461
+ <path
1462
+ fill="currentColor"
1463
+ d="M2.5 5A1.5 1.5 0 0 0 1 6.5v10A1.5 1.5 0 0 0 2.5 18h13a1.5 1.5 0 0 0 1.5-1.5v-10A1.5 1.5 0 0 0 15.5 5h-5v5.25h-3V5m-2 11.5h-3v-4.75h3m0-1.5h-3V6.5h3m5 10h-3v-4.75h3m5-1.5h-3V6.5h3m0 10h-3v-4.75h3M12.5 0l4 2.5-4 2.5V3.25h-6v-1.5h6"
1464
+ />
1465
+ </svg>
1466
+ </t>
1467
+ <t t-name="o-spreadsheet-Icon.DELETE_CELL_SHIFT_UP" owl="1">
1468
+ <svg class="o-icon">
1469
+ <path
1470
+ fill="currentColor"
1471
+ d="M5 2.5A1.5 1.5 0 0 1 6.5 1h10A1.5 1.5 0 0 1 18 2.5v13a1.5 1.5 0 0 1-1.5 1.5h-10A1.5 1.5 0 0 1 5 15.5v-5h5.25v-3H5m11.5-2v-3h-4.75v3m-1.5 0v-3H6.5v3m10 5v-3h-4.75v3m-1.5 5v-3H6.5v3m10 0v-3h-4.75v3M0 10l2.5-4L5 10H3.25v6h-1.5v-6"
1472
+ />
1473
+ </svg>
1474
+ </t>
1475
+ <t t-name="o-spreadsheet-Icon.DELETE_CELL_SHIFT_LEFT" owl="1">
1476
+ <svg class="o-icon">
1477
+ <path
1478
+ fill="currentColor"
1479
+ d="M2.5 5A1.5 1.5 0 0 0 1 6.5v10A1.5 1.5 0 0 0 2.5 18h13a1.5 1.5 0 0 0 1.5-1.5v-10A1.5 1.5 0 0 0 15.5 5h-5v5.25h-3V5m-2 11.5h-3v-4.75h3m0-1.5h-3V6.5h3m5 10h-3v-4.75h3m5-1.5h-3V6.5h3m0 10h-3v-4.75h3M10 0 6 2.5 10 5V3.25h6v-1.5h-6"
1480
+ />
1481
+ </svg>
1482
+ </t>
1483
+ <t t-name="o-spreadsheet-Icon.INSERT_CHART" owl="1">
1484
+ <svg class="o-icon">
1485
+ <path
1486
+ fill="currentColor"
1487
+ d="M.5 2A1.5 1.5 0 0 1 2 .5h14A1.5 1.5 0 0 1 17.5 2v14a1.5 1.5 0 0 1-1.5 1.5H2A1.5 1.5 0 0 1 .5 16V2H2v14h14V2H2m1.5 12.5h2v-7h-2m3 7h2v-10h-2m3 10h2v-5h-2m3 5h2v-11h-2M2 14.5h14v1H2"
1488
+ />
1489
+ </svg>
1490
+ </t>
1491
+ <t t-name="o-spreadsheet-Icon.INSERT_IMAGE" owl="1">
1492
+ <svg class="o-icon" fill="currentColor">
1493
+ <path
1494
+ d="M.5 2A1.5 1.5 0 0 1 2 .5h14A1.5 1.5 0 0 1 17.5 2v14a1.5 1.5 0 0 1-1.5 1.5H2A1.5 1.5 0 0 1 .5 16V2H2v14h14V2H2m10 4.5L10 11 8.5 9.5l-2 2.5L5 10.5l-2 3h12M3.5,5a1.5,1.5,0,0,1,3,0a1.5,1.5,0,0,1,-3,0"
1495
+ />
1496
+ </svg>
1497
+ </t>
1498
+ <t t-name="o-spreadsheet-Icon.INSERT_LINK" owl="1">
1499
+ <svg class="o-icon" fill="currentColor">
1500
+ <path
1501
+ d="M6.88 13.69c.19-.19.41-.28.68-.28.27 0 .51.09.72.28.43.45.43.92 0 1.4l-.84.8c-.75.75-1.63 1.12-2.64 1.12-1.04 0-1.93-.37-2.68-1.12C1.37 15.14 1 14.26 1 13.25c0-1.04.37-1.93 1.12-2.68l2.96-2.96c.93-.9 1.89-1.42 2.88-1.54.98-.12 1.84.17 2.56.86.21.21.32.45.32.72 0 .26-.1.51-.32.72-.48.43-.95.43-1.4 0-.67-.64-1.55-.41-2.67.68l-2.93 2.92c-.35.35-.52.77-.52 1.28s.17.92.52 1.24c.35.35.76.52 1.26.52.49 0 .91-.17 1.26-.52l.84-.8m9-11.48c.75.75 1.12 1.63 1.12 2.64 0 1.04-.37 1.94-1.12 2.68l-3.16 3.16c-.99.96-1.99 1.44-3 1.44-.83 0-1.57-.33-2.24-1a.913.913 0 0 1-.28-.68c0-.27.09-.5.27-.72.19-.19.43-.28.71-.28.28 0 .51.09.7.28.66.64 1.48.48 2.44-.48l3.16-3.12c.37-.37.56-.8.56-1.28 0-.51-.19-.92-.56-1.24-.32-.35-.7-.56-1.12-.62-.43-.07-.83.07-1.2.42l-1 1c-.22.19-.45.28-.72.28-.26 0-.5-.09-.68-.28-.46-.45-.46-.92 0-1.4l1-1c.72-.72 1.56-1.06 2.54-1.02.97.04 1.83.45 2.58 1.22"
1502
+ />
1503
+ </svg>
1504
+ </t>
1505
+ <t t-name="o-spreadsheet-Icon.INSERT_SHEET" owl="1">
1506
+ <svg class="o-icon" fill="currentColor">
1507
+ <path
1508
+ d="M17.5 5.5V16a1.5 1.5 0 0 1-1.5 1.5H2A1.5 1.5 0 0 1 .5 16V2A1.5 1.5 0 0 1 2 .5h10.5M2 5.5h3.5V2H2m5.25 3.5h3.5V2h-3.5M2 10.75h3.5v-3.5H2m5.25 3.5h3.5v-3.5h-3.5m5.25 3.5H16v-3.5h-3.5M2 16h3.5v-3.5H2M7.25 16h3.5v-3.5h-3.5M12.5 16H16v-3.5h-3.5"
1509
+ />
1510
+ </svg>
1511
+ </t>
1512
+ <t t-name="o-spreadsheet-Icon.PAINT_FORMAT" owl="1">
1513
+ <svg class="o-icon">
1514
+ <path
1515
+ fill="currentColor"
1516
+ d="M9,0 L1,0 C0.45,0 0,0.45 0,1 L0,4 C0,4.55 0.45,5 1,5 L9,5 C9.55,5 10,4.55 10,4 L10,3 L11,3 L11,6 L4,6 L4,14 L6,14 L6,8 L13,8 L13,2 L10,2 L10,1 C10,0.45 9.55,0 9,0 Z"
1517
+ transform="translate(3 2)"
1518
+ />
1519
+ </svg>
1520
+ </t>
1521
+ <t t-name="o-spreadsheet-Icon.CONDITIONAL_FORMAT" owl="1">
1522
+ <svg class="o-icon">
1523
+ <path
1524
+ fill="currentColor"
1525
+ d="M12.25.5c2 0 3.5 1.5 3.5 3.5v6.5c0 .5 0 2-2 2h-2.5v4c0 .5-.5 1-1 1h-2.5c-.5 0-1-.5-1-1v-4h-2.5c-1 0-2-1-2-2V.5m12 3a1.5 1.5 0 0 0-1.5-1.5h-3v2h-1.5V2h-1v4h-2V2h-1.5v8.5h10.5m-12-3h12.5V9H2.25"
1526
+ />
1527
+ </svg>
1528
+ </t>
1529
+ <t t-name="o-spreadsheet-Icon.CLEAR_FORMAT" owl="1">
1530
+ <svg class="o-icon">
1531
+ <path
1532
+ fill="currentColor"
1533
+ d="M2.12 4.05 7.28 9.2l-2.43 5.3h2.5l1.64-3.58 4.59 4.58 1.27-1.27L3.4 2.77 2.12 4.05ZM5.67 2.5l2 2h1.76l-.55 1.21 1.71 1.71 1.34-2.92h3.92v-2H5.67"
1534
+ />
1535
+ </svg>
1536
+ </t>
1537
+ <t t-name="o-spreadsheet-Icon.TRIANGLE_DOWN" owl="1">
1538
+ <svg class="o-icon">
1539
+ <polygon fill="currentColor" points="0 0 4 4 8 0" transform="translate(5 7)"/>
1540
+ </svg>
1541
+ </t>
1542
+ <t t-name="o-spreadsheet-Icon.TRIANGLE_UP" owl="1">
1543
+ <svg class="o-icon">
1544
+ <polygon fill="currentColor" points="4 0 0 4 8 4" transform="translate(5 7)"/>
1545
+ </svg>
1546
+ </t>
1547
+ <t t-name="o-spreadsheet-Icon.TRIANGLE_RIGHT" owl="1">
1548
+ <svg class="o-icon">
1549
+ <polygon fill="currentColor" points="0 0 4 4 0 8" transform="translate(5 5)"/>
1550
+ </svg>
1551
+ </t>
1552
+ <t t-name="o-spreadsheet-Icon.TRIANGLE_LEFT" owl="1">
1553
+ <svg class="o-icon">
1554
+ <polygon fill="currentColor" points="4 0 0 4 4 8" transform="translate(5 5)"/>
1555
+ </svg>
1556
+ </t>
1557
+ <t t-name="o-spreadsheet-Icon.BOLD" owl="1">
1558
+ <svg class="o-icon">
1559
+ <path
1560
+ fill="currentColor"
1561
+ d="M13.5 6.5C13.5 4.57 11.93 3 10 3H4.5v12h6.25c1.79 0 3.25-1.46 3.25-3.25 0-1.3-.77-2.41-1.87-2.93.83-.58 1.37-1.44 1.37-2.32M9.5 5c.83 0 1.5.67 1.5 1.5S10.33 8 9.5 8h-2V5h2m-2 8v-3H10c.83 0 1.5.67 1.5 1.5S10.83 13 10 13H7.5"
1562
+ />
1563
+ </svg>
1564
+ </t>
1565
+ <t t-name="o-spreadsheet-Icon.ITALIC" owl="1">
1566
+ <svg class="o-icon">
1567
+ <path fill="currentColor" d="M7 3v2h2.58l-3.66 8H3v2h8v-2H8.42l3.66-8H15V3"/>
1568
+ </svg>
1569
+ </t>
1570
+ <t t-name="o-spreadsheet-Icon.UNDERLINE" owl="1">
1571
+ <svg class="o-icon">
1572
+ <path
1573
+ fill="currentColor"
1574
+ d="M9 15c2.76 0 5-2.24 5-5V3h-2v7c0 1.75-1.5 3-3 3s-3-1.242-3-3V3H4v7c0 2.76 2.24 5 5 5Zm-6 1v2h12v-2H3"
1575
+ />
1576
+ </svg>
1577
+ </t>
1578
+ <t t-name="o-spreadsheet-Icon.STRIKE" owl="1">
1579
+ <svg class="o-icon">
1580
+ <path
1581
+ fill="currentColor"
1582
+ d="M4.89 6.06c0-.46.1-.87.3-1.25.2-.38.46-.7.84-.97s.78-.47 1.28-.62A5.71 5.71 0 0 1 8.93 3c.61 0 1.16.08 1.65.25.5.17.92.4 1.27.7.35.3.62.66.81 1.07.19.41.28.87.28 1.36h-2.26a1.85 1.85 0 0 0-.11-.64 1.26 1.26 0 0 0-.33-.51 1.53 1.53 0 0 0-.56-.33A2.42 2.42 0 0 0 8.89 4.8c-.3 0-.55.03-.77.1a1.52 1.52 0 0 0-.54.27 1.14 1.14 0 0 0-.43.9c0 .36.18.66.55.91l.06.04C8.02 7.19 8.5 7.5 9 8H6s-.79-.62-.82-.69c-.19-.36-.29-.77-.29-1.25M16 9H2v2h7.22c.14.05.3.1.41.15.28.12.5.26.65.38.16.13.26.27.32.42.06.15.08.33.08.51 0 .18-.03.34-.1.49a1.02 1.02 0 0 1-.31.39 1.6 1.6 0 0 1-.53.26 2.71 2.71 0 0 1-.76.09c-.33 0-.62-.03-.89-.1a1.8 1.8 0 0 1-.68-.31 1.45 1.45 0 0 1-.44-.56c-.11-.23-.19-.57-.19-.74H4.55c0 .25.06.69.18 1.02a3.15 3.15 0 0 0 1.22 1.6c.28.2.58.36.92.49.33.13.67.23 1.04.29.36.06.72.09 1.08.09.6 0 1.15-.07 1.64-.21a3.88 3.88 0 0 0 1.25-.59 2.69 2.69 0 0 0 .8-.95c.19-.38.28-.81.28-1.29 0-.45-.08-.86-.23-1.211a2.26 2.26 0 0 0-.13-.25L16 11V9"
1583
+ />
1584
+ </svg>
1585
+ </t>
1586
+ <t t-name="o-spreadsheet-Icon.TEXT_COLOR" owl="1">
1587
+ <svg class="o-icon">
1588
+ <path
1589
+ fill="currentColor"
1590
+ d="M10 1H8L3.5 13h2l1.12-3h4.75l1.12 3h2L10 1ZM7.38 8 9 3.67 10.62 8H7.38"
1591
+ />
1592
+ </svg>
1593
+ </t>
1594
+ <t t-name="o-spreadsheet-Icon.FILL_COLOR" owl="1">
1595
+ <svg class="o-icon">
1596
+ <path
1597
+ fill="currentColor"
1598
+ d="M14.5 8.87S13 10.49 13 11.49c0 .83.67 1.5 1.5 1.5s1.5-.67 1.5-1.5c0-.99-1.5-2.62-1.5-2.62m-1.79-2.08L5.91 0 4.85 1.06l1.59 1.59-4.15 4.14a.996.996 0 0 0 0 1.41l4.5 4.5c.2.2.45.3.71.3.26 0 .51-.1.71-.29l4.5-4.5c.39-.39.39-1.03 0-1.42M4.21 7 7.5 3.71 10.79 7H4.21"
1599
+ />
1600
+ </svg>
1601
+ </t>
1602
+ <t t-name="o-spreadsheet-Icon.MERGE_CELL" owl="1">
1603
+ <svg class="o-icon">
1604
+ <path
1605
+ fill="currentColor"
1606
+ d="M3 6H1V2h7v2H3v2m7-2V2h7v4h-2V4h-5m0 10h5v-2h2v4h-7v-2m-9-2h2v2h5v2H1v-4m0-4h4V6l3 3-3 3v-2H1V8m9 1 3-3v2h4v2h-4v2l-3-3"
1607
+ />
1608
+ </svg>
1609
+ </t>
1610
+ <t t-name="o-spreadsheet-Icon.ALIGN_LEFT" owl="1">
1611
+ <svg class="o-icon align-left">
1612
+ <path fill="currentColor" d="M2 16h10v-2H2v2M12 6H2v2h10V6M2 2v2h14V2H2m0 10h14v-2H2v2"/>
1613
+ </svg>
1614
+ </t>
1615
+ <t t-name="o-spreadsheet-Icon.ALIGN_CENTER" owl="1">
1616
+ <svg class="o-icon align-center">
1617
+ <path fill="currentColor" d="M4 14v2h10v-2H4m0-8v2h10V6H4m-2 6h14v-2H2v2M2 2v2h14V2H2"/>
1618
+ </svg>
1619
+ </t>
1620
+ <t t-name="o-spreadsheet-Icon.ALIGN_RIGHT" owl="1">
1621
+ <svg class="o-icon align-right">
1622
+ <path fill="currentColor" d="M6 16h10v-2H6v2m-4-4h14v-2H2v2M2 2v2h14V2H2m4 6h10V6H6v2"/>
1623
+ </svg>
1624
+ </t>
1625
+ <t t-name="o-spreadsheet-Icon.ALIGN_TOP" owl="1">
1626
+ <svg class="o-icon align-top">
1627
+ <path d="M3 2h12v2H3m2.5 5H8v7h2V9h2.5L9 5.5" fill="currentColor"/>
1628
+ </svg>
1629
+ </t>
1630
+ <t t-name="o-spreadsheet-Icon.ALIGN_MIDDLE" owl="1">
1631
+ <svg class="o-icon align-middle">
1632
+ <path
1633
+ d="M12.5 3H10V0H8v3H5.5L9 6.5M5.5 15H8v3h2v-3h2.5L9 11.5M3 8v2h12V8"
1634
+ fill="currentColor"
1635
+ />
1636
+ </svg>
1637
+ </t>
1638
+ <t t-name="o-spreadsheet-Icon.ALIGN_BOTTOM" owl="1">
1639
+ <svg class="o-icon align-bottom">
1640
+ <path d="M5.5 9H8V2h2v7h2.5L9 12.5M3 14v2h12v-2" fill="currentColor"/>
1641
+ </svg>
1642
+ </t>
1643
+ <t t-name="o-spreadsheet-Icon.WRAPPING_OVERFLOW" owl="1">
1644
+ <svg class="o-icon wrapping-overflow">
1645
+ <path d="M13 8H6v2h7v2l3-3-3-3M2 2h2v14H2M9 2h2v4H9m0 6h2v4H9" fill="currentColor"/>
1646
+ </svg>
1647
+ </t>
1648
+ <t t-name="o-spreadsheet-Icon.WRAPPING_WRAP" owl="1">
1649
+ <svg class="o-icon wrapping-wrap">
1650
+ <path
1651
+ fill="currentColor"
1652
+ d="M6 5v2h3.75c.75 0 1.5.67 1.5 1.5 0 .75-.75 1.5-1.5 1.5H8V8l-3 3 3 3v-2h1.5c2 0 3.5-1.5 3.5-3.5S11.5 5 9.5 5M2 2h2v14H2M14 2M14,2,h2v14h-2"
1653
+ />
1654
+ </svg>
1655
+ </t>
1656
+ <t t-name="o-spreadsheet-Icon.WRAPPING_CLIP" owl="1">
1657
+ <svg class="o-icon wrapping-clip">
1658
+ <path fill="currentColor" d="M2 2h2v14H2M14 2h2v14h-2v-6H6V8h8"/>
1659
+ </svg>
1660
+ </t>
1661
+ <t t-name="o-spreadsheet-Icon.BORDERS" owl="1">
1662
+ <svg class="o-icon">
1663
+ <path
1664
+ fill="currentColor"
1665
+ d="M2 2v14h14V2H2m6 12H4v-4h4v4m0-6H4V4h4v4m6 6h-4v-4h4v4m0-6h-4V4h4v4"
1666
+ />
1667
+ </svg>
1668
+ </t>
1669
+ <t t-name="o-spreadsheet-Icon.BORDER_HV" owl="1">
1670
+ <svg class="o-icon" fill="currentColor">
1671
+ <path
1672
+ d="M2 16h2v-2H2v2M4 5H2v2h2V5m1 11h2v-2H5v2m8-14h-2v2h2V2M4 2H2v2h2V2m3 0H5v2h2V2M2 13h2v-2H2v2m9 3h2v-2h-2v2m3-14v2h2V2h-2m0 5h2V5h-2v2m0 9h2v-2h-2v2m0-3h2v-2h-2v2"
1673
+ opacity=".54"
1674
+ />
1675
+ <path d="M10 2H8v6H2v2h6v6h2v-6h6V8h-6"/>
1676
+ </svg>
1677
+ </t>
1678
+ <t t-name="o-spreadsheet-Icon.BORDER_H" owl="1">
1679
+ <svg class="o-icon" fill="currentColor">
1680
+ <path
1681
+ d="M8 16h2v-2H8v2M5 4h2V2H5v2m3 9h2v-2H8v2m-3 3h2v-2H5v2M2 7h2V5H2v2m0 9h2v-2H2v2M2 4h2V2H2v2m0 9h2v-2H2v2m12 0h2v-2h-2v2m0 3h2v-2h-2v2m0-9h2V5h-2v2m0-5v2h2V2h-2M8 4h2V2H8v2m3 0h2V2h-2v2M8 7h2V5H8v2m3 9h2v-2h-2v2"
1682
+ opacity=".54"
1683
+ />
1684
+ <path d="M2 10h14V8H2"/>
1685
+ </svg>
1686
+ </t>
1687
+ <t t-name="o-spreadsheet-Icon.BORDER_V" owl="1">
1688
+ <svg class="o-icon" fill="currentColor">
1689
+ <path
1690
+ d="M5 16h2v-2H5v2M2 7h2V5H2v2m0-3h2V2H2v2m3 6h2V8H5v2m0-6h2V2H5v2M2 16h2v-2H2v2m0-6h2V8H2v2m0 3h2v-2H2v2M14 2v2h2V2h-2m0 8h2V8h-2v2m0 6h2v-2h-2v2m0-9h2V5h-2v2m0 6h2v-2h-2v2m-3 3h2v-2h-2v2m0-6h2V8h-2v2m0-6h2V2h-2v2"
1691
+ opacity=".54"
1692
+ />
1693
+ <path d="M8 16h2V2H8"/>
1694
+ </svg>
1695
+ </t>
1696
+ <t t-name="o-spreadsheet-Icon.BORDER_EXTERNAL" owl="1">
1697
+ <svg class="o-icon" fill="currentColor">
1698
+ <path d="M10 5H8v2h2V5m3 3h-2v2h2V8m-3 0H8v2h2V8m0 3H8v2h2v-2M7 8H5v2h2V8" opacity=".54"/>
1699
+ <path d="M2 2h14v14H2V2m12 12V4H4v10h10"/>
1700
+ </svg>
1701
+ </t>
1702
+ <t t-name="o-spreadsheet-Icon.BORDER_LEFT" owl="1">
1703
+ <svg class="o-icon" fill="currentColor">
1704
+ <path
1705
+ d="M8 10h2V8H8v2m0-3h2V5H8v2m0 6h2v-2H8v2m0 3h2v-2H8v2m-3 0h2v-2H5v2M5 4h2V2H5v2m0 6h2V8H5v2m9 6h2v-2h-2v2m0-6h2V8h-2v2m0 3h2v-2h-2v2m0-6h2V5h-2v2M8 4h2V2H8v2m6-2v2h2V2h-2m-3 14h2v-2h-2v2m0-6h2V8h-2v2m0-6h2V2h-2v2"
1706
+ opacity=".54"
1707
+ />
1708
+ <path d="M2 16h2V2H2"/>
1709
+ </svg>
1710
+ </t>
1711
+ <t t-name="o-spreadsheet-Icon.BORDER_TOP" owl="1">
1712
+ <svg class="o-icon" fill="currentColor">
1713
+ <path
1714
+ d="M5 10h2V8H5v2m-3 6h2v-2H2v2m6 0h2v-2H8v2m0-3h2v-2H8v2m-3 3h2v-2H5v2m-3-3h2v-2H2v2m6-3h2V8H8v2M2 7h2V5H2v2m0 3h2V8H2v2m12 0h2V8h-2v2m0 3h2v-2h-2v2m0-6h2V5h-2v2M8 7h2V5H8v2m3 9h2v-2h-2v2m0-6h2V8h-2v2m3 6h2v-2h-2v2"
1715
+ opacity=".54"
1716
+ />
1717
+ <path d="M2 2v2h14V2"/>
1718
+ </svg>
1719
+ </t>
1720
+ <t t-name="o-spreadsheet-Icon.BORDER_RIGHT" owl="1">
1721
+ <svg class="o-icon" fill="currentColor">
1722
+ <path
1723
+ d="M2 4h2V2H2v2m3 0h2V2H5v2m0 6h2V8H5v2m0 6h2v-2H5v2M2 7h2V5H2v2m0 3h2V8H2v2m0 6h2v-2H2v2m0-3h2v-2H2v2m9-3h2V8h-2v2m-3 6h2v-2H8v2m3 0h2v-2h-2v2M8 4h2V2H8v2m3 0h2V2h-2v2m-3 9h2v-2H8v2m0-6h2V5H8v2m0 3h2V8H8v2"
1724
+ opacity=".54"
1725
+ />
1726
+ <path d="M14 2v14h2V2"/>
1727
+ </svg>
1728
+ </t>
1729
+ <t t-name="o-spreadsheet-Icon.BORDER_BOTTOM" owl="1">
1730
+ <svg class="o-icon" fill="currentColor">
1731
+ <path
1732
+ d="M7 2H5v2h2V2m3 6H8v2h2V8m0 3H8v2h2v-2m3-3h-2v2h2V8M7 8H5v2h2V8m6-6h-2v2h2V2m-3 3H8v2h2V5m0-3H8v2h2V2m-6 9H2v2h2v-2m10 2h2v-2h-2v2m0-6h2V5h-2v2m0 3h2V8h-2v2m0-8v2h2V2h-2M4 2H2v2h2V2m0 3H2v2h2V5m0 3H2v2h2V8"
1733
+ opacity=".54"
1734
+ />
1735
+ <path d="M2 16h14v-2H2"/>
1736
+ </svg>
1737
+ </t>
1738
+ <t t-name="o-spreadsheet-Icon.BORDER_CLEAR" owl="1">
1739
+ <svg class="o-icon">
1740
+ <path
1741
+ fill="currentColor"
1742
+ d="M8 16h2v-2H8v2m-3-6h2V8H5v2m0-6h2V2H5v2m3 9h2v-2H8v2m-3 3h2v-2H5v2M2 7h2V5H2v2m0 9h2v-2H2v2M2 4h2V2H2v2m0 6h2V8H2v2m6 0h2V8H8v2m-6 3h2v-2H2v2m12 0h2v-2h-2v2m0 3h2v-2h-2v2m0-6h2V8h-2v2m0-3h2V5h-2v2m0-5v2h2V2h-2M8 4h2V2H8v2m3 0h2V2h-2v2M8 7h2V5H8v2m3 9h2v-2h-2v2m0-6h2V8h-2v2"
1743
+ opacity=".54"
1744
+ />
1745
+ </svg>
1746
+ </t>
1747
+ <t t-name="o-spreadsheet-Icon.BORDER_TYPE" owl="1">
1748
+ <svg class="o-icon">
1749
+ <g fill="currentColor" transform="translate(2 2)">
1750
+ <polygon points="0 0 0 2 14 2 14 0"/>
1751
+ <polygon points="0 6 0 8 5 8 5 6"/>
1752
+ <polygon points="9 6 9 8 14 8 14 6"/>
1753
+ <polygon points="0 12 0 14 2 14 2 12"/>
1754
+ <polygon points="4 12 4 14 6 14 6 12"/>
1755
+ <polygon points="8 12 8 14 10 14 10 12"/>
1756
+ <polygon points="12 12 12 14 14 14 14 12"/>
1757
+ </g>
1758
+ </svg>
1759
+ </t>
1760
+ <t t-name="o-spreadsheet-Icon.BORDER_COLOR" owl="1">
1761
+ <svg class="o-icon">
1762
+ <g fill="currentColor" transform="translate(4 2)">
1763
+ <polygon points="0 12 0 9 7 2 10 5 3 12"/>
1764
+ <polygon points="8 1 9 0 12 3 11 4"/>
1765
+ </g>
1766
+ </svg>
1767
+ </t>
1768
+ <t t-name="o-spreadsheet-Icon.BORDER_NO_COLOR" owl="1">
1769
+ <svg class="o-icon">
1770
+ <g fill="currentColor">
1771
+ <polygon points="4 12 4 9 11 2 14 5 7 12"/>
1772
+ <polygon points="12 1 13 0 16 3 15 4"/>
1773
+ </g>
1774
+ <g>
1775
+ <rect x="0" y="14" width="18" height="4" stroke="black" fill="none"/>
1776
+ </g>
1777
+ </svg>
1778
+ </t>
1779
+
1780
+ <t t-name="o-spreadsheet-Icon.PLUS" owl="1">
1781
+ <svg class="o-icon" viewBox="0 0 18 18">
1782
+ <path fill="currentColor" d="M8 0h2v8h8v2h-8v8H8v-8H0V8h8"/>
1783
+ </svg>
1784
+ </t>
1785
+ <t t-name="o-spreadsheet-Icon.LIST" owl="1">
1786
+ <svg class="o-icon" viewBox="0 0 384 384">
1787
+ <rect x="0" y="277.333" width="384" height="42.667" fill="currentColor"/>
1788
+ <rect x="0" y="170.667" width="384" height="42.667" fill="currentColor"/>
1789
+ <rect x="0" y="64" width="384" height="42.667" fill="currentColor"/>
1790
+ </svg>
1791
+ </t>
1792
+
1793
+ <t t-name="o-spreadsheet-Icon.EDIT" owl="1">
1794
+ <svg class="o-icon" viewBox="0 0 576 512">
1795
+ <path
1796
+ fill="currentColor"
1797
+ d="M402.6 83.2l90.2 90.2c3.8 3.8 3.8 10 0 13.8L274.4 405.6l-92.8 10.3c-12.4 1.4-22.9-9.1-21.5-21.5l10.3-92.8L388.8 83.2c3.8-3.8 10-3.8 13.8 0zm162-22.9l-48.8-48.8c-15.2-15.2-39.9-15.2-55.2 0l-35.4 35.4c-3.8 3.8-3.8 10 0 13.8l90.2 90.2c3.8 3.8 10 3.8 13.8 0l35.4-35.4c15.2-15.3 15.2-40 0-55.2zM384 346.2V448H64V128h229.8c3.2 0 6.2-1.3 8.5-3.5l40-40c7.6-7.6 2.2-20.5-8.5-20.5H48C21.5 64 0 85.5 0 112v352c0 26.5 21.5 48 48 48h352c26.5 0 48-21.5 48-48V306.2c0-10.7-12.9-16-20.5-8.5l-40 40c-2.2 2.3-3.5 5.3-3.5 8.5z"
1798
+ />
1799
+ </svg>
1800
+ </t>
1801
+ <t t-name="o-spreadsheet-Icon.UNLINK" owl="1">
1802
+ <svg class="o-icon" viewBox="0 0 512 512">
1803
+ <path
1804
+ fill="currentColor"
1805
+ d="M304.083 405.907c4.686 4.686 4.686 12.284 0 16.971l-44.674 44.674c-59.263 59.262-155.693 59.266-214.961 0-59.264-59.265-59.264-155.696 0-214.96l44.675-44.675c4.686-4.686 12.284-4.686 16.971 0l39.598 39.598c4.686 4.686 4.686 12.284 0 16.971l-44.675 44.674c-28.072 28.073-28.072 73.75 0 101.823 28.072 28.072 73.75 28.073 101.824 0l44.674-44.674c4.686-4.686 12.284-4.686 16.971 0l39.597 39.598zm-56.568-260.216c4.686 4.686 12.284 4.686 16.971 0l44.674-44.674c28.072-28.075 73.75-28.073 101.824 0 28.072 28.073 28.072 73.75 0 101.823l-44.675 44.674c-4.686 4.686-4.686 12.284 0 16.971l39.598 39.598c4.686 4.686 12.284 4.686 16.971 0l44.675-44.675c59.265-59.265 59.265-155.695 0-214.96-59.266-59.264-155.695-59.264-214.961 0l-44.674 44.674c-4.686 4.686-4.686 12.284 0 16.971l39.597 39.598zm234.828 359.28l22.627-22.627c9.373-9.373 9.373-24.569 0-33.941L63.598 7.029c-9.373-9.373-24.569-9.373-33.941 0L7.029 29.657c-9.373 9.373-9.373 24.569 0 33.941l441.373 441.373c9.373 9.372 24.569 9.372 33.941 0z"
1806
+ />
1807
+ </svg>
1808
+ </t>
1809
+ /** Font Awesome by Dave Gandy
1810
+ * http://fontawesome.io/
1811
+ * https://fontawesome.com/license
1812
+ */
1813
+ <t t-name="o-spreadsheet-Icon.CARET_UP" owl="1">
1814
+ <svg class="caret-up" viewBox="0 0 320 512">
1815
+ <path
1816
+ fill="currentColor"
1817
+ d="M288.662 352H31.338c-17.818 0-26.741-21.543-14.142-34.142l128.662-128.662c7.81-7.81 20.474-7.81 28.284 0l128.662 128.662c12.6 12.599 3.676 34.142-14.142 34.142z"
1818
+ />
1819
+ </svg>
1820
+ </t>
1821
+ <t t-name="o-spreadsheet-Icon.CARET_DOWN" owl="1">
1822
+ <svg class="caret-down" viewBox="0 0 320 512">
1823
+ <path
1824
+ fill="currentColor"
1825
+ d="M31.3 192h257.3c17.8 0 26.7 21.5 14.1 34.1L174.1 354.8c-7.8 7.8-20.5 7.8-28.3 0L17.2 226.1C4.6 213.5 13.5 192 31.3 192z"
1826
+ />
1827
+ </svg>
1828
+ </t>
1829
+ <t t-name="o-spreadsheet-Icon.CARET_RIGHT" owl="1">
1830
+ <svg class="o-icon caret-right" viewBox="0 0 192 512">
1831
+ <path
1832
+ d="M0 384.662V127.338c0-17.818 21.543-26.741 34.142-14.142l128.662 128.662c7.81 7.81 7.81 20.474 0 28.284L34.142 398.804C21.543 411.404 0 402.48 0 384.662z"
1833
+ />
1834
+ </svg>
1835
+ </t>
1836
+ <t t-name="o-spreadsheet-Icon.CARET_LEFT" owl="1">
1837
+ <svg class="o-icon caret-left" viewBox="0 0 192 512">
1838
+ <path
1839
+ d="M192 127.338v257.324c0 17.818-21.543 26.741-34.142 14.142L29.196 270.142c-7.81-7.81-7.81-20.474 0-28.284l128.662-128.662c12.599-12.6 34.142-3.676 34.142 14.142z"
1840
+ />
1841
+ </svg>
1842
+ </t>
1843
+
1844
+ <t t-name="o-spreadsheet-Icon.TRASH" owl="1">
1845
+ <svg class="o-cf-icon trash" viewBox="0 0 448 512">
1846
+ <path
1847
+ fill="currentColor"
1848
+ d="M432 32H312l-9.4-18.7A24 24 0 0 0 281.1 0H166.8a23.72 23.72 0 0 0-21.4 13.3L136 32H16A16 16 0 0 0 0 48v32a16 16 0 0 0 16 16h416a16 16 0 0 0 16-16V48a16 16 0 0 0-16-16zM53.2 467a48 48 0 0 0 47.9 45h245.8a48 48 0 0 0 47.9-45L416 128H32z"
1849
+ />
1850
+ </svg>
1851
+ </t>
1852
+ <t t-name="o-spreadsheet-Icon.REFRESH" owl="1">
1853
+ <svg class="o-cf-icon refresh" viewBox="0 0 512 512">
1854
+ <path
1855
+ fill="currentColor"
1856
+ d="M440.65 12.57l4 82.77A247.16 247.16 0 0 0 255.83 8C134.73 8 33.91 94.92 12.29 209.82A12 12 0 0 0 24.09 224h49.05a12 12 0 0 0 11.67-9.26 175.91 175.91 0 0 1 317-56.94l-101.46-4.86a12 12 0 0 0-12.57 12v47.41a12 12 0 0 0 12 12H500a12 12 0 0 0 12-12V12a12 12 0 0 0-12-12h-47.37a12 12 0 0 0-11.98 12.57zM255.83 432a175.61 175.61 0 0 1-146-77.8l101.8 4.87a12 12 0 0 0 12.57-12v-47.4a12 12 0 0 0-12-12H12a12 12 0 0 0-12 12V500a12 12 0 0 0 12 12h47.35a12 12 0 0 0 12-12.6l-4.15-82.57A247.17 247.17 0 0 0 255.83 504c121.11 0 221.93-86.92 243.55-201.82a12 12 0 0 0-11.8-14.18h-49.05a12 12 0 0 0-11.67 9.26A175.86 175.86 0 0 1 255.83 432z"
1857
+ />
1858
+ </svg>
1859
+ </t>
1860
+
1861
+ <t t-name="o-spreadsheet-Icon.ARROW_DOWN" owl="1">
1862
+ <svg
1863
+ class="o-cf-icon arrow-down"
1864
+ width="10"
1865
+ height="10"
1866
+ focusable="false"
1867
+ viewBox="0 0 448 512">
1868
+ <path
1869
+ fill="#DC6965"
1870
+ t-att-style="color"
1871
+ d="M413.1 222.5l22.2 22.2c9.4 9.4 9.4 24.6 0 33.9L241 473c-9.4 9.4-24.6 9.4-33.9 0L12.7 278.6c-9.4-9.4-9.4-24.6 0-33.9l22.2-22.2c9.5-9.5 25-9.3 34.3.4L184 343.4V56c0-13.3 10.7-24 24-24h32c13.3 0 24 10.7 24 24v287.4l114.8-120.5c9.3-9.8 24.8-10 34.3-.4z"
1872
+ />
1873
+ </svg>
1874
+ </t>
1875
+ <t t-name="o-spreadsheet-Icon.ARROW_UP" owl="1">
1876
+ <svg class="o-cf-icon arrow-up" width="10" height="10" focusable="false" viewBox="0 0 448 512">
1877
+ <path
1878
+ fill="#00A04A"
1879
+ t-att-style="color"
1880
+ d="M34.9 289.5l-22.2-22.2c-9.4-9.4-9.4-24.6 0-33.9L207 39c9.4-9.4 24.6-9.4 33.9 0l194.3 194.3c9.4 9.4 9.4 24.6 0 33.9L413 289.4c-9.5 9.5-25 9.3-34.3-.4L264 168.6V456c0 13.3-10.7 24-24 24h-32c-13.3 0-24-10.7-24-24V168.6L69.2 289.1c-9.3 9.8-24.8 10-34.3.4z"
1881
+ />
1882
+ </svg>
1883
+ </t>
1884
+ <t t-name="o-spreadsheet-Icon.ARROW_RIGHT" owl="1">
1885
+ <svg
1886
+ class="o-cf-icon arrow-right"
1887
+ width="10"
1888
+ height="10"
1889
+ focusable="false"
1890
+ viewBox="0 0 448 512">
1891
+ <path
1892
+ fill="#F0AD4E"
1893
+ d="M190.5 66.9l22.2-22.2c9.4-9.4 24.6-9.4 33.9 0L441 239c9.4 9.4 9.4 24.6 0 33.9L246.6 467.3c-9.4 9.4-24.6 9.4-33.9 0l-22.2-22.2c-9.5-9.5-9.3-25 .4-34.3L311.4 296H24c-13.3 0-24-10.7-24-24v-32c0-13.3 10.7-24 24-24h287.4L190.9 101.2c-9.8-9.3-10-24.8-.4-34.3z"
1894
+ />
1895
+ </svg>
1896
+ </t>
1897
+
1898
+ <t t-name="o-spreadsheet-Icon.SMILE" owl="1">
1899
+ <svg class="o-cf-icon smile" width="10" height="10" focusable="false" viewBox="0 0 496 512">
1900
+ <path
1901
+ fill="#00A04A"
1902
+ d="M248 8C111 8 0 119 0 256s111 248 248 248 248-111 248-248S385 8 248 8zm0 448c-110.3 0-200-89.7-200-200S137.7 56 248 56s200 89.7 200 200-89.7 200-200 200zm-80-216c17.7 0 32-14.3 32-32s-14.3-32-32-32-32 14.3-32 32 14.3 32 32 32zm160 0c17.7 0 32-14.3 32-32s-14.3-32-32-32-32 14.3-32 32 14.3 32 32 32zm4 72.6c-20.8 25-51.5 39.4-84 39.4s-63.2-14.3-84-39.4c-8.5-10.2-23.7-11.5-33.8-3.1-10.2 8.5-11.5 23.6-3.1 33.8 30 36 74.1 56.6 120.9 56.6s90.9-20.6 120.9-56.6c8.5-10.2 7.1-25.3-3.1-33.8-10.1-8.4-25.3-7.1-33.8 3.1z"
1903
+ />
1904
+ </svg>
1905
+ </t>
1906
+ <t t-name="o-spreadsheet-Icon.MEH" owl="1">
1907
+ <svg class="o-cf-icon meh" width="10" height="10" focusable="false" viewBox="0 0 496 512">
1908
+ <path
1909
+ fill="#F0AD4E"
1910
+ d="M248 8C111 8 0 119 0 256s111 248 248 248 248-111 248-248S385 8 248 8zm0 448c-110.3 0-200-89.7-200-200S137.7 56 248 56s200 89.7 200 200-89.7 200-200 200zm-80-216c17.7 0 32-14.3 32-32s-14.3-32-32-32-32 14.3-32 32 14.3 32 32 32zm160-64c-17.7 0-32 14.3-32 32s14.3 32 32 32 32-14.3 32-32-14.3-32-32-32zm8 144H160c-13.2 0-24 10.8-24 24s10.8 24 24 24h176c13.2 0 24-10.8 24-24s-10.8-24-24-24z"
1911
+ />
1912
+ </svg>
1913
+ </t>
1914
+ <t t-name="o-spreadsheet-Icon.FROWN" owl="1">
1915
+ <svg class="o-cf-icon frown" width="10" height="10" focusable="false" viewBox="0 0 496 512">
1916
+ <path
1917
+ fill="#DC6965"
1918
+ d="M248 8C111 8 0 119 0 256s111 248 248 248 248-111 248-248S385 8 248 8zm0 448c-110.3 0-200-89.7-200-200S137.7 56 248 56s200 89.7 200 200-89.7 200-200 200zm-80-216c17.7 0 32-14.3 32-32s-14.3-32-32-32-32 14.3-32 32 14.3 32 32 32zm160-64c-17.7 0-32 14.3-32 32s14.3 32 32 32 32-14.3 32-32-14.3-32-32-32zm-80 128c-40.2 0-78 17.7-103.8 48.6-8.5 10.2-7.1 25.3 3.1 33.8 10.2 8.4 25.3 7.1 33.8-3.1 16.6-19.9 41-31.4 66.9-31.4s50.3 11.4 66.9 31.4c8.1 9.7 23.1 11.9 33.8 3.1 10.2-8.5 11.5-23.6 3.1-33.8C326 321.7 288.2 304 248 304z"
1919
+ />
1920
+ </svg>
1921
+ </t>
1922
+
1923
+ <t t-name="o-spreadsheet-Icon.GREEN_DOT" owl="1">
1924
+ <svg class="o-cf-icon green-dot" width="10" height="10" focusable="false" viewBox="0 0 512 512">
1925
+ <path
1926
+ fill="#00A04A"
1927
+ d="M256 8C119 8 8 119 8 256s111 248 248 248 248-111 248-248S393 8 256 8z"
1928
+ />
1929
+ </svg>
1930
+ </t>
1931
+ <t t-name="o-spreadsheet-Icon.YELLOW_DOT" owl="1">
1932
+ <svg
1933
+ class="o-cf-icon yellow-dot"
1934
+ width="10"
1935
+ height="10"
1936
+ focusable="false"
1937
+ viewBox="0 0 512 512">
1938
+ <path
1939
+ fill="#F0AD4E"
1940
+ d="M256 8C119 8 8 119 8 256s111 248 248 248 248-111 248-248S393 8 256 8z"
1941
+ />
1942
+ </svg>
1943
+ </t>
1944
+ <t t-name="o-spreadsheet-Icon.RED_DOT" owl="1">
1945
+ <svg class="o-cf-icon red-dot" width="10" height="10" focusable="false" viewBox="0 0 512 512">
1946
+ <path
1947
+ fill="#DC6965"
1948
+ d="M256 8C119 8 8 119 8 256s111 248 248 248 248-111 248-248S393 8 256 8z"
1949
+ />
1950
+ </svg>
1951
+ </t>
1952
+ <t t-name="o-spreadsheet-Icon.SORT_RANGE" owl="1">
1953
+ <svg class="o-icon">
1954
+ <path
1955
+ fill="currentColor"
1956
+ d="M9 3.5h8v2H9M9 8h6v2H9m0 2.5h3v2H9M6 6l1-1-3-3-3 3 1 1 1-1v8l-1-1-1 1 3 3 3-3-1-1-1 1V5"
1957
+ />
1958
+ </svg>
1959
+ </t>
1960
+ <t t-name="o-spreadsheet-Icon.SORT_ASCENDING" owl="1">
1961
+ <svg class="o-icon" fill="currentColor">
1962
+ <path d="m3 13-1-1-1 1 3 3 3-3-1-1-1 1V0H3"/>
1963
+ <text x="9" y="7" class="small-text">A</text>
1964
+ <text x="9.3" y="15" class="small-text">Z</text>
1965
+ </svg>
1966
+ </t>
1967
+ <t t-name="o-spreadsheet-Icon.SORT_DESCENDING" owl="1">
1968
+ <svg class="o-icon" fill="currentColor">
1969
+ <path d="m3 13.9-1-1-1 1 3 3 3-3-1-1-1 1V.9H3"/>
1970
+ <text x="9.3" y="7.9" class="small-text">Z</text>
1971
+ <text x="9" y="15.9" class="small-text">A</text>
1972
+ </svg>
1973
+ </t>
1974
+ <t t-name="o-spreadsheet-Icon.FILTER_ICON" owl="1">
1975
+ <svg
1976
+ class="o-cf-icon filter-icon"
1977
+ width="10"
1978
+ height="10"
1979
+ focusable="false"
1980
+ viewBox="0 0 850 850">
1981
+ <path
1982
+ fill="currentColor"
1983
+ d="M 339.667 681 L 510.333 681 L 510.333 595.667 L 339.667 595.667 L 339.667 681 Z M 41 169 L 41 254.333 L 809 254.333 L 809 169 L 41 169 Z M 169 467.667 L 681 467.667 L 681 382.333 L 169 382.333 L 169 467.667 Z"
1984
+ />
1985
+ </svg>
1986
+ </t>
1987
+ <t t-name="o-spreadsheet-Icon.FILTER_ICON_ACTIVE" owl="1">
1988
+ <svg
1989
+ class="o-cf-icon filter-icon-active"
1990
+ width="10"
1991
+ height="10"
1992
+ focusable="false"
1993
+ viewBox="0 0 512 512">
1994
+ <path
1995
+ fill="currentColor"
1996
+ d="M487.976 0H24.028C2.71 0-8.047 25.866 7.058 40.971L192 225.941V432c0 7.831 3.821 15.17 10.237 19.662l80 55.98C298.02 518.69 320 507.493 320 487.98V225.941l184.947-184.97C520.021 25.896 509.338 0 487.976 0z"
1997
+ />
1998
+ </svg>
1999
+ </t>
2000
+ <t t-name="o-spreadsheet-Icon.FILTER_ICON_INACTIVE" owl="1">
2001
+ <svg
2002
+ class="o-cf-icon filter-icon-inactive"
2003
+ width="10"
2004
+ height="10"
2005
+ focusable="false"
2006
+ viewBox="0 0 512 512">
2007
+ <path
2008
+ fill="currentColor"
2009
+ d="M487.976 0H24.028C2.71 0-8.047 25.866 7.058 40.971L192 225.941V432c0 7.831 3.821 15.17 10.237 19.662l80 55.98C298.02 518.69 320 507.493 320 487.98V225.941l184.947-184.97C520.021 25.896 509.338 0 487.976 0z"
2010
+ />
2011
+ </svg>
2012
+ </t>
2013
+ <t t-name="o-spreadsheet-Icon.MENU_FILTER_ICON" owl="1">
2014
+ <svg class="o-icon">
2015
+ <path
2016
+ fill="currentColor"
2017
+ d="M16.6.5H1.29C.59.5.23 1.35.73 1.85l6.1 6.1v6.8c0 .26.13.5.34.65l2.64 1.85a.79.79 0 0 0 1.25-.65V7.96l6.1-6.1A.79.79 0 0 0 16.6.51"
2018
+ />
2019
+ </svg>
2020
+ </t>
2021
+ <t t-name="o-spreadsheet-Icon.SEARCH" owl="1">
2022
+ <svg class="search-icon" width="10" height="10" focusable="false" viewBox="0 0 512 512">
2023
+ <path
2024
+ fill="currentColor"
2025
+ d="M500.3 443.7l-119.7-119.7c27.22-40.41 40.65-90.9 33.46-144.7C401.8 87.79 326.8 13.32 235.2 1.723C99.01-15.51-15.51 99.01 1.724 235.2c11.6 91.64 86.08 166.7 177.6 178.9c53.8 7.189 104.3-6.236 144.7-33.46l119.7 119.7c15.62 15.62 40.95 15.62 56.57 0C515.9 484.7 515.9 459.3 500.3 443.7zM79.1 208c0-70.58 57.42-128 128-128s128 57.42 128 128c0 70.58-57.42 128-128 128S79.1 278.6 79.1 208z"
2026
+ />
2027
+ </svg>
2028
+ </t>
2029
+ <t t-name="o-spreadsheet-Icon.CHECK" owl="1">
2030
+ <svg class="o-icon" viewBox="0 0 24 24">
2031
+ <path
2032
+ fill="currentColor"
2033
+ d="M18.707 7.293a1 1 0 0 1 0 1.414L11.414 16a2 2 0 0 1-2.828 0l-3.293-3.293a1 1 0 1 1 1.414-1.414L10 14.586l7.293-7.293a1 1 0 0 1 1.414 0z"
2034
+ />
2035
+ </svg>
2036
+ </t>
2037
+ <t t-name="o-spreadsheet-Icon.PERCENT" owl="1">
2038
+ <span class="o-text-icon">%</span>
2039
+ </t>
2040
+ <t t-name="o-spreadsheet-Icon.DECRASE_DECIMAL" owl="1">
2041
+ <span class="o-text-icon">.0</span>
2042
+ </t>
2043
+ <t t-name="o-spreadsheet-Icon.INCREASE_DECIMAL" owl="1">
2044
+ <span class="o-text-icon">.00</span>
2045
+ </t>
2046
+ <t t-name="o-spreadsheet-Icon.NUMBER_FORMATS" owl="1">
2047
+ <svg class="o-icon" fill="currentColor">
2048
+ <path
2049
+ d="M0 6h2v8h2V4H0m9 0H5v2h4v2H6.5A1.5 1.5 0 0 0 5 9.5V14h6v-2H7v-2h2.5A1.5 1.5 0 0 0 11 8.5v-3A1.5 1.5 0 0 0 9.5 4M12 4v2h4v2h-2v2h2v2h-4v2h4.5a1.5 1.5 0 0 0 1.5-1.5v-2A1.5 1.5 0 0 0 16.5 9 1.5 1.5 0 0 0 18 7.5v-2A1.5 1.5 0 0 0 16.5 4"
2050
+ />
2051
+ </svg>
2052
+ </t>
2053
+ <t t-name="o-spreadsheet-Icon.FONT_SIZE" owl="1">
2054
+ <svg class="o-icon" fill="currentColor">
2055
+ <text x="2" y="15" class="small-text">A</text>
2056
+ <text x="6" y="15" class="heavy-text">A</text>
2057
+ </svg>
2058
+ </t>
2059
+ <t t-name="o-spreadsheet-Icon.TRIANGLE_EXCLAMATION" owl="1">
2060
+ <svg class="o-icon" viewBox="0 0 512 512">
2061
+ <path
2062
+ fill="currentColor"
2063
+ d="M256 32c14.2 0 27.3 7.5 34.5 19.8l216 368c7.3 12.4 7.3 27.7 .2 40.1S486.3 480 472 480H40c-14.3 0-27.6-7.7-34.7-20.1s-7-27.8 .2-40.1l216-368C228.7 39.5 241.8 32 256 32zm0 128c-13.3 0-24 10.7-24 24V296c0 13.3 10.7 24 24 24s24-10.7 24-24V184c0-13.3-10.7-24-24-24zm32 224a32 32 0 1 0 -64 0 32 32 0 1 0 64 0z"
2064
+ />
2065
+ </svg>
2066
+ </t>
2067
+ <t t-name="o-spreadsheet-Icon.SPLIT_TEXT" owl="1">
2068
+ <svg class="o-icon">
2069
+ <path
2070
+ fill="currentColor"
2071
+ d="M14 6v2h-4v2h4v2l3-3m-9 1V8H4V6L1 9l3 3v-2m3.5-6.5h3V7H12V3.5h3V2H3v1.5h3V7h1.5m3 7.5h-3V11H6v3.5H3V16h12v-1.5h-3V11h-1.5"
2072
+ />
2073
+ </svg>
2074
+ </t>
2075
+ <t t-name="o-spreadsheet-Icon.ERROR" owl="1">
2076
+ <svg class="error-icon" width="14" height="14" viewBox="0 0 512 512">
2077
+ <path
2078
+ fill="currentColor"
2079
+ d="M504 256c0 136.997-111.043 248-248 248S8 392.997 8 256C8 119.083 119.043 8 256 8s248 111.083 248 248zm-248 50c-25.405 0-46 20.595-46 46s20.595 46 46 46 46-20.595 46-46-20.595-46-46-46zm-43.673-165.346l7.418 136c.347 6.364 5.609 11.346 11.982 11.346h48.546c6.373 0 11.635-4.982 11.982-11.346l7.418-136c.375-6.874-5.098-12.654-11.982-12.654h-63.383c-6.884 0-12.356 5.78-11.981 12.654z"
2080
+ />
2081
+ </svg>
2082
+ </t>
2083
+ <t t-name="o-spreadsheet-Icon.DISPLAY_HEADER" owl="1">
2084
+ <svg class="o-icon" width="18" height="18">
2085
+ <path
2086
+ fill="currentColor"
2087
+ d="M.75.5h16.5v17H.75m1.5-12H.75V7h1.5v1.5H.75V10h1.5v1.5H.75V13h1.5v1.5H.75V16h1.5v1.5h1.5V16h1.5v1.5h1.5V16h1.5v1.5h1.5V16h1.5v1.5h1.5V16h1.5v1.5h1.5V16h1.5v-1.5h-1.5V13h1.5v-1.5h-1.5V10h1.5V8.5h-1.5V7h1.5V5.5M2.75 2.25v1.5h2v-1.5m2.5 0v1.5h7v-1.5"
2088
+ />
2089
+ </svg>
2090
+ </t>
2091
+ <t t-name="o-spreadsheet-Icon.COG" owl="1">
2092
+ <svg fill="currentColor" viewBox="0 0 16 16">
2093
+ <path
2094
+ d="M8 4.754a3.246 3.246 0 1 0 0 6.492 3.246 3.246 0 0 0 0-6.492zM5.754 8a2.246 2.246 0 1 1 4.492 0 2.246 2.246 0 0 1-4.492 0z"
2095
+ />
2096
+ <path
2097
+ d="M9.796 1.343c-.527-1.79-3.065-1.79-3.592 0l-.094.319a.873.873 0 0 1-1.255.52l-.292-.16c-1.64-.892-3.433.902-2.54 2.541l.159.292a.873.873 0 0 1-.52 1.255l-.319.094c-1.79.527-1.79 3.065 0 3.592l.319.094a.873.873 0 0 1 .52 1.255l-.16.292c-.892 1.64.901 3.434 2.541 2.54l.292-.159a.873.873 0 0 1 1.255.52l.094.319c.527 1.79 3.065 1.79 3.592 0l.094-.319a.873.873 0 0 1 1.255-.52l.292.16c1.64.893 3.434-.902 2.54-2.541l-.159-.292a.873.873 0 0 1 .52-1.255l.319-.094c1.79-.527 1.79-3.065 0-3.592l-.319-.094a.873.873 0 0 1-.52-1.255l.16-.292c.893-1.64-.902-3.433-2.541-2.54l-.292.159a.873.873 0 0 1-1.255-.52l-.094-.319zm-2.633.283c.246-.835 1.428-.835 1.674 0l.094.319a1.873 1.873 0 0 0 2.693 1.115l.291-.16c.764-.415 1.6.42 1.184 1.185l-.159.292a1.873 1.873 0 0 0 1.116 2.692l.318.094c.835.246.835 1.428 0 1.674l-.319.094a1.873 1.873 0 0 0-1.115 2.693l.16.291c.415.764-.42 1.6-1.185 1.184l-.291-.159a1.873 1.873 0 0 0-2.693 1.116l-.094.318c-.246.835-1.428.835-1.674 0l-.094-.319a1.873 1.873 0 0 0-2.692-1.115l-.292.16c-.764.415-1.6-.42-1.184-1.185l.159-.291A1.873 1.873 0 0 0 1.945 8.93l-.319-.094c-.835-.246-.835-1.428 0-1.674l.319-.094A1.873 1.873 0 0 0 3.06 4.377l-.16-.292c-.415-.764.42-1.6 1.185-1.184l.292.159a1.873 1.873 0 0 0 2.692-1.115l.094-.319z"
2098
+ />
2099
+ </svg>
2100
+ </t>
2101
+
2102
+ <t t-name="o-spreadsheet-LinkDisplay" owl="1">
2103
+ <div class="o-link-tool d-flex align-items-center">
2104
+ <!-- t-key to prevent owl from re-using the previous img element when the link changes.
2105
+ The wrong/previous image would be displayed while the new one loads -->
2106
+ <img
2107
+ t-if="link.isExternal"
2108
+ t-key="link.url"
2109
+ t-attf-src="https://www.google.com/s2/favicons?sz=16&amp;domain={{link.url}}"
2110
+ />
2111
+ <a
2112
+ t-if="link.isExternal"
2113
+ class="o-link"
2114
+ t-att-href="link.url"
2115
+ target="_blank"
2116
+ t-on-click.prevent="openLink"
2117
+ t-att-title="link.url">
2118
+ <t t-esc="getUrlRepresentation(link)"/>
2119
+ </a>
2120
+ <a
2121
+ t-else=""
2122
+ class="o-link"
2123
+ t-on-click.prevent="openLink"
2124
+ t-att-title="getUrlRepresentation(link)">
2125
+ <t t-esc="getUrlRepresentation(link)"/>
2126
+ </a>
2127
+ <span
2128
+ t-if="!env.model.getters.isReadonly()"
2129
+ class="o-link-icon o-unlink"
2130
+ t-on-click="unlink"
2131
+ title="Remove link">
2132
+ <t t-call="o-spreadsheet-Icon.UNLINK"/>
2133
+ </span>
2134
+ <span
2135
+ t-if="!env.model.getters.isReadonly()"
2136
+ class="o-link-icon o-edit-link"
2137
+ t-on-click="edit"
2138
+ title="Edit link">
2139
+ <t t-call="o-spreadsheet-Icon.EDIT"/>
2140
+ </span>
2141
+ </div>
2142
+ </t>
2143
+
2144
+ <t t-name="o-spreadsheet-LinkEditor" owl="1">
2145
+ <div
2146
+ class="o-link-editor"
2147
+ t-on-click.stop="() => this.menu.isOpen=false"
2148
+ t-on-keydown="onKeyDown"
2149
+ t-ref="linkEditor">
2150
+ <div class="o-section">
2151
+ <div class="o-section-title">Text</div>
2152
+ <div class="d-flex">
2153
+ <input type="text" title="Link label" class="o-input flex-grow-1" t-model="link.label"/>
2154
+ </div>
2155
+
2156
+ <div class="o-section-title mt-3">Link</div>
2157
+ <div class="o-link-url">
2158
+ <t t-if="link.isUrlEditable">
2159
+ <input type="text" title="Link URL" t-ref="urlInput" t-model="link.url"/>
2160
+ </t>
2161
+ <t t-else="">
2162
+ <input
2163
+ type="text"
2164
+ title="Link URL"
2165
+ t-att-value="getUrlRepresentation(link)"
2166
+ disabled="1"
2167
+ />
2168
+ </t>
2169
+ <button t-if="link.url" t-on-click="removeLink" class="o-remove-url">✖</button>
2170
+ <button t-if="!link.url" t-on-click.stop="openMenu" class="o-special-link">
2171
+ <t t-call="o-spreadsheet-Icon.LIST"/>
2172
+ </button>
2173
+ </div>
2174
+ </div>
2175
+ <Menu
2176
+ t-if="menu.isOpen"
2177
+ position="menuPosition"
2178
+ menuItems="menuItems"
2179
+ onMenuClicked="(ev) => this.onSpecialLink(ev)"
2180
+ onClose="() => this.menu.isOpen=false"
2181
+ />
2182
+ <div class="o-buttons">
2183
+ <button t-on-click="cancel" class="o-button o-cancel">Cancel</button>
2184
+ <button t-on-click="save" class="o-button o-save" t-att-disabled="!link.url">
2185
+ Confirm
2186
+ </button>
2187
+ </div>
2188
+ </div>
2189
+ </t>
2190
+
2191
+ <t t-name="o-spreadsheet-Menu" owl="1">
2192
+ <Popover t-if="menuItemsAndSeparators.length" t-props="popoverProps">
2193
+ <div
2194
+ t-ref="menu"
2195
+ class="o-menu"
2196
+ t-on-scroll="onScroll"
2197
+ t-on-wheel.stop=""
2198
+ t-on-click.stop=""
2199
+ t-on-contextmenu.prevent="">
2200
+ <t t-foreach="menuItemsAndSeparators" t-as="menuItem" t-key="menuItem_index">
2201
+ <div t-if="menuItem === 'separator'" class="o-separator"/>
2202
+ <t t-else="">
2203
+ <t t-set="isMenuRoot" t-value="isRoot(menuItem)"/>
2204
+ <t t-set="isMenuEnabled" t-value="isEnabled(menuItem)"/>
2205
+ <div
2206
+ t-att-title="getName(menuItem)"
2207
+ t-att-data-name="menuItem.id"
2208
+ t-on-click="(ev) => this.onClickMenu(menuItem, menuItem_index, ev)"
2209
+ t-on-mouseover="(ev) => this.onMouseOver(menuItem, menuItem_index, ev)"
2210
+ class="o-menu-item"
2211
+ t-att-class="{ 'o-menu-root': isMenuRoot, 'disabled': !isMenuEnabled, 'o-menu-item-active': isParentMenu(subMenu, menuItem)}"
2212
+ t-att-style="getColor(menuItem)">
2213
+ <div class="d-flex w-100">
2214
+ <div t-if="childrenHaveIcon" class="o-menu-item-icon align-middle">
2215
+ <t t-if="getIconName(menuItem)" t-call="{{getIconName(menuItem)}}"/>
2216
+ </div>
2217
+ <div class="o-menu-item-name align-middle text-truncate" t-esc="getName(menuItem)"/>
2218
+ <t t-set="description" t-value="menuItem.description(env)"/>
2219
+ <div
2220
+ t-if="description"
2221
+ class="o-menu-item-description ms-auto"
2222
+ t-esc="description"
2223
+ />
2224
+ <div
2225
+ t-if="isMenuRoot"
2226
+ class="o-menu-item-root align-middle ms-auto"
2227
+ t-call="o-spreadsheet-Icon.TRIANGLE_RIGHT"
2228
+ />
2229
+ </div>
2230
+ </div>
2231
+ </t>
2232
+ </t>
2233
+ </div>
2234
+ <Menu
2235
+ t-if="subMenu.isOpen"
2236
+ position="subMenuPosition"
2237
+ menuItems="subMenu.menuItems"
2238
+ depth="props.depth + 1"
2239
+ maxHeight="props.maxHeight"
2240
+ onMenuClicked="props.onMenuClicked"
2241
+ onClose="() => this.close()"
2242
+ menuId="props.menuId"
2243
+ />
2244
+ </Popover>
2245
+ </t>
2246
+
2247
+ <t t-name="o-spreadsheet-PaintFormatButton" owl="1">
2248
+ <span
2249
+ class="o-menu-item-button"
2250
+ title="Paint Format"
2251
+ t-att-class="{active: isActive}"
2252
+ t-attf-class="{{props.class}}"
2253
+ t-on-click="togglePaintFormat"
2254
+ t-on-dblclick="onDblClick">
2255
+ <span>
2256
+ <t t-call="o-spreadsheet-Icon.PAINT_FORMAT"/>
2257
+ </span>
2258
+ </span>
2259
+ </t>
2260
+
2261
+ <t t-name="o-spreadsheet-Popover" owl="1">
2262
+ <t t-portal="'.o-spreadsheet'">
2263
+ <div
2264
+ class="o-popover"
2265
+ t-ref="popover"
2266
+ t-on-wheel="props.onMouseWheel"
2267
+ t-att-style="popoverStyle">
2268
+ <t t-slot="default"/>
2269
+ </div>
2270
+ </t>
2271
+ </t>
2272
+
2273
+ <t t-name="o-spreadsheet-ScrollBar" owl="1">
2274
+ <div class="o-scrollbar" t-on-scroll="onScroll" t-ref="scrollbar" t-att-style="positionCss">
2275
+ <div t-att-style="sizeCss"/>
2276
+ </div>
2277
+ </t>
2278
+
2279
+ <t t-name="o-spreadsheet-SelectionInput" owl="1">
2280
+ <div class="o-selection">
2281
+ <div
2282
+ t-foreach="ranges"
2283
+ t-as="range"
2284
+ t-key="range.id"
2285
+ class="o-selection-input d-flex flex-row"
2286
+ t-att-class="props.class">
2287
+ <div class="position-relative w-100">
2288
+ <input
2289
+ type="text"
2290
+ spellcheck="false"
2291
+ t-on-input="(ev) => this.onInputChanged(range.id, ev)"
2292
+ t-on-focus="() => this.focus(range.id)"
2293
+ t-on-keydown="onKeydown"
2294
+ t-att-value="range.xc"
2295
+ t-att-style="getColor(range)"
2296
+ class="w-100"
2297
+ t-att-class="{
2298
+ 'o-focused' : range.isFocused,
2299
+ 'o-required': props.required,
2300
+ 'o-optional': !props.required,
2301
+ 'o-invalid border-danger position-relative': isInvalid || !range.isValidRange,
2302
+ 'text-decoration-underline': range.isFocused and state.mode === 'select-range'
2303
+ }"
2304
+ t-ref="{{range.isFocused ? 'focusedInput' : 'unfocusedInput' + range_index}}"
2305
+ />
2306
+ <span
2307
+ t-if="isInvalid || !range.isValidRange"
2308
+ class="error-icon text-danger position-absolute d-flex align-items-center"
2309
+ title="This range is invalid">
2310
+ <t t-call="o-spreadsheet-Icon.ERROR"/>
2311
+ </span>
2312
+ </div>
2313
+ <button
2314
+ class="o-btn border-0 bg-transparent fw-bold o-remove-selection"
2315
+ t-if="ranges.length > 1"
2316
+ t-on-click="() => this.removeInput(range.id)">
2317
+ ✕
2318
+ </button>
2319
+ </div>
2320
+
2321
+ <div class="o-selection-input d-flex flex-row">
2322
+ <button
2323
+ class="o-btn-action bg-transparent fw-bold o-add-selection"
2324
+ t-if="canAddRange"
2325
+ t-on-click="addEmptyInput">
2326
+ Add range
2327
+ </button>
2328
+ <button
2329
+ class="o-btn-action bg-transparent fw-bold o-selection-ko"
2330
+ t-if="isResettable"
2331
+ t-on-click="reset">
2332
+ Reset
2333
+ </button>
2334
+ <button
2335
+ class="o-btn-action bg-transparent fw-bold o-selection-ok"
2336
+ t-if="isConfirmable"
2337
+ t-on-click="confirm">
2338
+ Confirm
2339
+ </button>
2340
+ </div>
2341
+ </div>
2342
+ </t>
2343
+
2344
+ <t t-name="o-spreadsheet-BarConfigPanel" owl="1">
2345
+ <div>
2346
+ <div class="o-section pt-0">
2347
+ <div class="o-checkbox">
2348
+ <label>
2349
+ <input
2350
+ type="checkbox"
2351
+ name="stacked"
2352
+ t-att-checked="props.definition.stacked"
2353
+ t-on-change="onUpdateStacked"
2354
+ class="align-middle"
2355
+ />
2356
+ Stacked barchart
2357
+ </label>
2358
+ </div>
2359
+ </div>
2360
+ <div class="o-section o-data-series">
2361
+ <div class="o-section-title">Data Series</div>
2362
+ <SelectionInput
2363
+ ranges="() => this.getDataSeriesRanges()"
2364
+ required="true"
2365
+ onSelectionChanged="(ranges) => this.onDataSeriesRangesChanged(ranges)"
2366
+ onSelectionConfirmed="() => this.onDataSeriesConfirmed()"
2367
+ />
2368
+ </div>
2369
+ <div class="o-section o-data-labels">
2370
+ <div class="o-section-title">Categories / Labels</div>
2371
+ <SelectionInput
2372
+ ranges="() => [this.getLabelRange()]"
2373
+ isInvalid="isLabelInvalid"
2374
+ hasSingleRange="true"
2375
+ onSelectionChanged="(ranges) => this.onLabelRangeChanged(ranges)"
2376
+ onSelectionConfirmed="() => this.onLabelRangeConfirmed()"
2377
+ />
2378
+ <label>
2379
+ <input
2380
+ type="checkbox"
2381
+ name="aggregated"
2382
+ t-att-checked="props.definition.aggregated"
2383
+ t-on-change="onUpdateAggregated"
2384
+ class="align-middle"
2385
+ />
2386
+ Aggregate
2387
+ </label>
2388
+ </div>
2389
+ <div class="o-section o-use-row-as-headers" t-if="calculateHeaderPosition()">
2390
+ <label>
2391
+ <input
2392
+ type="checkbox"
2393
+ t-att-checked="props.definition.dataSetsHaveTitle"
2394
+ t-on-change="onUpdateDataSetsHaveTitle"
2395
+ class="align-middle"
2396
+ />
2397
+ Use row
2398
+ <span t-esc="calculateHeaderPosition()"/>
2399
+ as headers
2400
+ </label>
2401
+ </div>
2402
+
2403
+ <div class="o-section" t-if="errorMessages.length">
2404
+ <SidePanelErrors messages="errorMessages" msgType="'error'"/>
2405
+ </div>
2406
+ </div>
2407
+ </t>
2408
+
2409
+ <t t-name="o-spreadsheet-BarChartDesignPanel" owl="1">
2410
+ <div>
2411
+ <div class="o-section o-chart-background-color">
2412
+ <div class="o-section-title">Background color</div>
2413
+ <div class="d-flex align-items-center">
2414
+ <span class="pe-1">Select a color...</span>
2415
+ <ColorPickerWidget
2416
+ currentColor="props.definition.background"
2417
+ toggleColorPicker="() => this.toggleColorPicker()"
2418
+ showColorPicker="state.fillColorTool"
2419
+ onColorPicked="(color) => this.updateBackgroundColor(color)"
2420
+ title="env._t('Background Color')"
2421
+ icon="'o-spreadsheet-Icon.FILL_COLOR'"
2422
+ />
2423
+ </div>
2424
+ </div>
2425
+ <div class="o-section o-chart-title">
2426
+ <div class="o-section-title">Title</div>
2427
+ <input
2428
+ type="text"
2429
+ t-model="state.title"
2430
+ t-on-change="updateTitle"
2431
+ class="o-input o-optional"
2432
+ placeholder="New Chart"
2433
+ />
2434
+ </div>
2435
+ <div class="o-section">
2436
+ <div class="o-section-title">Vertical axis position</div>
2437
+ <select
2438
+ t-att-value="props.definition.verticalAxisPosition"
2439
+ class="o-input o-type-selector"
2440
+ t-on-change="(ev) => this.updateSelect('verticalAxisPosition', ev)">
2441
+ <option value="left">Left</option>
2442
+ <option value="right">Right</option>
2443
+ </select>
2444
+ </div>
2445
+ <div class="o-section">
2446
+ <div class="o-section-title">Legend position</div>
2447
+ <select
2448
+ t-att-value="props.definition.legendPosition"
2449
+ class="o-input o-type-selector"
2450
+ t-on-change="(ev) => this.updateSelect('legendPosition', ev)">
2451
+ <option value="none">None</option>
2452
+ <option value="top">Top</option>
2453
+ <option value="bottom">Bottom</option>
2454
+ <option value="left">Left</option>
2455
+ <option value="right">Right</option>
2456
+ </select>
2457
+ </div>
2458
+ </div>
2459
+ </t>
2460
+
2461
+ <t t-name="o-spreadsheet-GaugeChartConfigPanel" owl="1">
2462
+ <div>
2463
+ <div class="o-section o-data-series">
2464
+ <div class="o-section-title">Data range</div>
2465
+ <SelectionInput
2466
+ ranges="() => [this.getDataRange()]"
2467
+ isInvalid="isDataRangeInvalid"
2468
+ hasSingleRange="true"
2469
+ required="true"
2470
+ onSelectionChanged="(ranges) => this.onDataRangeChanged(ranges)"
2471
+ onSelectionConfirmed="() => this.updateDataRange()"
2472
+ />
2473
+ </div>
2474
+
2475
+ <div class="o-section" t-if="configurationErrorMessages.length">
2476
+ <SidePanelErrors messages="configurationErrorMessages" msgType="'error'"/>
2477
+ </div>
2478
+ </div>
2479
+ </t>
2480
+
2481
+ <t t-name="o-spreadsheet-GaugeChartDesignPanel" owl="1">
2482
+ <div>
2483
+ <div class="o-section o-chart-background-color">
2484
+ <div class="o-section-title">Background color</div>
2485
+ <div class="d-flex align-items-center">
2486
+ <span class="pe-1">Select a color...</span>
2487
+ <ColorPickerWidget
2488
+ currentColor="props.definition.background"
2489
+ toggleColorPicker="() => this.toggleMenu('backgroundColor', ev)"
2490
+ showColorPicker="state.openedMenu === 'backgroundColor'"
2491
+ onColorPicked="(color) => this.updateBackgroundColor(color)"
2492
+ title="env._t('Background Color')"
2493
+ icon="'o-spreadsheet-Icon.FILL_COLOR'"
2494
+ />
2495
+ </div>
2496
+ </div>
2497
+
2498
+ <div class="o-section o-chart-title">
2499
+ <div class="o-section-title">Title</div>
2500
+ <input
2501
+ type="text"
2502
+ t-model="state.title"
2503
+ t-on-change="updateTitle"
2504
+ class="o-input o-optional"
2505
+ placeholder="New Chart"
2506
+ />
2507
+ </div>
2508
+
2509
+ <div class="o-section">
2510
+ <div class="o-section-title">Range</div>
2511
+ <div class="o-subsection-left">
2512
+ <input
2513
+ type="text"
2514
+ t-model="state.sectionRule.rangeMin"
2515
+ t-on-change="() => this.updateSectionRule(state.sectionRule)"
2516
+ t-on-input="() => this.canUpdateSectionRule(state.sectionRule)"
2517
+ class="o-input o-data-range-min"
2518
+ t-att-class="{ 'o-invalid': isRangeMinInvalid() }"
2519
+ />
2520
+ </div>
2521
+ <div class="o-subsection-right">
2522
+ <input
2523
+ type="text"
2524
+ t-model="state.sectionRule.rangeMax"
2525
+ t-on-change="() => this.updateSectionRule(state.sectionRule)"
2526
+ t-on-input="() => this.canUpdateSectionRule(state.sectionRule)"
2527
+ class="o-input o-data-range-max"
2528
+ t-att-class="{ 'o-invalid': isRangeMaxInvalid() }"
2529
+ />
2530
+ </div>
2531
+ </div>
2532
+
2533
+ <div class="o-section">
2534
+ <div class="o-section-title">Thresholds</div>
2535
+ <t t-call="o-spreadsheet-GaugeChartColorSectionTemplate">
2536
+ <t t-set="sectionRule" t-value="state.sectionRule"/>
2537
+ </t>
2538
+ </div>
2539
+
2540
+ <div class="o-section" t-if="designErrorMessages.length">
2541
+ <SidePanelErrors messages="designErrorMessages" msgType="'error'"/>
2542
+ </div>
2543
+ </div>
2544
+ </t>
2545
+
2546
+ <t t-name="o-spreadsheet-GaugeChartColorSectionTemplate" owl="1">
2547
+ <div class="o-gauge-color-set">
2548
+ <table>
2549
+ <tr>
2550
+ <th class="o-gauge-color-set-colorPicker"/>
2551
+ <th class="o-gauge-color-set-text"/>
2552
+ <th class="o-gauge-color-set-value">Value</th>
2553
+ <th class="o-gauge-color-set-type">Type</th>
2554
+ </tr>
2555
+
2556
+ <t t-call="o-spreadsheet-GaugeChartColorSectionTemplateRow">
2557
+ <t t-set="sectionColor" t-value="sectionRule.colors.lowerColor"/>
2558
+ <t t-set="sectionType" t-value="'lowerColor'"/>
2559
+ <t t-set="inflectionPoint" t-value="sectionRule.lowerInflectionPoint"/>
2560
+ <t t-set="isInvalid" t-value="isLowerInflectionPointInvalid"/>
2561
+ <t t-set="inflectionPointName" t-value="'lowerInflectionPoint'"/>
2562
+ </t>
2563
+
2564
+ <t t-call="o-spreadsheet-GaugeChartColorSectionTemplateRow">
2565
+ <t t-set="sectionColor" t-value="sectionRule.colors.middleColor"/>
2566
+ <t t-set="sectionType" t-value="'middleColor'"/>
2567
+ <t t-set="inflectionPoint" t-value="sectionRule.upperInflectionPoint"/>
2568
+ <t t-set="isInvalid" t-value="isUpperInflectionPointInvalid"/>
2569
+ <t t-set="inflectionPointName" t-value="'upperInflectionPoint'"/>
2570
+ </t>
2571
+
2572
+ <tr>
2573
+ <td>
2574
+ <ColorPickerWidget
2575
+ currentColor="sectionRule.colors.upperColor"
2576
+ toggleColorPicker="(ev) => this.toggleMenu('sectionColor-upperColor', ev)"
2577
+ showColorPicker="state.openedMenu === 'sectionColor-upperColor'"
2578
+ onColorPicked="(color) => this.updateSectionColor('upperColor', color)"
2579
+ icon="'o-spreadsheet-Icon.FILL_COLOR'"
2580
+ />
2581
+ </td>
2582
+ <td>Else</td>
2583
+ <td/>
2584
+ <td/>
2585
+ <td/>
2586
+ </tr>
2587
+ </table>
2588
+ </div>
2589
+ </t>
2590
+
2591
+ <t t-name="o-spreadsheet-GaugeChartColorSectionTemplateRow" owl="1">
2592
+ <tr>
2593
+ <td>
2594
+ <ColorPickerWidget
2595
+ currentColor="sectionColor"
2596
+ toggleColorPicker="(ev) => this.toggleMenu('sectionColor-'+sectionType, ev)"
2597
+ showColorPicker="state.openedMenu === 'sectionColor-'+sectionType"
2598
+ onColorPicked="(color) => this.updateSectionColor(sectionType, color)"
2599
+ icon="'o-spreadsheet-Icon.FILL_COLOR'"
2600
+ />
2601
+ </td>
2602
+ <td>When value is below</td>
2603
+ <td>
2604
+ <input
2605
+ type="text"
2606
+ class="o-input"
2607
+ t-model="inflectionPoint.value"
2608
+ t-on-input="() => this.canUpdateSectionRule(state.sectionRule)"
2609
+ t-on-change="() => this.updateSectionRule(state.sectionRule)"
2610
+ t-attf-class="o-input-{{inflectionPointName}}"
2611
+ t-att-class="{ 'o-invalid': isInvalid }"
2612
+ />
2613
+ </td>
2614
+ <td>
2615
+ <select
2616
+ class="o-input"
2617
+ name="valueType"
2618
+ t-model="inflectionPoint.type"
2619
+ t-on-change="(ev) => this.updateSectionRule(state.sectionRule)">
2620
+ <option value="number">Number</option>
2621
+ <option value="percentage">Percentage</option>
2622
+ </select>
2623
+ </td>
2624
+ </tr>
2625
+ </t>
2626
+
2627
+ <t t-name="o-spreadsheet-LineBarPieConfigPanel" owl="1">
2628
+ <div>
2629
+ <div class="o-section o-data-series">
2630
+ <div class="o-section-title">Data Series</div>
2631
+ <SelectionInput
2632
+ ranges="() => this.getDataSeriesRanges()"
2633
+ required="true"
2634
+ onSelectionChanged="(ranges) => this.onDataSeriesRangesChanged(ranges)"
2635
+ onSelectionConfirmed="() => this.onDataSeriesConfirmed()"
2636
+ />
2637
+ </div>
2638
+ <div class="o-section o-data-labels">
2639
+ <div class="o-section-title">Categories / Labels</div>
2640
+ <SelectionInput
2641
+ ranges="() => [this.getLabelRange()]"
2642
+ isInvalid="isLabelInvalid"
2643
+ hasSingleRange="true"
2644
+ onSelectionChanged="(ranges) => this.onLabelRangeChanged(ranges)"
2645
+ onSelectionConfirmed="() => this.onLabelRangeConfirmed()"
2646
+ />
2647
+ <label>
2648
+ <input
2649
+ type="checkbox"
2650
+ name="aggregated"
2651
+ t-att-checked="props.definition.aggregated"
2652
+ t-on-change="onUpdateAggregated"
2653
+ class="align-middle"
2654
+ />
2655
+ Aggregate
2656
+ </label>
2657
+ </div>
2658
+ <div class="o-section o-use-row-as-headers" t-if="calculateHeaderPosition()">
2659
+ <label>
2660
+ <input
2661
+ type="checkbox"
2662
+ t-att-checked="props.definition.dataSetsHaveTitle"
2663
+ t-on-change="onUpdateDataSetsHaveTitle"
2664
+ class="align-middle"
2665
+ />
2666
+ Use row
2667
+ <span t-esc="calculateHeaderPosition()"/>
2668
+ as headers
2669
+ </label>
2670
+ </div>
2671
+
2672
+ <div class="o-section" t-if="errorMessages.length">
2673
+ <SidePanelErrors messages="errorMessages" msgType="'error'"/>
2674
+ </div>
2675
+ </div>
2676
+ </t>
2677
+
2678
+ <t t-name="o-spreadsheet-LineBarPieDesignPanel" owl="1">
2679
+ <div>
2680
+ <div class="o-section o-chart-background-color">
2681
+ <div class="o-section-title">Background color</div>
2682
+ <div class="d-flex align-items-center">
2683
+ <span class="pe-1">Select a color...</span>
2684
+ <ColorPickerWidget
2685
+ currentColor="props.definition.background"
2686
+ toggleColorPicker="() => this.toggleColorPicker()"
2687
+ showColorPicker="state.fillColorTool"
2688
+ onColorPicked="(color) => this.updateBackgroundColor(color)"
2689
+ title="env._t('Background Color')"
2690
+ icon="'o-spreadsheet-Icon.FILL_COLOR'"
2691
+ />
2692
+ </div>
2693
+ </div>
2694
+ <div class="o-section o-chart-title">
2695
+ <div class="o-section-title">Title</div>
2696
+ <input
2697
+ type="text"
2698
+ t-model="state.title"
2699
+ t-on-change="updateTitle"
2700
+ class="o-input o-optional"
2701
+ placeholder="New Chart"
2702
+ />
2703
+ </div>
2704
+ <div class="o-section">
2705
+ <div class="o-section-title">Legend position</div>
2706
+ <select
2707
+ t-att-value="props.definition.legendPosition"
2708
+ class="o-input o-type-selector"
2709
+ t-on-change="(ev) => this.updateSelect('legendPosition', ev)">
2710
+ <option value="none">None</option>
2711
+ <option value="top">Top</option>
2712
+ <option value="bottom">Bottom</option>
2713
+ <option value="left">Left</option>
2714
+ <option value="right">Right</option>
2715
+ </select>
2716
+ </div>
2717
+ </div>
2718
+ </t>
2719
+
2720
+ <t t-name="o-spreadsheet-LineConfigPanel" owl="1">
2721
+ <div>
2722
+ <div class="o-section pt-0">
2723
+ <div class="o-checkbox">
2724
+ <label>
2725
+ <input
2726
+ type="checkbox"
2727
+ name="stacked"
2728
+ t-att-checked="props.definition.stacked"
2729
+ t-on-change="onUpdateStacked"
2730
+ class="align-middle"
2731
+ />
2732
+ Stacked linechart
2733
+ </label>
2734
+ </div>
2735
+ <div class="o-checkbox">
2736
+ <label>
2737
+ <input
2738
+ type="checkbox"
2739
+ name="cumulative"
2740
+ t-att-checked="props.definition.cumulative"
2741
+ t-on-change="onUpdateCumulative"
2742
+ class="align-middle"
2743
+ />
2744
+ Cumulative data
2745
+ </label>
2746
+ </div>
2747
+ </div>
2748
+ <div class="o-section o-data-series">
2749
+ <div class="o-section-title">Data Series</div>
2750
+ <SelectionInput
2751
+ ranges="() => this.getDataSeriesRanges()"
2752
+ required="true"
2753
+ onSelectionChanged="(ranges) => this.onDataSeriesRangesChanged(ranges)"
2754
+ onSelectionConfirmed="() => this.onDataSeriesConfirmed()"
2755
+ />
2756
+ </div>
2757
+ <div class="o-section o-data-labels">
2758
+ <div class="o-section-title">Categories / Labels</div>
2759
+ <SelectionInput
2760
+ ranges="() => [this.getLabelRange()]"
2761
+ isInvalid="isLabelInvalid"
2762
+ hasSingleRange="true"
2763
+ onSelectionChanged="(ranges) => this.onLabelRangeChanged(ranges)"
2764
+ onSelectionConfirmed="() => this.onLabelRangeConfirmed()"
2765
+ />
2766
+ <label>
2767
+ <input
2768
+ type="checkbox"
2769
+ name="aggregated"
2770
+ t-att-checked="props.definition.aggregated"
2771
+ t-on-change="onUpdateAggregated"
2772
+ class="align-middle"
2773
+ />
2774
+ Aggregate
2775
+ </label>
2776
+ <div t-if="canTreatLabelsAsText">
2777
+ <label>
2778
+ <input
2779
+ type="checkbox"
2780
+ name="labelsAsText"
2781
+ t-att-checked="props.definition.labelsAsText"
2782
+ t-on-change="onUpdateLabelsAsText"
2783
+ />
2784
+ Treat labels as text
2785
+ </label>
2786
+ </div>
2787
+ </div>
2788
+ <div class="o-section o-use-row-as-headers" t-if="calculateHeaderPosition()">
2789
+ <label>
2790
+ <input
2791
+ type="checkbox"
2792
+ t-att-checked="props.definition.dataSetsHaveTitle"
2793
+ t-on-change="onUpdateDataSetsHaveTitle"
2794
+ class="align-middle"
2795
+ />
2796
+ Use row
2797
+ <span t-esc="calculateHeaderPosition()"/>
2798
+ as headers
2799
+ </label>
2800
+ </div>
2801
+
2802
+ <div class="o-section" t-if="errorMessages.length">
2803
+ <SidePanelErrors messages="errorMessages" msgType="'error'"/>
2804
+ </div>
2805
+ </div>
2806
+ </t>
2807
+
2808
+ <t t-name="o-spreadsheet-LineChartDesignPanel" owl="1">
2809
+ <div>
2810
+ <div class="o-section o-chart-background-color">
2811
+ <div class="o-section-title">Background color</div>
2812
+ <div class="d-flex align-items-center">
2813
+ <span class="pe-1">Select a color...</span>
2814
+ <ColorPickerWidget
2815
+ currentColor="props.definition.background"
2816
+ toggleColorPicker="() => this.toggleColorPicker()"
2817
+ showColorPicker="state.fillColorTool"
2818
+ onColorPicked="(color) => this.updateBackgroundColor(color)"
2819
+ title="env._t('Background Color')"
2820
+ icon="'o-spreadsheet-Icon.FILL_COLOR'"
2821
+ />
2822
+ </div>
2823
+ </div>
2824
+ <div class="o-section o-chart-title">
2825
+ <div class="o-section-title">Title</div>
2826
+ <input
2827
+ type="text"
2828
+ t-model="state.title"
2829
+ t-on-change="updateTitle"
2830
+ class="o-input o-optional"
2831
+ placeholder="New Chart"
2832
+ />
2833
+ </div>
2834
+ <div class="o-section">
2835
+ <div class="o-section-title">Vertical axis position</div>
2836
+ <select
2837
+ t-att-value="props.definition.verticalAxisPosition"
2838
+ class="o-input o-type-selector"
2839
+ t-on-change="(ev) => this.updateSelect('verticalAxisPosition', ev)">
2840
+ <option value="left">Left</option>
2841
+ <option value="right">Right</option>
2842
+ </select>
2843
+ </div>
2844
+ <div class="o-section">
2845
+ <div class="o-section-title">Legend position</div>
2846
+ <select
2847
+ t-att-value="props.definition.legendPosition"
2848
+ class="o-input o-type-selector"
2849
+ t-on-change="(ev) => this.updateSelect('legendPosition', ev)">
2850
+ <option value="none">None</option>
2851
+ <option value="top">Top</option>
2852
+ <option value="bottom">Bottom</option>
2853
+ <option value="left">Left</option>
2854
+ <option value="right">Right</option>
2855
+ </select>
2856
+ </div>
2857
+ </div>
2858
+ </t>
2859
+
2860
+ <t t-name="o-spreadsheet-ChartPanel" owl="1">
2861
+ <div class="o-chart">
2862
+ <div class="o-panel">
2863
+ <div
2864
+ class="o-panel-element o-panel-configuration"
2865
+ t-att-class="state.panel !== 'configuration' ? 'inactive' : ''"
2866
+ t-on-click="() => this.activatePanel('configuration')">
2867
+ <i class="fa fa-sliders"/>
2868
+ Configuration
2869
+ </div>
2870
+ <div
2871
+ class="o-panel-element o-panel-design"
2872
+ t-att-class="state.panel !== 'design' ? 'inactive' : ''"
2873
+ t-on-click="() => this.activatePanel('design')">
2874
+ <i class="fa fa-paint-brush"/>
2875
+ Design
2876
+ </div>
2877
+ </div>
2878
+
2879
+ <t t-set="definition" t-value="getChartDefinition()"/>
2880
+ <t t-if="state.panel === 'configuration'">
2881
+ <div class="o-section">
2882
+ <div class="o-section-title">Chart type</div>
2883
+ <t t-set="types" t-value="chartTypes"/>
2884
+ <select
2885
+ class="o-input o-type-selector"
2886
+ t-on-change="(ev) => this.onTypeChange(ev.target.value)">
2887
+ <option
2888
+ t-foreach="chartTypes"
2889
+ t-as="type"
2890
+ t-key="type"
2891
+ t-att-value="type"
2892
+ t-esc="types[type]"
2893
+ t-att-selected="definition.type === type"
2894
+ />
2895
+ </select>
2896
+ </div>
2897
+ <t
2898
+ t-component="chartPanel.configuration"
2899
+ definition="definition"
2900
+ figureId="figureId"
2901
+ updateChart.bind="updateChart"
2902
+ canUpdateChart.bind="canUpdateChart"
2903
+ t-key="figureId + definition.type"
2904
+ />
2905
+ </t>
2906
+ <t t-else="">
2907
+ <t
2908
+ t-component="chartPanel.design"
2909
+ definition="definition"
2910
+ figureId="figureId"
2911
+ updateChart.bind="updateChart"
2912
+ canUpdateChart.bind="canUpdateChart"
2913
+ t-key="figureId + definition.type"
2914
+ />
2915
+ </t>
2916
+ </div>
2917
+ </t>
2918
+
2919
+ <t t-name="o-spreadsheet-ScorecardChartConfigPanel" owl="1">
2920
+ <div>
2921
+ <div class="o-section o-data-series">
2922
+ <div class="o-section-title">Key value</div>
2923
+ <SelectionInput
2924
+ ranges="() => [this.getKeyValueRange()]"
2925
+ isInvalid="isKeyValueInvalid"
2926
+ hasSingleRange="true"
2927
+ required="true"
2928
+ onSelectionChanged="(ranges) => this.onKeyValueRangeChanged(ranges)"
2929
+ onSelectionConfirmed="() => this.updateKeyValueRange()"
2930
+ />
2931
+ </div>
2932
+ <div class="o-section o-data-labels">
2933
+ <div class="o-section-title">Baseline configuration</div>
2934
+ <div class="o-section-subtitle">Baseline value</div>
2935
+ <SelectionInput
2936
+ ranges="() => [this.getBaselineRange()]"
2937
+ isInvalid="isBaselineInvalid"
2938
+ hasSingleRange="true"
2939
+ onSelectionChanged="(ranges) => this.onBaselineRangeChanged(ranges)"
2940
+ onSelectionConfirmed="() => this.updateBaselineRange()"
2941
+ />
2942
+ <div class="o-section-subtitle">Baseline format</div>
2943
+ <select
2944
+ t-att-value="props.definition.baselineMode"
2945
+ class="o-input o-type-selector o-optional"
2946
+ t-on-change="(ev) => this.updateBaselineMode(ev)">
2947
+ <option value="text">Absolute value</option>
2948
+ <option value="difference">Value change from key value</option>
2949
+ <option value="percentage">Percentage change from key value</option>
2950
+ </select>
2951
+ </div>
2952
+
2953
+ <div class="o-section" t-if="errorMessages.length">
2954
+ <SidePanelErrors messages="errorMessages" msgType="'error'"/>
2955
+ </div>
2956
+ </div>
2957
+ </t>
2958
+
2959
+ <t t-name="o-spreadsheet-ScorecardChartDesignPanel" owl="1">
2960
+ <div>
2961
+ <div class="o-section o-chart-background-color">
2962
+ <div class="o-section-title">Background color</div>
2963
+ <div class="d-flex align-items-center">
2964
+ <span class="pe-1">Select a color...</span>
2965
+ <ColorPickerWidget
2966
+ currentColor="props.definition.background"
2967
+ toggleColorPicker="() => this.toggleColorPicker('backgroundColor')"
2968
+ showColorPicker="state.openedColorPicker === 'backgroundColor'"
2969
+ onColorPicked="(color) => this.setColor(color, 'backgroundColor')"
2970
+ title="env._t('Background Color')"
2971
+ icon="'o-spreadsheet-Icon.FILL_COLOR'"
2972
+ />
2973
+ </div>
2974
+ </div>
2975
+
2976
+ <div class="o-section o-chart-title">
2977
+ <div class="o-section-title">Title</div>
2978
+ <input
2979
+ type="text"
2980
+ t-model="state.title"
2981
+ t-on-change="updateTitle"
2982
+ class="o-input o-optional"
2983
+ placeholder="New Chart"
2984
+ />
2985
+ </div>
2986
+ <div class="o-section">
2987
+ <div class="o-section-title">Baseline description</div>
2988
+ <input
2989
+ type="text"
2990
+ t-att-value="env._t(props.definition.baselineDescr)"
2991
+ t-on-change="updateBaselineDescr"
2992
+ class="o-input o-optional"
2993
+ />
2994
+ </div>
2995
+ </div>
2996
+ <div class="o-section o-chart-baseline-color">
2997
+ <div class="o-section-title">Baseline color</div>
2998
+ <div class="d-flex align-items-center">
2999
+ <span class="pe-1">Color on value increase</span>
3000
+ <ColorPickerWidget
3001
+ currentColor="props.definition.baselineColorUp"
3002
+ toggleColorPicker="() => this.toggleColorPicker('baselineColorUp')"
3003
+ showColorPicker="state.openedColorPicker === 'baselineColorUp'"
3004
+ onColorPicked="(color) => this.setColor(color, 'baselineColorUp')"
3005
+ title="env._t('Color Up')"
3006
+ icon="'o-spreadsheet-Icon.FILL_COLOR'"
3007
+ />
3008
+ </div>
3009
+ <div class="d-flex align-items-center">
3010
+ <span class="pe-1">Color on value decrease</span>
3011
+ <ColorPickerWidget
3012
+ currentColor="props.definition.baselineColorDown"
3013
+ toggleColorPicker="() => this.toggleColorPicker('baselineColorDown')"
3014
+ showColorPicker="state.openedColorPicker === 'baselineColorDown'"
3015
+ onColorPicked="(color) => this.setColor(color, 'baselineColorDown')"
3016
+ title="env._t('Color Down')"
3017
+ icon="'o-spreadsheet-Icon.FILL_COLOR'"
3018
+ />
3019
+ </div>
3020
+ </div>
3021
+ </t>
3022
+
3023
+ <t t-name="o-spreadsheet-CellIsRuleEditorPreview" owl="1">
3024
+ <div
3025
+ class="o-cf-preview-line"
3026
+ t-attf-style="font-weight:{{currentStyle.bold ?'bold':'normal'}};
3027
+ text-decoration:{{getTextDecoration(currentStyle)}};
3028
+ font-style:{{currentStyle.italic?'italic':'normal'}};
3029
+ color:{{currentStyle.textColor || '#000'}};
3030
+ border-radius: 4px;
3031
+ background-color:{{currentStyle.fillColor}};">
3032
+ <t t-if="previewText" t-esc="previewText"/>
3033
+ <t t-else="">Preview text</t>
3034
+ </div>
3035
+ </t>
3036
+
3037
+ <t t-name="o-spreadsheet-CellIsRuleEditor" owl="1">
3038
+ <div class="o-cf-cell-is-rule">
3039
+ <div class="o-section-subtitle">Format cells if...</div>
3040
+ <select t-model="rule.operator" class="o-input o-cell-is-operator">
3041
+ <t t-foreach="Object.keys(cellIsOperators)" t-as="op" t-key="op_index">
3042
+ <option t-att-value="op" t-esc="cellIsOperators[op]"/>
3043
+ </t>
3044
+ </select>
3045
+ <t t-if="rule.operator !== 'IsEmpty' and rule.operator !== 'IsNotEmpty'">
3046
+ <input
3047
+ type="text"
3048
+ placeholder="Value"
3049
+ t-model="rule.values[0]"
3050
+ t-att-class="{ 'o-invalid': isValue1Invalid }"
3051
+ class="o-input o-cell-is-value o-required"
3052
+ />
3053
+ <t t-if="rule.operator === 'Between' || rule.operator === 'NotBetween'">
3054
+ <input
3055
+ type="text"
3056
+ placeholder="and value"
3057
+ t-model="rule.values[1]"
3058
+ t-att-class="{ 'o-invalid': isValue2Invalid }"
3059
+ class="o-input o-cell-is-value o-required"
3060
+ />
3061
+ </t>
3062
+ </t>
3063
+ <div class="o-section-subtitle">Formatting style</div>
3064
+
3065
+ <t t-call="o-spreadsheet-CellIsRuleEditorPreview">
3066
+ <t t-set="currentStyle" t-value="rule.style"/>
3067
+ </t>
3068
+ <div class="o-sidePanel-tools">
3069
+ <div
3070
+ class="o-tool"
3071
+ title="Bold"
3072
+ t-att-class="{active:rule.style.bold}"
3073
+ t-on-click="() => this.toggleStyle('bold')">
3074
+ <t t-call="o-spreadsheet-Icon.BOLD"/>
3075
+ </div>
3076
+ <div
3077
+ class="o-tool"
3078
+ title="Italic"
3079
+ t-att-class="{active:rule.style.italic}"
3080
+ t-on-click="() => this.toggleStyle('italic')">
3081
+ <t t-call="o-spreadsheet-Icon.ITALIC"/>
3082
+ </div>
3083
+ <div
3084
+ class="o-tool"
3085
+ title="Underline"
3086
+ t-att-class="{active:rule.style.underline}"
3087
+ t-on-click="(ev) => this.toggleStyle('underline', ev)">
3088
+ <t t-call="o-spreadsheet-Icon.UNDERLINE"/>
3089
+ </div>
3090
+ <div
3091
+ class="o-tool"
3092
+ title="Strikethrough"
3093
+ t-att-class="{active:rule.style.strikethrough}"
3094
+ t-on-click="(ev) => this.toggleStyle('strikethrough', ev)">
3095
+ <t t-call="o-spreadsheet-Icon.STRIKE"/>
3096
+ </div>
3097
+ <ColorPickerWidget
3098
+ currentColor="rule.style.textColor || '#000000'"
3099
+ toggleColorPicker="(ev) => this.toggleMenu('cellIsRule-textColor', ev)"
3100
+ showColorPicker="state.openedMenu === 'cellIsRule-textColor'"
3101
+ onColorPicked="(color) => this.setColor('textColor', color)"
3102
+ title="env._t('Text Color')"
3103
+ icon="'o-spreadsheet-Icon.TEXT_COLOR'"
3104
+ class="'o-tool'"
3105
+ />
3106
+ <div class="o-divider"/>
3107
+ <ColorPickerWidget
3108
+ currentColor="rule.style.fillColor"
3109
+ toggleColorPicker="(ev) => this.toggleMenu('cellIsRule-fillColor', ev)"
3110
+ showColorPicker="state.openedMenu === 'cellIsRule-fillColor'"
3111
+ onColorPicked="(color) => this.setColor('fillColor', color)"
3112
+ title="env._t('Fill Color')"
3113
+ icon="'o-spreadsheet-Icon.FILL_COLOR'"
3114
+ class="'o-tool'"
3115
+ />
3116
+ </div>
3117
+ </div>
3118
+ </t>
3119
+
3120
+ <t t-name="o-spreadsheet-ColorScaleRuleEditorPreview" owl="1">
3121
+ <div class="o-cf-preview-gradient" t-attf-style="{{getPreviewGradient()}}">Preview text</div>
3122
+ </t>
3123
+
3124
+ <t t-name="o-spreadsheet-ColorScaleRuleEditorThreshold" owl="1">
3125
+ <div t-attf-class="o-threshold o-threshold-{{thresholdType}}">
3126
+ <t t-if="thresholdType === 'midpoint'">
3127
+ <t t-set="type" t-value="threshold and threshold.type"/>
3128
+ <select
3129
+ class="o-input"
3130
+ name="valueType"
3131
+ t-on-change="onMidpointChange"
3132
+ t-on-click="closeMenus">
3133
+ <option value="none" t-att-selected="threshold === undefined">None</option>
3134
+ <option value="number" t-att-selected="type === 'number'">FixedNumber</option>
3135
+ <option value="percentage" t-att-selected="type === 'percentage'">Percentage</option>
3136
+ <option value="percentile" t-att-selected="type === 'percentile'">Percentile</option>
3137
+ <option value="formula" t-att-selected="type === 'formula'">Formula</option>
3138
+ </select>
3139
+ </t>
3140
+ <t t-else="">
3141
+ <select class="o-input" name="valueType" t-model="threshold.type" t-on-click="closeMenus">
3142
+ <option value="value">Cell values</option>
3143
+ <option value="number">Number</option>
3144
+ <option value="percentage">Percentage</option>
3145
+ <option value="percentile">Percentile</option>
3146
+ <option value="formula">Formula</option>
3147
+ </select>
3148
+ </t>
3149
+ <input
3150
+ type="text"
3151
+ class="o-input o-threshold-value o-required"
3152
+ t-model="rule[thresholdType].value"
3153
+ t-att-class="{ 'o-invalid': isValueInvalid(thresholdType) }"
3154
+ t-if="threshold !== undefined and threshold.type !== 'value'"
3155
+ />
3156
+ <input type="text" class="o-input o-threshold-value" t-else="" disabled="1"/>
3157
+ <ColorPickerWidget
3158
+ currentColor="getThresholdColor(threshold)"
3159
+ toggleColorPicker="(ev) => this.toggleMenu('colorScale-'+thresholdType+'Color', ev)"
3160
+ showColorPicker="state.openedMenu === 'colorScale-'+thresholdType+'Color'"
3161
+ onColorPicked="(color) => this.setColorScaleColor(thresholdType, color)"
3162
+ title="env._t('Fill Color')"
3163
+ icon="'o-spreadsheet-Icon.FILL_COLOR'"
3164
+ disabled="threshold === undefined"
3165
+ />
3166
+ </div>
3167
+ </t>
3168
+
3169
+ <t t-name="o-spreadsheet-ColorScaleRuleEditor" owl="1">
3170
+ <div class="o-cf-color-scale-editor">
3171
+ <div class="o-section-subtitle">Preview</div>
3172
+ <t t-call="o-spreadsheet-ColorScaleRuleEditorPreview"/>
3173
+ <div class="o-section-subtitle">Minpoint</div>
3174
+ <t t-call="o-spreadsheet-ColorScaleRuleEditorThreshold">
3175
+ <t t-set="threshold" t-value="rule.minimum"/>
3176
+ <t t-set="thresholdType" t-value="'minimum'"/>
3177
+ </t>
3178
+ <div class="o-section-subtitle">MidPoint</div>
3179
+ <t t-call="o-spreadsheet-ColorScaleRuleEditorThreshold">
3180
+ <t t-set="threshold" t-value="rule.midpoint"/>
3181
+ <t t-set="thresholdType" t-value="'midpoint'"/>
3182
+ </t>
3183
+ <div class="o-section-subtitle">MaxPoint</div>
3184
+ <t t-call="o-spreadsheet-ColorScaleRuleEditorThreshold">
3185
+ <t t-set="threshold" t-value="rule.maximum"/>
3186
+ <t t-set="thresholdType" t-value="'maximum'"/>
3187
+ </t>
3188
+ </div>
3189
+ </t>
3190
+
3191
+ <t t-name="o-spreadsheet-ConditionalFormattingPanel" owl="1">
3192
+ <div class="o-cf">
3193
+ <t t-if="state.mode === 'list' || state.mode === 'reorder'">
3194
+ <div class="o-cf-preview-list">
3195
+ <div
3196
+ t-on-click="(ev) => this.editConditionalFormat(cf, ev)"
3197
+ t-foreach="conditionalFormats"
3198
+ t-as="cf"
3199
+ t-key="cf.id">
3200
+ <t t-call="o-spreadsheet-ConditionalFormattingPanelPreview"/>
3201
+ </div>
3202
+ </div>
3203
+ <t t-if="state.mode === 'list'">
3204
+ <div
3205
+ class="btn btn-link o-cf-btn-link o-cf-add"
3206
+ t-on-click.prevent.stop="addConditionalFormat">
3207
+ + Add another rule
3208
+ </div>
3209
+ <div
3210
+ class="btn btn-link o-cf-btn-link o-cf-reorder"
3211
+ t-on-click="reorderConditionalFormats">
3212
+ Reorder rules
3213
+ </div>
3214
+ </t>
3215
+ <t t-if="state.mode === 'reorder'">
3216
+ <div class="btn btn-link o-cf-btn-link o-cf-exit-reorder" t-on-click="switchToList">
3217
+ Stop reordering rules
3218
+ </div>
3219
+ </t>
3220
+ </t>
3221
+ <t t-if="state.mode === 'edit' || state.mode === 'add'" t-key="state.currentCF.id">
3222
+ <div class="o-cf-ruleEditor">
3223
+ <div class="o-section o-cf-range">
3224
+ <div class="o-section-title">Apply to range</div>
3225
+ <div class="o-selection-cf">
3226
+ <SelectionInput
3227
+ ranges="() => state.currentCF.ranges"
3228
+ class="'o-range'"
3229
+ isInvalid="isRangeValid"
3230
+ onSelectionChanged="(ranges) => this.onRangesChanged(ranges)"
3231
+ required="true"
3232
+ />
3233
+ </div>
3234
+ <div class="o-section-title">Format rules</div>
3235
+ <div class="o_field_radio o_horizontal o_field_widget o-cf-type-selector">
3236
+ <div
3237
+ class="custom-control form-check o_cf_radio_item"
3238
+ t-on-click="() => this.changeRuleType('CellIsRule')">
3239
+ <input
3240
+ class="form-check-input o_radio_input"
3241
+ t-att-checked="state.currentCFType === 'CellIsRule'"
3242
+ type="radio"
3243
+ id="cellIsRule"
3244
+ name="ruleType"
3245
+ value="CellIsRule"
3246
+ />
3247
+ <label for="cellIsRule" class="form-check-label o_form_label">Single color</label>
3248
+ </div>
3249
+ <div
3250
+ class="custom-control form-check o_cf_radio_item"
3251
+ t-on-click="() => this.changeRuleType('ColorScaleRule')">
3252
+ <input
3253
+ class="form-check-input o_radio_input"
3254
+ t-att-checked="state.currentCFType === 'ColorScaleRule'"
3255
+ type="radio"
3256
+ id="colorScaleRule"
3257
+ name="ruleType"
3258
+ value="ColorScaleRule"
3259
+ />
3260
+ <label for="colorScaleRule" class="form-check-label o_form_label">
3261
+ Color scale
3262
+ </label>
3263
+ </div>
3264
+
3265
+ <div
3266
+ class="custom-control form-check o_cf_radio_item"
3267
+ t-on-click="() => this.changeRuleType('IconSetRule')">
3268
+ <input
3269
+ class="form-check-input o_radio_input"
3270
+ t-att-checked="state.currentCFType === 'IconSetRule'"
3271
+ type="radio"
3272
+ id="iconSetRule"
3273
+ name="ruleType"
3274
+ value="IconSetRule"
3275
+ />
3276
+ <label for="iconSetRule" class="form-check-label o_form_label">Icon set</label>
3277
+ </div>
3278
+ </div>
3279
+ </div>
3280
+ <div class="o-section o-cf-editor">
3281
+ <t t-if="state.currentCFType === 'CellIsRule'" t-call="o-spreadsheet-CellIsRuleEditor">
3282
+ <t t-set="rule" t-value="state.rules.cellIs"/>
3283
+ </t>
3284
+ <t
3285
+ t-if="state.currentCFType === 'ColorScaleRule'"
3286
+ t-call="o-spreadsheet-ColorScaleRuleEditor">
3287
+ <t t-set="rule" t-value="state.rules.colorScale"/>
3288
+ </t>
3289
+ <t t-if="state.currentCFType === 'IconSetRule'" t-call="o-spreadsheet-IconSetEditor">
3290
+ <t t-set="rule" t-value="state.rules.iconSet"/>
3291
+ </t>
3292
+ <div class="o-sidePanelButtons">
3293
+ <button t-on-click="switchToList" class="o-sidePanelButton o-cf-cancel">
3294
+ Cancel
3295
+ </button>
3296
+ <button t-on-click="saveConditionalFormat" class="o-sidePanelButton o-cf-save">
3297
+ Save
3298
+ </button>
3299
+ </div>
3300
+ </div>
3301
+ <div class="o-section">
3302
+ <div class="o-cf-error" t-foreach="state.errors || []" t-as="error" t-key="error_index">
3303
+ <t t-esc="errorMessage(error)"/>
3304
+ </div>
3305
+ </div>
3306
+ </div>
3307
+ </t>
3308
+ </div>
3309
+ </t>
3310
+
3311
+ <t t-name="o-spreadsheet-ConditionalFormattingPanelPreview" owl="1">
3312
+ <div class="o-cf-preview" t-att-class="{ 'o-cf-cursor-ptr': state.mode !== 'reorder' }">
3313
+ <t t-if="cf.rule.type==='IconSetRule'">
3314
+ <div class="o-cf-preview-icon">
3315
+ <t t-call="o-spreadsheet-Icon.{{icons[cf.rule.icons.upper].template}}"/>
3316
+ <t t-call="o-spreadsheet-Icon.{{icons[cf.rule.icons.middle].template}}"/>
3317
+ <t t-call="o-spreadsheet-Icon.{{icons[cf.rule.icons.lower].template}}"/>
3318
+ </div>
3319
+ </t>
3320
+ <t t-else="">
3321
+ <div t-att-style="getStyle(cf.rule)" class="o-cf-preview-image">123</div>
3322
+ </t>
3323
+ <div class="o-cf-preview-description">
3324
+ <div class="o-cf-preview-ruletype">
3325
+ <div class="o-cf-preview-description-rule">
3326
+ <t t-esc="getDescription(cf)"/>
3327
+ </div>
3328
+ </div>
3329
+ <div class="o-cf-preview-range" t-esc="cf.ranges"/>
3330
+ </div>
3331
+ <t t-if="state.mode === 'reorder'">
3332
+ <div class="o-cf-reorder">
3333
+ <t t-if="!cf_first">
3334
+ <div
3335
+ class="o-cf-reorder-button-up o-cf-reorder-button"
3336
+ t-on-click="(ev) => this.reorderRule(cf, 'up', ev)">
3337
+ <t t-call="o-spreadsheet-Icon.CARET_UP"/>
3338
+ </div>
3339
+ </t>
3340
+ <t t-if="!cf_last">
3341
+ <div
3342
+ class="o-cf-reorder-button-down o-cf-reorder-button"
3343
+ t-on-click="(ev) => this.reorderRule(cf, 'down', ev)">
3344
+ <t t-call="o-spreadsheet-Icon.CARET_DOWN"/>
3345
+ </div>
3346
+ </t>
3347
+ </div>
3348
+ </t>
3349
+ <t t-else="">
3350
+ <div class="o-cf-delete">
3351
+ <div
3352
+ class="o-cf-delete-button"
3353
+ t-on-click.stop="(ev) => this.deleteConditionalFormat(cf, ev)"
3354
+ aria-label="Remove rule">
3355
+ <t t-call="o-spreadsheet-Icon.TRASH"/>
3356
+ </div>
3357
+ </div>
3358
+ </t>
3359
+ </div>
3360
+ </t>
3361
+
3362
+ <t t-name="o-spreadsheet-IconSets" owl="1">
3363
+ <div>
3364
+ <div class="o-section-subtitle">Icons</div>
3365
+ <div class="o-cf-iconsets">
3366
+ <div
3367
+ class="o-cf-iconset"
3368
+ t-foreach="['arrows', 'smiley', 'dots']"
3369
+ t-as="iconSet"
3370
+ t-key="iconSet"
3371
+ t-on-click="(ev) => this.setIconSet(iconSet, ev)">
3372
+ <div class="o-cf-icon">
3373
+ <t t-call="o-spreadsheet-Icon.{{icons[iconSets[iconSet].good].template}}"/>
3374
+ </div>
3375
+ <div class="o-cf-icon">
3376
+ <t t-call="o-spreadsheet-Icon.{{icons[iconSets[iconSet].neutral].template}}"/>
3377
+ </div>
3378
+ <div class="o-cf-icon">
3379
+ <t t-call="o-spreadsheet-Icon.{{icons[iconSets[iconSet].bad].template}}"/>
3380
+ </div>
3381
+ </div>
3382
+ </div>
3383
+ </div>
3384
+ </t>
3385
+
3386
+ <t t-name="o-spreadsheet-IconSetInflexionPointRow" owl="1">
3387
+ <tr>
3388
+ <td>
3389
+ <div t-on-click.stop="(ev) => this.toggleMenu('iconSet-'+icon+'Icon', ev)">
3390
+ <div class="o-cf-icon-button">
3391
+ <t t-call="o-spreadsheet-Icon.{{icons[iconValue].template}}"/>
3392
+ </div>
3393
+ </div>
3394
+ <IconPicker
3395
+ t-if="state.openedMenu === 'iconSet-'+icon+'Icon'"
3396
+ onIconPicked="(i) => this.setIcon(icon, i)"
3397
+ />
3398
+ </td>
3399
+ <td>When value is</td>
3400
+ <td>
3401
+ <select class="o-input" name="valueType" t-model="inflectionPointValue.operator">
3402
+ <option value="gt">
3403
+ <span>&#62;</span>
3404
+ </option>
3405
+ <option value="ge">
3406
+ <span>&#8805;</span>
3407
+ </option>
3408
+ </select>
3409
+ </td>
3410
+ <td>
3411
+ <input
3412
+ type="text"
3413
+ class="o-input"
3414
+ t-att-class="{ 'o-invalid': isInflectionPointInvalid(inflectionPoint) }"
3415
+ t-model="rule[inflectionPoint].value"
3416
+ />
3417
+ </td>
3418
+ <td>
3419
+ <select class="o-input" name="valueType" t-model="inflectionPointValue.type">
3420
+ <option value="number">Number</option>
3421
+ <option value="percentage">Percentage</option>
3422
+ <option value="percentile">Percentile</option>
3423
+ <option value="formula">Formula</option>
3424
+ </select>
3425
+ </td>
3426
+ </tr>
3427
+ </t>
3428
+
3429
+ <t t-name="o-spreadsheet-IconSetInflexionPoints" owl="1">
3430
+ <div class="o-inflection">
3431
+ <table>
3432
+ <tr>
3433
+ <th class="o-cf-iconset-icons"/>
3434
+ <th class="o-cf-iconset-text"/>
3435
+ <th class="o-cf-iconset-operator"/>
3436
+ <th class="o-cf-iconset-value">Value</th>
3437
+ <th class="o-cf-iconset-type">Type</th>
3438
+ </tr>
3439
+ <t t-call="o-spreadsheet-IconSetInflexionPointRow">
3440
+ <t t-set="iconValue" t-value="rule.icons.upper"/>
3441
+ <t t-set="icon" t-value="'upper'"/>
3442
+ <t t-set="inflectionPointValue" t-value="rule.upperInflectionPoint"/>
3443
+ <t t-set="inflectionPoint" t-value="'upperInflectionPoint'"/>
3444
+ </t>
3445
+ <t t-call="o-spreadsheet-IconSetInflexionPointRow">
3446
+ <t t-set="iconValue" t-value="rule.icons.middle"/>
3447
+ <t t-set="icon" t-value="'middle'"/>
3448
+ <t t-set="inflectionPointValue" t-value="rule.lowerInflectionPoint"/>
3449
+ <t t-set="inflectionPoint" t-value="'lowerInflectionPoint'"/>
3450
+ </t>
3451
+ <tr>
3452
+ <td>
3453
+ <div t-on-click.stop="(ev) => this.toggleMenu('iconSet-lowerIcon', ev)">
3454
+ <div class="o-cf-icon-button">
3455
+ <t t-call="o-spreadsheet-Icon.{{icons[rule.icons.lower].template}}"/>
3456
+ </div>
3457
+ </div>
3458
+ <IconPicker
3459
+ t-if="state.openedMenu === 'iconSet-lowerIcon'"
3460
+ onIconPicked="(icon) => this.setIcon('lower', icon)"
3461
+ />
3462
+ </td>
3463
+ <td>Else</td>
3464
+ <td/>
3465
+ <td/>
3466
+ <td/>
3467
+ </tr>
3468
+ </table>
3469
+ </div>
3470
+ </t>
3471
+ <t t-name="o-spreadsheet-IconSetEditor" owl="1">
3472
+ <div class="o-cf-iconset-rule">
3473
+ <t t-call="o-spreadsheet-IconSets"/>
3474
+ <t t-call="o-spreadsheet-IconSetInflexionPoints"/>
3475
+ <div class="btn btn-link o_refresh_measures o-cf-iconset-reverse" t-on-click="reverseIcons">
3476
+ <div class="me-1 d-inline-block">
3477
+ <t t-call="o-spreadsheet-Icon.REFRESH"/>
3478
+ </div>
3479
+ Reverse icons
3480
+ </div>
3481
+ </div>
3482
+ </t>
3483
+
3484
+ <t t-name="o-spreadsheet-CustomCurrencyPanel" owl="1">
3485
+ <div class="o-custom-currency">
3486
+ <div class="o-section" t-if="availableCurrencies.length > 1">
3487
+ <div class="o-section-title">Currency</div>
3488
+ <select
3489
+ class="o-input o-available-currencies"
3490
+ t-on-change="(ev) => this.updateSelectCurrency(ev)">
3491
+ <t t-foreach="availableCurrencies" t-as="currency" t-key="currency_index">
3492
+ <option
3493
+ t-att-value="currency_index"
3494
+ t-esc="currencyDisplayName(currency)"
3495
+ t-att-selected="currency_index === state.selectedCurrencyIndex"
3496
+ />
3497
+ </t>
3498
+ </select>
3499
+ </div>
3500
+ <div class="o-section">
3501
+ <div class="o-subsection-left">
3502
+ <div class="o-section-title">Code</div>
3503
+ <input
3504
+ type="text"
3505
+ class="o-input"
3506
+ t-model="state.currencyCode"
3507
+ t-on-input="(ev) => this.updateCode(ev)"
3508
+ />
3509
+ </div>
3510
+ <div class="o-subsection-right">
3511
+ <div class="o-section-title">Symbol</div>
3512
+ <input
3513
+ type="text"
3514
+ class="o-input"
3515
+ t-model="state.currencySymbol"
3516
+ t-on-input="(ev) => this.updateSymbol(ev)"
3517
+ />
3518
+ </div>
3519
+ </div>
3520
+ <div class="o-section">
3521
+ <div class="o-section-title">Format</div>
3522
+ <select
3523
+ class="o-input o-format-proposals"
3524
+ t-on-change="(ev) => this.updateSelectFormat(ev)"
3525
+ t-att-disabled="!formatProposals.length">
3526
+ <t t-foreach="formatProposals" t-as="proposal" t-key="proposal_index">
3527
+ <option
3528
+ t-att-value="proposal_index"
3529
+ t-esc="proposal.example"
3530
+ t-att-selected="proposal_index === state.selectedFormatIndex"
3531
+ />
3532
+ </t>
3533
+ </select>
3534
+ </div>
3535
+ <div class="o-sidePanelButtons">
3536
+ <button
3537
+ class="o-sidePanelButton"
3538
+ t-on-click="() => this.apply()"
3539
+ t-att-disabled="!formatProposals.length || isSameFormat">
3540
+ Apply
3541
+ </button>
3542
+ </div>
3543
+ </div>
3544
+ </t>
3545
+
3546
+ <t t-name="o-spreadsheet-FindAndReplacePanel" owl="1">
3547
+ <div class="o-find-and-replace" tabindex="0" t-ref="findAndReplace">
3548
+ <div class="o-section">
3549
+ <div class="o-section-title">Search</div>
3550
+ <div class="o-input-search-container">
3551
+ <input
3552
+ type="text"
3553
+ class="o-input o-input-with-count"
3554
+ t-on-input="onInput"
3555
+ t-on-keydown="onKeydownSearch"
3556
+ />
3557
+ <div class="o-input-count" t-if="hasSearchResult">
3558
+ <t t-esc="env.model.getters.getCurrentSelectedMatchIndex()+1"/>
3559
+ /
3560
+ <t t-esc="env.model.getters.getSearchMatches().length"/>
3561
+ </div>
3562
+ <div t-elif="!pendingSearch and state.toSearch !== ''" class="o-input-count">0 / 0</div>
3563
+ </div>
3564
+ <div>
3565
+ <!-- TODO: go through this css, the group misses a padding and could profit from BootStrap -->
3566
+ <div class="o-far-item">
3567
+ <label class="o-far-checkbox">
3568
+ <input
3569
+ t-model="state.searchOptions.matchCase"
3570
+ t-on-change="updateSearch"
3571
+ class="o-far-input"
3572
+ type="checkbox"
3573
+ />
3574
+ <span class="o-far-label">Match case</span>
3575
+ </label>
3576
+ </div>
3577
+ <div class="o-far-item">
3578
+ <label class="o-far-checkbox">
3579
+ <input
3580
+ t-model="state.searchOptions.exactMatch"
3581
+ t-on-change="updateSearch"
3582
+ class="o-far-input"
3583
+ type="checkbox"
3584
+ />
3585
+ <span class="o-far-label">Match entire cell content</span>
3586
+ </label>
3587
+ </div>
3588
+ <div class="o-far-item">
3589
+ <label class="o-far-checkbox">
3590
+ <input
3591
+ t-model="state.searchOptions.searchFormulas"
3592
+ t-on-change="searchFormulas"
3593
+ class="o-far-input"
3594
+ type="checkbox"
3595
+ />
3596
+ <span class="o-far-label">Search in formulas</span>
3597
+ </label>
3598
+ </div>
3599
+ </div>
3600
+ </div>
3601
+ <div class="o-sidePanelButtons">
3602
+ <button
3603
+ t-att-disabled="!hasSearchResult"
3604
+ t-on-click="onSelectPreviousCell"
3605
+ class="o-sidePanelButton">
3606
+ Previous
3607
+ </button>
3608
+ <button
3609
+ t-att-disabled="!hasSearchResult"
3610
+ t-on-click="onSelectNextCell"
3611
+ class="o-sidePanelButton">
3612
+ Next
3613
+ </button>
3614
+ </div>
3615
+ <div class="o-section" t-if="!env.model.getters.isReadonly()">
3616
+ <div class="o-section-title">Replace</div>
3617
+ <div class="o-input-search-container">
3618
+ <input
3619
+ type="text"
3620
+ class="o-input o-input-without-count"
3621
+ t-model="state.replaceWith"
3622
+ t-on-keydown="onKeydownReplace"
3623
+ />
3624
+ </div>
3625
+ </div>
3626
+
3627
+ <div class="o-sidePanelButtons" t-if="!env.model.getters.isReadonly()">
3628
+ <button
3629
+ t-att-disabled="env.model.getters.getCurrentSelectedMatchIndex() === null"
3630
+ t-on-click="replace"
3631
+ class="o-sidePanelButton">
3632
+ Replace
3633
+ </button>
3634
+ <button
3635
+ t-att-disabled="env.model.getters.getCurrentSelectedMatchIndex() === null"
3636
+ t-on-click="replaceAll"
3637
+ class="o-sidePanelButton">
3638
+ Replace all
3639
+ </button>
3640
+ </div>
3641
+ </div>
3642
+ </t>
3643
+
3644
+ <t t-name="o-spreadsheet-SettingsPanel" owl="1">
3645
+ <div class="o-settings-panel">
3646
+ <div class="o-section">
3647
+ <div class="o-section-title">Locale</div>
3648
+ <select
3649
+ class="o-input o-type-selector"
3650
+ t-on-change="(ev) => this.onLocaleChange(ev.target.value)">
3651
+ <option
3652
+ t-foreach="supportedLocales"
3653
+ t-as="locale"
3654
+ t-key="locale.code"
3655
+ t-att-value="locale.code"
3656
+ t-esc="locale.name"
3657
+ t-att-selected="currentLocale.code === locale.code"
3658
+ />
3659
+ </select>
3660
+ <div class="o-locale-preview mt-2 ms-3">
3661
+ <div>
3662
+ <span class="fw-bold me-1">Number:</span>
3663
+ <span t-esc="numberFormatPreview"/>
3664
+ </div>
3665
+ <div>
3666
+ <span class="fw-bold me-1">Date:</span>
3667
+ <span t-esc="dateFormatPreview"/>
3668
+ </div>
3669
+ <div>
3670
+ <span class="fw-bold me-1">Date time:</span>
3671
+ <span t-esc="dateTimeFormatPreview"/>
3672
+ </div>
3673
+ </div>
3674
+ </div>
3675
+ </div>
3676
+ </t>
3677
+
3678
+ <t t-name="o-spreadsheet-SidePanel" owl="1">
3679
+ <div class="o-sidePanel">
3680
+ <div class="o-sidePanelHeader">
3681
+ <div class="o-sidePanelTitle" t-esc="getTitle()"/>
3682
+ <div class="o-sidePanelClose" t-on-click="() => this.props.onCloseSidePanel()">✕</div>
3683
+ </div>
3684
+ <div class="o-sidePanelBody">
3685
+ <t
3686
+ t-component="state.panel.Body"
3687
+ t-props="props.panelProps"
3688
+ onCloseSidePanel="props.onCloseSidePanel"
3689
+ t-key="'Body_' + props.component"
3690
+ />
3691
+ </div>
3692
+ <div class="o-sidePanelFooter" t-if="state.panel.Footer">
3693
+ <t
3694
+ t-component="state.panel.Footer"
3695
+ t-props="props.panelProps"
3696
+ t-key="'Footer_' + props.component"
3697
+ />
3698
+ </div>
3699
+ </div>
3700
+ </t>
3701
+
3702
+ <t t-name="o-spreadsheet-SidePanelErrors" owl="1">
3703
+ <t t-foreach="props.messages" t-as="msg" t-key="msg">
3704
+ <div class="d-flex align-items-center" t-att-class="divClasses">
3705
+ <t t-call="o-spreadsheet-Icon.TRIANGLE_EXCLAMATION"/>
3706
+ <span t-esc="msg"/>
3707
+ </div>
3708
+ </t>
3709
+ </t>
3710
+
3711
+ <t t-name="o-spreadsheet-SplitIntoColumnsPanel" owl="1">
3712
+ <div class="o-split-to-cols-panel">
3713
+ <div class="o-section">
3714
+ <div class="o-section-title">Separator</div>
3715
+ <select
3716
+ class="o-input o-type-selector"
3717
+ t-on-change="(ev) => this.onSeparatorChange(ev.target.value)">
3718
+ <option
3719
+ t-foreach="separators"
3720
+ t-as="separator"
3721
+ t-key="separator.value"
3722
+ t-att-value="separator.value"
3723
+ t-esc="separator.name"
3724
+ t-att-selected="state.separatorValue === separator.value"
3725
+ />
3726
+ </select>
3727
+
3728
+ <input
3729
+ class="o-input o-required mt-3"
3730
+ type="text"
3731
+ t-if="state.separatorValue === 'custom'"
3732
+ t-att-value="state.customSeparator"
3733
+ t-on-input="updateCustomSeparator"
3734
+ placeholder="Add any characters or symbol"
3735
+ />
3736
+
3737
+ <div class="o-checkbox">
3738
+ <label>
3739
+ <input
3740
+ type="checkbox"
3741
+ name="add columns"
3742
+ t-att-checked="state.addNewColumns"
3743
+ t-on-change="updateAddNewColumnsCheckbox"
3744
+ />
3745
+ Add new columns to avoid overwriting cells
3746
+ </label>
3747
+ </div>
3748
+
3749
+ <div class="o-sidePanelButtons">
3750
+ <button
3751
+ class="o-sidePanelButton"
3752
+ t-att-class="{'o-disabled': isConfirmDisabled}"
3753
+ t-on-click="confirm">
3754
+ Confirm
3755
+ </button>
3756
+ </div>
3757
+
3758
+ <SidePanelErrors messages="errorMessages" msgType="'error'"/>
3759
+ <SidePanelErrors messages="warningMessages" msgType="'warning'"/>
3760
+ </div>
3761
+ </div>
3762
+ </t>
3763
+
3764
+ <t t-name="o-spreadsheet-Spreadsheet" owl="1">
3765
+ <div
3766
+ class="o-spreadsheet"
3767
+ t-on-keydown="(ev) => !env.isDashboard() and this.onKeydown(ev)"
3768
+ t-att-style="getStyle()">
3769
+ <t t-if="env.isDashboard()">
3770
+ <SpreadsheetDashboard/>
3771
+ </t>
3772
+ <t t-else="">
3773
+ <TopBar
3774
+ onClick="() => this.focusGrid()"
3775
+ onComposerContentFocused="(selection) => this.onTopBarComposerFocused(selection)"
3776
+ focusComposer="focusTopBarComposer"
3777
+ dropdownMaxHeight="gridHeight"
3778
+ />
3779
+ <Grid
3780
+ sidePanelIsOpen="sidePanel.isOpen"
3781
+ focusComposer="focusGridComposer"
3782
+ exposeFocus="(focus) => this._focusGrid = focus"
3783
+ onComposerContentFocused="() => this.onGridComposerContentFocused()"
3784
+ onGridComposerCellFocused="(content, selection) => this.onGridComposerCellFocused(content, selection)"
3785
+ />
3786
+ <SidePanel
3787
+ t-if="sidePanel.isOpen"
3788
+ onCloseSidePanel="() => this.closeSidePanel()"
3789
+ component="sidePanel.component"
3790
+ panelProps="sidePanel.panelProps"
3791
+ />
3792
+ <BottomBar onClick="() => this.focusGrid()"/>
3793
+ </t>
3794
+ </div>
3795
+ </t>
3796
+
3797
+ <t t-name="o-spreadsheet-TopBar" owl="1">
3798
+ <div
3799
+ class="o-spreadsheet-topbar o-two-columns d-flex flex-column user-select-none"
3800
+ t-on-click="props.onClick">
3801
+ <div class="o-topbar-top d-flex justify-content-between">
3802
+ <!-- Menus -->
3803
+ <div class="o-topbar-topleft d-flex">
3804
+ <t t-foreach="menus" t-as="menu" t-key="menu_index">
3805
+ <div
3806
+ t-if="menu.children.length !== 0"
3807
+ class="o-topbar-menu o-hoverable-button rounded"
3808
+ t-att-class="{'active': state.menuState.parentMenu and state.menuState.parentMenu.id === menu.id}"
3809
+ t-on-click="(ev) => this.toggleContextMenu(menu, ev)"
3810
+ t-on-mouseover="(ev) => this.onMenuMouseOver(menu, ev)"
3811
+ t-att-data-id="menu.id">
3812
+ <t t-esc="getMenuName(menu)"/>
3813
+ </div>
3814
+ </t>
3815
+ </div>
3816
+ <div class="o-topbar-topright d-flex justify-content-end">
3817
+ <div t-foreach="topbarComponents" t-as="comp" t-key="comp.id">
3818
+ <t t-component="comp.component"/>
3819
+ </div>
3820
+ </div>
3821
+ </div>
3822
+ <!-- Toolbar and Cell Content -->
3823
+ <div class="d-flex">
3824
+ <div class="o-topbar-toolbar d-flex flex-shrink-0">
3825
+ <!-- Toolbar -->
3826
+ <div
3827
+ t-if="env.model.getters.isReadonly()"
3828
+ class="o-readonly-toolbar d-flex align-items-center text-muted">
3829
+ <span>
3830
+ <i class="fa fa-eye"/>
3831
+ Readonly Access
3832
+ </span>
3833
+ </div>
3834
+ <div t-else="" class="o-toolbar-tools d-flex flex-shrink-0 ms-4">
3835
+ <ActionButton action="EDIT.undo" class="'o-hoverable-button'"/>
3836
+ <ActionButton action="EDIT.redo" class="'o-hoverable-button'"/>
3837
+ <PaintFormatButton class="'o-hoverable-button'"/>
3838
+ <ActionButton action="FORMAT.clearFormat" class="'o-hoverable-button'"/>
3839
+
3840
+ <div class="o-divider"/>
3841
+
3842
+ <ActionButton action="FORMAT.formatPercent" class="'o-hoverable-button'"/>
3843
+ <ActionButton action="FORMAT.decraseDecimalPlaces" class="'o-hoverable-button'"/>
3844
+ <ActionButton action="FORMAT.incraseDecimalPlaces" class="'o-hoverable-button'"/>
3845
+ <ActionButton
3846
+ action="formatNumberMenuItemSpec"
3847
+ onClick="(ev) => this.toggleToolbarContextMenu(formatNumberMenuItemSpec, ev)"
3848
+ hasTriangleDownIcon="true"
3849
+ class="'o-hoverable-button'"
3850
+ />
3851
+
3852
+ <div class="o-divider"/>
3853
+ <FontSizeEditor
3854
+ class="'o-hoverable-button'"
3855
+ onToggle.bind="this.onClick"
3856
+ dropdownStyle="this.dropdownStyle"
3857
+ />
3858
+ <div class="o-divider"/>
3859
+
3860
+ <ActionButton action="FORMAT.formatBold" class="'o-hoverable-button'"/>
3861
+ <ActionButton action="FORMAT.formatItalic" class="'o-hoverable-button'"/>
3862
+ <ActionButton action="FORMAT.formatStrikethrough" class="'o-hoverable-button'"/>
3863
+
3864
+ <ColorPickerWidget
3865
+ currentColor="state.textColor"
3866
+ toggleColorPicker="(ev) => this.toggleDropdownTool('textColorTool', ev)"
3867
+ showColorPicker="state.activeTool === 'textColorTool'"
3868
+ onColorPicked="(color) => this.setColor('textColor', color)"
3869
+ title="env._t('Text Color')"
3870
+ icon="'o-spreadsheet-Icon.TEXT_COLOR'"
3871
+ dropdownMaxHeight="this.props.dropdownMaxHeight"
3872
+ class="'o-hoverable-button o-menu-item-button'"
3873
+ />
3874
+
3875
+ <div class="o-divider"/>
3876
+
3877
+ <ColorPickerWidget
3878
+ currentColor="state.fillColor"
3879
+ toggleColorPicker="(ev) => this.toggleDropdownTool('fillColorTool', ev)"
3880
+ showColorPicker="state.activeTool === 'fillColorTool'"
3881
+ onColorPicked="(color) => this.setColor('fillColor', color)"
3882
+ title="env._t('Fill Color')"
3883
+ icon="'o-spreadsheet-Icon.FILL_COLOR'"
3884
+ dropdownMaxHeight="this.props.dropdownMaxHeight"
3885
+ class="'o-hoverable-button o-menu-item-button'"
3886
+ />
3887
+
3888
+ <BorderEditorWidget
3889
+ class="'o-hoverable-button o-menu-item-button'"
3890
+ toggleBorderEditor="(ev) => this.toggleDropdownTool('borderTool', ev)"
3891
+ showBorderEditor="state.activeTool === 'borderTool'"
3892
+ dropdownMaxHeight="this.props.dropdownMaxHeight"
3893
+ />
3894
+ <ActionButton action="EDIT.mergeCells" class="'o-hoverable-button'"/>
3895
+ <div class="o-divider"/>
3896
+
3897
+ <div class="o-dropdown">
3898
+ <ActionButton
3899
+ action="FORMAT.formatAlignmentHorizontal"
3900
+ hasTriangleDownIcon="true"
3901
+ t-on-click="(ev) => this.toggleDropdownTool('horizontalAlignTool', ev)"
3902
+ class="'o-hoverable-button'"
3903
+ />
3904
+ <div
3905
+ class="o-dropdown-content"
3906
+ t-if="state.activeTool === 'horizontalAlignTool'"
3907
+ t-att-style="dropdownStyle"
3908
+ t-on-click.stop="">
3909
+ <div class="o-dropdown-line">
3910
+ <ActionButton action="FORMAT.formatAlignmentLeft" class="'o-hoverable-button'"/>
3911
+ <ActionButton action="FORMAT.formatAlignmentCenter" class="'o-hoverable-button'"/>
3912
+ <ActionButton action="FORMAT.formatAlignmentRight" class="'o-hoverable-button'"/>
3913
+ </div>
3914
+ </div>
3915
+ </div>
3916
+ <div class="o-dropdown">
3917
+ <ActionButton
3918
+ action="FORMAT.formatAlignmentVertical"
3919
+ hasTriangleDownIcon="true"
3920
+ t-on-click="(ev) => this.toggleDropdownTool('verticalAlignTool', ev)"
3921
+ class="'o-hoverable-button'"
3922
+ />
3923
+ <div
3924
+ class="o-dropdown-content"
3925
+ t-att-style="dropdownStyle"
3926
+ t-if="state.activeTool === 'verticalAlignTool'"
3927
+ t-on-click.stop="">
3928
+ <div class="o-dropdown-line">
3929
+ <ActionButton action="FORMAT.formatAlignmentTop" class="'o-hoverable-button'"/>
3930
+ <ActionButton action="FORMAT.formatAlignmentMiddle" class="'o-hoverable-button'"/>
3931
+ <ActionButton action="FORMAT.formatAlignmentBottom" class="'o-hoverable-button'"/>
3932
+ </div>
3933
+ </div>
3934
+ </div>
3935
+ <div class="o-dropdown">
3936
+ <ActionButton
3937
+ action="FORMAT.formatWrapping"
3938
+ hasTriangleDownIcon="true"
3939
+ t-on-click="(ev) => this.toggleDropdownTool('textWrappingTool', ev)"
3940
+ class="'o-hoverable-button'"
3941
+ />
3942
+ <div
3943
+ class="o-dropdown-content"
3944
+ t-att-style="dropdownStyle"
3945
+ t-if="state.activeTool === 'textWrappingTool'"
3946
+ t-on-click.stop="">
3947
+ <div class="o-dropdown-line">
3948
+ <ActionButton
3949
+ action="FORMAT.formatWrappingOverflow"
3950
+ class="'o-hoverable-button'"
3951
+ />
3952
+ <ActionButton action="FORMAT.formatWrappingWrap" class="'o-hoverable-button'"/>
3953
+ <ActionButton action="FORMAT.formatWrappingClip" class="'o-hoverable-button'"/>
3954
+ </div>
3955
+ </div>
3956
+ </div>
3957
+
3958
+ <div class="o-divider"/>
3959
+
3960
+ <ActionButton action="VIEW.createRemoveFilter" class="'o-hoverable-button'"/>
3961
+ </div>
3962
+ </div>
3963
+ <TopBarComposer
3964
+ focus="props.focusComposer"
3965
+ onComposerContentFocused="props.onComposerContentFocused"
3966
+ />
3967
+ </div>
3968
+ </div>
3969
+ <Menu
3970
+ t-if="state.menuState.isOpen"
3971
+ position="state.menuState.position"
3972
+ menuItems="state.menuState.menuItems"
3973
+ onClose="() => this.closeMenus()"
3974
+ onMenuClicked="() => this.props.onClick()"
3975
+ />
3976
+ </t>
3977
+ </odoo>
3978
+ <!--
3979
+ __info__.version = '16.4.13';
3980
+ __info__.date = '2023-11-03T12:21:35.009Z';
3981
+ __info__.hash = '001985e';
3982
+ -->