@itfin/components 1.2.105 → 1.2.107

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@itfin/components",
3
- "version": "1.2.105",
3
+ "version": "1.2.107",
4
4
  "author": "Vitalii Savchuk <esvit666@gmail.com>",
5
5
  "scripts": {
6
6
  "serve": "vue-cli-service serve",
@@ -1,13 +1,13 @@
1
1
  <template>
2
2
  <div class="itf-append-context" style="min-width: 300px">
3
3
  <div class="d-flex align-items-center px-3 py-2">
4
- <div class="me-1">
4
+ <!--div class="me-1">
5
5
  <itf-icon-popover title="Icon" removable :value="value.Icon" @input="setParam({ Icon: $event })">
6
6
  <itf-button slot="activator" icon>
7
7
  <itf-icon :name="value.Icon" />
8
8
  </itf-button>
9
9
  </itf-icon-popover>
10
- </div>
10
+ </div-->
11
11
 
12
12
  <div class="flex-grow-1">
13
13
  <itf-text-field ref="input" :value="value.Name" @input="setParam({ Name: $event })" />
@@ -29,7 +29,7 @@
29
29
  </li>
30
30
  </ul>
31
31
  </div>
32
- <div v-if="value.Type === 'multiselect'">
32
+ <div v-if="isListType">
33
33
  <div class="d-flex justify-content-between pe-2">
34
34
  <h6 class="dropdown-header">{{ $t('components.customize.options') }}</h6>
35
35
  <div v-if="value.Options && value.Options.length">
@@ -63,21 +63,43 @@
63
63
  :read-only="false"
64
64
  auto-scroll="window"
65
65
  >
66
- <div v-for="option of value.Options" class="dropdown-item d-flex justify-content-between">
67
- <div>
68
- <itf-icon sortable class="dragHandle" name="drag_vertical" />
69
- <span>{{ option.Name }}</span>
66
+ <div v-for="(option, i) of value.Options" :key="`options${i}`">
67
+ <div class="dropdown-item d-flex justify-content-between">
68
+ <div>
69
+ <itf-icon sortable class="dragHandle" name="drag_vertical" />
70
+ <span>{{ option.Name }}</span>
71
+ </div>
72
+ <span class="text-muted">></span>
70
73
  </div>
71
- <span class="text-muted">></span>
74
+ <ul class="itf-dropdown__menu shadow dropdown-menu dropdown-submenu">
75
+ <!--li class="p-2">
76
+ <itf-text-field
77
+ ref="newOptionName"
78
+ :value="option.Name"
79
+ placeholder="Option name..."
80
+ @blur="onBlurOption"
81
+ @keydown.enter="submitNewOption"
82
+ />
83
+ </li-->
84
+ <div>
85
+ <itf-delete-confirm-modal @delete="removeItem(option)">
86
+ <template #activator="{ on }">
87
+ <a class="dropdown-item text-danger align-items-center d-flex" @click.prevent="on.click"><itf-icon name="trash" class="me-1" /> {{ $t('components.customize.deleteItem') }}</a>
88
+ </template>
89
+ <h5 class="mb-0">{{$t('components.popover.confirmDelete')}}</h5>
90
+ <p class="mb-0">{{ $t('components.customize.areYouSureYouWantToDeleteThisItem') }}</p>
91
+ </itf-delete-confirm-modal>
92
+ </div>
93
+ </ul>
72
94
  </div>
73
95
  </sortable>
74
96
  </div>
75
97
  <div><hr class="dropdown-divider"></div>
76
98
  <div><a class="dropdown-item" @click.prevent="$emit('duplicate')"><itf-icon name="duplicate" /> {{ $t('components.customize.duplicateProperty') }}</a></div>
77
99
  <div>
78
- <itf-delete-confirm-modal class="me-1" @delete="$emit('delete')">
100
+ <itf-delete-confirm-modal @delete="$emit('delete')">
79
101
  <template #activator="{ on }">
80
- <a class="dropdown-item text-danger" @click.prevent="on.click"><itf-icon name="trash" /> {{ $t('components.customize.deleteProperty') }}</a>
102
+ <a class="dropdown-item text-danger align-items-center d-flex" @click.prevent="on.click"><itf-icon name="trash" class="me-1" /> {{ $t('components.customize.deleteProperty') }}</a>
81
103
  </template>
82
104
  <h5 class="mb-0">{{$t('components.popover.confirmDelete')}}</h5>
83
105
  <p class="mb-0">{{ $t('components.customize.areYouSureYouWantToDeleteThisField') }}</p>
@@ -125,6 +147,10 @@ class PropertiesEditMenu extends Vue {
125
147
  return type ? type.Name : '';
126
148
  }
127
149
 
150
+ get isListType() {
151
+ return ['select', 'multiselect'].includes(this.value.Type);
152
+ }
153
+
128
154
  mounted() {
129
155
  this.$nextTick(() => {
130
156
  this.$refs.input.focus();
@@ -140,12 +166,18 @@ class PropertiesEditMenu extends Vue {
140
166
  }
141
167
 
142
168
  addNewOption() {
169
+ this.newOption = '';
143
170
  this.isNewOptionVisible = true;
144
171
  this.$nextTick(() => {
145
172
  this.$refs.newOptionInput.focus();
146
173
  });
147
174
  }
148
175
 
176
+ removeItem(option) {
177
+ const newOptions = this.value.Options.filter((item) => item !== option);
178
+ this.setParam({ Options: newOptions });
179
+ }
180
+
149
181
  submitNewOption() {
150
182
  const newOption = this.newOption;
151
183
  if (newOption) {
@@ -7,23 +7,25 @@
7
7
  :read-only="!editable"
8
8
  auto-scroll="window"
9
9
  >
10
- <property-item
11
- v-for="(field, n) of list"
12
- :key="n"
13
- ref="properties"
14
- :field="field"
15
- :editable="editable"
16
- :lock-fields="lockFields"
17
- :value="value[field.Id]"
18
- @input="$emit('input', { ...value, [field.Id]: $event })"
19
- @delete="onDelete(field)"
20
- @duplicate="onDuplicate(field)"
21
- @update:field="onChange($event, n)"
22
- />
10
+ <template v-for="(field, n) of listToHide">
11
+ <property-item
12
+ v-if="field.isVisible || isShowAll"
13
+ :key="n"
14
+ ref="properties"
15
+ :field="field"
16
+ :editable="editable"
17
+ :lock-fields="lockFields"
18
+ :value="value[field.Id]"
19
+ @input="$emit('input', { ...value, [field.Id]: $event })"
20
+ @delete="onDelete(field)"
21
+ @duplicate="onDuplicate(field)"
22
+ @update:field="onChange($event, n)"
23
+ />
24
+ </template>
23
25
  </sortable>
24
26
 
25
27
  <div v-if="editable && !lockFields" class="text-start">
26
- <div v-if="isShowAll">
28
+ <div v-if="isShowAll || !hiddenItemsCount">
27
29
  <itf-dropdown ref="newItemDd" autoclose="outside" class="flex-grow-1 mw-100" shadow :button-options="{ small: true }">
28
30
  <template #button>
29
31
  <span class="text-muted d-flex align-items-center">
@@ -41,9 +43,9 @@
41
43
  </itf-dropdown>
42
44
  </div>
43
45
 
44
- <itf-button small class="text-muted" @click="toggleShowAll">
46
+ <itf-button v-if="hiddenItemsCount" small class="text-muted" @click="toggleShowAll">
45
47
  <itf-icon :name="isShowAll ? 'chevron_up' : 'chevron_down'" />
46
- {{isShowAll ? $tc('components.customize.hideMoreProperties', 1, { n: 1 }) : $tc('components.customize.showMoreProperties', 1, { n: 1 })}}
48
+ {{isShowAll ? $tc('components.customize.hideMoreProperties', hiddenItemsCount, { n: hiddenItemsCount }) : $tc('components.customize.showMoreProperties', hiddenItemsCount, { n: hiddenItemsCount })}}
47
49
  </itf-button>
48
50
  </div>
49
51
  </div>
@@ -113,6 +115,29 @@ class itfPropertiesList extends Vue {
113
115
  return INLINE_TYPES;
114
116
  }
115
117
 
118
+ get hiddenItemsCount() {
119
+ return this.listToHide.filter((item) => !item.isVisible).length;
120
+ }
121
+
122
+ get listToHide() {
123
+ return this.list.map((item) => {
124
+ return {
125
+ ...item,
126
+ isVisible: this.isVisible(item)
127
+ }
128
+ });
129
+ }
130
+
131
+ isVisible(field) {
132
+ if (field.Visible === 'show') {
133
+ return true;
134
+ }
135
+ if (field.Visible === 'hide') {
136
+ return false;
137
+ }
138
+ return !!this.value[field.Id];
139
+ }
140
+
116
141
  onChange(item, index) {
117
142
  const list = [...this.list];
118
143
  list[index] = item;
@@ -2,6 +2,7 @@
2
2
  <div>
3
3
  <div>
4
4
  <div><a class="dropdown-item" @click.prevent="$emit('edit')"><itf-icon name="pen" /> {{ $t('components.customize.editProperty') }}</a></div>
5
+ <div><hr class="dropdown-divider"></div>
5
6
  <div>
6
7
  <a class="dropdown-item" @click.prevent><itf-icon name="eye_no" /> {{ $t('components.customize.hideProperty') }}</a>
7
8
  <ul class="itf-dropdown__menu shadow dropdown-menu dropdown-submenu">
@@ -1,20 +1,20 @@
1
1
  <template>
2
2
  <div class="b-properties-list__inner">
3
- <div class="b-properties-list__name" :class="{'editable': editable}">
3
+ <div class="b-properties-list__name" :class="{'editable': editable && !lockFields}">
4
4
  <div class="b-properties-list__icon">
5
5
  <div v-if="editable && !lockFields" role="button" tabindex="-1" class="b-properties-list__draghandler" sortable>
6
6
  <itf-icon class="dragHandle" name="drag_vertical" />
7
7
  </div>
8
8
  </div>
9
9
 
10
- <itf-dropdown :disabled="!editable || lockFields" ref="editDd" autoclose="outside" class="flex-grow-1 mw-100" shadow :button-options="{ icon: true, block: true }" @close="onClose">
11
- <template #button>
10
+ <itf-dropdown text :disabled="!editable || lockFields" ref="editDd" autoclose="outside" class="flex-grow-1 mw-100 editable-field" shadow @close="onClose">
11
+ <div slot="button">
12
12
  <div class="d-flex align-items-center">
13
- <itf-icon :name="field.Icon" :size="16" class="me-1" />
13
+ <!-- <itf-icon :name="field.Icon" :size="16" class="me-1" />-->
14
14
 
15
15
  <div style="white-space: nowrap; overflow: hidden; text-overflow: ellipsis;" v-text="field.Name" />
16
16
  </div>
17
- </template>
17
+ </div>
18
18
  <properties-edit-menu
19
19
  v-if="isEditMode"
20
20
  :value="field"
@@ -39,7 +39,7 @@
39
39
  <property-inline-edit
40
40
  @focus="onFocus(field.Id)"
41
41
  @blur="onBlur(field.Id)"
42
- class="flex-grow-1 b-properties-list__inline-editor"
42
+ class="flex-grow-1 b-properties-list__inline-editor editable-field"
43
43
  :field="field"
44
44
  :value="value"
45
45
  :editable="editable"
@@ -51,6 +51,17 @@
51
51
  </template>
52
52
  <style lang="scss">
53
53
  .b-properties-list {
54
+ .editable .editable-field {
55
+ &.dropdown {
56
+ min-height: 24px;
57
+ padding: 5px;
58
+ font-size: 14px;
59
+ color: rgba(55, 53, 47, 0.65);
60
+ }
61
+ &:hover {
62
+ background: rgba(0, 0, 0, 0.05);
63
+ }
64
+ }
54
65
  &__draghandler {
55
66
  user-select: none;
56
67
  transition: opacity 150ms ease-in 0s;
@@ -40,8 +40,8 @@
40
40
  </div>
41
41
  </div>
42
42
  <div class="align-items-end d-flex pb-1">
43
- <slot name="add-column" @click="$emit('addColumn')">
44
- <itf-button icon small>
43
+ <slot name="add-column">
44
+ <itf-button icon small @click="$emit('add-сolumn')">
45
45
  <itf-icon name="plus" />
46
46
  </itf-button>
47
47
  </slot>
@@ -1,9 +1,18 @@
1
1
  <template>
2
2
  <div class="itf-board-column-wrapper">
3
- <itf-button v-if="showAddButton" block small class="text-muted">
3
+ <div v-if="isNewOptionVisible">
4
+ <itf-text-field
5
+ style="margin: -4px 0"
6
+ ref="newOptionInput"
7
+ v-model="newOption"
8
+ :placeholder="newItemPlaceholder"
9
+ @blur="onBlurOption"
10
+ @keydown.enter="submitNewOption"
11
+ />
12
+ </div>
13
+ <itf-button v-else-if="showAddButton" :loading="loading" block small class="text-muted" @click="addNewOption">
4
14
  <itf-icon name="plus" />
5
-
6
- Add entry
15
+ {{ newItemText }}
7
16
  </itf-button>
8
17
 
9
18
  <div class="itf-board-cards-wrapper" ref="container">
@@ -43,6 +52,7 @@ import itfButton from '../button/Button';
43
52
  import loading from '../../directives/loading';
44
53
  import itfForm from '../form/Form';
45
54
  import itfEditButton from '../editable/EditButton';
55
+ import itfTextField from '../text-field/TextField.vue';
46
56
  import createDraggable from '../sortable/draggable';
47
57
 
48
58
  const { Node, ...draggableDirectives } = createDraggable({
@@ -59,6 +69,7 @@ const { Node, ...draggableDirectives } = createDraggable({
59
69
 
60
70
  export default @Component({
61
71
  components: {
72
+ itfTextField,
62
73
  itfIcon,
63
74
  itfForm,
64
75
  itfEditButton,
@@ -77,6 +88,12 @@ class BoardColumn extends Vue {
77
88
  @Prop(Array) items;
78
89
  @Prop(Boolean) showAddButton;
79
90
  @Prop(Boolean) cardSorting;
91
+ @Prop(Boolean) loading;
92
+ @Prop({ type: String, default: 'Add new task' }) newItemText;
93
+ @Prop({ type: String, default: 'Type a new task...' }) newItemPlaceholder;
94
+
95
+ isNewOptionVisible = false;
96
+ newOption = '';
80
97
 
81
98
  beforeDestroy() {
82
99
  if (this.cardSorting) {
@@ -107,5 +124,26 @@ class BoardColumn extends Vue {
107
124
  }
108
125
  });
109
126
  }
127
+
128
+ onBlurOption() {
129
+ this.isNewOptionVisible = false;
130
+ }
131
+
132
+ addNewOption() {
133
+ this.newOption = '';
134
+ this.isNewOptionVisible = true;
135
+ this.$nextTick(() => {
136
+ this.$refs.newOptionInput.focus();
137
+ });
138
+ }
139
+
140
+ submitNewOption() {
141
+ const newOption = this.newOption;
142
+ if (newOption) {
143
+ this.$emit('create', newOption);
144
+ this.newOption = '';
145
+ this.isNewOptionVisible = false;
146
+ }
147
+ }
110
148
  }
111
149
  </script>
package/src/locales/en.js CHANGED
@@ -91,5 +91,7 @@ module.exports = {
91
91
  addOption: 'Add an option',
92
92
  showMoreProperties: '{n} more property|{n} more properties',
93
93
  hideMoreProperties: 'Hide {n} property|Hide {n} properties',
94
+ deleteItem: 'Delete',
95
+ areYouSureYouWantToDeleteThisItem: 'Are you sure you want to remove this option?',
94
96
  }
95
97
  };
package/src/locales/uk.js CHANGED
@@ -91,5 +91,7 @@ module.exports = {
91
91
  addOption: 'Додати опцію',
92
92
  showMoreProperties: 'Ще {n} поле|Ще {n} полів',
93
93
  hideMoreProperties: 'Приховати {n} поле|Приховати {n} полів',
94
+ deleteItem: 'Видалити',
95
+ areYouSureYouWantToDeleteThisItem: 'Ви впевнені, що хочете видалити цю опцію?',
94
96
  }
95
97
  };