add new tag in transaction edit page / dialog

This commit is contained in:
MaysWind
2024-12-08 21:04:42 +08:00
parent db94282207
commit 5a9141e10c
6 changed files with 146 additions and 20 deletions
@@ -1,6 +1,6 @@
<template>
<f7-sheet swipe-to-close swipe-handler=".swipe-handler"
:opened="show" :class="{ 'tag-selection-huge-sheet': hugeListItemRows }"
:class="heightClass" :opened="show"
@sheet:open="onSheetOpen" @sheet:closed="onSheetClosed">
<f7-toolbar>
<div class="swipe-handler"></div>
@@ -12,42 +12,78 @@
</div>
</f7-toolbar>
<f7-page-content>
<f7-list class="no-margin-top no-margin-bottom" v-if="!items || !items.length || noAvailableTag">
<f7-list class="no-margin-top no-margin-bottom" v-if="!allTags || !allTags.length || noAvailableTag">
<f7-list-item :title="$t('No available tag')"></f7-list-item>
</f7-list>
<f7-list dividers class="no-margin-top no-margin-bottom" v-else-if="items && items.length && !noAvailableTag">
<f7-list dividers class="no-margin-top no-margin-bottom tag-selection-list" v-else-if="allTags && allTags.length && !noAvailableTag">
<f7-list-item checkbox
:class="isChecked(item.id) ? 'list-item-selected' : ''"
:value="item.id"
:checked="isChecked(item.id)"
:key="item.id"
v-for="item in items"
v-show="!item.hidden || isChecked(item.id)"
@change="changeItemSelection">
:class="isChecked(tag.id) ? 'list-item-selected' : ''"
:value="tag.id"
:checked="isChecked(tag.id)"
:key="tag.id"
v-for="tag in allTags"
v-show="!tag.hidden || isChecked(tag.id)"
@change="changeTagSelection">
<template #title>
<f7-block class="no-padding no-margin">
<div class="display-flex">
<f7-icon f7="number"></f7-icon>
<div class="tag-selection-list-item list-item-valign-middle padding-left-half">
{{ item.name }}
{{ tag.name }}
</div>
</div>
</f7-block>
</template>
</f7-list-item>
<f7-list-item :title="$t('Add new tag')"
v-if="allowAddNewTag && !newTag"
@click="addNewTag()">
</f7-list-item>
<f7-list-item checkbox indeterminate disabled v-if="allowAddNewTag && newTag">
<template #media>
<f7-icon f7="number"></f7-icon>
</template>
<template #title>
<div class="display-flex">
<f7-input class="list-title-input padding-left-half"
type="text"
:placeholder="$t('Tag Title')"
v-model:value="newTag.name"
@keyup.enter="saveNewTag()">
</f7-input>
</div>
</template>
<template #after>
<f7-button class="no-padding"
raised fill
icon-f7="checkmark_alt"
color="blue"
@click="saveNewTag()">
</f7-button>
<f7-button class="no-padding margin-left-half"
raised fill
icon-f7="xmark"
color="gray"
@click="cancelSaveNewTag()">
</f7-button>
</template>
</f7-list-item>
</f7-list>
</f7-page-content>
</f7-sheet>
</template>
<script>
import { mapStores } from 'pinia';
import { useTransactionTagsStore } from '@/stores/transactionTag.js';
import { copyArrayTo } from '@/lib/common.js';
import { scrollToSelectedItem } from '@/lib/ui.mobile.js';
export default {
props: [
'modelValue',
'items',
'allowAddNewTag',
'show'
],
emits: [
@@ -56,18 +92,22 @@ export default {
],
data() {
const self = this;
const transactionTagsStore = useTransactionTagsStore();
return {
selectedItemIds: copyArrayTo(self.modelValue, [])
heightClass: self.getHeightClass(transactionTagsStore.allTransactionTags),
selectedItemIds: copyArrayTo(self.modelValue, []),
newTag: null
}
},
computed: {
hugeListItemRows() {
return this.items.length > 10;
...mapStores(useTransactionTagsStore),
allTags() {
return this.transactionTagsStore.allTransactionTags;
},
noAvailableTag() {
for (let i = 0; i < this.items.length; i++) {
if (!this.items[i].hidden) {
for (let i = 0; i < this.allTags.length; i++) {
if (!this.allTags[i].hidden) {
return false;
}
}
@@ -82,12 +122,14 @@ export default {
},
onSheetOpen(event) {
this.selectedItemIds = copyArrayTo(this.modelValue, []);
this.newTag = null;
scrollToSelectedItem(event.$el, '.page-content', 'li.list-item-selected');
},
onSheetClosed() {
this.$emit('update:show', false);
this.heightClass = this.getHeightClass(this.allTags);
},
changeItemSelection(e) {
changeTagSelection(e) {
const tagId = e.target.value;
if (e.target.checked) {
@@ -107,6 +149,36 @@ export default {
}
}
},
addNewTag() {
this.newTag = {
name: ''
};
},
saveNewTag() {
const self = this;
self.$showLoading();
self.transactionTagsStore.saveTag({
tag: self.newTag
}).then(tag => {
self.$hideLoading();
self.newTag = null;
if (tag && tag.id) {
self.selectedItemIds.push(tag.id);
}
}).catch(error => {
self.$hideLoading();
if (!error.processed) {
self.$toast(error.message || error);
}
});
},
cancelSaveNewTag() {
this.newTag = null;
},
isChecked(itemId) {
for (let i = 0; i < this.selectedItemIds.length; i++) {
if (this.selectedItemIds[i] === itemId) {
@@ -115,6 +187,15 @@ export default {
}
return false;
},
getHeightClass(allTags) {
if (allTags && allTags.length > 10) {
return 'tag-selection-huge-sheet';
} else if (allTags && allTags.length > 6) {
return 'tag-selection-large-sheet';
} else {
return '';
}
}
}
}
@@ -122,11 +203,19 @@ export default {
<style>
@media (min-height: 630px) {
.tag-selection-large-sheet {
height: 310px;
}
.tag-selection-huge-sheet {
height: 400px;
}
}
.tag-selection-list.list .item-media + .item-inner {
margin-left: 0;
}
.tag-selection-list-item {
overflow: hidden;
text-overflow: ellipsis;
+2
View File
@@ -90,6 +90,7 @@
"everyMultiDaysOfWeek": "Every {days}",
"everyMultiDaysOfMonth": "Every {days} of month",
"youHaveAccounts": "You have recorded {count} accounts",
"addNewTag": "Add new tag \"{tag}\"",
"clickToSelectedFile": "Click to select import file ({extensions})",
"selectedCount": "Selected {count} of {totalCount}",
"youHaveUpdatedTransactions": "You have updated {count} transactions",
@@ -1809,6 +1810,7 @@
"Unable to retrieve tag list": "Unable to retrieve tag list",
"Tag list is up to date": "Tag list is up to date",
"Tag list has been updated": "Tag list has been updated",
"Add new tag": "Add new tag",
"Unable to add tag": "Unable to add tag",
"Unable to save tag": "Unable to save tag",
"Unable to move tag": "Unable to move tag",
+2
View File
@@ -90,6 +90,7 @@
"everyMultiDaysOfWeek": "Mỗi {days}",
"everyMultiDaysOfMonth": "Mỗi ngày {days} trong tháng",
"youHaveAccounts": "Bạn đã ghi nhận {count} tài khoản",
"addNewTag": "Add new tag \"{tag}\"",
"clickToSelectedFile": "Nhấp để chọn tệp nhập khẩu ({extensions})",
"selectedCount": "Đã chọn {count} trên {totalCount}",
"youHaveUpdatedTransactions": "Bạn đã cập nhật {count} giao dịch",
@@ -1809,6 +1810,7 @@
"Unable to retrieve tag list": "Không thể truy xuất danh sách thẻ",
"Tag list is up to date": "Danh sách thẻ đã được cập nhật",
"Tag list has been updated": "Danh sách thẻ đã được cập nhật",
"Add new tag": "Add new tag",
"Unable to add tag": "Không thể thêm thẻ",
"Unable to save tag": "Không thể lưu thẻ",
"Unable to move tag": "Không thể di chuyển thẻ",
+2
View File
@@ -90,6 +90,7 @@
"everyMultiDaysOfWeek": "每{days}",
"everyMultiDaysOfMonth": "每月{days}",
"youHaveAccounts": "您已经记录了 {count} 个账户",
"addNewTag": "添加新标签 \"{tag}\"",
"clickToSelectedFile": "点击选择导入文件 ({extensions})",
"selectedCount": "已选择 {count} / {totalCount}",
"youHaveUpdatedTransactions": "您已经更新 {count} 个交易",
@@ -1809,6 +1810,7 @@
"Unable to retrieve tag list": "无法获取标签列表",
"Tag list is up to date": "标签列表已是最新",
"Tag list has been updated": "标签列表已更新",
"Add new tag": "添加新标签",
"Unable to add tag": "无法添加标签",
"Unable to save tag": "无法保存标签",
"Unable to move tag": "无法移动标签",
@@ -266,8 +266,8 @@
:label="$t('Tags')"
:placeholder="$t('None')"
:items="allTags"
:no-data-text="$t('No available tag')"
v-model="transaction.tagIds"
v-model:search="tagSearchContent"
>
<template #chip="{ props, item }">
<v-chip :prepend-icon="icons.tag" :text="item.title" v-bind="props"/>
@@ -285,6 +285,13 @@
</template>
</v-list-item>
</template>
<template #no-data>
<v-list class="py-0">
<v-list-item v-if="tagSearchContent" @click="saveNewTag(tagSearchContent)">{{ $t('format.misc.addNewTag', { tag: tagSearchContent }) }}</v-list-item>
<v-list-item v-else-if="!tagSearchContent">{{ $t('No available tag') }}</v-list-item>
</v-list>
</template>
</v-autocomplete>
</v-col>
<v-col cols="12" md="12">
@@ -458,6 +465,7 @@ export default {
transaction: newTransaction,
geoLocationStatus: null,
geoMenuState: false,
tagSearchContent: '',
submitting: false,
uploadingPicture: false,
removingPictureId: '',
@@ -1166,6 +1174,29 @@ export default {
this.geoLocationStatus = null;
this.transaction.geoLocation = null;
},
saveNewTag(tagName) {
const self = this;
self.submitting = true;
self.transactionTagsStore.saveTag({
tag: {
name: tagName
}
}).then(tag => {
self.submitting = false;
if (tag && tag.id) {
self.transaction.tagIds.push(tag.id);
}
}).catch(error => {
self.submitting = false;
if (!error.processed) {
self.$refs.snackbar.showError(error);
}
});
},
swapTransactionData(swapAccount, swapAmount) {
if (swapAccount) {
const oldSourceAccountId = this.transaction.sourceAccountId;
+1 -1
View File
@@ -313,7 +313,7 @@
:header="$t('Tags')"
@click="showTransactionTagSheet = true"
>
<transaction-tag-selection-sheet :items="allTags"
<transaction-tag-selection-sheet :allow-add-new-tag="true"
v-model:show="showTransactionTagSheet"
v-model="transaction.tagIds">
</transaction-tag-selection-sheet>