mirror of
https://github.com/mayswind/ezbookkeeping.git
synced 2026-05-19 17:24:26 +08:00
migrate transaction tag store to composition API and typescript
This commit is contained in:
@@ -77,7 +77,9 @@
|
|||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { mapStores } from 'pinia';
|
import { mapStores } from 'pinia';
|
||||||
import { useTransactionTagsStore } from '@/stores/transactionTag.js';
|
import { useTransactionTagsStore } from '@/stores/transactionTag.ts';
|
||||||
|
|
||||||
|
import { TransactionTag } from '@/models/transaction_tag.ts';
|
||||||
|
|
||||||
import { copyArrayTo } from '@/lib/common.ts';
|
import { copyArrayTo } from '@/lib/common.ts';
|
||||||
import { scrollToSelectedItem } from '@/lib/ui/mobile.ts';
|
import { scrollToSelectedItem } from '@/lib/ui/mobile.ts';
|
||||||
@@ -152,9 +154,7 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
addNewTag() {
|
addNewTag() {
|
||||||
this.newTag = {
|
this.newTag = TransactionTag.createNewTag();
|
||||||
name: ''
|
|
||||||
};
|
|
||||||
},
|
},
|
||||||
saveNewTag() {
|
saveNewTag() {
|
||||||
const self = this;
|
const self = this;
|
||||||
|
|||||||
@@ -12,3 +12,5 @@ export interface TypeAndDisplayName {
|
|||||||
readonly type: number;
|
readonly type: number;
|
||||||
readonly displayName: string;
|
readonly displayName: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export type BeforeResolveFunction = (callback: () => void) => void;
|
||||||
|
|||||||
+1
-1
@@ -137,7 +137,7 @@ interface ApiRequestConfig extends AxiosRequestConfig {
|
|||||||
timeout?: number;
|
timeout?: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
type ApiResponsePromise<T> = Promise<AxiosResponse<ApiResponse<T>>>;
|
export type ApiResponsePromise<T> = Promise<AxiosResponse<ApiResponse<T>>>;
|
||||||
|
|
||||||
let needBlockRequest = false;
|
let needBlockRequest = false;
|
||||||
const blockedRequests: ((token: string | undefined) => void)[] = [];
|
const blockedRequests: ((token: string | undefined) => void)[] = [];
|
||||||
|
|||||||
@@ -1,3 +1,48 @@
|
|||||||
|
export class TransactionTag implements TransactionTagInfoResponse {
|
||||||
|
public id: string;
|
||||||
|
public name: string;
|
||||||
|
public displayOrder: number;
|
||||||
|
public hidden: boolean;
|
||||||
|
|
||||||
|
private constructor(id: string, name: string, displayOrder: number, hidden: boolean) {
|
||||||
|
this.id = id;
|
||||||
|
this.name = name;
|
||||||
|
this.displayOrder = displayOrder;
|
||||||
|
this.hidden = hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
public toCreateRequest(): TransactionTagCreateRequest {
|
||||||
|
return {
|
||||||
|
name: this.name
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public toModifyRequest(): TransactionTagModifyRequest {
|
||||||
|
return {
|
||||||
|
id: this.id,
|
||||||
|
name: this.name
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public static of(tagResponse: TransactionTagInfoResponse): TransactionTag {
|
||||||
|
return new TransactionTag(tagResponse.id, tagResponse.name, tagResponse.displayOrder, tagResponse.hidden);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ofMany(tagResponses: TransactionTagInfoResponse[]): TransactionTag[] {
|
||||||
|
const tags: TransactionTag[] = [];
|
||||||
|
|
||||||
|
for (const tagResponse of tagResponses) {
|
||||||
|
tags.push(TransactionTag.of(tagResponse));
|
||||||
|
}
|
||||||
|
|
||||||
|
return tags;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static createNewTag(): TransactionTag {
|
||||||
|
return new TransactionTag('', '', 0, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export interface TransactionTagCreateRequest {
|
export interface TransactionTagCreateRequest {
|
||||||
readonly name: string;
|
readonly name: string;
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -4,7 +4,7 @@ import { useSettingsStore } from './setting.ts';
|
|||||||
import { useUserStore } from './user.ts';
|
import { useUserStore } from './user.ts';
|
||||||
import { useAccountsStore } from './account.js';
|
import { useAccountsStore } from './account.js';
|
||||||
import { useTransactionCategoriesStore } from './transactionCategory.js';
|
import { useTransactionCategoriesStore } from './transactionCategory.js';
|
||||||
import { useTransactionTagsStore } from './transactionTag.js';
|
import { useTransactionTagsStore } from './transactionTag.ts';
|
||||||
import { useTransactionTemplatesStore } from './transactionTemplate.js';
|
import { useTransactionTemplatesStore } from './transactionTemplate.js';
|
||||||
import { useTransactionsStore } from './transaction.js';
|
import { useTransactionsStore } from './transaction.js';
|
||||||
import { useOverviewStore } from './overview.ts';
|
import { useOverviewStore } from './overview.ts';
|
||||||
|
|||||||
@@ -1,344 +0,0 @@
|
|||||||
import { defineStore } from 'pinia';
|
|
||||||
|
|
||||||
import { isEquals } from '@/lib/common.ts';
|
|
||||||
import services from '@/lib/services.ts';
|
|
||||||
import logger from '@/lib/logger.ts';
|
|
||||||
|
|
||||||
function loadTransactionTagList(state, tags) {
|
|
||||||
state.allTransactionTags = tags;
|
|
||||||
state.allTransactionTagsMap = {};
|
|
||||||
|
|
||||||
for (let i = 0; i < tags.length; i++) {
|
|
||||||
const tag = tags[i];
|
|
||||||
state.allTransactionTagsMap[tag.id] = tag;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function addTagToTransactionTagList(state, tag) {
|
|
||||||
state.allTransactionTags.push(tag);
|
|
||||||
state.allTransactionTagsMap[tag.id] = tag;
|
|
||||||
}
|
|
||||||
|
|
||||||
function updateTagInTransactionTagList(state, tag) {
|
|
||||||
for (let i = 0; i < state.allTransactionTags.length; i++) {
|
|
||||||
if (state.allTransactionTags[i].id === tag.id) {
|
|
||||||
state.allTransactionTags.splice(i, 1, tag);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
state.allTransactionTagsMap[tag.id] = tag;
|
|
||||||
}
|
|
||||||
|
|
||||||
function updateTagDisplayOrderInTransactionTagList(state, { from, to }) {
|
|
||||||
state.allTransactionTags.splice(to, 0, state.allTransactionTags.splice(from, 1)[0]);
|
|
||||||
}
|
|
||||||
|
|
||||||
function updateTagVisibilityInTransactionTagList(state, { tag, hidden }) {
|
|
||||||
if (state.allTransactionTagsMap[tag.id]) {
|
|
||||||
state.allTransactionTagsMap[tag.id].hidden = hidden;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function removeTagFromTransactionTagList(state, tag) {
|
|
||||||
for (let i = 0; i < state.allTransactionTags.length; i++) {
|
|
||||||
if (state.allTransactionTags[i].id === tag.id) {
|
|
||||||
state.allTransactionTags.splice(i, 1);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (state.allTransactionTagsMap[tag.id]) {
|
|
||||||
delete state.allTransactionTagsMap[tag.id];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export const useTransactionTagsStore = defineStore('transactionTags', {
|
|
||||||
state: () => ({
|
|
||||||
allTransactionTags: [],
|
|
||||||
allTransactionTagsMap: {},
|
|
||||||
transactionTagListStateInvalid: true,
|
|
||||||
}),
|
|
||||||
getters: {
|
|
||||||
allVisibleTags(state) {
|
|
||||||
const allVisibleTags = [];
|
|
||||||
|
|
||||||
for (let i = 0; i < state.allTransactionTags.length; i++) {
|
|
||||||
const tag = state.allTransactionTags[i];
|
|
||||||
|
|
||||||
if (!tag.hidden) {
|
|
||||||
allVisibleTags.push(tag);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return allVisibleTags;
|
|
||||||
},
|
|
||||||
allAvailableTagsCount(state) {
|
|
||||||
return state.allTransactionTags.length;
|
|
||||||
},
|
|
||||||
allVisibleTagsCount(state) {
|
|
||||||
return state.allVisibleTags.length;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
actions: {
|
|
||||||
generateNewTransactionTagModel() {
|
|
||||||
return {
|
|
||||||
id: '',
|
|
||||||
name: ''
|
|
||||||
};
|
|
||||||
},
|
|
||||||
updateTransactionTagListInvalidState(invalidState) {
|
|
||||||
this.transactionTagListStateInvalid = invalidState;
|
|
||||||
},
|
|
||||||
resetTransactionTags() {
|
|
||||||
this.allTransactionTags = [];
|
|
||||||
this.allTransactionTagsMap = {};
|
|
||||||
this.transactionTagListStateInvalid = true;
|
|
||||||
},
|
|
||||||
loadAllTags({ force }) {
|
|
||||||
const self = this;
|
|
||||||
|
|
||||||
if (!force && !self.transactionTagListStateInvalid) {
|
|
||||||
return new Promise((resolve) => {
|
|
||||||
resolve(self.allTransactionTags);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
services.getAllTransactionTags().then(response => {
|
|
||||||
const data = response.data;
|
|
||||||
|
|
||||||
if (!data || !data.success || !data.result) {
|
|
||||||
reject({ message: 'Unable to retrieve tag list' });
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (self.transactionTagListStateInvalid) {
|
|
||||||
self.updateTransactionTagListInvalidState(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (force && data.result && isEquals(self.allTransactionTags, data.result)) {
|
|
||||||
reject({ message: 'Tag list is up to date' });
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
loadTransactionTagList(self, data.result);
|
|
||||||
|
|
||||||
resolve(data.result);
|
|
||||||
}).catch(error => {
|
|
||||||
if (force) {
|
|
||||||
logger.error('failed to force load tag list', error);
|
|
||||||
} else {
|
|
||||||
logger.error('failed to load tag list', error);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (error.response && error.response.data && error.response.data.errorMessage) {
|
|
||||||
reject({ error: error.response.data });
|
|
||||||
} else if (!error.processed) {
|
|
||||||
reject({ message: 'Unable to retrieve tag list' });
|
|
||||||
} else {
|
|
||||||
reject(error);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
},
|
|
||||||
saveTag({ tag }) {
|
|
||||||
const self = this;
|
|
||||||
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
let promise = null;
|
|
||||||
|
|
||||||
if (!tag.id) {
|
|
||||||
promise = services.addTransactionTag(tag);
|
|
||||||
} else {
|
|
||||||
promise = services.modifyTransactionTag(tag);
|
|
||||||
}
|
|
||||||
|
|
||||||
promise.then(response => {
|
|
||||||
const data = response.data;
|
|
||||||
|
|
||||||
if (!data || !data.success || !data.result) {
|
|
||||||
if (!tag.id) {
|
|
||||||
reject({ message: 'Unable to add tag' });
|
|
||||||
} else {
|
|
||||||
reject({ message: 'Unable to save tag' });
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!tag.id) {
|
|
||||||
addTagToTransactionTagList(self, data.result);
|
|
||||||
} else {
|
|
||||||
updateTagInTransactionTagList(self, data.result);
|
|
||||||
}
|
|
||||||
|
|
||||||
resolve(data.result);
|
|
||||||
}).catch(error => {
|
|
||||||
logger.error('failed to save tag', error);
|
|
||||||
|
|
||||||
if (error.response && error.response.data && error.response.data.errorMessage) {
|
|
||||||
reject({ error: error.response.data });
|
|
||||||
} else if (!error.processed) {
|
|
||||||
if (!tag.id) {
|
|
||||||
reject({ message: 'Unable to add tag' });
|
|
||||||
} else {
|
|
||||||
reject({ message: 'Unable to save tag' });
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
reject(error);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
},
|
|
||||||
changeTagDisplayOrder({ tagId, from, to }) {
|
|
||||||
const self = this;
|
|
||||||
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
let tag = null;
|
|
||||||
|
|
||||||
for (let i = 0; i < self.allTransactionTags.length; i++) {
|
|
||||||
if (self.allTransactionTags[i].id === tagId) {
|
|
||||||
tag = self.allTransactionTags[i];
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!tag || !self.allTransactionTags[to]) {
|
|
||||||
reject({ message: 'Unable to move tag' });
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!self.transactionTagListStateInvalid) {
|
|
||||||
self.updateTransactionTagListInvalidState(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
updateTagDisplayOrderInTransactionTagList(self, {
|
|
||||||
tag: tag,
|
|
||||||
from: from,
|
|
||||||
to: to
|
|
||||||
});
|
|
||||||
|
|
||||||
resolve();
|
|
||||||
});
|
|
||||||
},
|
|
||||||
updateTagDisplayOrders() {
|
|
||||||
const self = this;
|
|
||||||
const newDisplayOrders = [];
|
|
||||||
|
|
||||||
for (let i = 0; i < self.allTransactionTags.length; i++) {
|
|
||||||
newDisplayOrders.push({
|
|
||||||
id: self.allTransactionTags[i].id,
|
|
||||||
displayOrder: i + 1
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
services.moveTransactionTag({
|
|
||||||
newDisplayOrders: newDisplayOrders
|
|
||||||
}).then(response => {
|
|
||||||
const data = response.data;
|
|
||||||
|
|
||||||
if (!data || !data.success || !data.result) {
|
|
||||||
reject({ message: 'Unable to move tag' });
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (self.transactionTagListStateInvalid) {
|
|
||||||
self.updateTransactionTagListInvalidState(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
resolve(data.result);
|
|
||||||
}).catch(error => {
|
|
||||||
logger.error('failed to save tags display order', error);
|
|
||||||
|
|
||||||
if (error.response && error.response.data && error.response.data.errorMessage) {
|
|
||||||
reject({ error: error.response.data });
|
|
||||||
} else if (!error.processed) {
|
|
||||||
reject({ message: 'Unable to move tag' });
|
|
||||||
} else {
|
|
||||||
reject(error);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
},
|
|
||||||
hideTag({ tag, hidden }) {
|
|
||||||
const self = this;
|
|
||||||
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
services.hideTransactionTag({
|
|
||||||
id: tag.id,
|
|
||||||
hidden: hidden
|
|
||||||
}).then(response => {
|
|
||||||
const data = response.data;
|
|
||||||
|
|
||||||
if (!data || !data.success || !data.result) {
|
|
||||||
if (hidden) {
|
|
||||||
reject({ message: 'Unable to hide this tag' });
|
|
||||||
} else {
|
|
||||||
reject({ message: 'Unable to unhide this tag' });
|
|
||||||
}
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
updateTagVisibilityInTransactionTagList(self, {
|
|
||||||
tag: tag,
|
|
||||||
hidden: hidden
|
|
||||||
});
|
|
||||||
|
|
||||||
resolve(data.result);
|
|
||||||
}).catch(error => {
|
|
||||||
logger.error('failed to change tag visibility', error);
|
|
||||||
|
|
||||||
if (error.response && error.response.data && error.response.data.errorMessage) {
|
|
||||||
reject({ error: error.response.data });
|
|
||||||
} else if (!error.processed) {
|
|
||||||
if (hidden) {
|
|
||||||
reject({ message: 'Unable to hide this tag' });
|
|
||||||
} else {
|
|
||||||
reject({ message: 'Unable to unhide this tag' });
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
reject(error);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
},
|
|
||||||
deleteTag({ tag, beforeResolve }) {
|
|
||||||
const self = this;
|
|
||||||
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
services.deleteTransactionTag({
|
|
||||||
id: tag.id
|
|
||||||
}).then(response => {
|
|
||||||
const data = response.data;
|
|
||||||
|
|
||||||
if (!data || !data.success || !data.result) {
|
|
||||||
reject({ message: 'Unable to delete this tag' });
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (beforeResolve) {
|
|
||||||
beforeResolve(() => {
|
|
||||||
removeTagFromTransactionTagList(self, tag);
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
removeTagFromTransactionTagList(self, tag);
|
|
||||||
}
|
|
||||||
|
|
||||||
resolve(data.result);
|
|
||||||
}).catch(error => {
|
|
||||||
logger.error('failed to delete tag', error);
|
|
||||||
|
|
||||||
if (error.response && error.response.data && error.response.data.errorMessage) {
|
|
||||||
reject({ error: error.response.data });
|
|
||||||
} else if (!error.processed) {
|
|
||||||
reject({ message: 'Unable to delete this tag' });
|
|
||||||
} else {
|
|
||||||
reject(error);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
@@ -0,0 +1,356 @@
|
|||||||
|
import { ref, computed } from 'vue';
|
||||||
|
import { defineStore } from 'pinia';
|
||||||
|
|
||||||
|
import type { BeforeResolveFunction } from '@/core/base.ts';
|
||||||
|
|
||||||
|
import {
|
||||||
|
type TransactionTagInfoResponse,
|
||||||
|
type TransactionTagNewDisplayOrderRequest,
|
||||||
|
TransactionTag
|
||||||
|
} from '@/models/transaction_tag.ts';
|
||||||
|
|
||||||
|
import { isEquals } from '@/lib/common.ts';
|
||||||
|
|
||||||
|
import logger from '@/lib/logger.ts';
|
||||||
|
import services, { type ApiResponsePromise } from '@/lib/services.ts';
|
||||||
|
|
||||||
|
export const useTransactionTagsStore = defineStore('transactionTags', () => {
|
||||||
|
const allTransactionTags = ref<TransactionTag[]>([]);
|
||||||
|
const allTransactionTagsMap = ref<Record<string, TransactionTag>>({});
|
||||||
|
const transactionTagListStateInvalid = ref<boolean>(true);
|
||||||
|
|
||||||
|
const allVisibleTags = computed<TransactionTag[]>(() => {
|
||||||
|
const visibleTags: TransactionTag[] = [];
|
||||||
|
|
||||||
|
for (const tag of allTransactionTags.value) {
|
||||||
|
if (!tag.hidden) {
|
||||||
|
visibleTags.push(tag);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return visibleTags;
|
||||||
|
});
|
||||||
|
|
||||||
|
const allAvailableTagsCount = computed<number>(() => allTransactionTags.value.length);
|
||||||
|
const allVisibleTagsCount = computed<number>(() => allVisibleTags.value.length);
|
||||||
|
|
||||||
|
function loadTransactionTagList(tags: TransactionTag[]): void {
|
||||||
|
allTransactionTags.value = tags;
|
||||||
|
allTransactionTagsMap.value = {};
|
||||||
|
|
||||||
|
for (const tag of tags) {
|
||||||
|
allTransactionTagsMap.value[tag.id] = tag;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function addTagToTransactionTagList(tag: TransactionTag): void {
|
||||||
|
allTransactionTags.value.push(tag);
|
||||||
|
allTransactionTagsMap.value[tag.id] = tag;
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateTagInTransactionTagList(tag: TransactionTag): void {
|
||||||
|
for (let i = 0; i < allTransactionTags.value.length; i++) {
|
||||||
|
if (allTransactionTags.value[i].id === tag.id) {
|
||||||
|
allTransactionTags.value.splice(i, 1, tag);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
allTransactionTagsMap.value[tag.id] = tag;
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateTagDisplayOrderInTransactionTagList(params: { from: number, to: number }): void {
|
||||||
|
allTransactionTags.value.splice(params.to, 0, allTransactionTags.value.splice(params.from, 1)[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateTagVisibilityInTransactionTagList(params: { tag: TransactionTag, hidden: boolean }): void {
|
||||||
|
if (allTransactionTagsMap.value[params.tag.id]) {
|
||||||
|
allTransactionTagsMap.value[params.tag.id].hidden = params.hidden;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function removeTagFromTransactionTagList(tag: TransactionTag): void {
|
||||||
|
for (let i = 0; i < allTransactionTags.value.length; i++) {
|
||||||
|
if (allTransactionTags.value[i].id === tag.id) {
|
||||||
|
allTransactionTags.value.splice(i, 1);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (allTransactionTagsMap.value[tag.id]) {
|
||||||
|
delete allTransactionTagsMap.value[tag.id];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateTransactionTagListInvalidState(invalidState: boolean): void {
|
||||||
|
transactionTagListStateInvalid.value = invalidState;
|
||||||
|
}
|
||||||
|
|
||||||
|
function resetTransactionTags(): void {
|
||||||
|
allTransactionTags.value = [];
|
||||||
|
allTransactionTagsMap.value = {};
|
||||||
|
transactionTagListStateInvalid.value = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
function loadAllTags(params: { force?: boolean }): Promise<TransactionTag[]> {
|
||||||
|
if (!params.force && !transactionTagListStateInvalid.value) {
|
||||||
|
return new Promise((resolve) => {
|
||||||
|
resolve(allTransactionTags.value);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
services.getAllTransactionTags().then(response => {
|
||||||
|
const data = response.data;
|
||||||
|
|
||||||
|
if (!data || !data.success || !data.result) {
|
||||||
|
reject({ message: 'Unable to retrieve tag list' });
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (transactionTagListStateInvalid.value) {
|
||||||
|
updateTransactionTagListInvalidState(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
const transactionTags = TransactionTag.ofMany(data.result);
|
||||||
|
|
||||||
|
if (params.force && data.result && isEquals(allTransactionTags.value, transactionTags)) {
|
||||||
|
reject({ message: 'Tag list is up to date' });
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
loadTransactionTagList(transactionTags);
|
||||||
|
|
||||||
|
resolve(transactionTags);
|
||||||
|
}).catch(error => {
|
||||||
|
if (params.force) {
|
||||||
|
logger.error('failed to force load tag list', error);
|
||||||
|
} else {
|
||||||
|
logger.error('failed to load tag list', error);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (error.response && error.response.data && error.response.data.errorMessage) {
|
||||||
|
reject({ error: error.response.data });
|
||||||
|
} else if (!error.processed) {
|
||||||
|
reject({ message: 'Unable to retrieve tag list' });
|
||||||
|
} else {
|
||||||
|
reject(error);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function saveTag(params: { tag: TransactionTag }): Promise<TransactionTag> {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
let promise: ApiResponsePromise<TransactionTagInfoResponse>;
|
||||||
|
|
||||||
|
if (!params.tag.id) {
|
||||||
|
promise = services.addTransactionTag(params.tag.toCreateRequest());
|
||||||
|
} else {
|
||||||
|
promise = services.modifyTransactionTag(params.tag.toModifyRequest());
|
||||||
|
}
|
||||||
|
|
||||||
|
promise.then(response => {
|
||||||
|
const data = response.data;
|
||||||
|
|
||||||
|
if (!data || !data.success || !data.result) {
|
||||||
|
if (!params.tag.id) {
|
||||||
|
reject({ message: 'Unable to add tag' });
|
||||||
|
} else {
|
||||||
|
reject({ message: 'Unable to save tag' });
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const transactionTag = TransactionTag.of(data.result);
|
||||||
|
|
||||||
|
if (!params.tag.id) {
|
||||||
|
addTagToTransactionTagList(transactionTag);
|
||||||
|
} else {
|
||||||
|
updateTagInTransactionTagList(transactionTag);
|
||||||
|
}
|
||||||
|
|
||||||
|
resolve(transactionTag);
|
||||||
|
}).catch(error => {
|
||||||
|
logger.error('failed to save tag', error);
|
||||||
|
|
||||||
|
if (error.response && error.response.data && error.response.data.errorMessage) {
|
||||||
|
reject({ error: error.response.data });
|
||||||
|
} else if (!error.processed) {
|
||||||
|
if (!params.tag.id) {
|
||||||
|
reject({ message: 'Unable to add tag' });
|
||||||
|
} else {
|
||||||
|
reject({ message: 'Unable to save tag' });
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
reject(error);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function changeTagDisplayOrder(params: { tagId: string, from: number, to: number }): Promise<void> {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
let tag: TransactionTag | null = null;
|
||||||
|
|
||||||
|
for (let i = 0; i < allTransactionTags.value.length; i++) {
|
||||||
|
if (allTransactionTags.value[i].id === params.tagId) {
|
||||||
|
tag = allTransactionTags.value[i];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!tag || !allTransactionTags.value[params.to]) {
|
||||||
|
reject({ message: 'Unable to move tag' });
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!transactionTagListStateInvalid.value) {
|
||||||
|
updateTransactionTagListInvalidState(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
updateTagDisplayOrderInTransactionTagList({
|
||||||
|
from: params.from,
|
||||||
|
to: params.to
|
||||||
|
});
|
||||||
|
|
||||||
|
resolve();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateTagDisplayOrders(): Promise<boolean> {
|
||||||
|
const newDisplayOrders: TransactionTagNewDisplayOrderRequest[] = [];
|
||||||
|
|
||||||
|
for (let i = 0; i < allTransactionTags.value.length; i++) {
|
||||||
|
newDisplayOrders.push({
|
||||||
|
id: allTransactionTags.value[i].id,
|
||||||
|
displayOrder: i + 1
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
services.moveTransactionTag({
|
||||||
|
newDisplayOrders: newDisplayOrders
|
||||||
|
}).then(response => {
|
||||||
|
const data = response.data;
|
||||||
|
|
||||||
|
if (!data || !data.success || !data.result) {
|
||||||
|
reject({ message: 'Unable to move tag' });
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (transactionTagListStateInvalid.value) {
|
||||||
|
updateTransactionTagListInvalidState(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
resolve(data.result);
|
||||||
|
}).catch(error => {
|
||||||
|
logger.error('failed to save tags display order', error);
|
||||||
|
|
||||||
|
if (error.response && error.response.data && error.response.data.errorMessage) {
|
||||||
|
reject({ error: error.response.data });
|
||||||
|
} else if (!error.processed) {
|
||||||
|
reject({ message: 'Unable to move tag' });
|
||||||
|
} else {
|
||||||
|
reject(error);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function hideTag(params: { tag: TransactionTag, hidden: boolean }): Promise<boolean> {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
services.hideTransactionTag({
|
||||||
|
id: params.tag.id,
|
||||||
|
hidden: params.hidden
|
||||||
|
}).then(response => {
|
||||||
|
const data = response.data;
|
||||||
|
|
||||||
|
if (!data || !data.success || !data.result) {
|
||||||
|
if (params.hidden) {
|
||||||
|
reject({ message: 'Unable to hide this tag' });
|
||||||
|
} else {
|
||||||
|
reject({ message: 'Unable to unhide this tag' });
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
updateTagVisibilityInTransactionTagList({
|
||||||
|
tag: params.tag,
|
||||||
|
hidden: params.hidden
|
||||||
|
});
|
||||||
|
|
||||||
|
resolve(data.result);
|
||||||
|
}).catch(error => {
|
||||||
|
logger.error('failed to change tag visibility', error);
|
||||||
|
|
||||||
|
if (error.response && error.response.data && error.response.data.errorMessage) {
|
||||||
|
reject({ error: error.response.data });
|
||||||
|
} else if (!error.processed) {
|
||||||
|
if (params.hidden) {
|
||||||
|
reject({ message: 'Unable to hide this tag' });
|
||||||
|
} else {
|
||||||
|
reject({ message: 'Unable to unhide this tag' });
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
reject(error);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function deleteTag(params: { tag: TransactionTag, beforeResolve?: BeforeResolveFunction }): Promise<boolean> {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
services.deleteTransactionTag({
|
||||||
|
id: params.tag.id
|
||||||
|
}).then(response => {
|
||||||
|
const data = response.data;
|
||||||
|
|
||||||
|
if (!data || !data.success || !data.result) {
|
||||||
|
reject({ message: 'Unable to delete this tag' });
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (params.beforeResolve) {
|
||||||
|
params.beforeResolve(() => {
|
||||||
|
removeTagFromTransactionTagList(params.tag);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
removeTagFromTransactionTagList(params.tag);
|
||||||
|
}
|
||||||
|
|
||||||
|
resolve(data.result);
|
||||||
|
}).catch(error => {
|
||||||
|
logger.error('failed to delete tag', error);
|
||||||
|
|
||||||
|
if (error.response && error.response.data && error.response.data.errorMessage) {
|
||||||
|
reject({ error: error.response.data });
|
||||||
|
} else if (!error.processed) {
|
||||||
|
reject({ message: 'Unable to delete this tag' });
|
||||||
|
} else {
|
||||||
|
reject(error);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
// states
|
||||||
|
allTransactionTags,
|
||||||
|
allTransactionTagsMap,
|
||||||
|
transactionTagListStateInvalid,
|
||||||
|
// computed states
|
||||||
|
allVisibleTags,
|
||||||
|
allAvailableTagsCount,
|
||||||
|
allVisibleTagsCount,
|
||||||
|
// functions
|
||||||
|
updateTransactionTagListInvalidState,
|
||||||
|
resetTransactionTags,
|
||||||
|
loadAllTags,
|
||||||
|
saveTag,
|
||||||
|
changeTagDisplayOrder,
|
||||||
|
updateTagDisplayOrders,
|
||||||
|
hideTag,
|
||||||
|
deleteTag
|
||||||
|
}
|
||||||
|
});
|
||||||
@@ -132,7 +132,7 @@
|
|||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { mapStores } from 'pinia';
|
import { mapStores } from 'pinia';
|
||||||
import { useTransactionTagsStore } from '@/stores/transactionTag.js';
|
import { useTransactionTagsStore } from '@/stores/transactionTag.ts';
|
||||||
import { useTransactionsStore } from '@/stores/transaction.js';
|
import { useTransactionsStore } from '@/stores/transaction.js';
|
||||||
import { useStatisticsStore } from '@/stores/statistics.js';
|
import { useStatisticsStore } from '@/stores/statistics.js';
|
||||||
|
|
||||||
|
|||||||
@@ -224,7 +224,9 @@
|
|||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { mapStores } from 'pinia';
|
import { mapStores } from 'pinia';
|
||||||
import { useTransactionTagsStore } from '@/stores/transactionTag.js';
|
import { useTransactionTagsStore } from '@/stores/transactionTag.ts';
|
||||||
|
|
||||||
|
import { TransactionTag } from '@/models/transaction_tag.ts';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
isNoAvailableTag,
|
isNoAvailableTag,
|
||||||
@@ -247,12 +249,9 @@ import {
|
|||||||
|
|
||||||
export default {
|
export default {
|
||||||
data() {
|
data() {
|
||||||
const transactionTagsStore = useTransactionTagsStore();
|
|
||||||
const newTransactionTag = transactionTagsStore.generateNewTransactionTagModel();
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
newTag: null,
|
newTag: null,
|
||||||
editingTag: newTransactionTag,
|
editingTag: TransactionTag.createNewTag(),
|
||||||
loading: true,
|
loading: true,
|
||||||
updating: false,
|
updating: false,
|
||||||
tagUpdating: {},
|
tagUpdating: {},
|
||||||
@@ -375,9 +374,7 @@ export default {
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
add() {
|
add() {
|
||||||
this.newTag = {
|
this.newTag = TransactionTag.createNewTag();
|
||||||
name: ''
|
|
||||||
};
|
|
||||||
},
|
},
|
||||||
edit(tag) {
|
edit(tag) {
|
||||||
this.editingTag.id = tag.id;
|
this.editingTag.id = tag.id;
|
||||||
|
|||||||
@@ -592,7 +592,7 @@ import { useSettingsStore } from '@/stores/setting.ts';
|
|||||||
import { useUserStore } from '@/stores/user.ts';
|
import { useUserStore } from '@/stores/user.ts';
|
||||||
import { useAccountsStore } from '@/stores/account.js';
|
import { useAccountsStore } from '@/stores/account.js';
|
||||||
import { useTransactionCategoriesStore } from '@/stores/transactionCategory.js';
|
import { useTransactionCategoriesStore } from '@/stores/transactionCategory.js';
|
||||||
import { useTransactionTagsStore } from '@/stores/transactionTag.js';
|
import { useTransactionTagsStore } from '@/stores/transactionTag.ts';
|
||||||
import { useTransactionsStore } from '@/stores/transaction.js';
|
import { useTransactionsStore } from '@/stores/transaction.js';
|
||||||
import { useTransactionTemplatesStore } from '@/stores/transactionTemplate.js';
|
import { useTransactionTemplatesStore } from '@/stores/transactionTemplate.js';
|
||||||
|
|
||||||
|
|||||||
@@ -176,7 +176,7 @@ import { useSettingsStore } from '@/stores/setting.ts';
|
|||||||
import { useUserStore } from '@/stores/user.ts';
|
import { useUserStore } from '@/stores/user.ts';
|
||||||
import { useAccountsStore } from '@/stores/account.js';
|
import { useAccountsStore } from '@/stores/account.js';
|
||||||
import { useTransactionCategoriesStore } from '@/stores/transactionCategory.js';
|
import { useTransactionCategoriesStore } from '@/stores/transactionCategory.js';
|
||||||
import { useTransactionTagsStore } from '@/stores/transactionTag.js';
|
import { useTransactionTagsStore } from '@/stores/transactionTag.ts';
|
||||||
import { useExchangeRatesStore } from '@/stores/exchangeRates.ts';
|
import { useExchangeRatesStore } from '@/stores/exchangeRates.ts';
|
||||||
|
|
||||||
import { CategoryType } from '@/core/category.ts';
|
import { CategoryType } from '@/core/category.ts';
|
||||||
|
|||||||
@@ -395,7 +395,7 @@ import { useSettingsStore } from '@/stores/setting.ts';
|
|||||||
import { useUserStore } from '@/stores/user.ts';
|
import { useUserStore } from '@/stores/user.ts';
|
||||||
import { useAccountsStore } from '@/stores/account.js';
|
import { useAccountsStore } from '@/stores/account.js';
|
||||||
import { useTransactionCategoriesStore } from '@/stores/transactionCategory.js';
|
import { useTransactionCategoriesStore } from '@/stores/transactionCategory.js';
|
||||||
import { useTransactionTagsStore } from '@/stores/transactionTag.js';
|
import { useTransactionTagsStore } from '@/stores/transactionTag.ts';
|
||||||
import { useTransactionsStore } from '@/stores/transaction.js';
|
import { useTransactionsStore } from '@/stores/transaction.js';
|
||||||
import { useTransactionTemplatesStore } from '@/stores/transactionTemplate.js';
|
import { useTransactionTemplatesStore } from '@/stores/transactionTemplate.js';
|
||||||
import { useExchangeRatesStore } from '@/stores/exchangeRates.ts';
|
import { useExchangeRatesStore } from '@/stores/exchangeRates.ts';
|
||||||
|
|||||||
@@ -601,7 +601,7 @@ import { useSettingsStore } from '@/stores/setting.ts';
|
|||||||
import { useUserStore } from '@/stores/user.ts';
|
import { useUserStore } from '@/stores/user.ts';
|
||||||
import { useAccountsStore } from '@/stores/account.js';
|
import { useAccountsStore } from '@/stores/account.js';
|
||||||
import { useTransactionCategoriesStore } from '@/stores/transactionCategory.js';
|
import { useTransactionCategoriesStore } from '@/stores/transactionCategory.js';
|
||||||
import { useTransactionTagsStore } from '@/stores/transactionTag.js';
|
import { useTransactionTagsStore } from '@/stores/transactionTag.ts';
|
||||||
import { useTransactionsStore } from '@/stores/transaction.js';
|
import { useTransactionsStore } from '@/stores/transaction.js';
|
||||||
import { useOverviewStore } from '@/stores/overview.ts';
|
import { useOverviewStore } from '@/stores/overview.ts';
|
||||||
import { useStatisticsStore } from '@/stores/statistics.js';
|
import { useStatisticsStore } from '@/stores/statistics.js';
|
||||||
|
|||||||
@@ -112,7 +112,7 @@
|
|||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { mapStores } from 'pinia';
|
import { mapStores } from 'pinia';
|
||||||
import { useTransactionTagsStore } from '@/stores/transactionTag.js';
|
import { useTransactionTagsStore } from '@/stores/transactionTag.ts';
|
||||||
import { useTransactionsStore } from '@/stores/transaction.js';
|
import { useTransactionsStore } from '@/stores/transaction.js';
|
||||||
import { useStatisticsStore } from '@/stores/statistics.js';
|
import { useStatisticsStore } from '@/stores/statistics.js';
|
||||||
|
|
||||||
|
|||||||
@@ -145,7 +145,9 @@
|
|||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { mapStores } from 'pinia';
|
import { mapStores } from 'pinia';
|
||||||
import { useTransactionTagsStore } from '@/stores/transactionTag.js';
|
import { useTransactionTagsStore } from '@/stores/transactionTag.ts';
|
||||||
|
|
||||||
|
import { TransactionTag } from '@/models/transaction_tag.ts';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
isNoAvailableTag,
|
isNoAvailableTag,
|
||||||
@@ -159,12 +161,9 @@ export default {
|
|||||||
'f7router'
|
'f7router'
|
||||||
],
|
],
|
||||||
data() {
|
data() {
|
||||||
const transactionTagsStore = useTransactionTagsStore();
|
|
||||||
const newTransactionTag = transactionTagsStore.generateNewTransactionTagModel();
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
newTag: null,
|
newTag: null,
|
||||||
editingTag: newTransactionTag,
|
editingTag: TransactionTag.createNewTag(),
|
||||||
loading: true,
|
loading: true,
|
||||||
loadingError: null,
|
loadingError: null,
|
||||||
showHidden: false,
|
showHidden: false,
|
||||||
@@ -179,7 +178,6 @@ export default {
|
|||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
...mapStores(useTransactionTagsStore),
|
...mapStores(useTransactionTagsStore),
|
||||||
|
|
||||||
tags() {
|
tags() {
|
||||||
return this.transactionTagsStore.allTransactionTags;
|
return this.transactionTagsStore.allTransactionTags;
|
||||||
},
|
},
|
||||||
@@ -310,9 +308,7 @@ export default {
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
add() {
|
add() {
|
||||||
this.newTag = {
|
this.newTag = TransactionTag.createNewTag();
|
||||||
name: ''
|
|
||||||
};
|
|
||||||
},
|
},
|
||||||
edit(tag) {
|
edit(tag) {
|
||||||
this.editingTag.id = tag.id;
|
this.editingTag.id = tag.id;
|
||||||
|
|||||||
@@ -435,7 +435,7 @@ import { useEnvironmentsStore } from '@/stores/environment.ts';
|
|||||||
import { useUserStore } from '@/stores/user.ts';
|
import { useUserStore } from '@/stores/user.ts';
|
||||||
import { useAccountsStore } from '@/stores/account.js';
|
import { useAccountsStore } from '@/stores/account.js';
|
||||||
import { useTransactionCategoriesStore } from '@/stores/transactionCategory.js';
|
import { useTransactionCategoriesStore } from '@/stores/transactionCategory.js';
|
||||||
import { useTransactionTagsStore } from '@/stores/transactionTag.js';
|
import { useTransactionTagsStore } from '@/stores/transactionTag.ts';
|
||||||
import { useTransactionsStore } from '@/stores/transaction.js';
|
import { useTransactionsStore } from '@/stores/transaction.js';
|
||||||
import { useTransactionTemplatesStore } from '@/stores/transactionTemplate.js';
|
import { useTransactionTemplatesStore } from '@/stores/transactionTemplate.js';
|
||||||
import { useExchangeRatesStore } from '@/stores/exchangeRates.ts';
|
import { useExchangeRatesStore } from '@/stores/exchangeRates.ts';
|
||||||
|
|||||||
@@ -525,7 +525,7 @@ import { useSettingsStore } from '@/stores/setting.ts';
|
|||||||
import { useUserStore } from '@/stores/user.ts';
|
import { useUserStore } from '@/stores/user.ts';
|
||||||
import { useAccountsStore } from '@/stores/account.js';
|
import { useAccountsStore } from '@/stores/account.js';
|
||||||
import { useTransactionCategoriesStore } from '@/stores/transactionCategory.js';
|
import { useTransactionCategoriesStore } from '@/stores/transactionCategory.js';
|
||||||
import { useTransactionTagsStore } from '@/stores/transactionTag.js';
|
import { useTransactionTagsStore } from '@/stores/transactionTag.ts';
|
||||||
import { useTransactionsStore } from '@/stores/transaction.js';
|
import { useTransactionsStore } from '@/stores/transaction.js';
|
||||||
|
|
||||||
import { DateRangeScene, DateRange } from '@/core/datetime.ts';
|
import { DateRangeScene, DateRange } from '@/core/datetime.ts';
|
||||||
|
|||||||
Reference in New Issue
Block a user