@odoo/o-spreadsheet 16.1.25 → 16.1.27

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,3329 @@
1
+ <odoo>
2
+ <t t-name="o-spreadsheet-Autofill" owl="1">
3
+ <div
4
+ class="o-autofill"
5
+ t-on-mousedown="onMouseDown"
6
+ t-att-style="style"
7
+ t-on-dblclick="onDblClick">
8
+ <div class="o-autofill-handler" t-att-style="styleHandler"/>
9
+ <t t-set="tooltip" t-value="getTooltip()"/>
10
+ <div t-if="tooltip" class="o-autofill-nextvalue" t-att-style="styleNextvalue">
11
+ <t t-component="tooltip.component" t-props="tooltip.props"/>
12
+ </div>
13
+ </div>
14
+ </t>
15
+
16
+ <t t-name="o-spreadsheet-BottomBar" owl="1">
17
+ <div
18
+ class="o-spreadsheet-bottom-bar o-two-columns"
19
+ t-on-click="props.onClick"
20
+ t-ref="bottomBar">
21
+ <div
22
+ class="o-sheet-item o-add-sheet"
23
+ t-att-class="{'disabled': env.model.getters.isReadonly()}"
24
+ t-on-click="addSheet">
25
+ <t t-call="o-spreadsheet-Icon.PLUS"/>
26
+ </div>
27
+ <div class="o-sheet-item o-list-sheets" t-on-click="listSheets">
28
+ <t t-call="o-spreadsheet-Icon.LIST"/>
29
+ </div>
30
+ <div class="o-all-sheets flex-shrink-0 me-3">
31
+ <t t-foreach="getVisibleSheets()" t-as="sheet" t-key="sheet.id">
32
+ <div
33
+ class="o-sheet-item o-sheet"
34
+ t-on-click="(ev) => this.activateSheet(sheet.id, ev)"
35
+ t-on-contextmenu.prevent="(ev) => this.onContextMenu(sheet.id, ev)"
36
+ t-att-title="sheet.name"
37
+ t-att-data-id="sheet.id"
38
+ t-att-class="{active: sheet.id === env.model.getters.getActiveSheetId()}">
39
+ <span
40
+ class="o-sheet-name"
41
+ t-esc="sheet.name"
42
+ t-on-dblclick="(ev) => this.onDblClick(sheet.id, ev)"
43
+ />
44
+ <span class="o-sheet-icon" t-on-click="(ev) => this.onIconClick(sheet.id, ev)">
45
+ <t t-call="o-spreadsheet-Icon.TRIANGLE_DOWN"/>
46
+ </span>
47
+ </div>
48
+ </t>
49
+ </div>
50
+
51
+ <t t-set="selectedStatistic" t-value="getSelectedStatistic()"/>
52
+ <div
53
+ t-if="selectedStatistic !== undefined"
54
+ class="o-selection-statistic text-truncate"
55
+ t-on-click="listSelectionStatistics">
56
+ <t t-esc="selectedStatistic"/>
57
+ <span>
58
+ <t t-call="o-spreadsheet-Icon.TRIANGLE_DOWN"/>
59
+ </span>
60
+ </div>
61
+
62
+ <Menu
63
+ t-if="menuState.isOpen"
64
+ position="menuState.position"
65
+ menuItems="menuState.menuItems"
66
+ onClose="() => this.menuState.isOpen=false"
67
+ menuId="menuState.menuId"
68
+ />
69
+ </div>
70
+ </t>
71
+
72
+ <t t-name="o-spreadsheet-ClientTag" owl="1">
73
+ <div>
74
+ <div class="o-client-tag" t-att-style="tagStyle" t-esc="props.name"/>
75
+ </div>
76
+ </t>
77
+
78
+ <t t-name="o-spreadsheet-ColorPicker" owl="1">
79
+ <div
80
+ class="o-color-picker"
81
+ t-att-class="props.dropdownDirection || 'right'"
82
+ t-on-click.stop=""
83
+ t-att-style="colorPickerStyle">
84
+ <div class="o-color-picker-section-name">Standard</div>
85
+ <div class="colors-grid">
86
+ <div
87
+ t-foreach="COLORS"
88
+ t-as="color"
89
+ t-key="color"
90
+ class="o-color-picker-line-item"
91
+ t-att-data-color="color"
92
+ t-on-click="() => this.onColorClick(color)"
93
+ t-attf-style="background-color:{{color}};">
94
+ <div
95
+ t-if="isSameColor(props.currentColor, color)"
96
+ align="center"
97
+ t-attf-style="color:{{getCheckMarkColor()}}">
98
+ ✓
99
+ </div>
100
+ </div>
101
+ </div>
102
+ <div class="o-separator"/>
103
+ <div class="o-color-picker-section-name">
104
+ <span>Custom</span>
105
+ </div>
106
+ <div class="colors-grid">
107
+ <div
108
+ class="o-color-picker-toggler o-color-picker-line-item"
109
+ t-on-click.stop="toggleColorPicker">
110
+ <div class="o-color-picker-toggler-sign">
111
+ <t t-call="o-spreadsheet-Icon.PLUS"/>
112
+ </div>
113
+ </div>
114
+ <div
115
+ t-foreach="env.model.getters.getCustomColors()"
116
+ t-as="color"
117
+ t-key="color"
118
+ class="o-color-picker-line-item"
119
+ t-att-data-color="color"
120
+ t-attf-style="background-color:{{color}};"
121
+ t-on-click="() => this.onColorClick(color)">
122
+ <div
123
+ t-if="isSameColor(props.currentColor, color)"
124
+ align="center"
125
+ t-attf-style="color:{{getCheckMarkColor()}}">
126
+ ✓
127
+ </div>
128
+ </div>
129
+ </div>
130
+ <div t-if="state.showGradient" class="o-custom-selector">
131
+ <div class="o-magnifier-glass" t-att-style="magnifyingGlassStyle"/>
132
+ <div
133
+ class="o-gradient"
134
+ t-on-click.stop="computeCustomColor"
135
+ t-on-mouseout="hideMagnifier"
136
+ t-on-mousemove="moveMagnifier"
137
+ t-on-mouseover="showMagnifier"
138
+ />
139
+ <div class="o-custom-input-preview">
140
+ <input
141
+ type="text"
142
+ t-att-class="{'o-wrong-color': state.isCurrentColorInvalid }"
143
+ t-on-click.stop=""
144
+ t-model="state.currentColor"
145
+ />
146
+ <div class="o-color-preview" t-attf-style="background-color:{{state.currentColor}}"/>
147
+ </div>
148
+ <div class="o-custom-input-buttons">
149
+ <button class="o-add-button" t-on-click="setCustomColor">Add</button>
150
+ </div>
151
+ </div>
152
+ <div class="o-separator"/>
153
+ <div class="o-buttons">
154
+ <button t-on-click="resetColor" class="o-cancel">Reset</button>
155
+ </div>
156
+ </div>
157
+ </t>
158
+
159
+ <t t-name="o-spreadsheet-TextValueProvider" owl="1">
160
+ <div t-att-class="{'o-autocomplete-dropdown':props.values.length}">
161
+ <t t-foreach="props.values" t-as="v" t-key="v.text">
162
+ <div
163
+ t-att-class="{'o-autocomplete-value-focus': props.selectedIndex === v_index}"
164
+ t-on-click.stop.prevent="() => this.props.onValueSelected(v.text)">
165
+ <div class="o-autocomplete-value" t-esc="v.text"/>
166
+ <div
167
+ class="o-autocomplete-description"
168
+ t-esc="v.description"
169
+ t-if="props.selectedIndex === v_index"
170
+ />
171
+ </div>
172
+ </t>
173
+ </div>
174
+ </t>
175
+
176
+ <t t-name="o-spreadsheet-Composer" owl="1">
177
+ <div class="o-composer-container">
178
+ <div
179
+ t-att-class="{ 'o-composer': true, 'text-muted': env.model.getters.isReadonly(), 'unfocusable': env.model.getters.isReadonly() }"
180
+ t-att-style="props.inputStyle"
181
+ t-ref="o_composer"
182
+ tabindex="1"
183
+ t-att-contenteditable="env.model.getters.isReadonly() ? 'false' : 'true'"
184
+ spellcheck="false"
185
+ t-on-keydown="onKeydown"
186
+ t-on-mousedown="onMousedown"
187
+ t-on-input="onInput"
188
+ t-on-keyup="onKeyup"
189
+ t-on-click="onClick"
190
+ t-on-blur="onBlur"
191
+ t-on-paste.stop=""
192
+ t-on-compositionstart="onCompositionStart"
193
+ t-on-compositionend="onCompositionEnd"
194
+ />
195
+
196
+ <div
197
+ t-if="props.focus !== 'inactive' and (autoCompleteState.showProvider or functionDescriptionState.showDescription)"
198
+ class="o-composer-assistant"
199
+ t-att-style="assistantStyle">
200
+ <TextValueProvider
201
+ t-if="autoCompleteState.showProvider"
202
+ values="autoCompleteState.values"
203
+ selectedIndex="autoCompleteState.selectedIndex"
204
+ onValueSelected.bind="this.autoComplete"
205
+ />
206
+ <FunctionDescriptionProvider
207
+ t-if="functionDescriptionState.showDescription"
208
+ functionName="functionDescriptionState.functionName"
209
+ functionDescription="functionDescriptionState.functionDescription"
210
+ argToFocus="functionDescriptionState.argToFocus"
211
+ />
212
+ </div>
213
+ </div>
214
+ </t>
215
+
216
+ <t t-name="o-spreadsheet-FunctionDescriptionProvider" owl="1">
217
+ <div
218
+ class="o-formula-assistant-container"
219
+ t-att-class="{
220
+ 'o-formula-assistant-event-none': assistantState.allowCellSelectionBehind,
221
+ 'o-formula-assistant-event-auto': !assistantState.allowCellSelectionBehind
222
+ }">
223
+ <t t-set="context" t-value="getContext()"/>
224
+ <div
225
+ class="o-formula-assistant"
226
+ t-if="context.functionName"
227
+ t-on-mousemove="onMouseMove"
228
+ t-att-class="{'o-formula-assistant-transparency': assistantState.allowCellSelectionBehind}">
229
+ <div class="o-formula-assistant-head">
230
+ <span t-esc="context.functionName"/>
231
+ (
232
+ <t t-foreach="context.functionDescription.args" t-as="arg" t-key="arg.name">
233
+ <span t-if="arg_index > '0'">,&#xA0;</span>
234
+ <span t-att-class="{ 'o-formula-assistant-focus': context.argToFocus === arg_index }">
235
+ <span>
236
+ <span t-if="arg.optional || arg.repeating || arg.default">[</span>
237
+ <span t-esc="arg.name"/>
238
+ <span t-if="arg.repeating">, ...</span>
239
+ <span t-if="arg.optional || arg.repeating || arg.default">]</span>
240
+ </span>
241
+ </span>
242
+ </t>
243
+ )
244
+ </div>
245
+
246
+ <div class="o-formula-assistant-core">
247
+ <div class="o-formula-assistant-gray">ABOUT</div>
248
+ <div t-esc="context.functionDescription.description"/>
249
+ </div>
250
+
251
+ <t t-foreach="context.functionDescription.args" t-as="arg" t-key="arg.name">
252
+ <div
253
+ class="o-formula-assistant-arg"
254
+ t-att-class="{
255
+ 'o-formula-assistant-gray': context.argToFocus >= '0',
256
+ 'o-formula-assistant-focus': context.argToFocus === arg_index,
257
+ }">
258
+ <div>
259
+ <span t-esc="arg.name"/>
260
+ <span
261
+ t-if="arg.optional || arg.repeating || arg.default ">&#xA0;- [optional]&#xA0;</span>
262
+ <span t-if="arg.default">
263
+ <t t-esc="arg.defaultValue"/>
264
+ <span>&#xA0;by default</span>
265
+ </span>
266
+ <span t-if="arg.repeating">repeatable</span>
267
+ </div>
268
+ <div class="o-formula-assistant-arg-description" t-esc="arg.description"/>
269
+ </div>
270
+ </t>
271
+ </div>
272
+ </div>
273
+ </t>
274
+
275
+ <t t-name="o-spreadsheet-GridComposer" owl="1">
276
+ <div class="o-grid-composer" t-att-style="containerStyle" t-ref="gridComposer">
277
+ <Composer
278
+ focus="props.focus"
279
+ inputStyle="composerStyle"
280
+ rect="composerState.rect"
281
+ delimitation="composerState.delimitation"
282
+ onComposerUnmounted="props.onComposerUnmounted"
283
+ onComposerContentFocused="props.onComposerContentFocused"
284
+ />
285
+ </div>
286
+ </t>
287
+
288
+ <t t-name="o-spreadsheet-SpreadsheetDashboard" owl="1">
289
+ <div
290
+ class="o-grid o-two-columns"
291
+ tabindex="-1"
292
+ t-on-wheel="onMouseWheel"
293
+ t-on-click="onClosePopover">
294
+ <div class="mx-auto h-100 position-relative" t-ref="grid" t-att-style="gridContainer">
295
+ <GridOverlay
296
+ onCellHovered.bind="onCellHovered"
297
+ onGridResized.bind="onGridResized"
298
+ onGridMoved.bind="moveCanvas"
299
+ gridOverlayDimensions="gridOverlayDimensions"
300
+ />
301
+ <canvas t-ref="canvas"/>
302
+ <GridPopover
303
+ hoveredCell="hoveredCell"
304
+ gridRect="getGridRect()"
305
+ onMouseWheel.bind="onMouseWheel"
306
+ onClosePopover.bind="onClosePopover"
307
+ />
308
+ <div
309
+ t-foreach="getClickableCells()"
310
+ t-as="clickableCell"
311
+ t-key="clickableCell.tKey"
312
+ class="o-dashboard-clickable-cell"
313
+ t-on-click="() => this.selectClickableCell(clickableCell)"
314
+ t-on-contextmenu.prevent=""
315
+ t-att-style="getCellClickableStyle(clickableCell.coordinates)"
316
+ />
317
+ <FilterIconsOverlay/>
318
+ </div>
319
+ <VerticalScrollBar/>
320
+ <HorizontalScrollBar/>
321
+ <div class="o-scrollbar corner"/>
322
+ </div>
323
+ </t>
324
+
325
+ <t t-name="o-spreadsheet-ErrorToolTip" owl="1">
326
+ <div class="o-error-tooltip">
327
+ <t t-esc="props.text"/>
328
+ </div>
329
+ </t>
330
+
331
+ <t t-name="o-spreadsheet-ChartJsComponent" owl="1">
332
+ <canvas class="o-figure-canvas w-100 h-100" t-att-style="canvasStyle" t-ref="graphContainer"/>
333
+ </t>
334
+
335
+ <t t-name="o-spreadsheet-ScorecardChart" owl="1">
336
+ <div class="o-scorecard w-100 h-100" t-att-style="chartStyle" t-ref="chart">
337
+ <t t-set="textStyles" t-value="getTextStyles()"/>
338
+ <div t-if="title" class="o-title-text" t-esc="title" t-att-style="textStyles.titleStyle"/>
339
+ <div class="o-scorecard-content" t-att-style="chartContentStyle">
340
+ <div class="o-key-text" t-if="keyValue" t-esc="keyValue" t-att-style="textStyles.keyStyle"/>
341
+ <t t-if="baseline || baselineDescr">
342
+ <div class="o-baseline-text" t-att-style="textStyles.baselineStyle">
343
+ <t t-if="baseline">
344
+ <t t-if="baselineArrowDirection === 'up'">
345
+ <t t-call="o-spreadsheet-Icon.ARROW_UP">
346
+ <t t-set="color" t-value="'fill : ' + runtime.baselineColor"/>
347
+ </t>
348
+ </t>
349
+ <t t-if="baselineArrowDirection === 'down'">
350
+ <t t-call="o-spreadsheet-Icon.ARROW_DOWN">
351
+ <t t-set="color" t-value="'fill : ' + runtime.baselineColor"/>
352
+ </t>
353
+ </t>
354
+ <span t-att-style="textStyles.baselineValueStyle" class="o-baseline-text-value">
355
+ <t t-esc="baseline"/>
356
+ </span>
357
+ </t>
358
+ <span t-att-style="textStyles.baselineDescrStyle" class="o-baseline-text-description">
359
+ <t t-esc="env._t(baselineDescr)"/>
360
+ </span>
361
+ </div>
362
+ </t>
363
+ </div>
364
+ </div>
365
+ </t>
366
+
367
+ <t t-name="o-spreadsheet-FigureComponent" owl="1">
368
+ <div class="o-figure-wrapper pe-auto" t-att-style="wrapperStyle">
369
+ <div
370
+ class="o-figure w-100 h-100"
371
+ t-on-mousedown.stop="(ev) => this.onMouseDown(ev)"
372
+ t-ref="figure"
373
+ t-att-style="props.style"
374
+ tabindex="0"
375
+ t-on-keydown="(ev) => this.onKeyDown(ev)"
376
+ t-on-keyup.stop="">
377
+ <t
378
+ t-component="figureRegistry.get(props.figure.tag).Component"
379
+ t-key="props.figure.id"
380
+ onFigureDeleted="props.onFigureDeleted"
381
+ figure="props.figure"
382
+ />
383
+ </div>
384
+ <div class="o-figure-border w-100 h-100 position-absolute pe-none" t-att-style="borderStyle"/>
385
+ <t t-if="isSelected">
386
+ <div
387
+ class="o-fig-anchor o-top"
388
+ t-att-style="this.getResizerPosition('top')"
389
+ t-on-mousedown="(ev) => this.clickAnchor(0,-1, ev)"
390
+ />
391
+ <div
392
+ class="o-fig-anchor o-topRight"
393
+ t-att-style="this.getResizerPosition('top right')"
394
+ t-on-mousedown="(ev) => this.clickAnchor(1,-1, ev)"
395
+ />
396
+ <div
397
+ class="o-fig-anchor o-right"
398
+ t-att-style="this.getResizerPosition('right')"
399
+ t-on-mousedown="(ev) => this.clickAnchor(1,0, ev)"
400
+ />
401
+ <div
402
+ class="o-fig-anchor o-bottomRight"
403
+ t-att-style="this.getResizerPosition('bottom right')"
404
+ t-on-mousedown="(ev) => this.clickAnchor(1,1, ev)"
405
+ />
406
+ <div
407
+ class="o-fig-anchor o-bottom"
408
+ t-att-style="this.getResizerPosition('bottom')"
409
+ t-on-mousedown="(ev) => this.clickAnchor(0,1, ev)"
410
+ />
411
+ <div
412
+ class="o-fig-anchor o-bottomLeft"
413
+ t-att-style="this.getResizerPosition('bottom left')"
414
+ t-on-mousedown="(ev) => this.clickAnchor(-1,1, ev)"
415
+ />
416
+ <div
417
+ class="o-fig-anchor o-left"
418
+ t-att-style="this.getResizerPosition('left')"
419
+ t-on-mousedown="(ev) => this.clickAnchor(-1,0, ev)"
420
+ />
421
+ <div
422
+ class="o-fig-anchor o-topLeft"
423
+ t-att-style="this.getResizerPosition('top left')"
424
+ t-on-mousedown="(ev) => this.clickAnchor(-1,-1, ev)"
425
+ />
426
+ </t>
427
+ </div>
428
+ </t>
429
+
430
+ <t t-name="o-spreadsheet-ChartFigure" owl="1">
431
+ <div
432
+ class="o-chart-container w-100 h-100"
433
+ t-ref="chartContainer"
434
+ t-on-contextmenu.prevent.stop="(ev) => !env.isDashboard() and !env.model.getters.isReadonly() and this.onContextMenu(ev)">
435
+ <div class="o-figure-menu" t-if="!env.isDashboard()">
436
+ <div
437
+ class="o-figure-menu-item"
438
+ t-if="!env.model.getters.isReadonly()"
439
+ t-on-click="showMenu"
440
+ t-ref="menuButton"
441
+ t-on-contextmenu.prevent.stop="showMenu">
442
+ <t t-call="o-spreadsheet-Icon.LIST"/>
443
+ </div>
444
+ </div>
445
+ <t
446
+ t-component="chartComponent"
447
+ figure="this.props.figure"
448
+ t-key="this.props.figure.id + '-' + chartType"
449
+ />
450
+
451
+ <Menu
452
+ t-if="menuState.isOpen"
453
+ position="menuState.position"
454
+ menuItems="menuState.menuItems"
455
+ onClose="() => this.menuState.isOpen=false"
456
+ />
457
+ </div>
458
+ </t>
459
+
460
+ <t t-name="o-spreadsheet-FiguresContainer" owl="1">
461
+ <div>
462
+ <t t-foreach="containers" t-as="container" t-key="container.type">
463
+ <div
464
+ class="o-figure-container position-absolute pe-none overflow-hidden"
465
+ t-att-style="container.style"
466
+ t-att-data-id="container.type + 'Container'">
467
+ <div
468
+ class="o-figure-viewport-inverse w-0 h-0 overflow-visible position-absolute"
469
+ t-att-style="container.inverseViewportStyle">
470
+ <t t-foreach="container.figures" t-as="figure" t-key="figure.id">
471
+ <FigureComponent
472
+ onFigureDeleted="this.props.onFigureDeleted"
473
+ figure="figure"
474
+ style="getFigureStyle(figure)"
475
+ onMouseDown="(ev) => this.startDraggingFigure(figure, ev)"
476
+ onClickAnchor="(dirX, dirY, ev) => this.startResize(figure, dirX, dirY, ev)"
477
+ />
478
+ </t>
479
+ </div>
480
+ </div>
481
+ </t>
482
+ </div>
483
+ </t>
484
+
485
+ <t t-name="o-spreadsheet-ImageFigure" owl="1">
486
+ <div class="o-figure-menu" t-if="!env.isDashboard()">
487
+ <div
488
+ class="o-figure-menu-item"
489
+ t-if="!env.model.getters.isReadonly()"
490
+ t-on-click="showMenu"
491
+ t-ref="menuButton"
492
+ t-on-contextmenu.prevent.stop="showMenu">
493
+ <t t-call="o-spreadsheet-Icon.LIST"/>
494
+ </div>
495
+ </div>
496
+ <img
497
+ t-ref="o-image"
498
+ t-att-src="getImagePath"
499
+ class="w-100 h-100"
500
+ t-on-contextmenu.prevent.stop="(ev) => !env.isDashboard() and !env.model.getters.isReadonly() and this.onContextMenu(ev)"
501
+ />
502
+ <Menu
503
+ t-if="menuState.isOpen"
504
+ position="menuState.position"
505
+ menuItems="menuState.menuItems"
506
+ onClose="() => this.menuState.isOpen=false"
507
+ />
508
+ </t>
509
+
510
+ <t t-name="o-spreadsheet-FilterIcon" owl="1">
511
+ <div class="o-filter-icon" t-att-style="style" t-on-click.stop="props.onClick">
512
+ <t t-if="props.isActive" t-call="o-spreadsheet-Icon.FILTER_ICON_ACTIVE"/>
513
+ <t t-else="" t-call="o-spreadsheet-Icon.FILTER_ICON"/>
514
+ </div>
515
+ </t>
516
+
517
+ <t t-name="o-spreadsheet-FilterIconsOverlay" owl="1">
518
+ <t
519
+ t-foreach="getVisibleFilterHeaders()"
520
+ t-as="header"
521
+ t-key="'filter'+header.col + '_' + header.row">
522
+ <FilterIcon
523
+ position="getFilterHeaderPosition(header)"
524
+ isActive="isFilterActive(header)"
525
+ t-key="'icon_'+header.col + '_' + header.row"
526
+ onClick="() => this.toggleFilterMenu(header)"
527
+ />
528
+ </t>
529
+ </t>
530
+
531
+ <t t-name="o-spreadsheet-FilterMenu" owl="1">
532
+ <div class="o-filter-menu d-flex flex-column bg-white" t-on-wheel.stop="">
533
+ <div t-if="!isReadonly">
534
+ <div class="o-filter-menu-item" t-on-click="() => this.sortFilterZone('ascending')">
535
+ Sort ascending (A ⟶ Z)
536
+ </div>
537
+ <div class="o-filter-menu-item" t-on-click="() => this.sortFilterZone('descending')">
538
+ Sort descending (Z ⟶ A)
539
+ </div>
540
+ </div>
541
+ <div class="o-separator" t-if="!isReadonly"/>
542
+ <div class="o-filter-menu-actions">
543
+ <div class="o-filter-menu-action-text" t-on-click="selectAll">Select all</div>
544
+ <div class="o-filter-menu-action-text" t-on-click="clearAll">Clear</div>
545
+ </div>
546
+ <div class="position-relative">
547
+ <input
548
+ class="w-100"
549
+ t-ref="filterMenuSearchBar"
550
+ type="text"
551
+ t-model="state.textFilter"
552
+ placeholder="Search..."
553
+ t-on-keydown="onKeyDown"
554
+ />
555
+ <i class="o-search-icon position-absolute">
556
+ <t t-call="o-spreadsheet-Icon.SEARCH"/>
557
+ </i>
558
+ </div>
559
+ <div
560
+ class="o-filter-menu-list d-flex flex-column rounded"
561
+ t-ref="filterValueList"
562
+ t-on-click="this.clearScrolledToValue"
563
+ t-on-scroll="this.clearScrolledToValue">
564
+ <t t-foreach="displayedValues" t-as="value" t-key="value.string">
565
+ <FilterMenuValueItem
566
+ onClick="() => this.checkValue(value)"
567
+ onMouseMove="() => this.onMouseMove(value)"
568
+ value="value.string"
569
+ isChecked="value.checked"
570
+ isSelected="value.string === state.selectedValue"
571
+ scrolledTo="value.scrolledTo"
572
+ />
573
+ </t>
574
+ <div
575
+ t-if="displayedValues.length === 0"
576
+ class="o-filter-menu-no-values d-flex align-items-center justify-content-center w-100 h-100 ">
577
+ No results
578
+ </div>
579
+ </div>
580
+ <div class="o-filter-menu-buttons d-flex justify-content-end">
581
+ <div class="o-filter-menu-button o-filter-menu-button-cancel" t-on-click="cancel">
582
+ Cancel
583
+ </div>
584
+ <div class="o-filter-menu-button o-filter-menu-button-primary" t-on-click="confirm">
585
+ Confirm
586
+ </div>
587
+ </div>
588
+ </div>
589
+ </t>
590
+
591
+ <t t-name="o-spreadsheet-FilterMenuValueItem" owl="1">
592
+ <div
593
+ t-on-click="this.props.onClick"
594
+ t-on-mousemove="this.props.onMouseMove"
595
+ class="o-filter-menu-item o-filter-menu-value"
596
+ t-ref="menuValueItem"
597
+ t-att-class="{'selected': this.props.isSelected}">
598
+ <div>
599
+ <div class="o-filter-menu-value-checked">
600
+ <span t-if="this.props.isChecked">✓</span>
601
+ </div>
602
+ </div>
603
+ <div class="o-filter-menu-value-text text-truncate">
604
+ <t t-if="this.props.value === ''">(Blanks)</t>
605
+ <t t-else="" t-esc="this.props.value"/>
606
+ </div>
607
+ </div>
608
+ </t>
609
+
610
+ <t t-name="o-spreadsheet-Grid" owl="1">
611
+ <div
612
+ class="o-grid"
613
+ tabindex="-1"
614
+ t-att-class="{'o-two-columns': !props.sidePanelIsOpen}"
615
+ t-on-click="focus"
616
+ t-on-keydown="onKeydown"
617
+ t-on-wheel="onMouseWheel"
618
+ t-ref="grid">
619
+ <GridOverlay
620
+ onCellClicked.bind="onCellClicked"
621
+ onCellDoubleClicked.bind="onCellDoubleClicked"
622
+ onCellRightClicked.bind="onCellRightClicked"
623
+ onCellHovered.bind="onCellHovered"
624
+ onGridResized.bind="onGridResized"
625
+ onGridMoved.bind="moveCanvas"
626
+ gridOverlayDimensions="gridOverlayDimensions"
627
+ onFigureDeleted.bind="focus"
628
+ />
629
+ <HeadersOverlay onOpenContextMenu="(type, x, y) => this.toggleContextMenu(type, x, y)"/>
630
+
631
+ <t t-if="env.model.getters.getEditionMode() !== 'inactive'">
632
+ <GridComposer
633
+ onComposerUnmounted="() => this.focus()"
634
+ onComposerContentFocused="props.onComposerContentFocused"
635
+ focus="props.focusComposer"
636
+ />
637
+ </t>
638
+ <t else="1">
639
+ <input
640
+ class="position-absolute"
641
+ style="z-index:-1000;"
642
+ t-on-input="onInput"
643
+ t-on-contextmenu="onInputContextMenu"
644
+ t-ref="hiddenInput"
645
+ />
646
+ </t>
647
+ <canvas t-ref="canvas"/>
648
+ <t
649
+ t-foreach="env.model.getters.getClientsToDisplay()"
650
+ t-as="client"
651
+ t-key="getClientPositionKey(client)">
652
+ <ClientTag
653
+ name="client.name"
654
+ color="client.color"
655
+ col="client.position.col"
656
+ row="client.position.row"
657
+ active="isCellHovered(client.position.col, client.position.row)"
658
+ />
659
+ </t>
660
+ <GridPopover
661
+ t-if="!menuState.isOpen"
662
+ hoveredCell="hoveredCell"
663
+ gridRect="getGridRect()"
664
+ onMouseWheel.bind="onMouseWheel"
665
+ onClosePopover.bind="onClosePopover"
666
+ />
667
+ <t t-if="env.model.getters.getEditionMode() === 'inactive' and isAutoFillActive()">
668
+ <Autofill position="getAutofillPosition()"/>
669
+ </t>
670
+ <t t-if="env.model.getters.getEditionMode() !== 'inactive'">
671
+ <t t-foreach="env.model.getters.getHighlights()" t-as="highlight" t-key="highlight_index">
672
+ <t t-if="highlight.sheetId === env.model.getters.getActiveSheetId()">
673
+ <Highlight zone="highlight.zone" color="highlight.color"/>
674
+ </t>
675
+ </t>
676
+ </t>
677
+ <Menu
678
+ t-if="menuState.isOpen"
679
+ menuItems="menuState.menuItems"
680
+ position="menuState.position"
681
+ onClose="() => this.closeMenu()"
682
+ />
683
+ <FilterIconsOverlay gridPosition="{ x: HEADER_WIDTH, y : HEADER_HEIGHT }"/>
684
+ <VerticalScrollBar topOffset="HEADER_HEIGHT"/>
685
+ <HorizontalScrollBar leftOffset="HEADER_WIDTH"/>
686
+ <div class="o-scrollbar corner"/>
687
+ </div>
688
+ </t>
689
+
690
+ <t t-name="o-spreadsheet-GridOverlay" owl="1">
691
+ <div
692
+ t-ref="gridOverlay"
693
+ class="o-grid-overlay overflow-hidden"
694
+ t-att-style="props.gridOverlayDimensions"
695
+ t-on-mousedown="onMouseDown"
696
+ t-on-dblclick.self="onDoubleClick"
697
+ t-on-contextmenu="onContextMenu">
698
+ <FiguresContainer onFigureDeleted="props.onFigureDeleted"/>
699
+ </div>
700
+ </t>
701
+
702
+ <t t-name="o-spreadsheet-GridPopover" owl="1">
703
+ <Popover
704
+ t-if="cellPopover.isOpen"
705
+ positioning="cellPopover.cellCorner"
706
+ maxHeight="cellPopover.Component.size and cellPopover.Component.size.maxHeight"
707
+ maxWidth="cellPopover.Component.size and cellPopover.Component.size.maxHidth"
708
+ anchorRect="cellPopover.anchorRect"
709
+ containerRect="env.getPopoverContainerRect()"
710
+ onMouseWheel="props.onMouseWheel"
711
+ zIndex="zIndex">
712
+ <t
713
+ t-component="cellPopover.Component"
714
+ t-props="{...cellPopover.props, onClosed : () => props.onClosePopover()}"
715
+ />
716
+ </Popover>
717
+ </t>
718
+
719
+ <t t-name="o-spreadsheet-HeadersOverlay" owl="1">
720
+ <div class="o-overlay">
721
+ <ColResizer onOpenContextMenu="props.onOpenContextMenu"/>
722
+ <RowResizer onOpenContextMenu="props.onOpenContextMenu"/>
723
+ <div class="all" t-on-mousedown.self="selectAll"/>
724
+ </div>
725
+ </t>
726
+
727
+ <t t-name="o-spreadsheet-RowResizer" owl="1">
728
+ <div
729
+ class="o-row-resizer"
730
+ t-on-mousemove.self="onMouseMove"
731
+ t-on-mouseleave="onMouseLeave"
732
+ t-on-mousedown.self.prevent="select"
733
+ t-ref="rowResizer"
734
+ t-on-mouseup.self="onMouseUp"
735
+ t-on-contextmenu.self="onContextMenu"
736
+ t-att-class="{'o-grab': state.waitingForMove, 'o-dragging': state.isMoving}">
737
+ <div
738
+ t-if="state.isMoving"
739
+ class="dragging-row-line"
740
+ t-attf-style="top:{{state.draggerLinePosition}}px;"
741
+ />
742
+ <div
743
+ t-if="state.isMoving"
744
+ class="dragging-row-shadow"
745
+ t-attf-style="top:{{state.draggerShadowPosition}}px; height:{{state.draggerShadowThickness}}px;"
746
+ />
747
+ <t t-if="state.resizerIsActive">
748
+ <div
749
+ class="o-handle"
750
+ t-on-mousedown="onMouseDown"
751
+ t-on-dblclick="onDblClick"
752
+ t-on-contextmenu.prevent=""
753
+ t-attf-style="top:{{state.draggerLinePosition - 2}}px;">
754
+ <div class="dragging-resizer" t-if="state.isResizing"/>
755
+ </div>
756
+ </t>
757
+ <t
758
+ t-foreach="env.model.getters.getHiddenRowsGroups(env.model.getters.getActiveSheetId())"
759
+ t-as="hiddenItem"
760
+ t-key="hiddenItem_index">
761
+ <t t-if="!hiddenItem.includes(0)">
762
+ <div
763
+ class="o-unhide"
764
+ t-att-data-index="hiddenItem_index"
765
+ t-attf-style="top:{{unhideStyleValue(hiddenItem[0]) - 17}}px;"
766
+ t-on-click="() => this.unhide(hiddenItem)">
767
+ <t t-call="o-spreadsheet-Icon.TRIANGLE_UP"/>
768
+ </div>
769
+ </t>
770
+ <t
771
+ t-if="!hiddenItem.includes(env.model.getters.getNumberRows(env.model.getters.getActiveSheetId())-1)">
772
+ <div
773
+ class="o-unhide"
774
+ t-att-data-index="hiddenItem_index"
775
+ t-attf-style="top:{{unhideStyleValue(hiddenItem[0]) + 3}}px;"
776
+ t-on-click="() => this.unhide(hiddenItem)">
777
+ <t t-call="o-spreadsheet-Icon.TRIANGLE_DOWN"/>
778
+ </div>
779
+ </t>
780
+ </t>
781
+ </div>
782
+ </t>
783
+
784
+ <t t-name="o-spreadsheet-ColResizer" owl="1">
785
+ <div
786
+ class="o-col-resizer"
787
+ t-on-mousemove.self="onMouseMove"
788
+ t-on-mouseleave="onMouseLeave"
789
+ t-on-mousedown.self.prevent="select"
790
+ t-ref="colResizer"
791
+ t-on-mouseup.self="onMouseUp"
792
+ t-on-contextmenu.self="onContextMenu"
793
+ t-att-class="{'o-grab': state.waitingForMove, 'o-dragging': state.isMoving, }">
794
+ <div
795
+ t-if="state.isMoving"
796
+ class="dragging-col-line"
797
+ t-attf-style="left:{{state.draggerLinePosition}}px;"
798
+ />
799
+ <div
800
+ t-if="state.isMoving"
801
+ class="dragging-col-shadow"
802
+ t-attf-style="left:{{state.draggerShadowPosition}}px; width:{{state.draggerShadowThickness}}px"
803
+ />
804
+ <t t-if="state.resizerIsActive">
805
+ <div
806
+ class="o-handle"
807
+ t-on-mousedown="onMouseDown"
808
+ t-on-dblclick="onDblClick"
809
+ t-on-contextmenu.prevent=""
810
+ t-attf-style="left:{{state.draggerLinePosition - 2}}px;">
811
+ <div class="dragging-resizer" t-if="state.isResizing"/>
812
+ </div>
813
+ </t>
814
+ <t
815
+ t-foreach="env.model.getters.getHiddenColsGroups(env.model.getters.getActiveSheetId())"
816
+ t-as="hiddenItem"
817
+ t-key="hiddenItem_index">
818
+ <t t-if="!hiddenItem.includes(0)">
819
+ <div
820
+ class="o-unhide"
821
+ t-att-data-index="hiddenItem_index"
822
+ t-attf-style="left:{{unhideStyleValue(hiddenItem[0]) - 17}}px; margin-right:6px;"
823
+ t-on-click="() => this.unhide(hiddenItem)">
824
+ <t t-call="o-spreadsheet-Icon.TRIANGLE_LEFT"/>
825
+ </div>
826
+ </t>
827
+ <t
828
+ t-if="!hiddenItem.includes(env.model.getters.getNumberCols(env.model.getters.getActiveSheetId())-1)">
829
+ <div
830
+ class="o-unhide"
831
+ t-att-data-index="hiddenItem_index"
832
+ t-attf-style="left:{{unhideStyleValue(hiddenItem[0]) + 3}}px;"
833
+ t-on-click="() => this.unhide(hiddenItem)">
834
+ <t t-call="o-spreadsheet-Icon.TRIANGLE_RIGHT"/>
835
+ </div>
836
+ </t>
837
+ </t>
838
+ </div>
839
+ </t>
840
+
841
+ <t t-name="o-spreadsheet-Border" owl="1">
842
+ <div
843
+ class="o-border"
844
+ t-on-mousedown.prevent="onMouseDown"
845
+ t-att-style="style"
846
+ t-att-class="{
847
+ 'o-moving': props.isMoving,
848
+ 'o-border-n': props.orientation === 'n',
849
+ 'o-border-s': props.orientation === 's',
850
+ 'o-border-w': props.orientation === 'w',
851
+ 'o-border-e': props.orientation === 'e',
852
+ }"
853
+ />
854
+ </t>
855
+
856
+ <t t-name="o-spreadsheet-Corner" owl="1">
857
+ <div
858
+ class="o-corner"
859
+ t-on-mousedown.prevent="onMouseDown"
860
+ t-att-style="style"
861
+ t-att-class="{
862
+ 'o-resizing': props.isResizing,
863
+ 'o-corner-nw': props.orientation === 'nw',
864
+ 'o-corner-ne': props.orientation === 'ne',
865
+ 'o-corner-sw': props.orientation === 'sw',
866
+ 'o-corner-se': props.orientation === 'se',
867
+ }"
868
+ />
869
+ </t>
870
+
871
+ <t t-name="o-spreadsheet-Highlight" owl="1">
872
+ <div class="o-highlight" t-ref="highlight">
873
+ <t t-foreach="['n', 's', 'w', 'e']" t-as="orientation" t-key="orientation">
874
+ <Border
875
+ onMoveHighlight="(x, y) => this.onMoveHighlight(x,y)"
876
+ isMoving='highlightState.shiftingMode === "isMoving"'
877
+ orientation="orientation"
878
+ zone="props.zone"
879
+ />
880
+ </t>
881
+ <t t-foreach="['nw', 'ne', 'sw', 'se']" t-as="orientation" t-key="orientation">
882
+ <Corner
883
+ onResizeHighlight="(isLeft, isTop) => this.onResizeHighlight(isLeft, isTop)"
884
+ isResizing='highlightState.shiftingMode === "isResizing"'
885
+ orientation="orientation"
886
+ zone="props.zone"
887
+ color="props.color"
888
+ />
889
+ </t>
890
+ </div>
891
+ </t>
892
+
893
+ <t t-name="o-spreadsheet-IconPicker" owl="1">
894
+ <div class="o-icon-picker">
895
+ <t t-foreach="iconSets" t-as="iconSet" t-key="iconSet">
896
+ <div class="o-cf-icon-line">
897
+ <div
898
+ class="o-icon-picker-item"
899
+ t-on-click="() => this.onIconClick(iconSets[iconSet].good)">
900
+ <t t-call="o-spreadsheet-Icon.{{icons[iconSets[iconSet].good].template}}"/>
901
+ </div>
902
+ <div
903
+ class="o-icon-picker-item"
904
+ t-on-click="() => this.onIconClick(iconSets[iconSet].neutral)">
905
+ <t t-call="o-spreadsheet-Icon.{{icons[iconSets[iconSet].neutral].template}}"/>
906
+ </div>
907
+ <div
908
+ class="o-icon-picker-item"
909
+ t-on-click="() => this.onIconClick(iconSets[iconSet].bad)">
910
+ <t t-call="o-spreadsheet-Icon.{{icons[iconSets[iconSet].bad].template}}"/>
911
+ </div>
912
+ </div>
913
+ </t>
914
+ </div>
915
+ </t>
916
+
917
+ <t t-name="o-spreadsheet-Icon.UNDO" owl="1">
918
+ <svg class="o-icon">
919
+ <path
920
+ fill="#000000"
921
+ d="M11.5656391,4.43436088 L9,7 L16,7 L16,0 L13.0418424,2.95815758 C11.5936787,1.73635959 9.72260775,1 7.67955083,1 C4.22126258,1 1.25575599,3.10984908 0,6 L2,7 C2.93658775,4.60974406 5.12943697,3.08011229 7.67955083,3 C9.14881247,3.0528747 10.4994783,3.57862053 11.5656391,4.43436088 Z"
922
+ transform="matrix(-1 0 0 1 17 5)"
923
+ />
924
+ </svg>
925
+ </t>
926
+ <t t-name="o-spreadsheet-Icon.REDO" owl="1">
927
+ <svg class="o-icon">
928
+ <path
929
+ fill="#000000"
930
+ d="M11.5656391,4.43436088 L9,7 L16,7 L16,0 L13.0418424,2.95815758 C11.5936787,1.73635959 9.72260775,1 7.67955083,1 C4.22126258,1 1.25575599,3.10984908 0,6 L2,7 C2.93658775,4.60974406 5.12943697,3.08011229 7.67955083,3 C9.14881247,3.0528747 10.4994783,3.57862053 11.5656391,4.43436088 Z"
931
+ transform="translate(1 5)"
932
+ />
933
+ </svg>
934
+ </t>
935
+ <t t-name="o-spreadsheet-Icon.PAINT_FORMAT" owl="1">
936
+ <svg class="o-icon">
937
+ <path
938
+ fill="#000000"
939
+ 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"
940
+ transform="translate(3 2)"
941
+ />
942
+ </svg>
943
+ </t>
944
+ <t t-name="o-spreadsheet-Icon.CLEAR_FORMAT" owl="1">
945
+ <svg class="o-icon">
946
+ <path
947
+ fill="#000000"
948
+ d="M0.27,1.55 L5.43,6.7 L3,12 L5.5,12 L7.14,8.42 L11.73,13 L13,11.73 L1.55,0.27 L0.27,1.55 L0.27,1.55 Z M3.82,0 L5.82,2 L7.58,2 L7.03,3.21 L8.74,4.92 L10.08,2 L14,2 L14,0 L3.82,0 L3.82,0 Z"
949
+ transform="translate(2 3)"
950
+ />
951
+ </svg>
952
+ </t>
953
+ <t t-name="o-spreadsheet-Icon.TRIANGLE_DOWN" owl="1">
954
+ <svg class="o-icon">
955
+ <polygon fill="#000000" points="0 0 4 4 8 0" transform="translate(5 7)"/>
956
+ </svg>
957
+ </t>
958
+ <t t-name="o-spreadsheet-Icon.TRIANGLE_UP" owl="1">
959
+ <svg class="o-icon">
960
+ <polygon fill="#000000" points="4 0 0 4 8 4" transform="translate(5 7)"/>
961
+ </svg>
962
+ </t>
963
+ <t t-name="o-spreadsheet-Icon.TRIANGLE_RIGHT" owl="1">
964
+ <svg class="o-icon">
965
+ <polygon fill="#000000" points="0 0 4 4 0 8" transform="translate(5 5)"/>
966
+ </svg>
967
+ </t>
968
+ <t t-name="o-spreadsheet-Icon.TRIANGLE_LEFT" owl="1">
969
+ <svg class="o-icon">
970
+ <polygon fill="#000000" points="4 0 0 4 4 8" transform="translate(5 5)"/>
971
+ </svg>
972
+ </t>
973
+ <t t-name="o-spreadsheet-Icon.BOLD" owl="1">
974
+ <svg class="o-icon">
975
+ <path
976
+ fill="#000000"
977
+ fill-rule="evenodd"
978
+ d="M9,3.5 C9,1.57 7.43,0 5.5,0 L1.77635684e-15,0 L1.77635684e-15,12 L6.25,12 C8.04,12 9.5,10.54 9.5,8.75 C9.5,7.45 8.73,6.34 7.63,5.82 C8.46,5.24 9,4.38 9,3.5 Z M5,2 C5.82999992,2 6.5,2.67 6.5,3.5 C6.5,4.33 5.82999992,5 5,5 L3,5 L3,2 L5,2 Z M3,10 L3,7 L5.5,7 C6.32999992,7 7,7.67 7,8.5 C7,9.33 6.32999992,10 5.5,10 L3,10 Z"
979
+ transform="translate(4 3)"
980
+ />
981
+ </svg>
982
+ </t>
983
+ <t t-name="o-spreadsheet-Icon.ITALIC" owl="1">
984
+ <svg class="o-icon">
985
+ <polygon
986
+ fill="#000000"
987
+ fill-rule="evenodd"
988
+ points="4 0 4 2 6.58 2 2.92 10 0 10 0 12 8 12 8 10 5.42 10 9.08 2 12 2 12 0"
989
+ transform="translate(3 3)"
990
+ />
991
+ </svg>
992
+ </t>
993
+ <t t-name="o-spreadsheet-Icon.UNDERLINE" owl="1">
994
+ <svg class="o-icon">
995
+ <path
996
+ fill="#000000"
997
+ d="M6,12 C8.76,12 11,9.76 11,7 L11,0 L9,0 L9,7 C9,8.75029916 7.49912807,10 6,10 C4.50087193,10 3,8.75837486 3,7 L3,0 L1,0 L1,7 C1,9.76 3.24,12 6,12 Z M0,13 L0,15 L12,15 L12,13 L0,13 Z"
998
+ transform="translate(3 3)"
999
+ />
1000
+ </svg>
1001
+ </t>
1002
+ <t t-name="o-spreadsheet-Icon.STRIKE" owl="1">
1003
+ <svg class="o-icon">
1004
+ <path
1005
+ fill="#010101"
1006
+ fill-rule="evenodd"
1007
+ d="M2.8875,3.06 C2.8875,2.6025 2.985,2.18625 3.18375,1.8075 C3.3825,1.42875 3.66,1.10625 4.02,0.84 C4.38,0.57375 4.80375,0.3675 5.29875,0.22125 C5.79375,0.075 6.33375,0 6.92625,0 C7.53375,0 8.085,0.0825 8.58,0.25125 C9.075,0.42 9.49875,0.6525 9.85125,0.95625 C10.20375,1.25625 10.47375,1.6125 10.665,2.02875 C10.85625,2.44125 10.95,2.895 10.95,3.38625 L8.6925,3.38625 C8.6925,3.1575 8.655,2.94375 8.58375,2.74875 C8.5125,2.55 8.4,2.38125 8.25,2.2425 C8.1,2.10375 7.9125,1.99125 7.6875,1.91625 C7.4625,1.8375 7.19625,1.8 6.88875,1.8 C6.5925,1.8 6.3375,1.83375 6.11625,1.8975 C5.89875,1.96125 5.71875,2.05125 5.57625,2.1675 C5.43375,2.28375 5.325,2.41875 5.25375,2.5725 C5.1825,2.72625 5.145,2.895 5.145,3.0675 C5.145,3.4275 5.32875,3.73125 5.69625,3.975 C5.71780203,3.98908066 5.73942012,4.00311728 5.76118357,4.01733315 C6.02342923,4.18863185 6.5,4.5 7,5 L4,5 C4,5 3.21375,4.37625 3.17625,4.30875 C2.985,3.9525 2.8875,3.53625 2.8875,3.06 Z M14,6 L0,6 L0,8 L7.21875,8 C7.35375,8.0525 7.51875,8.105 7.63125,8.15375 C7.90875,8.2775 8.12625,8.40875 8.28375,8.53625 C8.44125,8.6675 8.54625,8.81 8.6025,8.96 C8.65875,9.11375 8.685,9.28625 8.685,9.47375 C8.685,9.65 8.65125,9.815 8.58375,9.965 C8.51625,10.11875 8.41125,10.25 8.2725,10.35875 C8.13375,10.4675 7.95375,10.55375 7.74,10.6175 C7.5225,10.68125 7.27125,10.71125 6.97875,10.71125 C6.6525,10.71125 6.35625,10.6775 6.09,10.61375 C5.82375,10.55 5.59875,10.445 5.41125,10.3025 C5.22375,10.16 5.0775,9.9725 4.9725,9.74375 C4.8675,9.515 4.78125,9.17 4.78125,9 L2.55,9 C2.55,9.2525 2.61,9.6875 2.72625,10.025 C2.8425,10.3625 3.0075,10.66625 3.21375,10.9325 C3.42,11.19875 3.6675,11.4275 3.94875,11.6225 C4.23,11.8175 4.53375,11.9825 4.86375,12.11 C5.19375,12.24125 5.535,12.33875 5.89875,12.39875 C6.25875,12.4625 6.6225,12.4925 6.9825,12.4925 C7.5825,12.4925 8.13,12.425 8.6175,12.28625 C9.105,12.1475 9.525,11.94875 9.87,11.69375 C10.215,11.435 10.48125,11.12 10.6725,10.74125 C10.86375,10.3625 10.95375,9.935 10.95375,9.455 C10.95375,9.005 10.875,8.6 10.72125,8.24375 C10.68375,8.1575 10.6425,8.075 10.59375,7.9925 L14,8 L14,6 Z"
1008
+ transform="translate(2 3)"
1009
+ />
1010
+ </svg>
1011
+ </t>
1012
+
1013
+ <t t-name="o-spreadsheet-Icon.TEXT_COLOR" owl="1">
1014
+ <svg class="o-icon">
1015
+ <path
1016
+ fill="#000000"
1017
+ d="M7,0 L5,0 L0.5,12 L2.5,12 L3.62,9 L8.37,9 L9.49,12 L11.49,12 L7,0 L7,0 Z M4.38,7 L6,2.67 L7.62,7 L4.38,7 L4.38,7 Z"
1018
+ transform="translate(3 1)"
1019
+ />
1020
+ </svg>
1021
+ </t>
1022
+ <t t-name="o-spreadsheet-Icon.FILL_COLOR" owl="1">
1023
+ <svg class="o-icon">
1024
+ <path
1025
+ fill="#000000"
1026
+ d="M14.5,8.87 C14.5,8.87 13,10.49 13,11.49 C13,12.32 13.67,12.99 14.5,12.99 C15.33,12.99 16,12.32 16,11.49 C16,10.5 14.5,8.87 14.5,8.87 L14.5,8.87 Z M12.71,6.79 L5.91,0 L4.85,1.06 L6.44,2.65 L2.29,6.79 C1.9,7.18 1.9,7.81 2.29,8.2 L6.79,12.7 C6.99,12.9 7.24,13 7.5,13 C7.76,13 8.01,12.9 8.21,12.71 L12.71,8.21 C13.1,7.82 13.1,7.18 12.71,6.79 L12.71,6.79 Z M4.21,7 L7.5,3.71 L10.79,7 L4.21,7 L4.21,7 Z"
1027
+ />
1028
+ </svg>
1029
+ </t>
1030
+ <t t-name="o-spreadsheet-Icon.MERGE_CELL" owl="1">
1031
+ <svg class="o-icon">
1032
+ <path
1033
+ fill="#000000"
1034
+ d="M3,6 L1,6 L1,2 L8,2 L8,4 L3,4 L3,6 Z M10,4 L10,2 L17,2 L17,6 L15,6 L15,4 L10,4 Z M10,14 L15,14 L15,12 L17,12 L17,16 L10,16 L10,14 Z M1,12 L3,12 L3,14 L8,14 L8,16 L1,16 L1,12 Z M1,8 L5,8 L5,6 L8,9 L5,12 L5,10 L1,10 L1,8 Z M10,9 L13,6 L13,8 L17,8 L17,10 L13,10 L13,12 L10,9 Z"
1035
+ />
1036
+ </svg>
1037
+ </t>
1038
+ <t t-name="o-spreadsheet-Icon.ALIGN_LEFT" owl="1">
1039
+ <svg class="o-icon align-left">
1040
+ <path
1041
+ fill="#000000"
1042
+ d="M0,14 L10,14 L10,12 L0,12 L0,14 Z M10,4 L0,4 L0,6 L10,6 L10,4 Z M0,0 L0,2 L14,2 L14,0 L0,0 Z M0,10 L14,10 L14,8 L0,8 L0,10 Z"
1043
+ transform="translate(2 2)"
1044
+ />
1045
+ </svg>
1046
+ </t>
1047
+ <t t-name="o-spreadsheet-Icon.ALIGN_CENTER" owl="1">
1048
+ <svg class="o-icon align-center">
1049
+ <path
1050
+ fill="#000000"
1051
+ d="M2,12 L2,14 L12,14 L12,12 L2,12 Z M2,4 L2,6 L12,6 L12,4 L2,4 Z M0,10 L14,10 L14,8 L0,8 L0,10 Z M0,0 L0,2 L14,2 L14,0 L0,0 Z"
1052
+ transform="translate(2 2)"
1053
+ />
1054
+ </svg>
1055
+ </t>
1056
+ <t t-name="o-spreadsheet-Icon.ALIGN_RIGHT" owl="1">
1057
+ <svg class="o-icon align-right">
1058
+ <path
1059
+ fill="#000000"
1060
+ d="M4,14 L14,14 L14,12 L4,12 L4,14 Z M0,10 L14,10 L14,8 L0,8 L0,10 Z M0,0 L0,2 L14,2 L14,0 L0,0 Z M4,6 L14,6 L14,4 L4,4 L4,6 Z"
1061
+ transform="translate(2 2)"
1062
+ />
1063
+ </svg>
1064
+ </t>
1065
+ <t t-name="o-spreadsheet-Icon.ALIGN_MIDDLE" owl="1">
1066
+ <svg class="o-icon">
1067
+ <path
1068
+ fill="#000000"
1069
+ d="M9.5,3 L7,3 L7,0 L5,0 L5,3 L2.5,3 L6,6.5 L9.5,3 L9.5,3 Z M0,8 L0,10 L12,10 L12,8 L0,8 L0,8 Z M2.5,15 L5,15 L5,18 L7,18 L7,15 L9.5,15 L6,11.5 L2.5,15 L2.5,15 Z"
1070
+ transform="translate(3)"
1071
+ />
1072
+ </svg>
1073
+ </t>
1074
+ <t t-name="o-spreadsheet-Icon.TEXT_WRAPPING" owl="1">
1075
+ <svg class="o-icon">
1076
+ <path
1077
+ fill="#000000"
1078
+ d="M14,0 L0,0 L0,2 L14,2 L14,0 Z M0,12 L4,12 L4,10 L0,10 L0,12 Z M11.5,5 L0,5 L0,7 L11.75,7 C12.58,7 13.25,7.67 13.25,8.5 C13.25,9.33 12.58,10 11.75,10 L9,10 L9,8 L6,11 L9,14 L9,12 L11.5,12 C13.43,12 15,10.43 15,8.5 C15,6.57 13.43,5 11.5,5 Z"
1079
+ transform="translate(2 3)"
1080
+ />
1081
+ </svg>
1082
+ </t>
1083
+ <t t-name="o-spreadsheet-Icon.BORDERS" owl="1">
1084
+ <svg class="o-icon">
1085
+ <path
1086
+ fill="#000000"
1087
+ d="M0,0 L0,14 L14,14 L14,0 L0,0 L0,0 Z M6,12 L2,12 L2,8 L6,8 L6,12 L6,12 Z M6,6 L2,6 L2,2 L6,2 L6,6 L6,6 Z M12,12 L8,12 L8,8 L12,8 L12,12 L12,12 Z M12,6 L8,6 L8,2 L12,2 L12,6 L12,6 Z"
1088
+ transform="translate(2 2)"
1089
+ />
1090
+ </svg>
1091
+ </t>
1092
+ <t t-name="o-spreadsheet-Icon.BORDER_HV" owl="1">
1093
+ <svg class="o-icon">
1094
+ <g fill="#000000" transform="translate(2 2)">
1095
+ <path
1096
+ d="M0,14 L2,14 L2,12 L0,12 L0,14 L0,14 Z M2,3 L0,3 L0,5 L2,5 L2,3 L2,3 Z M3,14 L5,14 L5,12 L3,12 L3,14 L3,14 Z M11,0 L9,0 L9,2 L11,2 L11,0 L11,0 Z M2,0 L0,0 L0,2 L2,2 L2,0 L2,0 Z M5,0 L3,0 L3,2 L5,2 L5,0 L5,0 Z M0,11 L2,11 L2,9 L0,9 L0,11 L0,11 Z M9,14 L11,14 L11,12 L9,12 L9,14 L9,14 Z M12,0 L12,2 L14,2 L14,0 L12,0 L12,0 Z M12,5 L14,5 L14,3 L12,3 L12,5 L12,5 Z M12,14 L14,14 L14,12 L12,12 L12,14 L12,14 Z M12,11 L14,11 L14,9 L12,9 L12,11 L12,11 Z"
1097
+ opacity=".54"
1098
+ />
1099
+ <polygon points="8 0 6 0 6 6 0 6 0 8 6 8 6 14 8 14 8 8 14 8 14 6 8 6"/>
1100
+ </g>
1101
+ </svg>
1102
+ </t>
1103
+ <t t-name="o-spreadsheet-Icon.BORDER_H" owl="1">
1104
+ <svg class="o-icon">
1105
+ <g fill="#000000" transform="translate(2 2)">
1106
+ <path
1107
+ d="M6,14 L8,14 L8,12 L6,12 L6,14 L6,14 Z M3,2 L5,2 L5,0 L3,0 L3,2 L3,2 Z M6,11 L8,11 L8,9 L6,9 L6,11 L6,11 Z M3,14 L5,14 L5,12 L3,12 L3,14 L3,14 Z M0,5 L2,5 L2,3 L0,3 L0,5 L0,5 Z M0,14 L2,14 L2,12 L0,12 L0,14 L0,14 Z M0,2 L2,2 L2,0 L0,0 L0,2 L0,2 Z M0,11 L2,11 L2,9 L0,9 L0,11 L0,11 Z M12,11 L14,11 L14,9 L12,9 L12,11 L12,11 Z M12,14 L14,14 L14,12 L12,12 L12,14 L12,14 Z M12,5 L14,5 L14,3 L12,3 L12,5 L12,5 Z M12,0 L12,2 L14,2 L14,0 L12,0 L12,0 Z M6,2 L8,2 L8,0 L6,0 L6,2 L6,2 Z M9,2 L11,2 L11,0 L9,0 L9,2 L9,2 Z M6,5 L8,5 L8,3 L6,3 L6,5 L6,5 Z M9,14 L11,14 L11,12 L9,12 L9,14 L9,14 Z"
1108
+ opacity=".54"
1109
+ />
1110
+ <polygon points="0 8 14 8 14 6 0 6"/>
1111
+ </g>
1112
+ </svg>
1113
+ </t>
1114
+ <t t-name="o-spreadsheet-Icon.BORDER_V" owl="1">
1115
+ <svg class="o-icon">
1116
+ <g fill="#000000" transform="translate(2 2)">
1117
+ <path
1118
+ d="M3,14 L5,14 L5,12 L3,12 L3,14 L3,14 Z M0,5 L2,5 L2,3 L0,3 L0,5 L0,5 Z M0,2 L2,2 L2,0 L0,0 L0,2 L0,2 Z M3,8 L5,8 L5,6 L3,6 L3,8 L3,8 Z M3,2 L5,2 L5,0 L3,0 L3,2 L3,2 Z M0,14 L2,14 L2,12 L0,12 L0,14 L0,14 Z M0,8 L2,8 L2,6 L0,6 L0,8 L0,8 Z M0,11 L2,11 L2,9 L0,9 L0,11 L0,11 Z M12,0 L12,2 L14,2 L14,0 L12,0 L12,0 Z M12,8 L14,8 L14,6 L12,6 L12,8 L12,8 Z M12,14 L14,14 L14,12 L12,12 L12,14 L12,14 Z M12,5 L14,5 L14,3 L12,3 L12,5 L12,5 Z M12,11 L14,11 L14,9 L12,9 L12,11 L12,11 Z M9,14 L11,14 L11,12 L9,12 L9,14 L9,14 Z M9,8 L11,8 L11,6 L9,6 L9,8 L9,8 Z M9,2 L11,2 L11,0 L9,0 L9,2 L9,2 Z"
1119
+ opacity=".54"
1120
+ />
1121
+ <polygon points="6 14 8 14 8 0 6 0"/>
1122
+ </g>
1123
+ </svg>
1124
+ </t>
1125
+ <t t-name="o-spreadsheet-Icon.BORDER_EXTERNAL" owl="1">
1126
+ <svg class="o-icon">
1127
+ <g fill="#000000" transform="translate(2 2)">
1128
+ <path
1129
+ d="M8,3 L6,3 L6,5 L8,5 L8,3 L8,3 Z M11,6 L9,6 L9,8 L11,8 L11,6 L11,6 Z M8,6 L6,6 L6,8 L8,8 L8,6 L8,6 Z M8,9 L6,9 L6,11 L8,11 L8,9 L8,9 Z M5,6 L3,6 L3,8 L5,8 L5,6 L5,6 Z"
1130
+ opacity=".54"
1131
+ />
1132
+ <path d="M0,0 L14,0 L14,14 L0,14 L0,0 Z M12,12 L12,2 L2,2 L2,12 L12,12 Z"/>
1133
+ </g>
1134
+ </svg>
1135
+ </t>
1136
+ <t t-name="o-spreadsheet-Icon.BORDER_LEFT" owl="1">
1137
+ <svg class="o-icon">
1138
+ <g fill="#000000" transform="translate(2 2)">
1139
+ <path
1140
+ d="M6,8 L8,8 L8,6 L6,6 L6,8 L6,8 Z M6,5 L8,5 L8,3 L6,3 L6,5 L6,5 Z M6,11 L8,11 L8,9 L6,9 L6,11 L6,11 Z M6,14 L8,14 L8,12 L6,12 L6,14 L6,14 Z M3,14 L5,14 L5,12 L3,12 L3,14 L3,14 Z M3,2 L5,2 L5,0 L3,0 L3,2 L3,2 Z M3,8 L5,8 L5,6 L3,6 L3,8 L3,8 Z M12,14 L14,14 L14,12 L12,12 L12,14 L12,14 Z M12,8 L14,8 L14,6 L12,6 L12,8 L12,8 Z M12,11 L14,11 L14,9 L12,9 L12,11 L12,11 Z M12,5 L14,5 L14,3 L12,3 L12,5 L12,5 Z M6,2 L8,2 L8,0 L6,0 L6,2 L6,2 Z M12,0 L12,2 L14,2 L14,0 L12,0 L12,0 Z M9,14 L11,14 L11,12 L9,12 L9,14 L9,14 Z M9,8 L11,8 L11,6 L9,6 L9,8 L9,8 Z M9,2 L11,2 L11,0 L9,0 L9,2 L9,2 Z"
1141
+ opacity=".54"
1142
+ />
1143
+ <polygon points="0 14 2 14 2 0 0 0"/>
1144
+ </g>
1145
+ </svg>
1146
+ </t>
1147
+ <t t-name="o-spreadsheet-Icon.BORDER_TOP" owl="1">
1148
+ <svg class="o-icon">
1149
+ <g fill="#000000" transform="translate(2 2)">
1150
+ <path
1151
+ d="M3,8 L5,8 L5,6 L3,6 L3,8 L3,8 Z M0,14 L2,14 L2,12 L0,12 L0,14 L0,14 Z M6,14 L8,14 L8,12 L6,12 L6,14 L6,14 Z M6,11 L8,11 L8,9 L6,9 L6,11 L6,11 Z M3,14 L5,14 L5,12 L3,12 L3,14 L3,14 Z M0,11 L2,11 L2,9 L0,9 L0,11 L0,11 Z M6,8 L8,8 L8,6 L6,6 L6,8 L6,8 Z M0,5 L2,5 L2,3 L0,3 L0,5 L0,5 Z M0,8 L2,8 L2,6 L0,6 L0,8 L0,8 Z M12,8 L14,8 L14,6 L12,6 L12,8 L12,8 Z M12,11 L14,11 L14,9 L12,9 L12,11 L12,11 Z M12,5 L14,5 L14,3 L12,3 L12,5 L12,5 Z M6,5 L8,5 L8,3 L6,3 L6,5 L6,5 Z M9,14 L11,14 L11,12 L9,12 L9,14 L9,14 Z M9,8 L11,8 L11,6 L9,6 L9,8 L9,8 Z M12,14 L14,14 L14,12 L12,12 L12,14 L12,14 Z"
1152
+ opacity=".54"
1153
+ />
1154
+ <polygon points="0 0 0 2 14 2 14 0"/>
1155
+ </g>
1156
+ </svg>
1157
+ </t>
1158
+ <t t-name="o-spreadsheet-Icon.BORDER_RIGHT" owl="1">
1159
+ <svg class="o-icon">
1160
+ <g fill="#000000" transform="translate(2 2)">
1161
+ <path
1162
+ d="M0,2 L2,2 L2,0 L0,0 L0,2 L0,2 Z M3,2 L5,2 L5,0 L3,0 L3,2 L3,2 Z M3,8 L5,8 L5,6 L3,6 L3,8 L3,8 Z M3,14 L5,14 L5,12 L3,12 L3,14 L3,14 Z M0,5 L2,5 L2,3 L0,3 L0,5 L0,5 Z M0,8 L2,8 L2,6 L0,6 L0,8 L0,8 Z M0,14 L2,14 L2,12 L0,12 L0,14 L0,14 Z M0,11 L2,11 L2,9 L0,9 L0,11 L0,11 Z M9,8 L11,8 L11,6 L9,6 L9,8 L9,8 Z M6,14 L8,14 L8,12 L6,12 L6,14 L6,14 Z M9,14 L11,14 L11,12 L9,12 L9,14 L9,14 Z M6,2 L8,2 L8,0 L6,0 L6,2 L6,2 Z M9,2 L11,2 L11,0 L9,0 L9,2 L9,2 Z M6,11 L8,11 L8,9 L6,9 L6,11 L6,11 Z M6,5 L8,5 L8,3 L6,3 L6,5 L6,5 Z M6,8 L8,8 L8,6 L6,6 L6,8 L6,8 Z"
1163
+ opacity=".54"
1164
+ />
1165
+ <polygon points="12 0 12 14 14 14 14 0"/>
1166
+ </g>
1167
+ </svg>
1168
+ </t>
1169
+ <t t-name="o-spreadsheet-Icon.BORDER_BOTTOM" owl="1">
1170
+ <svg class="o-icon">
1171
+ <g fill="#000000" transform="translate(2 2)">
1172
+ <path
1173
+ d="M5,0 L3,0 L3,2 L5,2 L5,0 L5,0 Z M8,6 L6,6 L6,8 L8,8 L8,6 L8,6 Z M8,9 L6,9 L6,11 L8,11 L8,9 L8,9 Z M11,6 L9,6 L9,8 L11,8 L11,6 L11,6 Z M5,6 L3,6 L3,8 L5,8 L5,6 L5,6 Z M11,0 L9,0 L9,2 L11,2 L11,0 L11,0 Z M8,3 L6,3 L6,5 L8,5 L8,3 L8,3 Z M8,0 L6,0 L6,2 L8,2 L8,0 L8,0 Z M2,9 L0,9 L0,11 L2,11 L2,9 L2,9 Z M12,11 L14,11 L14,9 L12,9 L12,11 L12,11 Z M12,5 L14,5 L14,3 L12,3 L12,5 L12,5 Z M12,8 L14,8 L14,6 L12,6 L12,8 L12,8 Z M12,0 L12,2 L14,2 L14,0 L12,0 L12,0 Z M2,0 L0,0 L0,2 L2,2 L2,0 L2,0 Z M2,3 L0,3 L0,5 L2,5 L2,3 L2,3 Z M2,6 L0,6 L0,8 L2,8 L2,6 L2,6 Z"
1174
+ opacity=".54"
1175
+ />
1176
+ <polygon points="0 14 14 14 14 12 0 12"/>
1177
+ </g>
1178
+ </svg>
1179
+ </t>
1180
+ <t t-name="o-spreadsheet-Icon.BORDER_CLEAR" owl="1">
1181
+ <svg class="o-icon">
1182
+ <path
1183
+ fill="#000000"
1184
+ fill-rule="evenodd"
1185
+ d="M6,14 L8,14 L8,12 L6,12 L6,14 L6,14 Z M3,8 L5,8 L5,6 L3,6 L3,8 L3,8 Z M3,2 L5,2 L5,0 L3,0 L3,2 L3,2 Z M6,11 L8,11 L8,9 L6,9 L6,11 L6,11 Z M3,14 L5,14 L5,12 L3,12 L3,14 L3,14 Z M0,5 L2,5 L2,3 L0,3 L0,5 L0,5 Z M0,14 L2,14 L2,12 L0,12 L0,14 L0,14 Z M0,2 L2,2 L2,0 L0,0 L0,2 L0,2 Z M0,8 L2,8 L2,6 L0,6 L0,8 L0,8 Z M6,8 L8,8 L8,6 L6,6 L6,8 L6,8 Z M0,11 L2,11 L2,9 L0,9 L0,11 L0,11 Z M12,11 L14,11 L14,9 L12,9 L12,11 L12,11 Z M12,14 L14,14 L14,12 L12,12 L12,14 L12,14 Z M12,8 L14,8 L14,6 L12,6 L12,8 L12,8 Z M12,5 L14,5 L14,3 L12,3 L12,5 L12,5 Z M12,0 L12,2 L14,2 L14,0 L12,0 L12,0 Z M6,2 L8,2 L8,0 L6,0 L6,2 L6,2 Z M9,2 L11,2 L11,0 L9,0 L9,2 L9,2 Z M6,5 L8,5 L8,3 L6,3 L6,5 L6,5 Z M9,14 L11,14 L11,12 L9,12 L9,14 L9,14 Z M9,8 L11,8 L11,6 L9,6 L9,8 L9,8 Z"
1186
+ transform="translate(2 2)"
1187
+ opacity=".54"
1188
+ />
1189
+ </svg>
1190
+ </t>
1191
+
1192
+ <t t-name="o-spreadsheet-Icon.PLUS" owl="1">
1193
+ <svg class="o-icon" viewBox="0 0 18 18">
1194
+ <path d="M8,0 L10,0 L10,8 L18,8 L18,10 L10,10 L10,18 L8,18 L8,10 L0,10 L0,8 L8,8"/>
1195
+ </svg>
1196
+ </t>
1197
+ <t t-name="o-spreadsheet-Icon.LIST" owl="1">
1198
+ <svg class="o-icon" viewBox="0 0 384 384">
1199
+ <rect x="0" y="277.333" width="384" height="42.667"/>
1200
+ <rect x="0" y="170.667" width="384" height="42.667"/>
1201
+ <rect x="0" y="64" width="384" height="42.667"/>
1202
+ </svg>
1203
+ </t>
1204
+
1205
+ <t t-name="o-spreadsheet-Icon.EDIT" owl="1">
1206
+ <svg class="o-icon" viewBox="0 0 576 512">
1207
+ <path
1208
+ fill="currentColor"
1209
+ 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"
1210
+ />
1211
+ </svg>
1212
+ </t>
1213
+ <t t-name="o-spreadsheet-Icon.UNLINK" owl="1">
1214
+ <svg class="o-icon" viewBox="0 0 512 512">
1215
+ <path
1216
+ fill="currentColor"
1217
+ 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"
1218
+ />
1219
+ </svg>
1220
+ </t>
1221
+ /** Font Awesome by Dave Gandy
1222
+ * http://fontawesome.io/
1223
+ * https://fontawesome.com/license
1224
+ */
1225
+ <t t-name="o-spreadsheet-Icon.CARET_UP" owl="1">
1226
+ <svg class="caret-up" viewBox="0 0 320 512">
1227
+ <path
1228
+ fill="currentColor"
1229
+ 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"
1230
+ />
1231
+ </svg>
1232
+ </t>
1233
+ <t t-name="o-spreadsheet-Icon.CARET_DOWN" owl="1">
1234
+ <svg class="caret-down" viewBox="0 0 320 512">
1235
+ <path
1236
+ fill="currentColor"
1237
+ 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"
1238
+ />
1239
+ </svg>
1240
+ </t>
1241
+
1242
+ <t t-name="o-spreadsheet-Icon.TRASH" owl="1">
1243
+ <svg class="o-cf-icon trash" viewBox="0 0 448 512">
1244
+ <path
1245
+ fill="currentColor"
1246
+ 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"
1247
+ />
1248
+ </svg>
1249
+ </t>
1250
+ <t t-name="o-spreadsheet-Icon.REFRESH" owl="1">
1251
+ <svg class="o-cf-icon refresh" viewBox="0 0 512 512">
1252
+ <path
1253
+ fill="currentColor"
1254
+ 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"
1255
+ />
1256
+ </svg>
1257
+ </t>
1258
+
1259
+ <t t-name="o-spreadsheet-Icon.ARROW_DOWN" owl="1">
1260
+ <svg
1261
+ class="o-cf-icon arrow-down"
1262
+ width="10"
1263
+ height="10"
1264
+ focusable="false"
1265
+ viewBox="0 0 448 512">
1266
+ <path
1267
+ fill="#DC6965"
1268
+ t-att-style="color"
1269
+ 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"
1270
+ />
1271
+ </svg>
1272
+ </t>
1273
+ <t t-name="o-spreadsheet-Icon.ARROW_UP" owl="1">
1274
+ <svg class="o-cf-icon arrow-up" width="10" height="10" focusable="false" viewBox="0 0 448 512">
1275
+ <path
1276
+ fill="#00A04A"
1277
+ t-att-style="color"
1278
+ 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"
1279
+ />
1280
+ </svg>
1281
+ </t>
1282
+ <t t-name="o-spreadsheet-Icon.ARROW_RIGHT" owl="1">
1283
+ <svg
1284
+ class="o-cf-icon arrow-right"
1285
+ width="10"
1286
+ height="10"
1287
+ focusable="false"
1288
+ viewBox="0 0 448 512">
1289
+ <path
1290
+ fill="#F0AD4E"
1291
+ 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"
1292
+ />
1293
+ </svg>
1294
+ </t>
1295
+
1296
+ <t t-name="o-spreadsheet-Icon.SMILE" owl="1">
1297
+ <svg class="o-cf-icon smile" width="10" height="10" focusable="false" viewBox="0 0 496 512">
1298
+ <path
1299
+ fill="#00A04A"
1300
+ 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"
1301
+ />
1302
+ </svg>
1303
+ </t>
1304
+ <t t-name="o-spreadsheet-Icon.MEH" owl="1">
1305
+ <svg class="o-cf-icon meh" width="10" height="10" focusable="false" viewBox="0 0 496 512">
1306
+ <path
1307
+ fill="#F0AD4E"
1308
+ 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"
1309
+ />
1310
+ </svg>
1311
+ </t>
1312
+ <t t-name="o-spreadsheet-Icon.FROWN" owl="1">
1313
+ <svg class="o-cf-icon frown" width="10" height="10" focusable="false" viewBox="0 0 496 512">
1314
+ <path
1315
+ fill="#DC6965"
1316
+ 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"
1317
+ />
1318
+ </svg>
1319
+ </t>
1320
+
1321
+ <t t-name="o-spreadsheet-Icon.GREEN_DOT" owl="1">
1322
+ <svg class="o-cf-icon green-dot" width="10" height="10" focusable="false" viewBox="0 0 512 512">
1323
+ <path
1324
+ fill="#00A04A"
1325
+ d="M256 8C119 8 8 119 8 256s111 248 248 248 248-111 248-248S393 8 256 8z"
1326
+ />
1327
+ </svg>
1328
+ </t>
1329
+ <t t-name="o-spreadsheet-Icon.YELLOW_DOT" owl="1">
1330
+ <svg
1331
+ class="o-cf-icon yellow-dot"
1332
+ width="10"
1333
+ height="10"
1334
+ focusable="false"
1335
+ viewBox="0 0 512 512">
1336
+ <path
1337
+ fill="#F0AD4E"
1338
+ d="M256 8C119 8 8 119 8 256s111 248 248 248 248-111 248-248S393 8 256 8z"
1339
+ />
1340
+ </svg>
1341
+ </t>
1342
+ <t t-name="o-spreadsheet-Icon.RED_DOT" owl="1">
1343
+ <svg class="o-cf-icon red-dot" width="10" height="10" focusable="false" viewBox="0 0 512 512">
1344
+ <path
1345
+ fill="#DC6965"
1346
+ d="M256 8C119 8 8 119 8 256s111 248 248 248 248-111 248-248S393 8 256 8z"
1347
+ />
1348
+ </svg>
1349
+ </t>
1350
+ <t t-name="o-spreadsheet-Icon.FILTER_ICON" owl="1">
1351
+ <svg
1352
+ class="o-cf-icon filter-icon"
1353
+ width="10"
1354
+ height="10"
1355
+ focusable="false"
1356
+ viewBox="0 0 850 850">
1357
+ <path
1358
+ fill="#000"
1359
+ 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"
1360
+ />
1361
+ </svg>
1362
+ </t>
1363
+ <t t-name="o-spreadsheet-Icon.FILTER_ICON_ACTIVE" owl="1">
1364
+ <svg
1365
+ class="o-cf-icon filter-icon-active"
1366
+ width="10"
1367
+ height="10"
1368
+ focusable="false"
1369
+ viewBox="0 0 512 512">
1370
+ <path
1371
+ fill="#188038"
1372
+ 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"
1373
+ />
1374
+ </svg>
1375
+ </t>
1376
+ <t t-name="o-spreadsheet-Icon.FILTER_ICON_INACTIVE" owl="1">
1377
+ <svg
1378
+ class="o-cf-icon filter-icon-inactive"
1379
+ width="10"
1380
+ height="10"
1381
+ focusable="false"
1382
+ viewBox="0 0 512 512">
1383
+ <path
1384
+ fill="#606162"
1385
+ 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"
1386
+ />
1387
+ </svg>
1388
+ </t>
1389
+ <t t-name="o-spreadsheet-Icon.SEARCH" owl="1">
1390
+ <svg class="search-icon" width="10" height="10" focusable="false" viewBox="0 0 512 512">
1391
+ <path
1392
+ fill="#949494"
1393
+ 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"
1394
+ />
1395
+ </svg>
1396
+ </t>
1397
+
1398
+ <t t-name="o-spreadsheet-LinkDisplay" owl="1">
1399
+ <div class="o-link-tool d-flex align-items-center">
1400
+ <!-- t-key to prevent owl from re-using the previous img element when the link changes.
1401
+ The wrong/previous image would be displayed while the new one loads -->
1402
+ <img
1403
+ t-if="link.isExternal"
1404
+ t-key="link.url"
1405
+ t-attf-src="https://www.google.com/s2/favicons?sz=16&amp;domain={{link.url}}"
1406
+ />
1407
+ <a
1408
+ t-if="link.isExternal"
1409
+ class="o-link"
1410
+ t-att-href="link.url"
1411
+ target="_blank"
1412
+ t-on-click.prevent="openLink"
1413
+ t-att-title="link.url">
1414
+ <t t-esc="getUrlRepresentation(link)"/>
1415
+ </a>
1416
+ <a
1417
+ t-else=""
1418
+ class="o-link"
1419
+ t-on-click.prevent="openLink"
1420
+ t-att-title="getUrlRepresentation(link)">
1421
+ <t t-esc="getUrlRepresentation(link)"/>
1422
+ </a>
1423
+ <span
1424
+ t-if="!env.model.getters.isReadonly()"
1425
+ class="o-link-icon o-unlink"
1426
+ t-on-click="unlink"
1427
+ title="Remove link">
1428
+ <t t-call="o-spreadsheet-Icon.UNLINK"/>
1429
+ </span>
1430
+ <span
1431
+ t-if="!env.model.getters.isReadonly()"
1432
+ class="o-link-icon o-edit-link"
1433
+ t-on-click="edit"
1434
+ title="Edit link">
1435
+ <t t-call="o-spreadsheet-Icon.EDIT"/>
1436
+ </span>
1437
+ </div>
1438
+ </t>
1439
+
1440
+ <t t-name="o-spreadsheet-LinkEditor" owl="1">
1441
+ <div
1442
+ class="o-link-editor"
1443
+ t-on-click.stop="() => this.menu.isOpen=false"
1444
+ t-on-keydown="onKeyDown"
1445
+ t-ref="linkEditor">
1446
+ <div class="o-section">
1447
+ <div class="o-section-title">Text</div>
1448
+ <div class="d-flex">
1449
+ <input type="text" class="o-input flex-grow-1" t-model="link.label"/>
1450
+ </div>
1451
+
1452
+ <div class="o-section-title mt-3">Link</div>
1453
+ <div class="o-link-url">
1454
+ <t t-if="link.isUrlEditable">
1455
+ <input type="text" t-ref="urlInput" t-model="link.url"/>
1456
+ </t>
1457
+ <t t-else="">
1458
+ <input type="text" t-att-value="getUrlRepresentation(link)" disabled="1"/>
1459
+ </t>
1460
+ <button t-if="link.url" t-on-click="removeLink" class="o-remove-url">✖</button>
1461
+ <button t-if="!link.url" t-on-click.stop="openMenu" class="o-special-link">
1462
+ <t t-call="o-spreadsheet-Icon.LIST"/>
1463
+ </button>
1464
+ </div>
1465
+ </div>
1466
+ <Menu
1467
+ t-if="menu.isOpen"
1468
+ position="menuPosition"
1469
+ menuItems="menuItems"
1470
+ onMenuClicked="(ev) => this.onSpecialLink(ev)"
1471
+ onClose="() => this.menu.isOpen=false"
1472
+ />
1473
+ <div class="o-buttons">
1474
+ <button t-on-click="cancel" class="o-button o-cancel">Cancel</button>
1475
+ <button t-on-click="save" class="o-button o-save" t-att-disabled="!link.url">
1476
+ Confirm
1477
+ </button>
1478
+ </div>
1479
+ </div>
1480
+ </t>
1481
+
1482
+ <t t-name="o-spreadsheet-Menu" owl="1">
1483
+ <Popover t-if="visibleMenuItems.length" t-props="popoverProps">
1484
+ <div
1485
+ t-ref="menu"
1486
+ class="o-menu"
1487
+ t-on-scroll="onScroll"
1488
+ t-on-wheel.stop=""
1489
+ t-on-click.stop=""
1490
+ t-on-contextmenu.prevent="">
1491
+ <t t-foreach="visibleMenuItems" t-as="menuItem" t-key="menuItem.id">
1492
+ <t t-set="isMenuRoot" t-value="isRoot(menuItem)"/>
1493
+ <t t-set="isMenuEnabled" t-value="isEnabled(menuItem)"/>
1494
+ <div
1495
+ t-att-title="getName(menuItem)"
1496
+ t-att-data-name="menuItem.id"
1497
+ t-on-click="() => this.onClickMenu(menuItem, menuItem_index)"
1498
+ t-on-mouseover="() => this.onMouseOver(menuItem, menuItem_index)"
1499
+ class="o-menu-item"
1500
+ t-att-class="{ 'o-menu-root': isMenuRoot, 'disabled': !isMenuEnabled, 'o-menu-item-active': isParentMenu(subMenu, menuItem)}"
1501
+ t-att-style="getColor(menuItem)">
1502
+ <span class="o-menu-item-name" t-esc="getName(menuItem)"/>
1503
+ <span
1504
+ t-if="getDescription(menuItem)"
1505
+ class="o-menu-item-description"
1506
+ t-esc="getDescription(menuItem)"
1507
+ />
1508
+ <t t-if="isMenuRoot">
1509
+ <span t-call="o-spreadsheet-Icon.TRIANGLE_RIGHT"/>
1510
+ </t>
1511
+ <t t-elif="menuItem.icon">
1512
+ <i t-att-class="menuItem.icon" class="o-menu-item-icon"/>
1513
+ </t>
1514
+ </div>
1515
+ <div t-if="menuItem.separator and !menuItem_last" class="o-separator"/>
1516
+ </t>
1517
+ </div>
1518
+ <Menu
1519
+ t-if="subMenu.isOpen"
1520
+ position="subMenuPosition"
1521
+ menuItems="subMenu.menuItems"
1522
+ depth="props.depth + 1"
1523
+ onMenuClicked="props.onMenuClicked"
1524
+ onClose="() => this.close()"
1525
+ menuId="props.menuId"
1526
+ />
1527
+ </Popover>
1528
+ </t>
1529
+
1530
+ <t t-name="o-spreadsheet-Popover" owl="1">
1531
+ <t t-portal="'.o-spreadsheet'">
1532
+ <div
1533
+ class="o-popover"
1534
+ t-ref="popover"
1535
+ t-on-wheel="props.onMouseWheel"
1536
+ t-att-style="popoverStyle">
1537
+ <t t-slot="default"/>
1538
+ </div>
1539
+ </t>
1540
+ </t>
1541
+
1542
+ <t t-name="o-spreadsheet-ScrollBar" owl="1">
1543
+ <div class="o-scrollbar" t-on-scroll="onScroll" t-ref="scrollbar" t-att-style="positionCss">
1544
+ <div t-att-style="sizeCss"/>
1545
+ </div>
1546
+ </t>
1547
+
1548
+ <t t-name="o-spreadsheet-SelectionInput" owl="1">
1549
+ <div class="o-selection">
1550
+ <div
1551
+ t-foreach="ranges"
1552
+ t-as="range"
1553
+ t-key="range.id"
1554
+ class="o-selection-input"
1555
+ t-att-class="props.class">
1556
+ <input
1557
+ type="text"
1558
+ spellcheck="false"
1559
+ t-on-change="(ev) => this.onInputChanged(range.id, ev)"
1560
+ t-on-focus="() => this.focus(range.id)"
1561
+ t-on-keydown="onKeydown"
1562
+ t-att-value="range.xc"
1563
+ t-att-style="getColor(range)"
1564
+ t-att-class="{
1565
+ 'o-focused' : range.isFocused,
1566
+ 'o-required': props.required,
1567
+ 'o-optional': !props.required,
1568
+ 'o-invalid': isInvalid || !range.isValidRange,
1569
+ 'text-decoration-underline': range.isFocused and state.mode === 'select-range'
1570
+ }"
1571
+ />
1572
+ <button
1573
+ class="o-btn o-remove-selection"
1574
+ t-if="ranges.length > 1"
1575
+ t-on-click="() => this.removeInput(range.id)">
1576
+ ✕
1577
+ </button>
1578
+ </div>
1579
+
1580
+ <div class="o-selection-input">
1581
+ <button class="o-btn-action o-add-selection" t-if="canAddRange" t-on-click="addEmptyInput">
1582
+ Add range
1583
+ </button>
1584
+ <button class="o-btn-action o-selection-ok" t-if="hasFocus" t-on-click="confirm">
1585
+ Confirm
1586
+ </button>
1587
+ </div>
1588
+ </div>
1589
+ </t>
1590
+
1591
+ <t t-name="o-spreadsheet-BarConfigPanel" owl="1">
1592
+ <div>
1593
+ <div class="o-section pt-0">
1594
+ <div class="o-checkbox">
1595
+ <label>
1596
+ <input
1597
+ type="checkbox"
1598
+ name="stacked"
1599
+ t-att-checked="props.definition.stacked"
1600
+ t-on-change="onUpdateStacked"
1601
+ class="align-middle"
1602
+ />
1603
+ Stacked barchart
1604
+ </label>
1605
+ </div>
1606
+ </div>
1607
+ <div class="o-section o-data-series">
1608
+ <div class="o-section-title">Data Series</div>
1609
+ <SelectionInput
1610
+ ranges="dataSeriesRanges"
1611
+ isInvalid="isDatasetInvalid"
1612
+ required="true"
1613
+ onSelectionChanged="(ranges) => this.onDataSeriesRangesChanged(ranges)"
1614
+ onSelectionConfirmed="() => this.onDataSeriesConfirmed()"
1615
+ />
1616
+ <label>
1617
+ <input
1618
+ type="checkbox"
1619
+ t-att-checked="props.definition.dataSetsHaveTitle"
1620
+ t-on-change="onUpdateDataSetsHaveTitle"
1621
+ class="align-middle"
1622
+ />
1623
+ Data series include title
1624
+ </label>
1625
+ </div>
1626
+ <div class="o-section o-data-labels">
1627
+ <div class="o-section-title">Categories / Labels</div>
1628
+ <SelectionInput
1629
+ ranges="[props.definition.labelRange || '']"
1630
+ isInvalid="isLabelInvalid"
1631
+ hasSingleRange="true"
1632
+ onSelectionChanged="(ranges) => this.onLabelRangeChanged(ranges)"
1633
+ onSelectionConfirmed="() => this.onLabelRangeConfirmed()"
1634
+ />
1635
+ <label>
1636
+ <input
1637
+ type="checkbox"
1638
+ name="aggregated"
1639
+ t-att-checked="props.definition.aggregated"
1640
+ t-on-change="onUpdateAggregated"
1641
+ class="align-middle"
1642
+ />
1643
+ Aggregate
1644
+ </label>
1645
+ </div>
1646
+ <div class="o-section o-sidepanel-error" t-if="errorMessages">
1647
+ <div t-foreach="errorMessages" t-as="error" t-key="error">
1648
+ <t t-esc="error"/>
1649
+ </div>
1650
+ </div>
1651
+ </div>
1652
+ </t>
1653
+
1654
+ <t t-name="o-spreadsheet-BarChartDesignPanel" owl="1">
1655
+ <div>
1656
+ <div class="o-section">
1657
+ <div class="o-section-title">Background color</div>
1658
+ <div class="o-with-color-picker">
1659
+ Select a color...
1660
+ <span
1661
+ t-att-style="props.definition.background ? `border-color: ${props.definition.background}` : 'border-bottom-style: hidden'"
1662
+ t-on-click.stop="toggleColorPicker">
1663
+ <t t-call="o-spreadsheet-Icon.FILL_COLOR"/>
1664
+ </span>
1665
+ <ColorPicker
1666
+ t-if="state.fillColorTool"
1667
+ onColorPicked="(color) => this.updateBackgroundColor(color)"
1668
+ currentColor="props.definition.background"
1669
+ t-key="backgroundColor"
1670
+ />
1671
+ </div>
1672
+ </div>
1673
+ <div class="o-section o-chart-title">
1674
+ <div class="o-section-title">Title</div>
1675
+ <input
1676
+ type="text"
1677
+ t-att-value="env._t(props.definition.title)"
1678
+ t-on-change="updateTitle"
1679
+ class="o-input o-optional"
1680
+ placeholder="New Chart"
1681
+ />
1682
+ </div>
1683
+ <div class="o-section">
1684
+ <div class="o-section-title">Vertical axis position</div>
1685
+ <select
1686
+ t-att-value="props.definition.verticalAxisPosition"
1687
+ class="o-input o-type-selector"
1688
+ t-on-change="(ev) => this.updateSelect('verticalAxisPosition', ev)">
1689
+ <option value="left">Left</option>
1690
+ <option value="right">Right</option>
1691
+ </select>
1692
+ </div>
1693
+ <div class="o-section">
1694
+ <div class="o-section-title">Legend position</div>
1695
+ <select
1696
+ t-att-value="props.definition.legendPosition"
1697
+ class="o-input o-type-selector"
1698
+ t-on-change="(ev) => this.updateSelect('legendPosition', ev)">
1699
+ <option value="none">None</option>
1700
+ <option value="top">Top</option>
1701
+ <option value="bottom">Bottom</option>
1702
+ <option value="left">Left</option>
1703
+ <option value="right">Right</option>
1704
+ </select>
1705
+ </div>
1706
+ </div>
1707
+ </t>
1708
+
1709
+ <t t-name="o-spreadsheet-GaugeChartConfigPanel" owl="1">
1710
+ <div>
1711
+ <div class="o-section o-data-series">
1712
+ <div class="o-section-title">Data range</div>
1713
+ <SelectionInput
1714
+ ranges="[props.definition.dataRange || '']"
1715
+ isInvalid="isDataRangeInvalid"
1716
+ hasSingleRange="true"
1717
+ required="true"
1718
+ onSelectionChanged="(ranges) => this.onDataRangeChanged(ranges)"
1719
+ onSelectionConfirmed="() => this.updateDataRange()"
1720
+ />
1721
+ </div>
1722
+ <div class="o-section o-sidepanel-error" t-if="configurationErrorMessages">
1723
+ <div t-foreach="configurationErrorMessages" t-as="error" t-key="error">
1724
+ <t t-esc="error"/>
1725
+ </div>
1726
+ </div>
1727
+ </div>
1728
+ </t>
1729
+
1730
+ <t t-name="o-spreadsheet-GaugeChartDesignPanel" owl="1">
1731
+ <div>
1732
+ <div class="o-section">
1733
+ <div class="o-section-title">Background color</div>
1734
+ <div class="o-with-color-picker">
1735
+ Select a color...
1736
+ <span
1737
+ title="Background Color"
1738
+ t-att-style="props.definition.background ? `border-color: ${props.definition.background}` : 'border-bottom-style: hidden'"
1739
+ t-on-click.stop="() => this.toggleMenu('backgroundColor', ev)">
1740
+ <t t-call="o-spreadsheet-Icon.FILL_COLOR"/>
1741
+ </span>
1742
+ <ColorPicker
1743
+ t-if="state.openedMenu === 'backgroundColor'"
1744
+ onColorPicked="(color) => this.updateBackgroundColor(color)"
1745
+ currentColor="props.definition.background"
1746
+ t-key="backgroundColor"
1747
+ />
1748
+ </div>
1749
+ </div>
1750
+
1751
+ <div class="o-section o-chart-title">
1752
+ <div class="o-section-title">Title</div>
1753
+ <input
1754
+ type="text"
1755
+ t-att-value="env._t(props.definition.title)"
1756
+ t-on-change="updateTitle"
1757
+ class="o-input o-optional"
1758
+ placeholder="New Chart"
1759
+ />
1760
+ </div>
1761
+
1762
+ <div class="o-section">
1763
+ <div class="o-section-title">Range</div>
1764
+ <div class="o-subsection-left">
1765
+ <input
1766
+ type="text"
1767
+ t-att-value="props.definition.sectionRule.rangeMin"
1768
+ t-on-change="updateRangeMin"
1769
+ class="o-input o-data-range-min"
1770
+ t-att-class="{ 'o-invalid': isRangeMinInvalid() }"
1771
+ />
1772
+ </div>
1773
+ <div class="o-subsection-right">
1774
+ <input
1775
+ type="text"
1776
+ t-att-value="props.definition.sectionRule.rangeMax"
1777
+ t-on-change="updateRangeMax"
1778
+ class="o-input o-data-range-max"
1779
+ t-att-class="{ 'o-invalid': isRangeMaxInvalid() }"
1780
+ />
1781
+ </div>
1782
+ </div>
1783
+
1784
+ <div class="o-section">
1785
+ <div class="o-section-title">Thresholds</div>
1786
+ <t t-call="o-spreadsheet-GaugeChartColorSectionTemplate">
1787
+ <t t-set="sectionRule" t-value="props.definition.sectionRule"/>
1788
+ </t>
1789
+ </div>
1790
+
1791
+ <div class="o-section o-sidepanel-error" t-if="designErrorMessages.length">
1792
+ <div t-foreach="designErrorMessages" t-as="error" t-key="error">
1793
+ <t t-esc="error"/>
1794
+ </div>
1795
+ </div>
1796
+ </div>
1797
+ </t>
1798
+
1799
+ <t t-name="o-spreadsheet-GaugeChartColorSectionTemplate" owl="1">
1800
+ <div class="o-gauge-color-set">
1801
+ <table>
1802
+ <tr>
1803
+ <th class="o-gauge-color-set-colorPicker"/>
1804
+ <th class="o-gauge-color-set-text"/>
1805
+ <th class="o-gauge-color-set-value">Value</th>
1806
+ <th class="o-gauge-color-set-type">Type</th>
1807
+ </tr>
1808
+
1809
+ <t t-call="o-spreadsheet-GaugeChartColorSectionTemplateRow">
1810
+ <t t-set="sectionColor" t-value="sectionRule.colors.lowerColor"/>
1811
+ <t t-set="sectionType" t-value="'lowerColor'"/>
1812
+ <t t-set="inflectionPoint" t-value="sectionRule.lowerInflectionPoint"/>
1813
+ <t t-set="isInvalid" t-value="isLowerInflectionPointInvalid"/>
1814
+ <t t-set="inflectionPointName" t-value="'lowerInflectionPoint'"/>
1815
+ </t>
1816
+
1817
+ <t t-call="o-spreadsheet-GaugeChartColorSectionTemplateRow">
1818
+ <t t-set="sectionColor" t-value="sectionRule.colors.middleColor"/>
1819
+ <t t-set="sectionType" t-value="'middleColor'"/>
1820
+ <t t-set="inflectionPoint" t-value="sectionRule.upperInflectionPoint"/>
1821
+ <t t-set="isInvalid" t-value="isUpperInflectionPointInvalid"/>
1822
+ <t t-set="inflectionPointName" t-value="'upperInflectionPoint'"/>
1823
+ </t>
1824
+
1825
+ <tr>
1826
+ <td>
1827
+ <div class="o-tools">
1828
+ <div class="o-tool o-dropdown o-with-color">
1829
+ <span
1830
+ title="Fill Color"
1831
+ t-attf-style="border-color:{{sectionRule.colors.upperColor}}"
1832
+ t-on-click.stop="(ev) => this.toggleMenu('sectionColor-upperColor', ev)">
1833
+ <t t-call="o-spreadsheet-Icon.FILL_COLOR"/>
1834
+ </span>
1835
+ <ColorPicker
1836
+ t-if="state.openedMenu === 'sectionColor-upperColor'"
1837
+ onColorPicked="(color) => this.updateSectionColor('upperColor', color)"
1838
+ currentColor="sectionRule.colors.upperColor"
1839
+ dropdownDirection="'right'"
1840
+ />
1841
+ </div>
1842
+ </div>
1843
+ </td>
1844
+ <td>Else</td>
1845
+ <td/>
1846
+ <td/>
1847
+ <td/>
1848
+ </tr>
1849
+ </table>
1850
+ </div>
1851
+ </t>
1852
+
1853
+ <t t-name="o-spreadsheet-GaugeChartColorSectionTemplateRow" owl="1">
1854
+ <tr>
1855
+ <td>
1856
+ <div class="o-tools">
1857
+ <div class="o-tool o-dropdown o-with-color">
1858
+ <span
1859
+ title="Fill Color"
1860
+ t-attf-style="border-color:{{sectionColor}}"
1861
+ t-on-click.stop="(ev) => this.toggleMenu('sectionColor-'+sectionType, ev)">
1862
+ <t t-call="o-spreadsheet-Icon.FILL_COLOR"/>
1863
+ </span>
1864
+ <ColorPicker
1865
+ t-if="state.openedMenu === 'sectionColor-'+sectionType"
1866
+ onColorPicked="(color) => this.updateSectionColor(sectionType, color)"
1867
+ currentColor="sectionColor"
1868
+ dropdownDirection="'right'"
1869
+ />
1870
+ </div>
1871
+ </div>
1872
+ </td>
1873
+ <td>When value is below</td>
1874
+ <td>
1875
+ <input
1876
+ type="text"
1877
+ class="o-input"
1878
+ t-on-change="(ev) => this.updateInflectionPointValue(inflectionPointName, ev)"
1879
+ t-attf-class="o-input-{{inflectionPointName}}"
1880
+ t-att-class="{ 'o-invalid': isInvalid }"
1881
+ t-model="inflectionPoint.value"
1882
+ />
1883
+ </td>
1884
+ <td>
1885
+ <select
1886
+ class="o-input"
1887
+ name="valueType"
1888
+ t-model="inflectionPoint.type"
1889
+ t-on-change="(ev) => this.updateInflectionPointType(inflectionPointName, ev)">
1890
+ <option value="number">Number</option>
1891
+ <option value="percentage">Percentage</option>
1892
+ </select>
1893
+ </td>
1894
+ </tr>
1895
+ </t>
1896
+
1897
+ <t t-name="o-spreadsheet-LineBarPieConfigPanel" owl="1">
1898
+ <div>
1899
+ <div class="o-section o-data-series">
1900
+ <div class="o-section-title">Data Series</div>
1901
+ <SelectionInput
1902
+ ranges="dataSeriesRanges"
1903
+ isInvalid="isDatasetInvalid"
1904
+ required="true"
1905
+ onSelectionChanged="(ranges) => this.onDataSeriesRangesChanged(ranges)"
1906
+ onSelectionConfirmed="() => this.onDataSeriesConfirmed()"
1907
+ />
1908
+ <label>
1909
+ <input
1910
+ type="checkbox"
1911
+ t-att-checked="props.definition.dataSetsHaveTitle"
1912
+ t-on-change="onUpdateDataSetsHaveTitle"
1913
+ class="align-middle"
1914
+ />
1915
+ Data series include title
1916
+ </label>
1917
+ </div>
1918
+ <div class="o-section o-data-labels">
1919
+ <div class="o-section-title">Categories / Labels</div>
1920
+ <SelectionInput
1921
+ ranges="[props.definition.labelRange || '']"
1922
+ isInvalid="isLabelInvalid"
1923
+ hasSingleRange="true"
1924
+ onSelectionChanged="(ranges) => this.onLabelRangeChanged(ranges)"
1925
+ onSelectionConfirmed="() => this.onLabelRangeConfirmed()"
1926
+ />
1927
+ <label>
1928
+ <input
1929
+ type="checkbox"
1930
+ name="aggregated"
1931
+ t-att-checked="props.definition.aggregated"
1932
+ t-on-change="onUpdateAggregated"
1933
+ class="align-middle"
1934
+ />
1935
+ Aggregate
1936
+ </label>
1937
+ </div>
1938
+ <div class="o-section o-sidepanel-error" t-if="errorMessages">
1939
+ <div t-foreach="errorMessages" t-as="error" t-key="error">
1940
+ <t t-esc="error"/>
1941
+ </div>
1942
+ </div>
1943
+ </div>
1944
+ </t>
1945
+
1946
+ <t t-name="o-spreadsheet-LineBarPieDesignPanel" owl="1">
1947
+ <div>
1948
+ <div class="o-section">
1949
+ <div class="o-section-title">Background color</div>
1950
+ <div class="o-with-color-picker">
1951
+ Select a color...
1952
+ <span
1953
+ t-att-style="props.definition.background ? `border-color: ${props.definition.background}` : 'border-bottom-style: hidden'"
1954
+ t-on-click.stop="toggleColorPicker">
1955
+ <t t-call="o-spreadsheet-Icon.FILL_COLOR"/>
1956
+ </span>
1957
+ <ColorPicker
1958
+ t-if="state.fillColorTool"
1959
+ onColorPicked="(color) => this.updateBackgroundColor(color)"
1960
+ currentColor="props.definition.background"
1961
+ t-key="backgroundColor"
1962
+ />
1963
+ </div>
1964
+ </div>
1965
+ <div class="o-section o-chart-title">
1966
+ <div class="o-section-title">Title</div>
1967
+ <input
1968
+ type="text"
1969
+ t-att-value="env._t(props.definition.title)"
1970
+ t-on-change="updateTitle"
1971
+ class="o-input o-optional"
1972
+ placeholder="New Chart"
1973
+ />
1974
+ </div>
1975
+ <div class="o-section">
1976
+ <div class="o-section-title">Legend position</div>
1977
+ <select
1978
+ t-att-value="props.definition.legendPosition"
1979
+ class="o-input o-type-selector"
1980
+ t-on-change="(ev) => this.updateSelect('legendPosition', ev)">
1981
+ <option value="none">None</option>
1982
+ <option value="top">Top</option>
1983
+ <option value="bottom">Bottom</option>
1984
+ <option value="left">Left</option>
1985
+ <option value="right">Right</option>
1986
+ </select>
1987
+ </div>
1988
+ </div>
1989
+ </t>
1990
+
1991
+ <t t-name="o-spreadsheet-LineConfigPanel" owl="1">
1992
+ <div>
1993
+ <div class="o-section pt-0">
1994
+ <div class="o-checkbox">
1995
+ <label>
1996
+ <input
1997
+ type="checkbox"
1998
+ name="stacked"
1999
+ t-att-checked="props.definition.stacked"
2000
+ t-on-change="onUpdateStacked"
2001
+ class="align-middle"
2002
+ />
2003
+ Stacked linechart
2004
+ </label>
2005
+ </div>
2006
+ <div class="o-checkbox">
2007
+ <label>
2008
+ <input
2009
+ type="checkbox"
2010
+ name="cumulative"
2011
+ t-att-checked="props.definition.cumulative"
2012
+ t-on-change="onUpdateCumulative"
2013
+ class="align-middle"
2014
+ />
2015
+ Cumulative data
2016
+ </label>
2017
+ </div>
2018
+ </div>
2019
+ <div class="o-section o-data-series">
2020
+ <div class="o-section-title">Data Series</div>
2021
+ <SelectionInput
2022
+ ranges="dataSeriesRanges"
2023
+ isInvalid="isDatasetInvalid"
2024
+ required="true"
2025
+ onSelectionChanged="(ranges) => this.onDataSeriesRangesChanged(ranges)"
2026
+ onSelectionConfirmed="() => this.onDataSeriesConfirmed()"
2027
+ />
2028
+ <label>
2029
+ <input
2030
+ type="checkbox"
2031
+ t-att-checked="props.definition.dataSetsHaveTitle"
2032
+ t-on-change="onUpdateDataSetsHaveTitle"
2033
+ class="align-middle"
2034
+ />
2035
+ Data series include title
2036
+ </label>
2037
+ </div>
2038
+ <div class="o-section o-data-labels">
2039
+ <div class="o-section-title">Categories / Labels</div>
2040
+ <SelectionInput
2041
+ ranges="[props.definition.labelRange || '']"
2042
+ isInvalid="isLabelInvalid"
2043
+ hasSingleRange="true"
2044
+ onSelectionChanged="(ranges) => this.onLabelRangeChanged(ranges)"
2045
+ onSelectionConfirmed="() => this.onLabelRangeConfirmed()"
2046
+ />
2047
+ <label>
2048
+ <input
2049
+ type="checkbox"
2050
+ name="aggregated"
2051
+ t-att-checked="props.definition.aggregated"
2052
+ t-on-change="onUpdateAggregated"
2053
+ class="align-middle"
2054
+ />
2055
+ Aggregate
2056
+ </label>
2057
+ <div t-if="canTreatLabelsAsText">
2058
+ <label>
2059
+ <input
2060
+ type="checkbox"
2061
+ name="labelsAsText"
2062
+ t-att-checked="props.definition.labelsAsText"
2063
+ t-on-change="onUpdateLabelsAsText"
2064
+ />
2065
+ Treat labels as text
2066
+ </label>
2067
+ </div>
2068
+ </div>
2069
+ <div class="o-section o-sidepanel-error" t-if="errorMessages">
2070
+ <div t-foreach="errorMessages" t-as="error" t-key="error">
2071
+ <t t-esc="error"/>
2072
+ </div>
2073
+ </div>
2074
+ </div>
2075
+ </t>
2076
+
2077
+ <t t-name="o-spreadsheet-LineChartDesignPanel" owl="1">
2078
+ <div>
2079
+ <div class="o-section">
2080
+ <div class="o-section-title">Background color</div>
2081
+ <div class="o-with-color-picker">
2082
+ Select a color...
2083
+ <span
2084
+ t-att-style="props.definition.background ? `border-color: ${props.definition.background}` : 'border-bottom-style: hidden'"
2085
+ t-on-click.stop="toggleColorPicker">
2086
+ <t t-call="o-spreadsheet-Icon.FILL_COLOR"/>
2087
+ </span>
2088
+ <ColorPicker
2089
+ t-if="state.fillColorTool"
2090
+ onColorPicked="(color) => this.updateBackgroundColor(color)"
2091
+ currentColor="props.definition.background"
2092
+ t-key="backgroundColor"
2093
+ />
2094
+ </div>
2095
+ </div>
2096
+ <div class="o-section o-chart-title">
2097
+ <div class="o-section-title">Title</div>
2098
+ <input
2099
+ type="text"
2100
+ t-att-value="props.definition.title"
2101
+ t-on-change="updateTitle"
2102
+ class="o-input o-optional"
2103
+ placeholder="New Chart"
2104
+ />
2105
+ </div>
2106
+ <div class="o-section">
2107
+ <div class="o-section-title">Vertical axis position</div>
2108
+ <select
2109
+ t-att-value="props.definition.verticalAxisPosition"
2110
+ class="o-input o-type-selector"
2111
+ t-on-change="(ev) => this.updateSelect('verticalAxisPosition', ev)">
2112
+ <option value="left">Left</option>
2113
+ <option value="right">Right</option>
2114
+ </select>
2115
+ </div>
2116
+ <div class="o-section">
2117
+ <div class="o-section-title">Legend position</div>
2118
+ <select
2119
+ t-att-value="props.definition.legendPosition"
2120
+ class="o-input o-type-selector"
2121
+ t-on-change="(ev) => this.updateSelect('legendPosition', ev)">
2122
+ <option value="none">None</option>
2123
+ <option value="top">Top</option>
2124
+ <option value="bottom">Bottom</option>
2125
+ <option value="left">Left</option>
2126
+ <option value="right">Right</option>
2127
+ </select>
2128
+ </div>
2129
+ </div>
2130
+ </t>
2131
+
2132
+ <t t-name="o-spreadsheet-ChartPanel" owl="1">
2133
+ <div class="o-chart">
2134
+ <div class="o-panel">
2135
+ <div
2136
+ class="o-panel-element o-panel-configuration"
2137
+ t-att-class="state.panel !== 'configuration' ? 'inactive' : ''"
2138
+ t-on-click="() => this.activatePanel('configuration')">
2139
+ <i class="fa fa-sliders"/>
2140
+ Configuration
2141
+ </div>
2142
+ <div
2143
+ class="o-panel-element o-panel-design"
2144
+ t-att-class="state.panel !== 'design' ? 'inactive' : ''"
2145
+ t-on-click="() => this.activatePanel('design')">
2146
+ <i class="fa fa-paint-brush"/>
2147
+ Design
2148
+ </div>
2149
+ </div>
2150
+
2151
+ <t t-set="definition" t-value="getChartDefinition()"/>
2152
+ <t t-if="state.panel === 'configuration'">
2153
+ <div class="o-section">
2154
+ <div class="o-section-title">Chart type</div>
2155
+ <t t-set="types" t-value="chartTypes"/>
2156
+ <select
2157
+ class="o-input o-type-selector"
2158
+ t-on-change="(ev) => this.onTypeChange(ev.target.value)">
2159
+ <option
2160
+ t-foreach="chartTypes"
2161
+ t-as="type"
2162
+ t-key="type"
2163
+ t-att-value="type"
2164
+ t-esc="types[type]"
2165
+ t-att-selected="definition.type === type"
2166
+ />
2167
+ </select>
2168
+ </div>
2169
+ <t
2170
+ t-component="chartPanel.configuration"
2171
+ definition="definition"
2172
+ figureId="figureId"
2173
+ updateChart.bind="updateChart"
2174
+ t-key="figureId + definition.type"
2175
+ />
2176
+ </t>
2177
+ <t t-else="">
2178
+ <t
2179
+ t-component="chartPanel.design"
2180
+ definition="definition"
2181
+ figureId="figureId"
2182
+ updateChart.bind="updateChart"
2183
+ t-key="figureId + definition.type"
2184
+ />
2185
+ </t>
2186
+ </div>
2187
+ </t>
2188
+
2189
+ <t t-name="o-spreadsheet-ScorecardChartConfigPanel" owl="1">
2190
+ <div>
2191
+ <div class="o-section o-data-series">
2192
+ <div class="o-section-title">Key value</div>
2193
+ <SelectionInput
2194
+ ranges="[props.definition.keyValue || '']"
2195
+ isInvalid="isKeyValueInvalid"
2196
+ hasSingleRange="true"
2197
+ required="true"
2198
+ onSelectionChanged="(ranges) => this.onKeyValueRangeChanged(ranges)"
2199
+ onSelectionConfirmed="() => this.updateKeyValueRange()"
2200
+ />
2201
+ </div>
2202
+ <div class="o-section o-data-labels">
2203
+ <div class="o-section-title">Baseline configuration</div>
2204
+ <div class="o-section-subtitle">Baseline value</div>
2205
+ <SelectionInput
2206
+ ranges="[props.definition.baseline || '']"
2207
+ isInvalid="isBaselineInvalid"
2208
+ hasSingleRange="true"
2209
+ onSelectionChanged="(ranges) => this.onBaselineRangeChanged(ranges)"
2210
+ onSelectionConfirmed="() => this.updateBaselineRange()"
2211
+ />
2212
+ <div class="o-section-subtitle">Baseline format</div>
2213
+ <select
2214
+ t-att-value="props.definition.baselineMode"
2215
+ class="o-input o-type-selector o-optional"
2216
+ t-on-change="(ev) => this.updateBaselineMode(ev)">
2217
+ <option value="text">Absolute value</option>
2218
+ <option value="difference">Value change from key value</option>
2219
+ <option value="percentage">Percentage change from key value</option>
2220
+ </select>
2221
+ </div>
2222
+ <div class="o-section o-sidepanel-error" t-if="errorMessages">
2223
+ <div t-foreach="errorMessages" t-as="error" t-key="error">
2224
+ <t t-esc="error"/>
2225
+ </div>
2226
+ </div>
2227
+ </div>
2228
+ </t>
2229
+
2230
+ <t t-name="o-spreadsheet-ScorecardChartDesignPanel" owl="1">
2231
+ <div>
2232
+ <div class="o-section">
2233
+ <div class="o-section-title">Background color</div>
2234
+ <div class="o-with-color-picker">
2235
+ Select a color...
2236
+ <span
2237
+ title="Background Color"
2238
+ t-att-style="props.definition.background ? `border-color: ${props.definition.background}` : 'border-bottom-style: hidden'"
2239
+ t-on-click.stop="() => this.openColorPicker('backgroundColor')">
2240
+ <t t-call="o-spreadsheet-Icon.FILL_COLOR"/>
2241
+ </span>
2242
+ <ColorPicker
2243
+ t-if="state.openedColorPicker === 'backgroundColor'"
2244
+ onColorPicked="(color) => this.setColor(color, 'backgroundColor')"
2245
+ currentColor="props.definition.background"
2246
+ t-key="backgroundColor"
2247
+ />
2248
+ </div>
2249
+ </div>
2250
+
2251
+ <div class="o-section o-chart-title">
2252
+ <div class="o-section-title">Title</div>
2253
+ <input
2254
+ type="text"
2255
+ t-att-value="env._t(props.definition.title)"
2256
+ t-on-change="updateTitle"
2257
+ class="o-input o-optional"
2258
+ placeholder="New Chart"
2259
+ />
2260
+ </div>
2261
+ <div class="o-section">
2262
+ <div class="o-section-title">Baseline description</div>
2263
+ <input
2264
+ type="text"
2265
+ t-att-value="env._t(props.definition.baselineDescr)"
2266
+ t-on-change="updateBaselineDescr"
2267
+ class="o-input o-optional"
2268
+ />
2269
+ </div>
2270
+ </div>
2271
+ <div class="o-section">
2272
+ <div class="o-section-title">Baseline color</div>
2273
+ <div class="o-with-color-picker">
2274
+ Color on value increase
2275
+ <span
2276
+ title="Color Up"
2277
+ t-attf-style="border-color:{{props.definition.baselineColorUp}}"
2278
+ t-on-click.stop="() => this.openColorPicker('baselineColorUp')">
2279
+ <t t-call="o-spreadsheet-Icon.FILL_COLOR"/>
2280
+ </span>
2281
+ <ColorPicker
2282
+ t-if="state.openedColorPicker === 'baselineColorUp'"
2283
+ onColorPicked="(color) => this.setColor(color, 'baselineColorUp')"
2284
+ currentColor="props.definition.baselineColorUp"
2285
+ t-key="baselineColorUp"
2286
+ />
2287
+ </div>
2288
+ <br/>
2289
+ <div class="o-with-color-picker">
2290
+ Color on value decrease
2291
+ <span
2292
+ title="Background Color"
2293
+ t-attf-style="border-color:{{props.definition.baselineColorDown}}"
2294
+ t-on-click.stop="() => this.openColorPicker('baselineColorDown')">
2295
+ <t t-call="o-spreadsheet-Icon.FILL_COLOR"/>
2296
+ </span>
2297
+ <ColorPicker
2298
+ t-if="state.openedColorPicker === 'baselineColorDown'"
2299
+ onColorPicked="(color) => this.setColor(color, 'baselineColorDown')"
2300
+ currentColor="props.definition.baselineColorDown"
2301
+ t-key="baselineColorDown"
2302
+ />
2303
+ </div>
2304
+ </div>
2305
+ </t>
2306
+
2307
+ <t t-name="o-spreadsheet-CellIsRuleEditorPreview" owl="1">
2308
+ <div
2309
+ class="o-cf-preview-line"
2310
+ t-attf-style="font-weight:{{currentStyle.bold ?'bold':'normal'}};
2311
+ text-decoration:{{getTextDecoration(currentStyle)}};
2312
+ font-style:{{currentStyle.italic?'italic':'normal'}};
2313
+ color:{{currentStyle.textColor || '#000'}};
2314
+ border-radius: 4px;
2315
+ background-color:{{currentStyle.fillColor}};">
2316
+ <t t-if="previewText" t-esc="previewText"/>
2317
+ <t t-else="">Preview text</t>
2318
+ </div>
2319
+ </t>
2320
+
2321
+ <t t-name="o-spreadsheet-CellIsRuleEditor" owl="1">
2322
+ <div class="o-cf-cell-is-rule">
2323
+ <div class="o-section-subtitle">Format cells if...</div>
2324
+ <select t-model="rule.operator" class="o-input o-cell-is-operator">
2325
+ <t t-foreach="Object.keys(cellIsOperators)" t-as="op" t-key="op_index">
2326
+ <option t-att-value="op" t-esc="cellIsOperators[op]"/>
2327
+ </t>
2328
+ </select>
2329
+ <t t-if="rule.operator !== 'IsEmpty' and rule.operator !== 'IsNotEmpty'">
2330
+ <input
2331
+ type="text"
2332
+ placeholder="Value"
2333
+ t-model="rule.values[0]"
2334
+ t-att-class="{ 'o-invalid': isValue1Invalid }"
2335
+ class="o-input o-cell-is-value o-required"
2336
+ />
2337
+ <t t-if="rule.operator === 'Between' || rule.operator === 'NotBetween'">
2338
+ <input
2339
+ type="text"
2340
+ placeholder="and value"
2341
+ t-model="rule.values[1]"
2342
+ t-att-class="{ 'o-invalid': isValue2Invalid }"
2343
+ class="o-input o-cell-is-value o-required"
2344
+ />
2345
+ </t>
2346
+ </t>
2347
+ <div class="o-section-subtitle">Formatting style</div>
2348
+
2349
+ <t t-call="o-spreadsheet-CellIsRuleEditorPreview">
2350
+ <t t-set="currentStyle" t-value="rule.style"/>
2351
+ </t>
2352
+ <div class="o-tools">
2353
+ <div
2354
+ class="o-tool"
2355
+ title="Bold"
2356
+ t-att-class="{active:rule.style.bold}"
2357
+ t-on-click="() => this.toggleStyle('bold')">
2358
+ <t t-call="o-spreadsheet-Icon.BOLD"/>
2359
+ </div>
2360
+ <div
2361
+ class="o-tool"
2362
+ title="Italic"
2363
+ t-att-class="{active:rule.style.italic}"
2364
+ t-on-click="() => this.toggleStyle('italic')">
2365
+ <t t-call="o-spreadsheet-Icon.ITALIC"/>
2366
+ </div>
2367
+ <div
2368
+ class="o-tool"
2369
+ title="Underline"
2370
+ t-att-class="{active:rule.style.underline}"
2371
+ t-on-click="(ev) => this.toggleStyle('underline', ev)">
2372
+ <t t-call="o-spreadsheet-Icon.UNDERLINE"/>
2373
+ </div>
2374
+ <div
2375
+ class="o-tool"
2376
+ title="Strikethrough"
2377
+ t-att-class="{active:rule.style.strikethrough}"
2378
+ t-on-click="(ev) => this.toggleStyle('strikethrough', ev)">
2379
+ <t t-call="o-spreadsheet-Icon.STRIKE"/>
2380
+ </div>
2381
+ <div class="o-tool o-dropdown o-with-color">
2382
+ <span
2383
+ title="TextColor"
2384
+ t-attf-style="border-color:{{rule.style.textColor}}"
2385
+ t-on-click.stop="(ev) => this.toggleMenu('cellIsRule-textColor', ev)">
2386
+ <t t-call="o-spreadsheet-Icon.TEXT_COLOR"/>
2387
+ </span>
2388
+ <ColorPicker
2389
+ t-if="state.openedMenu === 'cellIsRule-textColor'"
2390
+ dropdownDirection="'center'"
2391
+ onColorPicked="(color) => this.setColor('textColor', color)"
2392
+ currentColor="rule.style.textColor"
2393
+ t-key="textColor"
2394
+ />
2395
+ </div>
2396
+ <div class="o-divider"/>
2397
+ <div class="o-tool o-dropdown o-with-color">
2398
+ <span
2399
+ title="FillColor"
2400
+ t-attf-style="border-color:{{rule.style.fillColor}}"
2401
+ t-on-click.stop="(ev) => this.toggleMenu('cellIsRule-fillColor', ev)">
2402
+ <t t-call="o-spreadsheet-Icon.FILL_COLOR"/>
2403
+ </span>
2404
+ <ColorPicker
2405
+ t-if="state.openedMenu === 'cellIsRule-fillColor'"
2406
+ dropdownDirection="'center'"
2407
+ onColorPicked="(color) => this.setColor('fillColor', color)"
2408
+ currentColor="rule.style.fillColor"
2409
+ t-key="fillColor"
2410
+ />
2411
+ </div>
2412
+ </div>
2413
+ </div>
2414
+ </t>
2415
+
2416
+ <t t-name="o-spreadsheet-ColorScaleRuleEditorPreview" owl="1">
2417
+ <div class="o-cf-preview-gradient" t-attf-style="{{getPreviewGradient()}}">Preview text</div>
2418
+ </t>
2419
+
2420
+ <t t-name="o-spreadsheet-ColorScaleRuleEditorThreshold" owl="1">
2421
+ <div t-attf-class="o-threshold o-threshold-{{thresholdType}}">
2422
+ <t t-if="thresholdType === 'midpoint'">
2423
+ <t t-set="type" t-value="threshold and threshold.type"/>
2424
+ <select
2425
+ class="o-input"
2426
+ name="valueType"
2427
+ t-on-change="onMidpointChange"
2428
+ t-on-click="closeMenus">
2429
+ <option value="none" t-att-selected="threshold === undefined">None</option>
2430
+ <option value="number" t-att-selected="type === 'number'">FixedNumber</option>
2431
+ <option value="percentage" t-att-selected="type === 'percentage'">Percentage</option>
2432
+ <option value="percentile" t-att-selected="type === 'percentile'">Percentile</option>
2433
+ <option value="formula" t-att-selected="type === 'formula'">Formula</option>
2434
+ </select>
2435
+ </t>
2436
+ <t t-else="">
2437
+ <select class="o-input" name="valueType" t-model="threshold.type" t-on-click="closeMenus">
2438
+ <option value="value">Cell values</option>
2439
+ <option value="number">Number</option>
2440
+ <option value="percentage">Percentage</option>
2441
+ <option value="percentile">Percentile</option>
2442
+ <option value="formula">Formula</option>
2443
+ </select>
2444
+ </t>
2445
+ <input
2446
+ type="text"
2447
+ class="o-input o-threshold-value o-required"
2448
+ t-model="rule[thresholdType].value"
2449
+ t-att-class="{ 'o-invalid': isValueInvalid(thresholdType) }"
2450
+ t-if="threshold !== undefined and threshold.type !== 'value'"
2451
+ />
2452
+ <input type="text" class="o-input o-threshold-value" t-else="" disabled="1"/>
2453
+ <div class="o-tools">
2454
+ <div class="o-tool o-dropdown o-with-color" t-att-disabled="threshold === undefined">
2455
+ <span
2456
+ title="Fill Color"
2457
+ t-attf-style="border-color:{{getThresholdColor(threshold)}}"
2458
+ t-on-click.stop="(ev) => this.toggleMenu('colorScale-'+thresholdType+'Color', ev)">
2459
+ <t t-call="o-spreadsheet-Icon.FILL_COLOR"/>
2460
+ </span>
2461
+ <ColorPicker
2462
+ t-if="state.openedMenu === 'colorScale-'+thresholdType+'Color'"
2463
+ dropdownDirection="'left'"
2464
+ onColorPicked="(color) => this.setColorScaleColor(thresholdType, color)"
2465
+ currentColor="getThresholdColor(threshold)"
2466
+ />
2467
+ </div>
2468
+ </div>
2469
+ </div>
2470
+ </t>
2471
+
2472
+ <t t-name="o-spreadsheet-ColorScaleRuleEditor" owl="1">
2473
+ <div class="o-cf-color-scale-editor">
2474
+ <div class="o-section-subtitle">Preview</div>
2475
+ <t t-call="o-spreadsheet-ColorScaleRuleEditorPreview"/>
2476
+ <div class="o-section-subtitle">Minpoint</div>
2477
+ <t t-call="o-spreadsheet-ColorScaleRuleEditorThreshold">
2478
+ <t t-set="threshold" t-value="rule.minimum"/>
2479
+ <t t-set="thresholdType" t-value="'minimum'"/>
2480
+ </t>
2481
+ <div class="o-section-subtitle">MidPoint</div>
2482
+ <t t-call="o-spreadsheet-ColorScaleRuleEditorThreshold">
2483
+ <t t-set="threshold" t-value="rule.midpoint"/>
2484
+ <t t-set="thresholdType" t-value="'midpoint'"/>
2485
+ </t>
2486
+ <div class="o-section-subtitle">MaxPoint</div>
2487
+ <t t-call="o-spreadsheet-ColorScaleRuleEditorThreshold">
2488
+ <t t-set="threshold" t-value="rule.maximum"/>
2489
+ <t t-set="thresholdType" t-value="'maximum'"/>
2490
+ </t>
2491
+ </div>
2492
+ </t>
2493
+
2494
+ <t t-name="o-spreadsheet-ConditionalFormattingPanel" owl="1">
2495
+ <div class="o-cf">
2496
+ <t t-if="state.mode === 'list' || state.mode === 'reorder'">
2497
+ <div class="o-cf-preview-list">
2498
+ <div
2499
+ t-on-click="(ev) => this.editConditionalFormat(cf, ev)"
2500
+ t-foreach="conditionalFormats"
2501
+ t-as="cf"
2502
+ t-key="cf.id">
2503
+ <t t-call="o-spreadsheet-ConditionalFormattingPanelPreview"/>
2504
+ </div>
2505
+ </div>
2506
+ <t t-if="state.mode === 'list'">
2507
+ <div
2508
+ class="btn btn-link o-cf-btn-link o-cf-add"
2509
+ t-on-click.prevent.stop="addConditionalFormat">
2510
+ + Add another rule
2511
+ </div>
2512
+ <div
2513
+ class="btn btn-link o-cf-btn-link o-cf-reorder"
2514
+ t-on-click="reorderConditionalFormats">
2515
+ Reorder rules
2516
+ </div>
2517
+ </t>
2518
+ <t t-if="state.mode === 'reorder'">
2519
+ <div class="btn btn-link o-cf-btn-link o-cf-exit-reorder" t-on-click="switchToList">
2520
+ Stop reordering rules
2521
+ </div>
2522
+ </t>
2523
+ </t>
2524
+ <t t-if="state.mode === 'edit' || state.mode === 'add'" t-key="state.currentCF.id">
2525
+ <div class="o-cf-ruleEditor">
2526
+ <div class="o-section o-cf-range">
2527
+ <div class="o-section-title">Apply to range</div>
2528
+ <div class="o-selection-cf">
2529
+ <SelectionInput
2530
+ ranges="state.currentCF.ranges"
2531
+ class="'o-range'"
2532
+ isInvalid="isRangeValid"
2533
+ onSelectionChanged="(ranges) => this.onRangesChanged(ranges)"
2534
+ required="true"
2535
+ />
2536
+ </div>
2537
+ <div class="o-section-title">Format rules</div>
2538
+ <div class="o_field_radio o_horizontal o_field_widget o-cf-type-selector">
2539
+ <div
2540
+ class="custom-control form-check o_cf_radio_item"
2541
+ t-on-click="() => this.changeRuleType('CellIsRule')">
2542
+ <input
2543
+ class="form-check-input o_radio_input"
2544
+ t-att-checked="state.currentCFType === 'CellIsRule'"
2545
+ type="radio"
2546
+ id="cellIsRule"
2547
+ name="ruleType"
2548
+ value="CellIsRule"
2549
+ />
2550
+ <label for="cellIsRule" class="form-check-label o_form_label">Single color</label>
2551
+ </div>
2552
+ <div
2553
+ class="custom-control form-check o_cf_radio_item"
2554
+ t-on-click="() => this.changeRuleType('ColorScaleRule')">
2555
+ <input
2556
+ class="form-check-input o_radio_input"
2557
+ t-att-checked="state.currentCFType === 'ColorScaleRule'"
2558
+ type="radio"
2559
+ id="colorScaleRule"
2560
+ name="ruleType"
2561
+ value="ColorScaleRule"
2562
+ />
2563
+ <label for="colorScaleRule" class="form-check-label o_form_label">
2564
+ Color scale
2565
+ </label>
2566
+ </div>
2567
+
2568
+ <div
2569
+ class="custom-control form-check o_cf_radio_item"
2570
+ t-on-click="() => this.changeRuleType('IconSetRule')">
2571
+ <input
2572
+ class="form-check-input o_radio_input"
2573
+ t-att-checked="state.currentCFType === 'IconSetRule'"
2574
+ type="radio"
2575
+ id="iconSetRule"
2576
+ name="ruleType"
2577
+ value="IconSetRule"
2578
+ />
2579
+ <label for="iconSetRule" class="form-check-label o_form_label">Icon set</label>
2580
+ </div>
2581
+ </div>
2582
+ </div>
2583
+ <div class="o-section o-cf-editor">
2584
+ <t t-if="state.currentCFType === 'CellIsRule'" t-call="o-spreadsheet-CellIsRuleEditor">
2585
+ <t t-set="rule" t-value="state.rules.cellIs"/>
2586
+ </t>
2587
+ <t
2588
+ t-if="state.currentCFType === 'ColorScaleRule'"
2589
+ t-call="o-spreadsheet-ColorScaleRuleEditor">
2590
+ <t t-set="rule" t-value="state.rules.colorScale"/>
2591
+ </t>
2592
+ <t t-if="state.currentCFType === 'IconSetRule'" t-call="o-spreadsheet-IconSetEditor">
2593
+ <t t-set="rule" t-value="state.rules.iconSet"/>
2594
+ </t>
2595
+ <div class="o-sidePanelButtons">
2596
+ <button t-on-click="switchToList" class="o-sidePanelButton o-cf-cancel">
2597
+ Cancel
2598
+ </button>
2599
+ <button t-on-click="saveConditionalFormat" class="o-sidePanelButton o-cf-save">
2600
+ Save
2601
+ </button>
2602
+ </div>
2603
+ </div>
2604
+ <div class="o-section">
2605
+ <div class="o-cf-error" t-foreach="state.errors || []" t-as="error" t-key="error_index">
2606
+ <t t-esc="errorMessage(error)"/>
2607
+ </div>
2608
+ </div>
2609
+ </div>
2610
+ </t>
2611
+ </div>
2612
+ </t>
2613
+
2614
+ <t t-name="o-spreadsheet-ConditionalFormattingPanelPreview" owl="1">
2615
+ <div class="o-cf-preview" t-att-class="{ 'o-cf-cursor-ptr': state.mode !== 'reorder' }">
2616
+ <t t-if="cf.rule.type==='IconSetRule'">
2617
+ <div class="o-cf-preview-icon">
2618
+ <t t-call="o-spreadsheet-Icon.{{icons[cf.rule.icons.upper].template}}"/>
2619
+ <t t-call="o-spreadsheet-Icon.{{icons[cf.rule.icons.middle].template}}"/>
2620
+ <t t-call="o-spreadsheet-Icon.{{icons[cf.rule.icons.lower].template}}"/>
2621
+ </div>
2622
+ </t>
2623
+ <t t-else="">
2624
+ <div t-att-style="getStyle(cf.rule)" class="o-cf-preview-image">123</div>
2625
+ </t>
2626
+ <div class="o-cf-preview-description">
2627
+ <div class="o-cf-preview-ruletype">
2628
+ <div class="o-cf-preview-description-rule">
2629
+ <t t-esc="getDescription(cf)"/>
2630
+ </div>
2631
+ </div>
2632
+ <div class="o-cf-preview-range" t-esc="cf.ranges"/>
2633
+ </div>
2634
+ <t t-if="state.mode === 'reorder'">
2635
+ <div class="o-cf-reorder">
2636
+ <t t-if="!cf_first">
2637
+ <div
2638
+ class="o-cf-reorder-button-up o-cf-reorder-button"
2639
+ t-on-click="(ev) => this.reorderRule(cf, 'up', ev)">
2640
+ <t t-call="o-spreadsheet-Icon.CARET_UP"/>
2641
+ </div>
2642
+ </t>
2643
+ <t t-if="!cf_last">
2644
+ <div
2645
+ class="o-cf-reorder-button-down o-cf-reorder-button"
2646
+ t-on-click="(ev) => this.reorderRule(cf, 'down', ev)">
2647
+ <t t-call="o-spreadsheet-Icon.CARET_DOWN"/>
2648
+ </div>
2649
+ </t>
2650
+ </div>
2651
+ </t>
2652
+ <t t-else="">
2653
+ <div class="o-cf-delete">
2654
+ <div
2655
+ class="o-cf-delete-button"
2656
+ t-on-click.stop="(ev) => this.deleteConditionalFormat(cf, ev)"
2657
+ aria-label="Remove rule">
2658
+ <t t-call="o-spreadsheet-Icon.TRASH"/>
2659
+ </div>
2660
+ </div>
2661
+ </t>
2662
+ </div>
2663
+ </t>
2664
+
2665
+ <t t-name="o-spreadsheet-IconSets" owl="1">
2666
+ <div>
2667
+ <div class="o-section-subtitle">Icons</div>
2668
+ <div class="o-cf-iconsets">
2669
+ <div
2670
+ class="o-cf-iconset"
2671
+ t-foreach="['arrows', 'smiley', 'dots']"
2672
+ t-as="iconSet"
2673
+ t-key="iconSet"
2674
+ t-on-click="(ev) => this.setIconSet(iconSet, ev)">
2675
+ <div class="o-cf-icon">
2676
+ <t t-call="o-spreadsheet-Icon.{{icons[iconSets[iconSet].good].template}}"/>
2677
+ </div>
2678
+ <div class="o-cf-icon">
2679
+ <t t-call="o-spreadsheet-Icon.{{icons[iconSets[iconSet].neutral].template}}"/>
2680
+ </div>
2681
+ <div class="o-cf-icon">
2682
+ <t t-call="o-spreadsheet-Icon.{{icons[iconSets[iconSet].bad].template}}"/>
2683
+ </div>
2684
+ </div>
2685
+ </div>
2686
+ </div>
2687
+ </t>
2688
+
2689
+ <t t-name="o-spreadsheet-IconSetInflexionPointRow" owl="1">
2690
+ <tr>
2691
+ <td>
2692
+ <div t-on-click.stop="(ev) => this.toggleMenu('iconSet-'+icon+'Icon', ev)">
2693
+ <div class="o-cf-icon-button">
2694
+ <t t-call="o-spreadsheet-Icon.{{icons[iconValue].template}}"/>
2695
+ </div>
2696
+ </div>
2697
+ <IconPicker
2698
+ t-if="state.openedMenu === 'iconSet-'+icon+'Icon'"
2699
+ onIconPicked="(i) => this.setIcon(icon, i)"
2700
+ />
2701
+ </td>
2702
+ <td>When value is</td>
2703
+ <td>
2704
+ <select class="o-input" name="valueType" t-model="inflectionPointValue.operator">
2705
+ <option value="gt">
2706
+ <span>&#62;</span>
2707
+ </option>
2708
+ <option value="ge">
2709
+ <span>&#8805;</span>
2710
+ </option>
2711
+ </select>
2712
+ </td>
2713
+ <td>
2714
+ <input
2715
+ type="text"
2716
+ class="o-input"
2717
+ t-att-class="{ 'o-invalid': isInflectionPointInvalid(inflectionPoint) }"
2718
+ t-model="rule[inflectionPoint].value"
2719
+ />
2720
+ </td>
2721
+ <td>
2722
+ <select class="o-input" name="valueType" t-model="inflectionPointValue.type">
2723
+ <option value="number">Number</option>
2724
+ <option value="percentage">Percentage</option>
2725
+ <option value="percentile">Percentile</option>
2726
+ <option value="formula">Formula</option>
2727
+ </select>
2728
+ </td>
2729
+ </tr>
2730
+ </t>
2731
+
2732
+ <t t-name="o-spreadsheet-IconSetInflexionPoints" owl="1">
2733
+ <div class="o-inflection">
2734
+ <table>
2735
+ <tr>
2736
+ <th class="o-cf-iconset-icons"/>
2737
+ <th class="o-cf-iconset-text"/>
2738
+ <th class="o-cf-iconset-operator"/>
2739
+ <th class="o-cf-iconset-value">Value</th>
2740
+ <th class="o-cf-iconset-type">Type</th>
2741
+ </tr>
2742
+ <t t-call="o-spreadsheet-IconSetInflexionPointRow">
2743
+ <t t-set="iconValue" t-value="rule.icons.upper"/>
2744
+ <t t-set="icon" t-value="'upper'"/>
2745
+ <t t-set="inflectionPointValue" t-value="rule.upperInflectionPoint"/>
2746
+ <t t-set="inflectionPoint" t-value="'upperInflectionPoint'"/>
2747
+ </t>
2748
+ <t t-call="o-spreadsheet-IconSetInflexionPointRow">
2749
+ <t t-set="iconValue" t-value="rule.icons.middle"/>
2750
+ <t t-set="icon" t-value="'middle'"/>
2751
+ <t t-set="inflectionPointValue" t-value="rule.lowerInflectionPoint"/>
2752
+ <t t-set="inflectionPoint" t-value="'lowerInflectionPoint'"/>
2753
+ </t>
2754
+ <tr>
2755
+ <td>
2756
+ <div t-on-click.stop="(ev) => this.toggleMenu('iconSet-lowerIcon', ev)">
2757
+ <div class="o-cf-icon-button">
2758
+ <t t-call="o-spreadsheet-Icon.{{icons[rule.icons.lower].template}}"/>
2759
+ </div>
2760
+ </div>
2761
+ <IconPicker
2762
+ t-if="state.openedMenu === 'iconSet-lowerIcon'"
2763
+ onIconPicked="(icon) => this.setIcon('lower', icon)"
2764
+ />
2765
+ </td>
2766
+ <td>Else</td>
2767
+ <td/>
2768
+ <td/>
2769
+ <td/>
2770
+ </tr>
2771
+ </table>
2772
+ </div>
2773
+ </t>
2774
+ <t t-name="o-spreadsheet-IconSetEditor" owl="1">
2775
+ <div class="o-cf-iconset-rule">
2776
+ <t t-call="o-spreadsheet-IconSets"/>
2777
+ <t t-call="o-spreadsheet-IconSetInflexionPoints"/>
2778
+ <div class="btn btn-link o_refresh_measures o-cf-iconset-reverse" t-on-click="reverseIcons">
2779
+ <div class="me-1 d-inline-block">
2780
+ <t t-call="o-spreadsheet-Icon.REFRESH"/>
2781
+ </div>
2782
+ Reverse icons
2783
+ </div>
2784
+ </div>
2785
+ </t>
2786
+
2787
+ <t t-name="o-spreadsheet-CustomCurrencyPanel" owl="1">
2788
+ <div class="o-custom-currency">
2789
+ <div class="o-section" t-if="availableCurrencies.length > 1">
2790
+ <div class="o-section-title">Currency</div>
2791
+ <select
2792
+ class="o-input o-available-currencies"
2793
+ t-on-change="(ev) => this.updateSelectCurrency(ev)">
2794
+ <t t-foreach="availableCurrencies" t-as="currency" t-key="currency_index">
2795
+ <option
2796
+ t-att-value="currency_index"
2797
+ t-esc="currencyDisplayName(currency)"
2798
+ t-att-selected="currency_index === state.selectedCurrencyIndex"
2799
+ />
2800
+ </t>
2801
+ </select>
2802
+ </div>
2803
+ <div class="o-section">
2804
+ <div class="o-subsection-left">
2805
+ <div class="o-section-title">Code</div>
2806
+ <input
2807
+ type="text"
2808
+ class="o-input"
2809
+ t-model="state.currencyCode"
2810
+ t-on-input="(ev) => this.updateCode(ev)"
2811
+ />
2812
+ </div>
2813
+ <div class="o-subsection-right">
2814
+ <div class="o-section-title">Symbol</div>
2815
+ <input
2816
+ type="text"
2817
+ class="o-input"
2818
+ t-model="state.currencySymbol"
2819
+ t-on-input="(ev) => this.updateSymbol(ev)"
2820
+ />
2821
+ </div>
2822
+ </div>
2823
+ <div class="o-section">
2824
+ <div class="o-section-title">Format</div>
2825
+ <select
2826
+ class="o-input o-format-proposals"
2827
+ t-on-change="(ev) => this.updateSelectFormat(ev)"
2828
+ t-att-disabled="!formatProposals.length">
2829
+ <t t-foreach="formatProposals" t-as="proposal" t-key="proposal_index">
2830
+ <option
2831
+ t-att-value="proposal_index"
2832
+ t-esc="proposal.example"
2833
+ t-att-selected="proposal_index === state.selectedFormatIndex"
2834
+ />
2835
+ </t>
2836
+ </select>
2837
+ </div>
2838
+ <div class="o-sidePanelButtons">
2839
+ <button
2840
+ class="o-sidePanelButton"
2841
+ t-on-click="() => this.apply()"
2842
+ t-att-disabled="!formatProposals.length || isSameFormat">
2843
+ Apply
2844
+ </button>
2845
+ </div>
2846
+ </div>
2847
+ </t>
2848
+
2849
+ <t t-name="o-spreadsheet-FindAndReplacePanel" owl="1">
2850
+ <div class="o-find-and-replace" tabindex="0" t-ref="findAndReplace">
2851
+ <div class="o-section">
2852
+ <div class="o-section-title">Search</div>
2853
+ <div class="o-input-search-container">
2854
+ <input
2855
+ type="text"
2856
+ class="o-input o-input-with-count"
2857
+ t-on-input="onInput"
2858
+ t-on-keydown="onKeydownSearch"
2859
+ />
2860
+ <div class="o-input-count" t-if="hasSearchResult">
2861
+ <t t-esc="env.model.getters.getCurrentSelectedMatchIndex()+1"/>
2862
+ /
2863
+ <t t-esc="env.model.getters.getSearchMatches().length"/>
2864
+ </div>
2865
+ <div t-elif="!pendingSearch and state.toSearch !== ''" class="o-input-count">0 / 0</div>
2866
+ </div>
2867
+ <div>
2868
+ <!-- TODO: go through this css, the group misses a padding and could profit from BootStrap -->
2869
+ <div class="o-far-item">
2870
+ <label class="o-far-checkbox">
2871
+ <input
2872
+ t-model="state.searchOptions.matchCase"
2873
+ t-on-change="updateSearch"
2874
+ class="o-far-input"
2875
+ type="checkbox"
2876
+ />
2877
+ <span class="o-far-label">Match case</span>
2878
+ </label>
2879
+ </div>
2880
+ <div class="o-far-item">
2881
+ <label class="o-far-checkbox">
2882
+ <input
2883
+ t-model="state.searchOptions.exactMatch"
2884
+ t-on-change="updateSearch"
2885
+ class="o-far-input"
2886
+ type="checkbox"
2887
+ />
2888
+ <span class="o-far-label">Match entire cell content</span>
2889
+ </label>
2890
+ </div>
2891
+ <div class="o-far-item">
2892
+ <label class="o-far-checkbox">
2893
+ <input
2894
+ t-model="state.searchOptions.searchFormulas"
2895
+ t-on-change="searchFormulas"
2896
+ class="o-far-input"
2897
+ type="checkbox"
2898
+ />
2899
+ <span class="o-far-label">Search in formulas</span>
2900
+ </label>
2901
+ </div>
2902
+ </div>
2903
+ </div>
2904
+ <div class="o-sidePanelButtons">
2905
+ <button
2906
+ t-att-disabled="!hasSearchResult"
2907
+ t-on-click="onSelectPreviousCell"
2908
+ class="o-sidePanelButton">
2909
+ Previous
2910
+ </button>
2911
+ <button
2912
+ t-att-disabled="!hasSearchResult"
2913
+ t-on-click="onSelectNextCell"
2914
+ class="o-sidePanelButton">
2915
+ Next
2916
+ </button>
2917
+ </div>
2918
+ <div class="o-section" t-if="!env.model.getters.isReadonly()">
2919
+ <div class="o-section-title">Replace</div>
2920
+ <div class="o-input-search-container">
2921
+ <input
2922
+ type="text"
2923
+ class="o-input o-input-without-count"
2924
+ t-model="state.replaceWith"
2925
+ t-on-keydown="onKeydownReplace"
2926
+ />
2927
+ </div>
2928
+ </div>
2929
+
2930
+ <div class="o-sidePanelButtons" t-if="!env.model.getters.isReadonly()">
2931
+ <button
2932
+ t-att-disabled="env.model.getters.getCurrentSelectedMatchIndex() === null"
2933
+ t-on-click="replace"
2934
+ class="o-sidePanelButton">
2935
+ Replace
2936
+ </button>
2937
+ <button
2938
+ t-att-disabled="env.model.getters.getCurrentSelectedMatchIndex() === null"
2939
+ t-on-click="replaceAll"
2940
+ class="o-sidePanelButton">
2941
+ Replace all
2942
+ </button>
2943
+ </div>
2944
+ </div>
2945
+ </t>
2946
+
2947
+ <t t-name="o-spreadsheet-SidePanel" owl="1">
2948
+ <div class="o-sidePanel">
2949
+ <div class="o-sidePanelHeader">
2950
+ <div class="o-sidePanelTitle" t-esc="getTitle()"/>
2951
+ <div class="o-sidePanelClose" t-on-click="() => this.props.onCloseSidePanel()">✕</div>
2952
+ </div>
2953
+ <div class="o-sidePanelBody">
2954
+ <t
2955
+ t-component="state.panel.Body"
2956
+ t-props="props.panelProps"
2957
+ onCloseSidePanel="props.onCloseSidePanel"
2958
+ t-key="'Body_' + props.component"
2959
+ />
2960
+ </div>
2961
+ <div class="o-sidePanelFooter" t-if="state.panel.Footer">
2962
+ <t
2963
+ t-component="state.panel.Footer"
2964
+ t-props="props.panelProps"
2965
+ t-key="'Footer_' + props.component"
2966
+ />
2967
+ </div>
2968
+ </div>
2969
+ </t>
2970
+
2971
+ <t t-name="o-spreadsheet-Spreadsheet" owl="1">
2972
+ <div
2973
+ class="o-spreadsheet"
2974
+ t-on-keydown="(ev) => !env.isDashboard() and this.onKeydown(ev)"
2975
+ t-att-style="getStyle()">
2976
+ <t t-if="env.isDashboard()">
2977
+ <SpreadsheetDashboard/>
2978
+ </t>
2979
+ <t t-else="">
2980
+ <TopBar
2981
+ onClick="() => this.focusGrid()"
2982
+ onComposerContentFocused="(selection) => this.onTopBarComposerFocused(selection)"
2983
+ focusComposer="focusTopBarComposer"
2984
+ dropdownMaxHeight="gridHeight"
2985
+ />
2986
+ <Grid
2987
+ sidePanelIsOpen="sidePanel.isOpen"
2988
+ focusComposer="focusGridComposer"
2989
+ exposeFocus="(focus) => this._focusGrid = focus"
2990
+ onComposerContentFocused="() => this.onGridComposerContentFocused()"
2991
+ onGridComposerCellFocused="(content, selection) => this.onGridComposerCellFocused(content, selection)"
2992
+ />
2993
+ <SidePanel
2994
+ t-if="sidePanel.isOpen"
2995
+ onCloseSidePanel="() => this.closeSidePanel()"
2996
+ component="sidePanel.component"
2997
+ panelProps="sidePanel.panelProps"
2998
+ />
2999
+ <BottomBar onClick="() => this.focusGrid()"/>
3000
+ </t>
3001
+ </div>
3002
+ </t>
3003
+
3004
+ <t t-name="o-spreadsheet-TopBar" owl="1">
3005
+ <div class="o-spreadsheet-topbar o-two-columns" t-on-click="props.onClick">
3006
+ <div class="o-topbar-top">
3007
+ <!-- Menus -->
3008
+ <div class="o-topbar-topleft">
3009
+ <t t-foreach="menus" t-as="menu" t-key="menu_index">
3010
+ <div
3011
+ t-if="menu.children.length !== 0"
3012
+ class="o-topbar-menu"
3013
+ t-att-class="{'o-topbar-menu-active': state.menuState.parentMenu and state.menuState.parentMenu.id === menu.id}"
3014
+ t-on-click="(ev) => this.toggleContextMenu(menu, ev)"
3015
+ t-on-mouseover="(ev) => this.onMenuMouseOver(menu, ev)"
3016
+ t-att-data-id="menu.id">
3017
+ <t t-esc="getMenuName(menu)"/>
3018
+ </div>
3019
+ </t>
3020
+ <Menu
3021
+ t-if="state.menuState.isOpen"
3022
+ position="state.menuState.position"
3023
+ menuItems="state.menuState.menuItems"
3024
+ onClose="() => this.closeMenus()"
3025
+ onMenuClicked="() => this.props.onClick()"
3026
+ />
3027
+ </div>
3028
+ <div class="o-topbar-topright">
3029
+ <div t-foreach="topbarComponents" t-as="comp" t-key="comp.id">
3030
+ <t t-component="comp.component"/>
3031
+ </div>
3032
+ </div>
3033
+ </div>
3034
+ <!-- Toolbar and Cell Content -->
3035
+ <div class="o-topbar-toolbar">
3036
+ <!-- Toolbar -->
3037
+ <div t-if="env.model.getters.isReadonly()" class="o-readonly-toolbar text-muted">
3038
+ <span>
3039
+ <i class="fa fa-eye"/>
3040
+ Readonly Access
3041
+ </span>
3042
+ </div>
3043
+ <div t-else="" class="o-toolbar-tools">
3044
+ <div
3045
+ class="o-tool"
3046
+ title="Undo"
3047
+ t-att-class="{'o-disabled': !undoTool}"
3048
+ t-on-click="undo">
3049
+ <t t-call="o-spreadsheet-Icon.UNDO"/>
3050
+ </div>
3051
+ <div
3052
+ class="o-tool"
3053
+ t-att-class="{'o-disabled': !redoTool}"
3054
+ title="Redo"
3055
+ t-on-click="redo">
3056
+ <t t-call="o-spreadsheet-Icon.REDO"/>
3057
+ </div>
3058
+ <div
3059
+ class="o-tool"
3060
+ title="Paint Format"
3061
+ t-att-class="{active:paintFormatTool}"
3062
+ t-on-click="paintFormat">
3063
+ <t t-call="o-spreadsheet-Icon.PAINT_FORMAT"/>
3064
+ </div>
3065
+ <div class="o-tool" title="Clear Format" t-on-click="clearFormatting">
3066
+ <t t-call="o-spreadsheet-Icon.CLEAR_FORMAT"/>
3067
+ </div>
3068
+ <div class="o-divider"/>
3069
+ <div
3070
+ class="o-tool"
3071
+ title="Format as percent"
3072
+ t-on-click="(ev) => this.toggleFormat('percent', ev)">
3073
+ %
3074
+ </div>
3075
+ <div
3076
+ class="o-tool"
3077
+ title="Decrease decimal places"
3078
+ t-on-click="(ev) => this.setDecimal(-1, ev)">
3079
+ .0
3080
+ </div>
3081
+ <div
3082
+ class="o-tool"
3083
+ title="Increase decimal places"
3084
+ t-on-click="(ev) => this.setDecimal(+1, ev)">
3085
+ .00
3086
+ </div>
3087
+ <div class="o-dropdown">
3088
+ <div
3089
+ class="o-tool o-dropdown-button o-text-icon"
3090
+ title="More formats"
3091
+ t-on-click="(ev) => this.toggleDropdownTool('formatTool', ev)">
3092
+ 123
3093
+ <t t-call="o-spreadsheet-Icon.TRIANGLE_DOWN"/>
3094
+ </div>
3095
+ <div
3096
+ class="o-dropdown-content o-text-options o-format-tool "
3097
+ t-att-style="dropdownStyle"
3098
+ t-if="state.activeTool === 'formatTool'"
3099
+ t-on-click.stop="">
3100
+ <t t-foreach="commonFormats" t-as="commonFormat" t-key="commonFormat.name">
3101
+ <div
3102
+ class="o-dropdown-item"
3103
+ t-att-data-format="commonFormat.name"
3104
+ t-on-click="() => this.setFormat(commonFormat.name)"
3105
+ t-att-class="{active: currentFormatName === commonFormat.name}">
3106
+ <t t-esc="commonFormat.text"/>
3107
+ <span class="float-end text-muted" t-esc="commonFormat.description"/>
3108
+ </div>
3109
+ </t>
3110
+ <t t-foreach="customFormats" t-as="customFormat" t-key="customFormat.name">
3111
+ <div
3112
+ t-att-data-custom="customFormat.name"
3113
+ class="o-dropdown-item"
3114
+ t-on-click="() => this.setFormat(customFormat.name, true)">
3115
+ <t t-esc="customFormat.text"/>
3116
+ </div>
3117
+ </t>
3118
+ </div>
3119
+ </div>
3120
+ <div class="o-divider"/>
3121
+ <div class="o-dropdown">
3122
+ <div
3123
+ class="o-tool o-dropdown-button o-text-icon"
3124
+ title="Font Size"
3125
+ t-on-click="(ev) => this.toggleDropdownTool('fontSizeTool', ev)">
3126
+ <t t-esc="style.fontSize || DEFAULT_FONT_SIZE"/>
3127
+ <t t-call="o-spreadsheet-Icon.TRIANGLE_DOWN"/>
3128
+ </div>
3129
+ <div
3130
+ class="o-dropdown-content o-text-options "
3131
+ t-att-style="dropdownStyle"
3132
+ t-if="state.activeTool === 'fontSizeTool'"
3133
+ t-on-click.stop="">
3134
+ <t t-foreach="fontSizes" t-as="font" t-key="font_index">
3135
+ <div
3136
+ t-esc="font.pt"
3137
+ t-att-data-size="font.pt"
3138
+ class="o-dropdown-item"
3139
+ t-on-click="() => this.setSize(font.pt)"
3140
+ />
3141
+ </t>
3142
+ </div>
3143
+ </div>
3144
+ <div class="o-divider"/>
3145
+ <div
3146
+ class="o-tool"
3147
+ title="Bold"
3148
+ t-att-class="{active:style.bold}"
3149
+ t-on-click="(ev) => this.toggleStyle('bold', ev)">
3150
+ <t t-call="o-spreadsheet-Icon.BOLD"/>
3151
+ </div>
3152
+ <div
3153
+ class="o-tool"
3154
+ title="Italic"
3155
+ t-att-class="{active:style.italic}"
3156
+ t-on-click="(ev) => this.toggleStyle('italic', ev)">
3157
+ <t t-call="o-spreadsheet-Icon.ITALIC"/>
3158
+ </div>
3159
+ <div
3160
+ class="o-tool"
3161
+ title="Strikethrough"
3162
+ t-att-class="{active:style.strikethrough}"
3163
+ t-on-click="(ev) => this.toggleStyle('strikethrough', ev)">
3164
+ <t t-call="o-spreadsheet-Icon.STRIKE"/>
3165
+ </div>
3166
+ <div class="o-dropdown">
3167
+ <div
3168
+ class="o-tool o-dropdown-button o-with-color"
3169
+ title="Text Color"
3170
+ t-on-click="(ev) => this.toggleDropdownTool('textColorTool', ev)">
3171
+ <span t-attf-style="border-color:{{textColor}}">
3172
+ <t t-call="o-spreadsheet-Icon.TEXT_COLOR"/>
3173
+ </span>
3174
+ </div>
3175
+ <ColorPicker
3176
+ t-if="state.activeTool === 'textColorTool'"
3177
+ onColorPicked="(color) => this.setColor('textColor', color)"
3178
+ currentColor="textColor"
3179
+ t-key="textColor"
3180
+ maxHeight="this.props.dropdownMaxHeight"
3181
+ />
3182
+ </div>
3183
+ <div class="o-divider"/>
3184
+ <div class="o-dropdown ">
3185
+ <div
3186
+ class="o-tool o-dropdown-button o-with-color"
3187
+ title="Fill Color"
3188
+ t-on-click="(ev) => this.toggleDropdownTool('fillColorTool', ev)">
3189
+ <span t-attf-style="border-color:{{fillColor}}">
3190
+ <t t-call="o-spreadsheet-Icon.FILL_COLOR"/>
3191
+ </span>
3192
+ </div>
3193
+ <ColorPicker
3194
+ t-if="state.activeTool === 'fillColorTool'"
3195
+ onColorPicked="(color) => this.setColor('fillColor', color)"
3196
+ currentColor="fillColor"
3197
+ t-key="fillColor"
3198
+ maxHeight="this.props.dropdownMaxHeight"
3199
+ />
3200
+ </div>
3201
+ <div class="o-dropdown">
3202
+ <div
3203
+ class="o-tool o-dropdown-button"
3204
+ title="Borders"
3205
+ t-on-click="(ev) => this.toggleDropdownTool('borderTool', ev)">
3206
+ <span>
3207
+ <t t-call="o-spreadsheet-Icon.BORDERS"/>
3208
+ </span>
3209
+ </div>
3210
+ <div
3211
+ class="o-dropdown-content o-border-dropdown"
3212
+ t-if="state.activeTool === 'borderTool'"
3213
+ t-att-style="dropdownStyle"
3214
+ t-on-click.stop="">
3215
+ <div class="o-dropdown-line">
3216
+ <span class="o-line-item" t-on-click="(ev) => this.setBorder('all')">
3217
+ <t t-call="o-spreadsheet-Icon.BORDERS"/>
3218
+ </span>
3219
+ <span class="o-line-item" t-on-click="(ev) => this.setBorder('hv')">
3220
+ <t t-call="o-spreadsheet-Icon.BORDER_HV"/>
3221
+ </span>
3222
+ <span class="o-line-item" t-on-click="(ev) => this.setBorder('h')">
3223
+ <t t-call="o-spreadsheet-Icon.BORDER_H"/>
3224
+ </span>
3225
+ <span class="o-line-item" t-on-click="(ev) => this.setBorder('v')">
3226
+ <t t-call="o-spreadsheet-Icon.BORDER_V"/>
3227
+ </span>
3228
+ <span class="o-line-item" t-on-click="(ev) => this.setBorder('external')">
3229
+ <t t-call="o-spreadsheet-Icon.BORDER_EXTERNAL"/>
3230
+ </span>
3231
+ </div>
3232
+ <div class="o-dropdown-line">
3233
+ <span class="o-line-item" t-on-click="(ev) => this.setBorder('left')">
3234
+ <t t-call="o-spreadsheet-Icon.BORDER_LEFT"/>
3235
+ </span>
3236
+ <span class="o-line-item" t-on-click="(ev) => this.setBorder('top')">
3237
+ <t t-call="o-spreadsheet-Icon.BORDER_TOP"/>
3238
+ </span>
3239
+ <span class="o-line-item" t-on-click="(ev) => this.setBorder('right')">
3240
+ <t t-call="o-spreadsheet-Icon.BORDER_RIGHT"/>
3241
+ </span>
3242
+ <span class="o-line-item" t-on-click="(ev) => this.setBorder('bottom')">
3243
+ <t t-call="o-spreadsheet-Icon.BORDER_BOTTOM"/>
3244
+ </span>
3245
+ <span class="o-line-item" t-on-click="(ev) => this.setBorder('clear')">
3246
+ <t t-call="o-spreadsheet-Icon.BORDER_CLEAR"/>
3247
+ </span>
3248
+ </div>
3249
+ </div>
3250
+ </div>
3251
+ <div
3252
+ class="o-tool o-merge-tool"
3253
+ title="Merge Cells"
3254
+ t-att-class="{active:inMerge, 'o-disabled': cannotMerge}"
3255
+ t-on-click="toggleMerge">
3256
+ <t t-call="o-spreadsheet-Icon.MERGE_CELL"/>
3257
+ </div>
3258
+ <div class="o-divider"/>
3259
+ <div class="o-dropdown">
3260
+ <div
3261
+ class="o-tool o-dropdown-button"
3262
+ title="Horizontal align"
3263
+ t-on-click="(ev) => this.toggleDropdownTool('alignTool', ev)">
3264
+ <span>
3265
+ <t t-if="style.align === 'right'">
3266
+ <t t-call="o-spreadsheet-Icon.ALIGN_RIGHT"/>
3267
+ </t>
3268
+ <t t-elif="style.align === 'center'">
3269
+ <t t-call="o-spreadsheet-Icon.ALIGN_CENTER"/>
3270
+ </t>
3271
+ <t t-else="">
3272
+ <t t-call="o-spreadsheet-Icon.ALIGN_LEFT"/>
3273
+ </t>
3274
+ <t t-call="o-spreadsheet-Icon.TRIANGLE_DOWN"/>
3275
+ </span>
3276
+ </div>
3277
+ <div
3278
+ t-if="state.activeTool === 'alignTool'"
3279
+ class="o-dropdown-content"
3280
+ t-att-style="dropdownStyle"
3281
+ t-on-click.stop="">
3282
+ <div
3283
+ class="o-dropdown-item o-dropdown-align-item"
3284
+ t-on-click="(ev) => this.toggleAlign('left', ev)">
3285
+ <t t-call="o-spreadsheet-Icon.ALIGN_LEFT"/>
3286
+ </div>
3287
+ <div
3288
+ class="o-dropdown-item o-dropdown-align-item"
3289
+ t-on-click="(ev) => this.toggleAlign('center', ev)">
3290
+ <t t-call="o-spreadsheet-Icon.ALIGN_CENTER"/>
3291
+ </div>
3292
+ <div
3293
+ class="o-dropdown-item o-dropdown-align-item"
3294
+ t-on-click="(ev) => this.toggleAlign('right', ev)">
3295
+ <t t-call="o-spreadsheet-Icon.ALIGN_RIGHT"/>
3296
+ </div>
3297
+ </div>
3298
+ </div>
3299
+ <div class="o-divider"/>
3300
+ <div
3301
+ t-if="selectionContainsFilter"
3302
+ class="o-tool o-filter-tool o-tool-outlined"
3303
+ title="Remove selected filters"
3304
+ t-on-click="removeFilter">
3305
+ <t t-call="o-spreadsheet-Icon.FILTER_ICON_ACTIVE"/>
3306
+ </div>
3307
+ <div
3308
+ t-else=""
3309
+ class="o-tool o-filter-tool"
3310
+ t-att-class="{'o-disabled': cannotCreateFilter}"
3311
+ title="Create filter"
3312
+ t-on-click="createFilter">
3313
+ <t t-call="o-spreadsheet-Icon.FILTER_ICON_INACTIVE"/>
3314
+ </div>
3315
+ </div>
3316
+ <Composer
3317
+ inputStyle="composerStyle"
3318
+ focus="props.focusComposer"
3319
+ onComposerContentFocused="props.onComposerContentFocused"
3320
+ />
3321
+ </div>
3322
+ </div>
3323
+ </t>
3324
+ </odoo>
3325
+ <!--
3326
+ __info__.version = '16.1.27';
3327
+ __info__.date = '2023-11-16T11:57:27.903Z';
3328
+ __info__.hash = '81f7214';
3329
+ -->