@itfin/components 1.4.35 → 1.5.0
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.
- package/package.json +17 -20
- package/src/ITFSettings.js +6 -0
- package/src/assets/scss/_css_variables.scss +2 -7
- package/src/assets/scss/_dark-theme.scss +2 -12
- package/src/assets/scss/_variables.scss +34 -9
- package/src/assets/scss/components/_button.scss +147 -10
- package/src/assets/scss/components/_checkbox.scss +9 -0
- package/src/assets/scss/components/_datepicker.scss +3 -3
- package/src/assets/scss/components/_pagination.scss +4 -1
- package/src/assets/scss/components/_popover.scss +22 -0
- package/src/assets/scss/components/_segmeneted-control.scss +19 -8
- package/src/assets/scss/components/_select.scss +6 -8
- package/src/assets/scss/components/_text-field.scss +27 -11
- package/src/assets/scss/components/select/_dropdown-menu.scss +1 -0
- package/src/assets/scss/components/select/_dropdown-toggle.scss +0 -1
- package/src/assets/scss/directives/tooltip.scss +10 -5
- package/src/assets/scss/main.scss +48 -0
- package/src/components/alert/AlertBanner.vue +75 -0
- package/src/components/app/App.vue +1 -1
- package/src/components/button/Button.vue +3 -1
- package/src/components/button/NativeButton.js +4 -0
- package/src/components/button/index.stories.js +2 -2
- package/src/components/checkbox/Checkbox.vue +2 -1
- package/src/components/checkbox/RadioBox.vue +1 -2
- package/src/components/copyToClipboard/CopyToClipboard.vue +4 -1
- package/src/components/customize/PropertiesList.vue +0 -2
- package/src/components/customize/PropertiesPopupMenu.vue +1 -1
- package/src/components/customize/PropertyItem.vue +6 -24
- package/src/components/datepicker/DatePicker.vue +3 -1
- package/src/components/datepicker/DatePickerInline.vue +2 -2
- package/src/components/datepicker/DateRangePickerInline.vue +6 -1
- package/src/components/dropdown/Dropdown.vue +1 -1
- package/src/components/dropdown/DropdownMenu.vue +1 -1
- package/src/components/editable/EditButton.vue +1 -1
- package/src/components/filter/FilterBadge.vue +20 -1
- package/src/components/filter/FilterFacetsList.vue +67 -13
- package/src/components/filter/FilterPanel.vue +39 -14
- package/src/components/filter/NewFilter.vue +305 -0
- package/src/components/form/Label.vue +5 -5
- package/src/components/icon/components/nomi-ai-alt.vue +5 -0
- package/src/components/icon/components/nomi-arrow-right.vue +4 -0
- package/src/components/icon/components/nomi-bell.vue +5 -0
- package/src/components/icon/components/nomi-calendar-payment.vue +10 -0
- package/src/components/icon/components/nomi-card-plus.vue +1 -0
- package/src/components/icon/components/nomi-cash-provider.vue +9 -0
- package/src/components/icon/components/nomi-cash-repeat.vue +6 -0
- package/src/components/icon/components/nomi-category-edit.vue +5 -0
- package/src/components/icon/components/nomi-chavron-up.vue +4 -0
- package/src/components/icon/components/nomi-chavron_down.vue +4 -0
- package/src/components/icon/components/nomi-chavron_up.vue +4 -0
- package/src/components/icon/components/nomi-chevron-up.vue +4 -0
- package/src/components/icon/components/nomi-exit-right.vue +4 -0
- package/src/components/icon/components/nomi-help.vue +2 -3
- package/src/components/icon/components/nomi-history.vue +7 -0
- package/src/components/icon/components/nomi-lock.vue +1 -1
- package/src/components/icon/components/nomi-pen-alt.vue +4 -0
- package/src/components/icon/components/nomi-project.vue +2 -2
- package/src/components/icon/components/nomi-refresh-off.vue +4 -0
- package/src/components/icon/components/nomi-refresh.vue +4 -0
- package/src/components/icon/components/nomi-scissors.vue +1 -1
- package/src/components/icon/components/nomi-start.vue +28 -0
- package/src/components/icon/components/nomi-table-view.vue +1 -4
- package/src/components/icon/components/nomi-transactions-delete.vue +5 -0
- package/src/components/icon/components/nomi-type-array.vue +6 -0
- package/src/components/icon/components/nomi-type-boolean.vue +5 -0
- package/src/components/icon/components/nomi-type-date.vue +4 -0
- package/src/components/icon/components/nomi-type-null.vue +4 -0
- package/src/components/icon/components/nomi-type-number.vue +4 -0
- package/src/components/icon/components/nomi-type-object.vue +4 -0
- package/src/components/icon/components/nomi-type-string.vue +4 -0
- package/src/components/icon/components/nomi-unarchive.vue +17 -0
- package/src/components/icon/components/nomi-unlink.vue +10 -0
- package/src/components/icon/components/nomi-user.vue +3 -3
- package/src/components/icon/components/nomi-warning-triangle.vue +6 -0
- package/src/components/icon/components/nomi-warning_triangle_filled.vue +6 -0
- package/src/components/icon/convert-icons.js +3 -0
- package/src/components/icon/icons.js +390 -312
- package/src/components/icon/new-icons/ai-alt.svg +4 -0
- package/src/components/icon/new-icons/arrow-right-alt.svg +3 -0
- package/src/components/icon/new-icons/arrow-right.svg +3 -0
- package/src/components/icon/new-icons/arrow_left.svg +3 -0
- package/src/components/icon/new-icons/automation.svg +4 -0
- package/src/components/icon/new-icons/balance.svg +3 -0
- package/src/components/icon/new-icons/balance_turnover.svg +4 -0
- package/src/components/icon/new-icons/bar-horizontal.svg +6 -0
- package/src/components/icon/new-icons/bell.svg +4 -0
- package/src/components/icon/new-icons/calendar-payment.svg +9 -0
- package/src/components/icon/new-icons/card-plus.svg +1 -0
- package/src/components/icon/new-icons/cash-provider.svg +8 -0
- package/src/components/icon/new-icons/cash-repeat.svg +5 -0
- package/src/components/icon/new-icons/cash.svg +3 -0
- package/src/components/icon/new-icons/cashflow.svg +3 -0
- package/src/components/icon/new-icons/category-edit.svg +4 -0
- package/src/components/icon/new-icons/category.svg +4 -0
- package/src/components/icon/new-icons/category_alt.svg +3 -0
- package/src/components/icon/new-icons/chart-bars.svg +5 -0
- package/src/components/icon/new-icons/chart-donut.svg +3 -0
- package/src/components/icon/new-icons/chart-funnel.svg +5 -0
- package/src/components/icon/new-icons/chart-kpi.svg +7 -0
- package/src/components/icon/new-icons/chart-line.svg +4 -0
- package/src/components/icon/new-icons/chart-lines.svg +5 -0
- package/src/components/icon/new-icons/check-alt.svg +3 -0
- package/src/components/icon/new-icons/check.svg +3 -0
- package/src/components/icon/new-icons/chevron-down.svg +3 -0
- package/src/components/icon/new-icons/chevron-left.svg +3 -0
- package/src/components/icon/new-icons/chevron-right.svg +3 -0
- package/src/components/icon/new-icons/chevron-up.svg +3 -0
- package/src/components/icon/new-icons/collapse.svg +6 -0
- package/src/components/icon/new-icons/control-panel.svg +7 -0
- package/src/components/icon/new-icons/credit.svg +3 -0
- package/src/components/icon/new-icons/currencies.svg +3 -0
- package/src/components/icon/new-icons/debt.svg +3 -0
- package/src/components/icon/new-icons/demo.svg +6 -0
- package/src/components/icon/new-icons/dev.svg +3 -0
- package/src/components/icon/new-icons/dots.svg +5 -0
- package/src/components/icon/new-icons/duplicate.svg +4 -0
- package/src/components/icon/new-icons/exit-right.svg +3 -0
- package/src/components/icon/new-icons/export.svg +3 -0
- package/src/components/icon/new-icons/file.svg +3 -0
- package/src/components/icon/new-icons/folder.svg +3 -0
- package/src/components/icon/new-icons/goods-turnover.svg +3 -0
- package/src/components/icon/new-icons/goods.svg +4 -0
- package/src/components/icon/new-icons/help-alt.svg +3 -0
- package/src/components/icon/new-icons/help.svg +2 -3
- package/src/components/icon/new-icons/history.svg +6 -0
- package/src/components/icon/new-icons/integration.svg +3 -0
- package/src/components/icon/new-icons/link.svg +5 -0
- package/src/components/icon/new-icons/lock.svg +1 -1
- package/src/components/icon/new-icons/menu.svg +5 -0
- package/src/components/icon/new-icons/minus.svg +3 -0
- package/src/components/icon/new-icons/payment_calendar.svg +3 -0
- package/src/components/icon/new-icons/pc.svg +3 -0
- package/src/components/icon/new-icons/pen-alt.svg +3 -0
- package/src/components/icon/new-icons/planFact.svg +4 -0
- package/src/components/icon/new-icons/pnl.svg +7 -0
- package/src/components/icon/new-icons/project.svg +2 -2
- package/src/components/icon/new-icons/project_alt.svg +3 -0
- package/src/components/icon/new-icons/project_alt2.svg +3 -0
- package/src/components/icon/new-icons/promo.svg +3 -0
- package/src/components/icon/new-icons/refresh-off.svg +3 -0
- package/src/components/icon/new-icons/refresh.svg +3 -0
- package/src/components/icon/new-icons/scissors.svg +1 -1
- package/src/components/icon/new-icons/segment.svg +3 -0
- package/src/components/icon/new-icons/start.svg +27 -0
- package/src/components/icon/new-icons/strongbox.svg +3 -0
- package/src/components/icon/new-icons/subscription.svg +3 -0
- package/src/components/icon/new-icons/table-view.svg +1 -4
- package/src/components/icon/new-icons/time.svg +3 -0
- package/src/components/icon/new-icons/transactions_alt.svg +6 -0
- package/src/components/icon/new-icons/transactions_delete.svg +4 -0
- package/src/components/icon/new-icons/type-array.svg +5 -0
- package/src/components/icon/new-icons/type-boolean.svg +4 -0
- package/src/components/icon/new-icons/type-date.svg +3 -0
- package/src/components/icon/new-icons/type-null.svg +3 -0
- package/src/components/icon/new-icons/type-number.svg +3 -0
- package/src/components/icon/new-icons/type-object.svg +3 -0
- package/src/components/icon/new-icons/type-string.svg +3 -0
- package/src/components/icon/new-icons/types.svg +6 -0
- package/src/components/icon/new-icons/unarchive.svg +16 -0
- package/src/components/icon/new-icons/unlink.svg +9 -0
- package/src/components/icon/new-icons/user.svg +3 -3
- package/src/components/icon/new-icons/user_plus.svg +10 -0
- package/src/components/icon/new-icons/warehouse.svg +3 -0
- package/src/components/icon/new-icons/warning_triangle.svg +5 -0
- package/src/components/icon/new-icons/warning_triangle_filled.svg +5 -0
- package/src/components/kanban/BoardCard.vue +1 -1
- package/src/components/kanban/BoardCardTimer.vue +1 -1
- package/src/components/modal/DeleteConfirmModal.vue +10 -6
- package/src/components/modal/ItemEditor.vue +1 -1
- package/src/components/modal/Modal.vue +1 -1
- package/src/components/overlay/SensitiveOverlay.vue +2 -4
- package/src/components/panels/Panel.vue +110 -23
- package/src/components/panels/PanelItemEdit.vue +1 -1
- package/src/components/panels/PanelList.vue +65 -11
- package/src/components/popover/Popover.vue +105 -22
- package/src/components/segmented-control/SegmentedControl.vue +9 -3
- package/src/components/sortable/draggable.js +1 -1
- package/src/components/table/Table2.vue +8 -3
- package/src/components/table/TableBody.vue +17 -16
- package/src/components/table/TableGroup.vue +38 -12
- package/src/components/table/TableHeader.vue +83 -73
- package/src/components/table/TableRows.vue +15 -9
- package/src/components/table/mobile.js +4 -0
- package/src/components/table/table2.scss +9 -0
- package/src/components/text-field/MoneyField.vue +10 -4
- package/src/components/text-field/TextField.vue +17 -8
- package/src/components/tree/TreeEditor.vue +3 -2
- package/src/components/view/View.vue +86 -214
- package/src/directives/appendToBody.js +1 -0
- package/src/helpers/validators.js +9 -35
- package/src/helpers/validators.spec.js +11 -48
- package/src/locales/en.js +4 -6
- package/src/locales/pl.js +158 -0
- package/src/locales/uk.js +6 -7
- package/src/components/icon/components/nomi-calendar-view.vue +0 -4
- package/src/components/icon/components/nomi-kanban-view.vue +0 -6
- package/src/components/icon/components/nomi-list-view.vue +0 -7
- package/src/components/icon/components/nomi-table-config.vue +0 -9
- package/src/components/icon/new-icons/calendar-view.svg +0 -3
- package/src/components/icon/new-icons/kanban-view.svg +0 -5
- package/src/components/icon/new-icons/list-view.svg +0 -6
- package/src/components/icon/new-icons/table-config.svg +0 -8
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
<template v-for="(panel, n) of panelsStack">
|
|
11
11
|
<panel
|
|
12
12
|
:key="n"
|
|
13
|
+
:ref="`panel-${panel.id}`"
|
|
13
14
|
:index="n"
|
|
14
15
|
:panel="panel"
|
|
15
16
|
:title="panel.title"
|
|
@@ -27,6 +28,8 @@
|
|
|
27
28
|
@collapse="collapsePanel(panel)"
|
|
28
29
|
@close="closePanel(panel)"
|
|
29
30
|
@open-menu="$emit('open-menu', panel.type, panel.payload)"
|
|
31
|
+
@onboarding-progress="$emit('onboarding-progress', $event)"
|
|
32
|
+
@onboarding-step-viewed="$emit('onboarding-step-viewed', $event)"
|
|
30
33
|
>
|
|
31
34
|
<template #before-header>
|
|
32
35
|
<slot name="before-header" :panel="panel" :index="n" :payload="panel.payload"></slot>
|
|
@@ -163,7 +166,7 @@ $double-an-time: $an-time * 2;
|
|
|
163
166
|
//}
|
|
164
167
|
</style>
|
|
165
168
|
<script lang="ts">
|
|
166
|
-
import { Vue, Component, Prop } from 'vue-property-decorator';
|
|
169
|
+
import { Vue, Component, Prop, Watch } from 'vue-property-decorator';
|
|
167
170
|
import itfIcon from '../icon/Icon.vue';
|
|
168
171
|
import Panel from './Panel.vue';
|
|
169
172
|
import {hashToStack, stackToHash} from "@itfin/components/src/components/panels/helpers";
|
|
@@ -182,6 +185,7 @@ export interface IPanel {
|
|
|
182
185
|
payload: any;
|
|
183
186
|
nocard?: boolean;
|
|
184
187
|
isCollapsed: boolean;
|
|
188
|
+
isExpanded: boolean;
|
|
185
189
|
isCloseable: boolean;
|
|
186
190
|
isAnimate: boolean;
|
|
187
191
|
open: (type: string, visOptions: VisualOptions, payload: any) => void;
|
|
@@ -223,6 +227,17 @@ export default class PanelList extends Vue {
|
|
|
223
227
|
|
|
224
228
|
nextId:number = 0;
|
|
225
229
|
|
|
230
|
+
@Watch('panels', { deep: true })
|
|
231
|
+
onPanelsPropChanged(newPanels: Record<string, Component>) {
|
|
232
|
+
this.panelsStack.forEach(stackedPanel => {
|
|
233
|
+
const newPanel = newPanels[stackedPanel.type];
|
|
234
|
+
if (newPanel && typeof newPanel.inAppOnboarding === 'function') {
|
|
235
|
+
const updatedOnboarding = newPanel.inAppOnboarding(this.$t.bind(this));
|
|
236
|
+
stackedPanel.inAppOnboarding = updatedOnboarding;
|
|
237
|
+
}
|
|
238
|
+
});
|
|
239
|
+
}
|
|
240
|
+
|
|
226
241
|
created() {
|
|
227
242
|
setRootPanelList(this);
|
|
228
243
|
if (this.firstPanel) {
|
|
@@ -244,6 +259,7 @@ export default class PanelList extends Vue {
|
|
|
244
259
|
const newStack = [...this.panelsStack];
|
|
245
260
|
const index = newStack.findIndex(p => p.id === panel.id);
|
|
246
261
|
newStack[index].isCollapsed = false;
|
|
262
|
+
newStack[index].isExpanded = true;
|
|
247
263
|
this.panelsStack = newStack;
|
|
248
264
|
this.ensureOnlyTwoOpenPanels(panel.id);
|
|
249
265
|
this.setPanelHash();
|
|
@@ -265,10 +281,12 @@ export default class PanelList extends Vue {
|
|
|
265
281
|
keepOpenIds.push(panel2.id);
|
|
266
282
|
}
|
|
267
283
|
if (keepOpenIds.length === 1) {
|
|
268
|
-
if (
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
284
|
+
if (!openPanels.find(p => p.id === keepOpenId).isExpanded) {
|
|
285
|
+
if (newStack.length - 1 === indexKeep) {
|
|
286
|
+
keepOpenIds.push(newStack[indexKeep - 1].id);
|
|
287
|
+
} else {
|
|
288
|
+
keepOpenIds.push(newStack[indexKeep + 1].id);
|
|
289
|
+
}
|
|
272
290
|
}
|
|
273
291
|
}
|
|
274
292
|
for (const panel of newStack) {
|
|
@@ -278,7 +296,7 @@ export default class PanelList extends Vue {
|
|
|
278
296
|
this.panelsStack = newStack;
|
|
279
297
|
}
|
|
280
298
|
|
|
281
|
-
async internalOpenPanel(type: string, payload: any = {}, openIndex?: number, noEvents = false) {
|
|
299
|
+
async internalOpenPanel(type: string, payload: any = {}, openIndex?: number, noEvents = false, noExpand = false) {
|
|
282
300
|
let panel = this.panels[type];
|
|
283
301
|
if (!panel) {
|
|
284
302
|
panel = await this.searchPanel(type, this.panels);
|
|
@@ -307,6 +325,7 @@ export default class PanelList extends Vue {
|
|
|
307
325
|
isCollapsed: false,
|
|
308
326
|
isCloseable: true,
|
|
309
327
|
__events: {},
|
|
328
|
+
inAppOnboarding: panel.inAppOnboarding ? panel.inAppOnboarding(this.$t.bind(this)) : null,
|
|
310
329
|
};
|
|
311
330
|
if (!this.panelsStack.length || openIndex === 0) {
|
|
312
331
|
newPanel.isCloseable = false;
|
|
@@ -322,7 +341,7 @@ export default class PanelList extends Vue {
|
|
|
322
341
|
isAnimation = newStack.length === openIndex;
|
|
323
342
|
newStack = newStack.slice(0, openIndex);
|
|
324
343
|
}
|
|
325
|
-
if (newStack.length > 0 && !newStack.find(p => !p.isCollapsed)) {
|
|
344
|
+
if (newStack.length > 0 && !newStack.find(p => !p.isCollapsed) && !noExpand) {
|
|
326
345
|
// якщо немає відкритих панелей, то перша панель має бути розгорнута
|
|
327
346
|
newStack[0].isCollapsed = false;
|
|
328
347
|
}
|
|
@@ -369,6 +388,10 @@ export default class PanelList extends Vue {
|
|
|
369
388
|
newPanel.payload = value;
|
|
370
389
|
this.setPanelHash();
|
|
371
390
|
}
|
|
391
|
+
newPanel.rebuildAllOnboardingPopovers = (refreshDelay?: number) => this.rebuildAllOnboardingPopovers(refreshDelay);
|
|
392
|
+
newPanel.rebuildPanelOnboardingPopovers = (panelId: string | number, refreshDelay?: number) => {
|
|
393
|
+
this.rebuildPanelOnboardingPopovers(panelId, refreshDelay);
|
|
394
|
+
}
|
|
372
395
|
newStack.push(newPanel);
|
|
373
396
|
this.panelsStack = newStack;
|
|
374
397
|
this.ensureOnlyTwoOpenPanels(newPanel.id);
|
|
@@ -390,6 +413,7 @@ export default class PanelList extends Vue {
|
|
|
390
413
|
async openPanel(type: string, payload: any, openIndex?: number) {
|
|
391
414
|
await this.internalOpenPanel(type, payload, openIndex);
|
|
392
415
|
this.setPanelHash();
|
|
416
|
+
if(openIndex) this.$nextTick(() => { this.rebuildAllOnboardingPopovers() });
|
|
393
417
|
}
|
|
394
418
|
|
|
395
419
|
emitEvent(event: string, ...args: any[]) {
|
|
@@ -411,13 +435,14 @@ export default class PanelList extends Vue {
|
|
|
411
435
|
openPanel.isCollapsed = false;
|
|
412
436
|
}
|
|
413
437
|
const openPanelIndex = this.panelsStack.findIndex(p => p === openPanel);
|
|
414
|
-
if (openPanelIndex > 0 && !openPanel?.permanentExpanded) {
|
|
438
|
+
if (openPanelIndex > 0 && !openPanel?.permanentExpanded && !openPanel.isExpanded) {
|
|
415
439
|
this.panelsStack[openPanelIndex - 1].isCollapsed = false;
|
|
416
440
|
}
|
|
417
441
|
this.ensureOnlyTwoOpenPanels(openPanel.id);
|
|
418
442
|
this.setPanelHash();
|
|
419
443
|
this.emitEvent('panels.closed', panel);
|
|
420
444
|
this.emitEvent('panels.changed', this.panelsStack);
|
|
445
|
+
this.$nextTick(() => { this.rebuildAllOnboardingPopovers() });
|
|
421
446
|
}
|
|
422
447
|
|
|
423
448
|
fullsizePanel(panel: IPanel) {
|
|
@@ -425,9 +450,13 @@ export default class PanelList extends Vue {
|
|
|
425
450
|
for (const p of newStack) {
|
|
426
451
|
p.isLastOpened = !p.isCollapsed && p !== panel;
|
|
427
452
|
p.isCollapsed = p !== panel;
|
|
453
|
+
if (!p.isCollapsed) {
|
|
454
|
+
p.isExpanded = true;
|
|
455
|
+
}
|
|
428
456
|
}
|
|
429
457
|
this.panelsStack = newStack;
|
|
430
458
|
this.setPanelHash();
|
|
459
|
+
this.$nextTick(() => { this.rebuildAllOnboardingPopovers() });
|
|
431
460
|
}
|
|
432
461
|
|
|
433
462
|
get isFullSize() {
|
|
@@ -438,9 +467,13 @@ export default class PanelList extends Vue {
|
|
|
438
467
|
const newStack = [...this.panelsStack];
|
|
439
468
|
const index = newStack.findIndex(p => p.id === panel.id);
|
|
440
469
|
newStack[index].isCollapsed = false;
|
|
470
|
+
for (const p of newStack) {
|
|
471
|
+
p.isExpanded = false;
|
|
472
|
+
}
|
|
441
473
|
this.panelsStack = newStack;
|
|
442
474
|
this.ensureOnlyTwoOpenPanels(panel.id);
|
|
443
475
|
this.setPanelHash();
|
|
476
|
+
this.$nextTick(() => { this.rebuildAllOnboardingPopovers() });
|
|
444
477
|
}
|
|
445
478
|
|
|
446
479
|
collapsePanel(panel: IPanel) {
|
|
@@ -448,13 +481,17 @@ export default class PanelList extends Vue {
|
|
|
448
481
|
const currenctIndex = newStack.findIndex(p => p.id === panel.id);
|
|
449
482
|
const lastOpenedIndex = newStack.findIndex(p => p.isLastOpened);
|
|
450
483
|
if (lastOpenedIndex !== -1) { // якщо зебрежена остання відкрита панель
|
|
451
|
-
newStack[lastOpenedIndex].isCollapsed = false
|
|
484
|
+
newStack[lastOpenedIndex].isCollapsed = false;
|
|
452
485
|
} else if (newStack[currenctIndex-1]) { // якщо після оновлення сторінки відсутнє значення "остання відкрита", то відкриваємо ту, що зліва
|
|
453
486
|
newStack[currenctIndex-1].isCollapsed = false;
|
|
454
487
|
}
|
|
488
|
+
for (const p of newStack) {
|
|
489
|
+
p.isExpanded = false;
|
|
490
|
+
}
|
|
455
491
|
this.panelsStack = newStack;
|
|
456
492
|
this.ensureOnlyTwoOpenPanels(panel.id);
|
|
457
493
|
this.setPanelHash();
|
|
494
|
+
this.$nextTick(() => { this.rebuildAllOnboardingPopovers() });
|
|
458
495
|
}
|
|
459
496
|
|
|
460
497
|
getPanels(type) {
|
|
@@ -468,7 +505,7 @@ export default class PanelList extends Vue {
|
|
|
468
505
|
setPanelHash() {
|
|
469
506
|
const hash = stackToHash(this.panelsStack, this.routeType === 'path').replace(/^#/, '');
|
|
470
507
|
if (this.routeType === 'path') {
|
|
471
|
-
this.$router.push({ path:
|
|
508
|
+
this.$router.push({ path: `${hash}` });
|
|
472
509
|
} else {
|
|
473
510
|
this.$router.push({ hash });
|
|
474
511
|
}
|
|
@@ -487,16 +524,22 @@ export default class PanelList extends Vue {
|
|
|
487
524
|
// reuse panel
|
|
488
525
|
this.panelsStack[panelIndex].payload = panel.payload;
|
|
489
526
|
this.panelsStack[panelIndex].isCollapsed = panel.isCollapsed;
|
|
527
|
+
this.panelsStack[panelIndex].isExpanded = false;
|
|
490
528
|
newStack.push(this.panelsStack[panelIndex]);
|
|
491
529
|
} else {
|
|
492
|
-
const resPanel = await this.internalOpenPanel(panel.type, panel.payload, undefined, true);
|
|
530
|
+
const resPanel = await this.internalOpenPanel(panel.type, panel.payload, undefined, true, true);
|
|
493
531
|
if (resPanel) {
|
|
494
532
|
resPanel.isCollapsed = panel.isCollapsed;
|
|
533
|
+
resPanel.isExpanded = false;
|
|
495
534
|
resPanel.isAnimate = false;
|
|
496
535
|
newStack.push(resPanel);
|
|
497
536
|
}
|
|
498
537
|
}
|
|
499
538
|
}
|
|
539
|
+
const hasExpanded = newStack.length > 1 && newStack.filter(p => !p.isCollapsed).length === 1;
|
|
540
|
+
if (hasExpanded) {
|
|
541
|
+
newStack[newStack.findIndex(p => !p.isCollapsed)].isExpanded = true;
|
|
542
|
+
}
|
|
500
543
|
this.panelsStack = newStack;
|
|
501
544
|
this.emitEvent('panels.changed', this.panelsStack);
|
|
502
545
|
this.updateTitle();
|
|
@@ -521,5 +564,16 @@ export default class PanelList extends Vue {
|
|
|
521
564
|
element.classList.add('animate');
|
|
522
565
|
}
|
|
523
566
|
}
|
|
567
|
+
|
|
568
|
+
rebuildPanelOnboardingPopovers(panelId: string | number, refreshDelay?: number) {
|
|
569
|
+
const panelRef = this.$refs[`panel-${panelId}`];
|
|
570
|
+
if (panelRef?.[0]) panelRef[0].rebuildOnboardingPopovers(refreshDelay);
|
|
571
|
+
}
|
|
572
|
+
|
|
573
|
+
rebuildAllOnboardingPopovers(refreshDelay?: number) {
|
|
574
|
+
this.panelsStack.forEach((panel) => {
|
|
575
|
+
this.rebuildPanelOnboardingPopovers(panel.id, refreshDelay);
|
|
576
|
+
});
|
|
577
|
+
}
|
|
524
578
|
}
|
|
525
579
|
</script>
|
|
@@ -24,20 +24,26 @@ export default @Component({
|
|
|
24
24
|
class itfPopover extends Vue {
|
|
25
25
|
@PropSync('visible') value;
|
|
26
26
|
|
|
27
|
-
@Prop({ type: String, default: 'bottom', validator: (value) => ['bottom', 'left', 'right', 'top'].includes(value) }) placement;
|
|
27
|
+
@Prop({ type: String, default: 'bottom', validator: (value) => ['bottom', 'left', 'right', 'top', 'auto'].includes(value) }) placement;
|
|
28
28
|
|
|
29
29
|
@Prop({ type: String, default: 'click', validator: (value) => ['click', 'focus', 'hover', 'manual'].includes(value) }) trigger;
|
|
30
30
|
|
|
31
31
|
@Prop({ type: String, default: '' }) customClass;
|
|
32
|
+
@Prop({ type: Boolean }) appendToBody;
|
|
33
|
+
@Prop({ type: Boolean }) appendToContext;
|
|
34
|
+
@Prop({ type: String }) locator;
|
|
35
|
+
@Prop({ type: Boolean, default: false }) isActivatorHighlighted;
|
|
32
36
|
|
|
33
37
|
modalId = '';
|
|
34
|
-
|
|
35
38
|
modalEl = null;
|
|
39
|
+
targetEl = null;
|
|
36
40
|
|
|
37
41
|
ignoreUpdate = false; // потрібно щоб не оновлювалось visible декілька разів, бо буде баг коли вікно відкривається і одразу закривається
|
|
38
42
|
|
|
43
|
+
initTimeout = null;
|
|
44
|
+
|
|
39
45
|
beforeDestroy() {
|
|
40
|
-
this.
|
|
46
|
+
this.destroy();
|
|
41
47
|
}
|
|
42
48
|
|
|
43
49
|
@Watch('value')
|
|
@@ -46,9 +52,26 @@ class itfPopover extends Vue {
|
|
|
46
52
|
return;
|
|
47
53
|
}
|
|
48
54
|
if (newValue) {
|
|
49
|
-
this.modalEl
|
|
55
|
+
this.modalEl?.show();
|
|
56
|
+
} else {
|
|
57
|
+
this.modalEl?.hide();
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
@Watch('locator')
|
|
62
|
+
onLocatorChanged(newValue, oldValue) {
|
|
63
|
+
if (newValue !== oldValue && newValue && this.modalEl) {
|
|
64
|
+
this.initPopover();
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
@Watch('isActivatorHighlighted')
|
|
69
|
+
onIsActivatorHighlightedChanged(newValue, oldValue) {
|
|
70
|
+
if (!this.targetEl) return;
|
|
71
|
+
if (newValue) {
|
|
72
|
+
this.targetEl.classList.add('pulsing');
|
|
50
73
|
} else {
|
|
51
|
-
this.
|
|
74
|
+
this.targetEl.classList.remove('pulsing');
|
|
52
75
|
}
|
|
53
76
|
}
|
|
54
77
|
|
|
@@ -58,14 +81,62 @@ class itfPopover extends Vue {
|
|
|
58
81
|
}
|
|
59
82
|
|
|
60
83
|
async mounted() {
|
|
84
|
+
this.refresh(100);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
destroy() {
|
|
88
|
+
if (this.initTimeout) {
|
|
89
|
+
clearTimeout(this.initTimeout);
|
|
90
|
+
this.initTimeout = null;
|
|
91
|
+
}
|
|
92
|
+
if (this.modalEl) {
|
|
93
|
+
this.modalEl.dispose();
|
|
94
|
+
this.modalEl = null;
|
|
95
|
+
}
|
|
96
|
+
if (this.targetEl) this.resetTargetEl();
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
refresh(delay = 300) {
|
|
100
|
+
this.destroy();
|
|
101
|
+
|
|
102
|
+
if (this.initTimeout) clearTimeout(this.initTimeout);
|
|
103
|
+
this.initTimeout = setTimeout(() => this.initPopover(), delay);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
async initPopover() {
|
|
61
107
|
if (typeof window === 'undefined') {
|
|
62
108
|
return;
|
|
63
109
|
}
|
|
64
|
-
|
|
110
|
+
|
|
111
|
+
// Remove listeners from the previous target element before finding the new one
|
|
112
|
+
if (this.modalEl) this.destroy();
|
|
113
|
+
|
|
114
|
+
// Determine target
|
|
115
|
+
if (this.locator) {
|
|
116
|
+
this.targetEl = document.querySelector(this.locator);
|
|
117
|
+
if (!this.targetEl) return;
|
|
118
|
+
} else {
|
|
119
|
+
this.targetEl = this.$el;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
if (this.isActivatorHighlighted) this.targetEl.classList.add('pulsing');
|
|
123
|
+
|
|
124
|
+
const el = this.$refs.popover || "";
|
|
65
125
|
const { default: Popover } = await import('bootstrap/js/src/popover');
|
|
66
126
|
|
|
67
|
-
|
|
68
|
-
|
|
127
|
+
if (this._isDestroyed) return;
|
|
128
|
+
|
|
129
|
+
let context = document.body;
|
|
130
|
+
if (this.appendToContext && this.targetEl instanceof Node && this.targetEl.parentNode) {
|
|
131
|
+
context = this.targetEl.closest('.itf-append-context') || document.body;
|
|
132
|
+
this.targetEl.parentNode.removeChild(this.targetEl);
|
|
133
|
+
context.appendChild(this.targetEl); // should append only to body
|
|
134
|
+
} else if (this.appendToBody && this.targetEl instanceof Node && this.targetEl.parentNode) {
|
|
135
|
+
this.targetEl.parentNode.removeChild(this.targetEl);
|
|
136
|
+
context.appendChild(this.targetEl); // should append only to body
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
this.modalEl = new Popover(this.targetEl, {
|
|
69
140
|
content: el,
|
|
70
141
|
container: context,
|
|
71
142
|
sanitize: false,
|
|
@@ -74,26 +145,38 @@ class itfPopover extends Vue {
|
|
|
74
145
|
placement: this.placement,
|
|
75
146
|
trigger: this.trigger,
|
|
76
147
|
});
|
|
148
|
+
|
|
77
149
|
this.onVisibleChanged(this.value);
|
|
78
|
-
this
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
this
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
150
|
+
this.targetEl.addEventListener('shown.bs.popover', this.handleShown);
|
|
151
|
+
this.targetEl.addEventListener('hidden.bs.popover', this.handleHidden);
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
resetTargetEl() {
|
|
155
|
+
this.targetEl.removeEventListener('shown.bs.popover', this.handleShown);
|
|
156
|
+
this.targetEl.removeEventListener('hidden.bs.popover', this.handleHidden);
|
|
157
|
+
this.targetEl.classList.remove('pulsing');
|
|
158
|
+
this.targetEl = null;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
handleShown() {
|
|
162
|
+
this.ignoreUpdate = true;
|
|
163
|
+
this.value = true;
|
|
164
|
+
document.body.addEventListener('click', this.clickOutside);
|
|
165
|
+
this.$nextTick(() => this.ignoreUpdate = false);
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
handleHidden() {
|
|
169
|
+
this.ignoreUpdate = true;
|
|
170
|
+
this.value = false;
|
|
171
|
+
document.body.removeEventListener('click', this.clickOutside);
|
|
172
|
+
this.$nextTick(() => this.ignoreUpdate = false);
|
|
90
173
|
}
|
|
91
174
|
|
|
92
175
|
clickOutside(e) {
|
|
93
176
|
if (this.trigger !== 'click' || !e.target) {
|
|
94
177
|
return;
|
|
95
178
|
}
|
|
96
|
-
if (this
|
|
179
|
+
if (this.targetEl !== e.target && e.target.closest('.itf-popover') !== this.$refs.popover) {
|
|
97
180
|
this.hide();
|
|
98
181
|
}
|
|
99
182
|
}
|
|
@@ -107,7 +190,7 @@ class itfPopover extends Vue {
|
|
|
107
190
|
hide() {
|
|
108
191
|
if (this.modalEl) {
|
|
109
192
|
// треба затримка щоб попав не показався знову через отримання фокусу
|
|
110
|
-
setTimeout(() => this.modalEl
|
|
193
|
+
setTimeout(() => this.modalEl?.hide(), 10);
|
|
111
194
|
}
|
|
112
195
|
}
|
|
113
196
|
}
|
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<div>
|
|
3
|
-
<div class="itf-segmeneted-control d-none d-lg-grid">
|
|
3
|
+
<div class="itf-segmeneted-control d-none d-lg-grid" :class="{'small': small}">
|
|
4
4
|
<span v-if="!isUndefined" ref="slider" class="selection" :class="{'elevation-1': !disabled}"></span>
|
|
5
5
|
|
|
6
6
|
<div class="option" v-for="(item, n) in itemsWithNames" :key="n">
|
|
7
|
-
<label>
|
|
7
|
+
<label v-tooltip="tooltipCallback(item)" :key="n" :class="{'disabled': disabled || item[itemDisabled]}">
|
|
8
8
|
<slot name="itemMarkup" :item="item" />
|
|
9
9
|
<input
|
|
10
10
|
ref="input"
|
|
11
11
|
type="radio"
|
|
12
12
|
:name="name"
|
|
13
13
|
:value="n"
|
|
14
|
-
|
|
14
|
+
:disabled="disabled || item[itemDisabled]"
|
|
15
15
|
:checked="isChecked(item)"
|
|
16
16
|
@change="onItemChanged(item)" />
|
|
17
17
|
<span>
|
|
@@ -24,6 +24,7 @@
|
|
|
24
24
|
<itf-select
|
|
25
25
|
:value="value"
|
|
26
26
|
@input="$emit('input', $event)"
|
|
27
|
+
:disabled="disabled"
|
|
27
28
|
:options="itemsWithNames"
|
|
28
29
|
:reduce="(item) => item[itemKey]"
|
|
29
30
|
:get-option-label="(item) => item[itemText]"
|
|
@@ -50,8 +51,10 @@ class itfSegmentedControl extends Vue {
|
|
|
50
51
|
@Prop({ type: Array, required: true }) items;
|
|
51
52
|
@Prop({ type: String, default: 'Id' }) itemKey;
|
|
52
53
|
@Prop({ type: String, default: 'Name' }) itemText;
|
|
54
|
+
@Prop({ type: String, default: 'Disabled' }) itemDisabled;
|
|
53
55
|
@Prop({ type: Boolean, default: false }) returnObject;
|
|
54
56
|
@Prop({ type: Boolean, default: false }) disabled;
|
|
57
|
+
@Prop({ type: Boolean, default: false }) small;
|
|
55
58
|
@Prop({ type: Function, default: () => null }) tooltipCallback;
|
|
56
59
|
|
|
57
60
|
timers = [];
|
|
@@ -127,6 +130,9 @@ class itfSegmentedControl extends Vue {
|
|
|
127
130
|
}
|
|
128
131
|
|
|
129
132
|
onItemChanged (item) {
|
|
133
|
+
if (this.disabled) {
|
|
134
|
+
return;
|
|
135
|
+
}
|
|
130
136
|
this.$emit('input', this.returnObject ? item : item[this.itemKey]);
|
|
131
137
|
}
|
|
132
138
|
}
|
|
@@ -7,7 +7,7 @@ const SORTABLE_ATTRIBUTES = ['drag-ignore-handle', 'scrollable'];
|
|
|
7
7
|
|
|
8
8
|
const DEFAULT_OPTIONS = {
|
|
9
9
|
draggableClass: DRAGGABLE_CLASS,
|
|
10
|
-
dragHandleClass: DRAG_HANDLE_CLASS,
|
|
10
|
+
// dragHandleClass: DRAG_HANDLE_CLASS,
|
|
11
11
|
delay: 200,
|
|
12
12
|
tresholdDistance: 2,
|
|
13
13
|
draggable: `.${DRAGGABLE_CLASS}`,
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
</div>
|
|
20
20
|
</itf-notice-popout>
|
|
21
21
|
<div class="scrollable scrollable-x">
|
|
22
|
-
<itf-checkbox-group v-model="selectedIds">
|
|
22
|
+
<itf-checkbox-group v-model="selectedIds" class="d-flex flex-column" style="min-width: 100%; width: max-content">
|
|
23
23
|
<template v-for="(group, index) in groups">
|
|
24
24
|
<div class="table-view-body">
|
|
25
25
|
<itf-table-group
|
|
@@ -59,7 +59,10 @@
|
|
|
59
59
|
:editable-property="editableProperty"
|
|
60
60
|
:sorting.sync="_sorting"
|
|
61
61
|
:active="active"
|
|
62
|
+
:new-label="newLabel"
|
|
63
|
+
:collapsed-group-ids="collapsedGroupIds"
|
|
62
64
|
@update:expanded-ids="$emit('update:expanded-ids', $event)"
|
|
65
|
+
@update:collapsed-group-ids="$emit('update:collapsed-group-ids', $event)"
|
|
63
66
|
@new="$emit('new', $event)"
|
|
64
67
|
@filter="$emit('filter', $event)"
|
|
65
68
|
@add-column="$emit('add-column', $event)"
|
|
@@ -120,6 +123,7 @@ class itfTable2 extends Vue {
|
|
|
120
123
|
@ModelSync('value', 'input', { type: Array, default: () => ([]) }) selectedIds;
|
|
121
124
|
@PropSync('sorting') _sorting;
|
|
122
125
|
@Prop({ type: Array, default: () => [] }) expandedIds;
|
|
126
|
+
@Prop({ type: Array }) collapsedGroupIds;
|
|
123
127
|
@Prop() currency;
|
|
124
128
|
@Prop() currencies;
|
|
125
129
|
@Prop(Boolean) stickyHeader;
|
|
@@ -138,6 +142,7 @@ class itfTable2 extends Vue {
|
|
|
138
142
|
@Prop(Boolean) striped;
|
|
139
143
|
@Prop(Boolean) absolute;
|
|
140
144
|
@Prop(Boolean) clickable;
|
|
145
|
+
@Prop({type: String, default: function() { return this.$t('components.table.new'); } }) newLabel;
|
|
141
146
|
|
|
142
147
|
state = {
|
|
143
148
|
selectedIds: [],
|
|
@@ -186,7 +191,7 @@ class itfTable2 extends Vue {
|
|
|
186
191
|
if (stateColumnIndex === -1) {
|
|
187
192
|
state.columns.push(column);
|
|
188
193
|
} else {
|
|
189
|
-
state.columns[stateColumnIndex] = { ...column, width: state.columns[stateColumnIndex].width };
|
|
194
|
+
state.columns[stateColumnIndex] = { ...column, width: state.columns[stateColumnIndex].width, visible: state.columns[stateColumnIndex].visible };
|
|
190
195
|
}
|
|
191
196
|
}
|
|
192
197
|
for (const column of state.columns) {
|
|
@@ -206,7 +211,7 @@ class itfTable2 extends Vue {
|
|
|
206
211
|
if (!this.stateName) {
|
|
207
212
|
return;
|
|
208
213
|
}
|
|
209
|
-
const columns = this.state.columns.map((s) => ({ property: s.property, width: s.width, index: s.index }));
|
|
214
|
+
const columns = this.state.columns.map((s) => ({ property: s.property, width: s.width, index: s.index, visible: s.visible }));
|
|
210
215
|
localStorage.setItem(this.stateKey, JSON.stringify({ columns }));
|
|
211
216
|
}
|
|
212
217
|
|
|
@@ -1,6 +1,22 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<div>
|
|
3
|
+
<div v-if="!rows.length" data-test="table-no-results" class="scroller">
|
|
4
|
+
<div class="table-view-item">
|
|
5
|
+
<div class="table-row-template">
|
|
6
|
+
<div accept-group="items" class="table-view-body-space"></div>
|
|
7
|
+
<div class="shadow-area"></div>
|
|
8
|
+
<div class="indicator sticky"></div>
|
|
9
|
+
<div class="table-item-inner">
|
|
10
|
+
<div class="table-view-item-value w-100 align-items-center p-3 no-results">
|
|
11
|
+
{{$t('components.table.noResults')}}
|
|
12
|
+
</div>
|
|
13
|
+
<div class="boundary right"></div>
|
|
14
|
+
</div>
|
|
15
|
+
</div>
|
|
16
|
+
</div>
|
|
17
|
+
</div>
|
|
3
18
|
<itf-table-rows
|
|
19
|
+
v-else
|
|
4
20
|
class="scroller"
|
|
5
21
|
:rows="rows"
|
|
6
22
|
:selected-ids="selectedIds"
|
|
@@ -33,21 +49,6 @@
|
|
|
33
49
|
<slot :name="name" v-bind="slotData || {}"/>
|
|
34
50
|
</template>
|
|
35
51
|
</itf-table-rows>
|
|
36
|
-
<div v-if="!rows.length" data-test="table-no-results" class="scroller">
|
|
37
|
-
<div class="table-view-item">
|
|
38
|
-
<div class="table-row-template">
|
|
39
|
-
<div accept-group="items" class="table-view-body-space"></div>
|
|
40
|
-
<div class="shadow-area"></div>
|
|
41
|
-
<div class="indicator sticky"></div>
|
|
42
|
-
<div class="table-item-inner">
|
|
43
|
-
<div class="table-view-item-value w-100 align-items-center p-3 no-results">
|
|
44
|
-
{{$t('components.table.noResults')}}
|
|
45
|
-
</div>
|
|
46
|
-
<div class="boundary right"></div>
|
|
47
|
-
</div>
|
|
48
|
-
</div>
|
|
49
|
-
</div>
|
|
50
|
-
</div>
|
|
51
52
|
</div>
|
|
52
53
|
</template>
|
|
53
54
|
<style lang="scss">
|
|
@@ -92,7 +93,7 @@
|
|
|
92
93
|
display: flex;
|
|
93
94
|
align-items: center;
|
|
94
95
|
justify-content: center;
|
|
95
|
-
min-width: 1rem
|
|
96
|
+
min-width: 1rem; // важливо для скруглення //var(--itf-table-min-width);
|
|
96
97
|
}
|
|
97
98
|
|
|
98
99
|
.table-row-template, .table-view-header-value {
|