@itfin/components 1.2.87 → 1.2.89
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 +2 -1
- package/src/assets/scss/boostrap.scss +124 -0
- package/src/assets/scss/components/_icon.scss +3 -1
- package/src/assets/scss/main.scss +11 -0
- package/src/components/customize/Inline/Date.vue +84 -0
- package/src/components/customize/Inline/Multiselect.vue +55 -0
- package/src/components/customize/Inline/Text.vue +89 -0
- package/src/components/customize/PropertiesEditMenu.vue +110 -8
- package/src/components/customize/PropertiesList.vue +92 -102
- package/src/components/customize/PropertiesPopupMenu.vue +5 -4
- package/src/components/customize/PropertyInlineEdit.vue +26 -28
- package/src/components/customize/PropertyItem.vue +192 -0
- package/src/components/customize/constants.js +9 -0
- package/src/components/customize/index.stories.js +5 -3
- package/src/components/dropdown/Dropdown.vue +4 -1
- package/src/components/icon/MdiIcon.vue +70 -0
- package/src/components/modal/DeleteConfirmModal.vue +3 -1
- package/src/components/popover/IconPopover.vue +16 -10
- package/src/components/select/Select.vue +2 -2
- package/src/components/text-field/MoneyField.vue +9 -2
- package/src/helpers/formatters.js +3 -0
- package/src/locales/en.js +8 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@itfin/components",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.89",
|
|
4
4
|
"author": "Vitalii Savchuk <esvit666@gmail.com>",
|
|
5
5
|
"scripts": {
|
|
6
6
|
"serve": "vue-cli-service serve",
|
|
@@ -20,6 +20,7 @@
|
|
|
20
20
|
],
|
|
21
21
|
"dependencies": {
|
|
22
22
|
"@egjs/vue-flicking": "^4.10.4",
|
|
23
|
+
"@mdi/js": "^7.2.96",
|
|
23
24
|
"@popperjs/core": "^2.11.8",
|
|
24
25
|
"@vue/cli-service": "^5.0.1",
|
|
25
26
|
"@vue/composition-api": "^1.7.1",
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
// 1. Include functions first (so you can manipulate colors, SVGs, calc, etc)
|
|
2
|
+
@import "~bootstrap/scss/functions.scss";
|
|
3
|
+
|
|
4
|
+
// 2. Include any default variable overrides here
|
|
5
|
+
$font-family-base: 'Fira Sans', sans-serif;
|
|
6
|
+
$headings-font-family: 'Fira Sans', sans-serif;
|
|
7
|
+
$font-family-monospace: "Fira Mono", "Courier New", monospace;
|
|
8
|
+
|
|
9
|
+
$headings-font-size-base: 1rem;
|
|
10
|
+
$h1-font-size: $headings-font-size-base * 2;
|
|
11
|
+
$h2-font-size: $headings-font-size-base * 1.75;
|
|
12
|
+
$h3-font-size: $headings-font-size-base * 1.5;
|
|
13
|
+
$h4-font-size: $headings-font-size-base * 1.25;
|
|
14
|
+
$h5-font-size: $headings-font-size-base * 1.125;
|
|
15
|
+
$h6-font-size: $headings-font-size-base;
|
|
16
|
+
|
|
17
|
+
$zindex-toaster: 1071 !default;
|
|
18
|
+
|
|
19
|
+
$border-radius: .5rem;
|
|
20
|
+
$border-radius-sm: .375rem;
|
|
21
|
+
$border-radius-lg: .75rem;
|
|
22
|
+
|
|
23
|
+
$project-tnm: #311b92;
|
|
24
|
+
$project-fixed: #388E3C;
|
|
25
|
+
$project-nonprofit: #D32F2F;
|
|
26
|
+
|
|
27
|
+
$info: #5981c0;
|
|
28
|
+
$success: #10834e;
|
|
29
|
+
$warning: #cda277;
|
|
30
|
+
$danger: #cb4839;
|
|
31
|
+
|
|
32
|
+
$primary: #0B314F;
|
|
33
|
+
$link-color: #0B314F;
|
|
34
|
+
$input-btn-focus-width: .125rem;
|
|
35
|
+
|
|
36
|
+
$input-bg: #f3f3f3;
|
|
37
|
+
$input-border-color: rgba(#000, .08);
|
|
38
|
+
$input-border-radius: 10px;
|
|
39
|
+
$input-font-size: 0.875rem;
|
|
40
|
+
$input-font-family: "Fira Mono", "Courier New", monospace;
|
|
41
|
+
|
|
42
|
+
$input-focus-bg: #fff;
|
|
43
|
+
$input-focus-border-color: #fff;
|
|
44
|
+
|
|
45
|
+
$form-label-margin-bottom: .1rem;
|
|
46
|
+
$input-focus-border: rgb(11 49 79 / 25%);
|
|
47
|
+
|
|
48
|
+
$form-check-input-border: 1px solid rgba(#000, .08);
|
|
49
|
+
$form-switch-focus-color: tint-color($primary, 50%);
|
|
50
|
+
|
|
51
|
+
$modal-backdrop-bg: #999;
|
|
52
|
+
$modal-backdrop-opacity: .25;
|
|
53
|
+
$modal-content-border-radius: 0;
|
|
54
|
+
|
|
55
|
+
$secondary: #dfe1e6;
|
|
56
|
+
|
|
57
|
+
// popover
|
|
58
|
+
$popover-border-width: 2px;
|
|
59
|
+
|
|
60
|
+
// dropdown
|
|
61
|
+
|
|
62
|
+
// Dark theme
|
|
63
|
+
$dark-body-bg: #2e3136;
|
|
64
|
+
$dark-border-color: #4a4a4a;
|
|
65
|
+
$dark-body-color: #ddd;
|
|
66
|
+
$dark-input-bg: #383b41;
|
|
67
|
+
|
|
68
|
+
$dark-primary: #FFCC00;
|
|
69
|
+
$dark-link-color: #ead272;
|
|
70
|
+
$dark-secondary: #464a53;
|
|
71
|
+
$dark-input-focus-border-color: #3d3d3d;
|
|
72
|
+
$dark-btn-primary-color: $dark-primary;
|
|
73
|
+
$dark-btn-secondary-color: $dark-secondary;
|
|
74
|
+
$dark-input-box-shadow: #3d3d3d;
|
|
75
|
+
$dark-input-focus-border: rgb(244 206 176 / 25%);
|
|
76
|
+
|
|
77
|
+
$pagination-border-width: 0;
|
|
78
|
+
|
|
79
|
+
// 3. Include remainder of required Bootstrap stylesheets
|
|
80
|
+
@import "~bootstrap/scss/variables.scss";
|
|
81
|
+
@import "~bootstrap/scss/mixins.scss";
|
|
82
|
+
@import "~bootstrap/scss/maps.scss";
|
|
83
|
+
@import "~bootstrap/scss/utilities.scss";
|
|
84
|
+
|
|
85
|
+
$custom-colors: (
|
|
86
|
+
"white": #fff,
|
|
87
|
+
"black": #1e1e1e
|
|
88
|
+
);
|
|
89
|
+
$theme-colors: map-merge($theme-colors, $custom-colors);
|
|
90
|
+
|
|
91
|
+
// Text colors
|
|
92
|
+
$all-colors: map-merge-multiple($theme-colors, $custom-colors, $blues, $indigos, $purples, $pinks, $reds, $oranges, $yellows, $greens, $teals, $cyans);
|
|
93
|
+
$utilities: map-merge(
|
|
94
|
+
$utilities,
|
|
95
|
+
(
|
|
96
|
+
"color": map-merge(
|
|
97
|
+
map-get($utilities, "color"),
|
|
98
|
+
(
|
|
99
|
+
values: map-merge(
|
|
100
|
+
map-get(map-get($utilities, "color"), "values"),
|
|
101
|
+
(
|
|
102
|
+
$all-colors
|
|
103
|
+
),
|
|
104
|
+
),
|
|
105
|
+
),
|
|
106
|
+
),
|
|
107
|
+
)
|
|
108
|
+
);
|
|
109
|
+
@import "~bootstrap/scss/utilities/api";
|
|
110
|
+
|
|
111
|
+
// Fonts
|
|
112
|
+
$baseFontSize: 16px;
|
|
113
|
+
$hintFontSize: 12px;
|
|
114
|
+
|
|
115
|
+
// Border radius
|
|
116
|
+
$borderRadiusM: 4px;
|
|
117
|
+
$borderRadiusL: 8px;
|
|
118
|
+
|
|
119
|
+
// Colors
|
|
120
|
+
$primaryColor: #0B314F;
|
|
121
|
+
$primaryColor15: #DAE0E5;
|
|
122
|
+
$baseText: #1e1e1e;
|
|
123
|
+
$gray5: #F0F0F1;
|
|
124
|
+
$gray50: #787885;
|
|
@@ -47,3 +47,14 @@
|
|
|
47
47
|
.color-outcome {
|
|
48
48
|
color: #b91e1e !important;
|
|
49
49
|
}
|
|
50
|
+
|
|
51
|
+
kbd {
|
|
52
|
+
background-color: rgba(0, 0, 0, .15) !important;
|
|
53
|
+
color: #000 !important;
|
|
54
|
+
font-size: .75rem !important;
|
|
55
|
+
|
|
56
|
+
[data-theme="dark"] &, .btn-primary & {
|
|
57
|
+
background-color: rgba(255, 255, 255, .25) !important;
|
|
58
|
+
color: #fff !important;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div class="itf-inline-edit">
|
|
3
|
+
<div ref="input" class="input" :role="editable ? 'button' : 'textbox'" tabindex="1" @keydown.space="onEnter" @keydown.enter="onEnter" @focus="$emit('focus')" @blur="$emit('blur')">
|
|
4
|
+
<span v-if="value">{{ value | formatDate }}</span>
|
|
5
|
+
<span v-else class="text-muted">Empty</span>
|
|
6
|
+
</div>
|
|
7
|
+
|
|
8
|
+
<div style="display: none">
|
|
9
|
+
<div ref="dropdown" class="itf-datepicker__dropdown">
|
|
10
|
+
<itf-date-picker-inline
|
|
11
|
+
:value="value"
|
|
12
|
+
start-view="days"
|
|
13
|
+
display-format="MM/dd/yyyy"
|
|
14
|
+
value-format="yyyy-MM-dd"
|
|
15
|
+
@input="selectInlineDate"
|
|
16
|
+
></itf-date-picker-inline>
|
|
17
|
+
</div>
|
|
18
|
+
</div>
|
|
19
|
+
</div>
|
|
20
|
+
</template>
|
|
21
|
+
<style lang="scss" scoped>
|
|
22
|
+
.itf-inline-edit .input {
|
|
23
|
+
border: 0 none;
|
|
24
|
+
margin: 0;
|
|
25
|
+
outline: 0;
|
|
26
|
+
resize: none;
|
|
27
|
+
background: transparent;
|
|
28
|
+
}
|
|
29
|
+
</style>
|
|
30
|
+
<script>
|
|
31
|
+
import {Vue, Component, Model, Watch, Prop} from 'vue-property-decorator';
|
|
32
|
+
import itfTextField from '../../text-field/TextField.vue';
|
|
33
|
+
import itfDatePickerInline from '../../datepicker/DatePickerInline.vue';
|
|
34
|
+
import tippy from 'tippy.js';
|
|
35
|
+
import { formatDate } from '../../../helpers/formatters';
|
|
36
|
+
|
|
37
|
+
export default @Component({
|
|
38
|
+
name: 'itfCustomizeInlineDate',
|
|
39
|
+
components: {
|
|
40
|
+
itfTextField,
|
|
41
|
+
itfDatePickerInline
|
|
42
|
+
},
|
|
43
|
+
filters: {
|
|
44
|
+
formatDate
|
|
45
|
+
}
|
|
46
|
+
})
|
|
47
|
+
|
|
48
|
+
class itfCustomizeInlineText extends Vue {
|
|
49
|
+
@Model('input') value;
|
|
50
|
+
@Prop({ type: String, default: 'bottom-start' }) placement;
|
|
51
|
+
@Prop({ type: Boolean, default: false }) editable;
|
|
52
|
+
|
|
53
|
+
tooltip = null;
|
|
54
|
+
|
|
55
|
+
mounted() {
|
|
56
|
+
if (!this.editable) {
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
const context = this.$el.closest('.itf-append-context') || document.body;
|
|
60
|
+
this.tooltip = tippy(this.$refs.input, {
|
|
61
|
+
interactiveBorder: 30,
|
|
62
|
+
interactiveDebounce: 75,
|
|
63
|
+
animation: 'scale',
|
|
64
|
+
arrow: true,
|
|
65
|
+
content: this.$refs.dropdown,
|
|
66
|
+
allowHTML: true,
|
|
67
|
+
trigger: 'click',
|
|
68
|
+
interactive: true,
|
|
69
|
+
placement: this.placement,
|
|
70
|
+
appendTo: context
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
selectInlineDate(date) {
|
|
75
|
+
this.$emit('input', date);
|
|
76
|
+
this.tooltip.hide();
|
|
77
|
+
this.isFocused = false;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
onEnter() {
|
|
81
|
+
this.tooltip.show();
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
</script>
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div class="itf-inline-edit">
|
|
3
|
+
<itf-select
|
|
4
|
+
ref="input"
|
|
5
|
+
class="input"
|
|
6
|
+
role="button"
|
|
7
|
+
multiple
|
|
8
|
+
:placeholder="focused ? 'Search for an option...' : 'Empty'"
|
|
9
|
+
:tabindex="1"
|
|
10
|
+
:disabled="!editable"
|
|
11
|
+
:options="field && field.Options"
|
|
12
|
+
:reduce="option => option.Name"
|
|
13
|
+
:get-option-label="option => option.Name"
|
|
14
|
+
@search:focus="$emit('focus')"
|
|
15
|
+
@search:blur="$emit('blur')">
|
|
16
|
+
<template #option="{ option }">
|
|
17
|
+
<div>{{ option.Name }}</div>
|
|
18
|
+
</template>
|
|
19
|
+
</itf-select>
|
|
20
|
+
</div>
|
|
21
|
+
</template>
|
|
22
|
+
<style lang="scss">
|
|
23
|
+
.itf-inline-edit .itf-select .form-control {
|
|
24
|
+
border: 0 none;
|
|
25
|
+
margin: 0;
|
|
26
|
+
outline: 0;
|
|
27
|
+
resize: none;
|
|
28
|
+
min-height: auto;
|
|
29
|
+
padding: 0.1rem 0;
|
|
30
|
+
font-family: var(--bs-body-font-family);
|
|
31
|
+
font-size: var(--bs-body-font-size);
|
|
32
|
+
box-shadow: none !important;
|
|
33
|
+
background: transparent !important;
|
|
34
|
+
}
|
|
35
|
+
</style>
|
|
36
|
+
<script>
|
|
37
|
+
import {Vue, Component, Model, Watch, Prop} from 'vue-property-decorator';
|
|
38
|
+
import itfTextField from '../../text-field/TextField.vue';
|
|
39
|
+
import itfSelect from '../../select/Select.vue';
|
|
40
|
+
|
|
41
|
+
export default @Component({
|
|
42
|
+
name: 'itfCustomizeInlineMultiselect',
|
|
43
|
+
components: {
|
|
44
|
+
itfTextField,
|
|
45
|
+
itfSelect
|
|
46
|
+
}
|
|
47
|
+
})
|
|
48
|
+
|
|
49
|
+
class itfCustomizeInlineMultiselect extends Vue {
|
|
50
|
+
@Model('input') value;
|
|
51
|
+
@Prop(Boolean) focused;
|
|
52
|
+
@Prop(Boolean) editable;
|
|
53
|
+
@Prop() field;
|
|
54
|
+
}
|
|
55
|
+
</script>
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div class="itf-inline-edit">
|
|
3
|
+
<div
|
|
4
|
+
:role="editable ? 'button' : 'textbox'"
|
|
5
|
+
tabindex="1"
|
|
6
|
+
ref="input"
|
|
7
|
+
@focus="onFocus"
|
|
8
|
+
@blur="onBlur"
|
|
9
|
+
@keydown.enter="onEnter"
|
|
10
|
+
@keydown.esc="onCancel"
|
|
11
|
+
class="notranslate"
|
|
12
|
+
spellcheck="true"
|
|
13
|
+
placeholder=" "
|
|
14
|
+
:contenteditable="editable"
|
|
15
|
+
v-html="value">
|
|
16
|
+
</div>
|
|
17
|
+
</div>
|
|
18
|
+
</template>
|
|
19
|
+
<style lang="scss" scoped>
|
|
20
|
+
.itf-inline-edit {
|
|
21
|
+
margin: -5px;
|
|
22
|
+
padding: 5px;
|
|
23
|
+
}
|
|
24
|
+
.notranslate {
|
|
25
|
+
border: 0 none;
|
|
26
|
+
margin: 0;
|
|
27
|
+
outline: 0;
|
|
28
|
+
resize: none;
|
|
29
|
+
background: transparent;
|
|
30
|
+
max-width: 100%;
|
|
31
|
+
width: 100%;
|
|
32
|
+
white-space: pre-wrap;
|
|
33
|
+
word-break: break-word;
|
|
34
|
+
caret-color: var(--bs-body-color);
|
|
35
|
+
}
|
|
36
|
+
</style>
|
|
37
|
+
<script>
|
|
38
|
+
import { Vue, Component, Model, Prop } from 'vue-property-decorator';
|
|
39
|
+
import itfTextField from '../../text-field/TextField.vue';
|
|
40
|
+
|
|
41
|
+
export default @Component({
|
|
42
|
+
name: 'itfCustomizeInlineText',
|
|
43
|
+
components: {
|
|
44
|
+
itfTextField
|
|
45
|
+
}
|
|
46
|
+
})
|
|
47
|
+
|
|
48
|
+
class itfCustomizeInlineText extends Vue {
|
|
49
|
+
@Model('input') value;
|
|
50
|
+
@Prop(Boolean) editable;
|
|
51
|
+
|
|
52
|
+
mounted() {
|
|
53
|
+
this.$refs.input.addEventListener('paste', function(e) {
|
|
54
|
+
// cancel paste
|
|
55
|
+
e.preventDefault();
|
|
56
|
+
|
|
57
|
+
// get text representation of clipboard
|
|
58
|
+
var text = (e.originalEvent || e).clipboardData.getData('text/plain');
|
|
59
|
+
|
|
60
|
+
// insert text manually
|
|
61
|
+
document.execCommand("insertHTML", false, text);
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
onEnter(event) {
|
|
66
|
+
if (event.shiftKey) {
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
69
|
+
event.preventDefault();
|
|
70
|
+
event.stopPropagation();
|
|
71
|
+
|
|
72
|
+
this.$refs.input.blur();
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
onBlur() {
|
|
76
|
+
this.$emit('input', this.$refs.input.innerHTML);
|
|
77
|
+
this.$emit('blur');
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
onCancel(event) {
|
|
81
|
+
event.target.value = this.value;
|
|
82
|
+
this.$refs.input.blur();
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
onFocus() {
|
|
86
|
+
this.$emit('focus');
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
</script>
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<div class="itf-append-context">
|
|
2
|
+
<div class="itf-append-context" style="min-width: 300px">
|
|
3
3
|
<div class="d-flex align-items-center px-3 py-2">
|
|
4
4
|
<div class="me-1">
|
|
5
5
|
<itf-icon-popover title="Icon" removable :value="value.Icon" @input="setParam({ Icon: $event })">
|
|
@@ -10,20 +10,77 @@
|
|
|
10
10
|
</div>
|
|
11
11
|
|
|
12
12
|
<div class="flex-grow-1">
|
|
13
|
-
<itf-text-field :value="value.Name" @input="setParam({ Name: $event })" />
|
|
13
|
+
<itf-text-field ref="input" :value="value.Name" @input="setParam({ Name: $event })" />
|
|
14
14
|
</div>
|
|
15
15
|
</div>
|
|
16
16
|
<div>
|
|
17
17
|
<a class="dropdown-item d-flex justify-content-between" @click.prevent="$emit('edit')">
|
|
18
18
|
<span>{{ $t('components.customize.type') }}</span>
|
|
19
|
-
<span class="text-muted">{{
|
|
19
|
+
<span class="text-muted">{{ itemType }} ></span>
|
|
20
20
|
</a>
|
|
21
|
+
<ul class="itf-dropdown__menu shadow dropdown-menu dropdown-submenu">
|
|
22
|
+
<li><h6 class="dropdown-header">{{ $t('components.customize.type') }}</h6></li>
|
|
23
|
+
<li v-for="(type) of types">
|
|
24
|
+
<a class="dropdown-item d-flex align-items-center" href="" @click.prevent="setParam({ Type: type.Type })">
|
|
25
|
+
<itf-icon :name="type.Icon" :size="16" class="me-1" />
|
|
26
|
+
<span v-text="type.Name"></span>
|
|
27
|
+
<itf-icon v-if="value.Type === type.Type" name="check" />
|
|
28
|
+
</a>
|
|
29
|
+
</li>
|
|
30
|
+
</ul>
|
|
21
31
|
</div>
|
|
32
|
+
<div v-if="value.Type === 'multiselect'" sortable-skip>
|
|
33
|
+
<div class="d-flex justify-content-between pe-2">
|
|
34
|
+
<h6 class="dropdown-header">{{ $t('components.customize.options') }}</h6>
|
|
35
|
+
<div v-if="value.Options && value.Options.length">
|
|
36
|
+
<itf-button icon small @click.prevent="addNewOption">
|
|
37
|
+
<itf-icon name="plus" />
|
|
38
|
+
</itf-button>
|
|
39
|
+
</div>
|
|
40
|
+
</div>
|
|
41
|
+
|
|
42
|
+
<div v-if="isNewOptionVisible" class="px-3">
|
|
43
|
+
<itf-text-field
|
|
44
|
+
ref="newOptionInput"
|
|
45
|
+
v-model="newOption"
|
|
46
|
+
placeholder="Type a new option..."
|
|
47
|
+
@blur="onBlurOption"
|
|
48
|
+
@keydown.enter="submitNewOption"
|
|
49
|
+
/>
|
|
50
|
+
</div>
|
|
51
|
+
<div v-else-if="!value.Options || !value.Options.length" class="px-3">
|
|
52
|
+
<itf-button small block class="text-start" @click="addNewOption">
|
|
53
|
+
<itf-icon name="plus" />
|
|
54
|
+
{{ $t('components.customize.addOption') }}
|
|
55
|
+
</itf-button>
|
|
56
|
+
</div>
|
|
57
|
+
|
|
58
|
+
<sortable
|
|
59
|
+
:value="value.Options"
|
|
60
|
+
@input="setParam({ Options: $event })"
|
|
61
|
+
axis="y"
|
|
62
|
+
require-sortable-attribute
|
|
63
|
+
auto-scroll="window"
|
|
64
|
+
>
|
|
65
|
+
<div v-for="option of value.Options" class="dropdown-item d-flex justify-content-between" sortable>
|
|
66
|
+
<div>
|
|
67
|
+
<itf-icon class="dragHandle" name="drag_vertical" />
|
|
68
|
+
<span>{{ option.Name }}</span>
|
|
69
|
+
</div>
|
|
70
|
+
<span class="text-muted">></span>
|
|
71
|
+
</div>
|
|
72
|
+
</sortable>
|
|
73
|
+
</div>
|
|
74
|
+
<div><hr class="dropdown-divider"></div>
|
|
75
|
+
<div><a class="dropdown-item" @click.prevent="$emit('duplicate')"><itf-icon name="duplicate" /> {{ $t('components.customize.duplicateProperty') }}</a></div>
|
|
22
76
|
<div>
|
|
23
|
-
<
|
|
24
|
-
<
|
|
25
|
-
|
|
26
|
-
|
|
77
|
+
<itf-delete-confirm-modal class="me-1" @delete="$emit('delete')">
|
|
78
|
+
<template #activator="{ on }">
|
|
79
|
+
<a class="dropdown-item text-danger" @click.prevent="on.click"><itf-icon name="trash" /> {{ $t('components.customize.deleteProperty') }}</a>
|
|
80
|
+
</template>
|
|
81
|
+
<h5 class="mb-0">{{$t('components.popover.confirmDelete')}}</h5>
|
|
82
|
+
<p class="mb-0">{{ $t('components.customize.areYouSureYouWantToDeleteThisField') }}</p>
|
|
83
|
+
</itf-delete-confirm-modal>
|
|
27
84
|
</div>
|
|
28
85
|
</div>
|
|
29
86
|
</template>
|
|
@@ -32,22 +89,67 @@ import { Vue, Component, Model } from 'vue-property-decorator';
|
|
|
32
89
|
import itfTextField from '../text-field/TextField.vue';
|
|
33
90
|
import itfIcon from '../icon/Icon';
|
|
34
91
|
import itfButton from '../button/Button';
|
|
92
|
+
import Sortable from '../sortable/Sortable';
|
|
35
93
|
import itfIconPopover from '../popover/IconPopover.vue';
|
|
94
|
+
import {INLINE_TYPES} from './constants';
|
|
95
|
+
import itfDeleteConfirmModal from "../modal/DeleteConfirmModal.vue";
|
|
96
|
+
import PropertyItem from "./PropertyItem.vue";
|
|
36
97
|
|
|
37
98
|
export default @Component({
|
|
38
99
|
components: {
|
|
100
|
+
PropertyItem,
|
|
101
|
+
itfDeleteConfirmModal,
|
|
39
102
|
itfButton,
|
|
40
103
|
itfIcon,
|
|
41
104
|
itfTextField,
|
|
42
|
-
itfIconPopover
|
|
105
|
+
itfIconPopover,
|
|
106
|
+
Sortable
|
|
43
107
|
}
|
|
44
108
|
})
|
|
45
109
|
|
|
46
110
|
class PropertiesEditMenu extends Vue {
|
|
47
111
|
@Model('input') value;
|
|
48
112
|
|
|
113
|
+
isNewOptionVisible = false;
|
|
114
|
+
newOption = '';
|
|
115
|
+
|
|
116
|
+
get types() {
|
|
117
|
+
return INLINE_TYPES;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
get itemType() {
|
|
121
|
+
const type = INLINE_TYPES.find((type) => type.Type === this.value.Type);
|
|
122
|
+
return type ? type.Name : '';
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
mounted() {
|
|
126
|
+
this.$nextTick(() => {
|
|
127
|
+
this.$refs.input.focus();
|
|
128
|
+
});
|
|
129
|
+
}
|
|
130
|
+
|
|
49
131
|
setParam(obj) {
|
|
50
132
|
this.$emit('input', { ...this.value, ...obj });
|
|
51
133
|
}
|
|
134
|
+
|
|
135
|
+
onBlurOption() {
|
|
136
|
+
this.isNewOptionVisible = false;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
addNewOption() {
|
|
140
|
+
this.isNewOptionVisible = true;
|
|
141
|
+
this.$nextTick(() => {
|
|
142
|
+
this.$refs.newOptionInput.focus();
|
|
143
|
+
});
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
submitNewOption() {
|
|
147
|
+
const newOption = this.newOption;
|
|
148
|
+
if (newOption) {
|
|
149
|
+
this.setParam({ Options: [{ Name: newOption }, ...(this.value.Options || [])] });
|
|
150
|
+
this.newOption = '';
|
|
151
|
+
this.isNewOptionVisible = false;
|
|
152
|
+
}
|
|
153
|
+
}
|
|
52
154
|
}
|
|
53
155
|
</script>
|