insights explorer supports sub condition
This commit is contained in:
+12
-2
@@ -4,17 +4,27 @@ import { DateRange } from '@/core/datetime.ts';
|
||||
export enum TransactionExplorerConditionRelation {
|
||||
First = 'first',
|
||||
And = 'and',
|
||||
Or = 'or'
|
||||
Or = 'or',
|
||||
AndSub = 'and(',
|
||||
OrSub = 'or(',
|
||||
SubEnd = ')'
|
||||
}
|
||||
|
||||
export type TransactionExplorerSubConditionStartRelation = '(';
|
||||
export const TransactionExplorerSubConditionStartRelationPlaceholder: TransactionExplorerSubConditionStartRelation = '(';
|
||||
|
||||
export const TransactionExplorerConditionRelationPriority: Record<TransactionExplorerConditionRelation, number> = {
|
||||
[TransactionExplorerConditionRelation.First]: 0,
|
||||
[TransactionExplorerConditionRelation.Or]: 1,
|
||||
[TransactionExplorerConditionRelation.And]: 2
|
||||
[TransactionExplorerConditionRelation.And]: 2,
|
||||
[TransactionExplorerConditionRelation.AndSub]: 0,
|
||||
[TransactionExplorerConditionRelation.OrSub]: 0,
|
||||
[TransactionExplorerConditionRelation.SubEnd]: 0
|
||||
};
|
||||
|
||||
|
||||
export enum TransactionExplorerConditionFieldType {
|
||||
Undefined = 'undefined',
|
||||
TransactionType = 'transactionType',
|
||||
TransactionCategory = 'transactionCategory',
|
||||
SourceAccount = 'sourceAccount',
|
||||
|
||||
@@ -1517,6 +1517,8 @@
|
||||
"WHERE": "WHERE",
|
||||
"AND": "AND",
|
||||
"OR": "OR",
|
||||
"AND SUB": "AND SUB",
|
||||
"OR SUB": "OR SUB",
|
||||
"Today": "Heute",
|
||||
"Yesterday": "Gestern",
|
||||
"Recent 7 days": "Letzte 7 Tage",
|
||||
@@ -1750,6 +1752,7 @@
|
||||
"Remove Query": "Remove Query",
|
||||
"Modify Query Name": "Modify Query Name",
|
||||
"Add Condition": "Add Condition",
|
||||
"Add Sub Condition": "Add Sub Condition",
|
||||
"Remove Condition": "Remove Condition",
|
||||
"No conditions defined. All transactions will match.": "No conditions defined. All transactions will match.",
|
||||
"Unable to retrieve explorer list": "Unable to retrieve explorer list",
|
||||
|
||||
@@ -1517,6 +1517,8 @@
|
||||
"WHERE": "WHERE",
|
||||
"AND": "AND",
|
||||
"OR": "OR",
|
||||
"AND SUB": "AND SUB",
|
||||
"OR SUB": "OR SUB",
|
||||
"Today": "Today",
|
||||
"Yesterday": "Yesterday",
|
||||
"Recent 7 days": "Recent 7 days",
|
||||
@@ -1750,6 +1752,7 @@
|
||||
"Remove Query": "Remove Query",
|
||||
"Modify Query Name": "Modify Query Name",
|
||||
"Add Condition": "Add Condition",
|
||||
"Add Sub Condition": "Add Sub Condition",
|
||||
"Remove Condition": "Remove Condition",
|
||||
"No conditions defined. All transactions will match.": "No conditions defined. All transactions will match.",
|
||||
"Unable to retrieve explorer list": "Unable to retrieve explorer list",
|
||||
|
||||
@@ -1517,6 +1517,8 @@
|
||||
"WHERE": "WHERE",
|
||||
"AND": "AND",
|
||||
"OR": "OR",
|
||||
"AND SUB": "AND SUB",
|
||||
"OR SUB": "OR SUB",
|
||||
"Today": "Hoy",
|
||||
"Yesterday": "Ayer",
|
||||
"Recent 7 days": "Últimos 7 días",
|
||||
@@ -1750,6 +1752,7 @@
|
||||
"Remove Query": "Eliminar Consulta",
|
||||
"Modify Query Name": "Modificar el Nombre de la Consulta",
|
||||
"Add Condition": "Añadir Condición",
|
||||
"Add Sub Condition": "Add Sub Condition",
|
||||
"Remove Condition": "Eliminar Condición",
|
||||
"No conditions defined. All transactions will match.": "Sin condiciones definidas. Todas las transacciones coincidirán.",
|
||||
"Unable to retrieve explorer list": "No se puede recuperar la lista de exploraciones",
|
||||
|
||||
@@ -1517,6 +1517,8 @@
|
||||
"WHERE": "WHERE",
|
||||
"AND": "AND",
|
||||
"OR": "OR",
|
||||
"AND SUB": "AND SUB",
|
||||
"OR SUB": "OR SUB",
|
||||
"Today": "Aujourd'hui",
|
||||
"Yesterday": "Hier",
|
||||
"Recent 7 days": "7 derniers jours",
|
||||
@@ -1750,6 +1752,7 @@
|
||||
"Remove Query": "Remove Query",
|
||||
"Modify Query Name": "Modify Query Name",
|
||||
"Add Condition": "Add Condition",
|
||||
"Add Sub Condition": "Add Sub Condition",
|
||||
"Remove Condition": "Remove Condition",
|
||||
"No conditions defined. All transactions will match.": "No conditions defined. All transactions will match.",
|
||||
"Unable to retrieve explorer list": "Unable to retrieve explorer list",
|
||||
|
||||
@@ -1517,6 +1517,8 @@
|
||||
"WHERE": "WHERE",
|
||||
"AND": "AND",
|
||||
"OR": "OR",
|
||||
"AND SUB": "AND SUB",
|
||||
"OR SUB": "OR SUB",
|
||||
"Today": "Oggi",
|
||||
"Yesterday": "Ieri",
|
||||
"Recent 7 days": "Ultimi 7 giorni",
|
||||
@@ -1750,6 +1752,7 @@
|
||||
"Remove Query": "Remove Query",
|
||||
"Modify Query Name": "Modify Query Name",
|
||||
"Add Condition": "Add Condition",
|
||||
"Add Sub Condition": "Add Sub Condition",
|
||||
"Remove Condition": "Remove Condition",
|
||||
"No conditions defined. All transactions will match.": "No conditions defined. All transactions will match.",
|
||||
"Unable to retrieve explorer list": "Unable to retrieve explorer list",
|
||||
|
||||
@@ -1517,6 +1517,8 @@
|
||||
"WHERE": "WHERE",
|
||||
"AND": "AND",
|
||||
"OR": "OR",
|
||||
"AND SUB": "AND SUB",
|
||||
"OR SUB": "OR SUB",
|
||||
"Today": "今日",
|
||||
"Yesterday": "昨日",
|
||||
"Recent 7 days": "直近7日間",
|
||||
@@ -1750,6 +1752,7 @@
|
||||
"Remove Query": "Remove Query",
|
||||
"Modify Query Name": "Modify Query Name",
|
||||
"Add Condition": "Add Condition",
|
||||
"Add Sub Condition": "Add Sub Condition",
|
||||
"Remove Condition": "Remove Condition",
|
||||
"No conditions defined. All transactions will match.": "No conditions defined. All transactions will match.",
|
||||
"Unable to retrieve explorer list": "Unable to retrieve explorer list",
|
||||
|
||||
@@ -1517,6 +1517,8 @@
|
||||
"WHERE": "WHERE",
|
||||
"AND": "AND",
|
||||
"OR": "OR",
|
||||
"AND SUB": "AND SUB",
|
||||
"OR SUB": "OR SUB",
|
||||
"Today": "ಇಂದು",
|
||||
"Yesterday": "ನಿನ್ನೆ",
|
||||
"Recent 7 days": "ಇತ್ತೀಚಿನ 7 ದಿನಗಳು",
|
||||
@@ -1750,6 +1752,7 @@
|
||||
"Remove Query": "Remove Query",
|
||||
"Modify Query Name": "Modify Query Name",
|
||||
"Add Condition": "Add Condition",
|
||||
"Add Sub Condition": "Add Sub Condition",
|
||||
"Remove Condition": "Remove Condition",
|
||||
"No conditions defined. All transactions will match.": "No conditions defined. All transactions will match.",
|
||||
"Unable to retrieve explorer list": "Unable to retrieve explorer list",
|
||||
|
||||
@@ -1517,6 +1517,8 @@
|
||||
"WHERE": "WHERE",
|
||||
"AND": "AND",
|
||||
"OR": "OR",
|
||||
"AND SUB": "AND SUB",
|
||||
"OR SUB": "OR SUB",
|
||||
"Today": "오늘",
|
||||
"Yesterday": "어제",
|
||||
"Recent 7 days": "최근 7일",
|
||||
@@ -1750,6 +1752,7 @@
|
||||
"Remove Query": "쿼리 제거",
|
||||
"Modify Query Name": "쿼리 이름 수정",
|
||||
"Add Condition": "조건 추가",
|
||||
"Add Sub Condition": "Add Sub Condition",
|
||||
"Remove Condition": "조건 제거",
|
||||
"No conditions defined. All transactions will match.": "조건이 정의되지 않았습니다. 모든 거래가 일치합니다.",
|
||||
"Unable to retrieve explorer list": "탐색기 목록을 가져올 수 없습니다",
|
||||
|
||||
@@ -1517,6 +1517,8 @@
|
||||
"WHERE": "WHERE",
|
||||
"AND": "AND",
|
||||
"OR": "OR",
|
||||
"AND SUB": "AND SUB",
|
||||
"OR SUB": "OR SUB",
|
||||
"Today": "Vandaag",
|
||||
"Yesterday": "Gisteren",
|
||||
"Recent 7 days": "Afgelopen 7 dagen",
|
||||
@@ -1750,6 +1752,7 @@
|
||||
"Remove Query": "Remove Query",
|
||||
"Modify Query Name": "Modify Query Name",
|
||||
"Add Condition": "Add Condition",
|
||||
"Add Sub Condition": "Add Sub Condition",
|
||||
"Remove Condition": "Remove Condition",
|
||||
"No conditions defined. All transactions will match.": "No conditions defined. All transactions will match.",
|
||||
"Unable to retrieve explorer list": "Unable to retrieve explorer list",
|
||||
|
||||
@@ -1517,6 +1517,8 @@
|
||||
"WHERE": "WHERE",
|
||||
"AND": "AND",
|
||||
"OR": "OR",
|
||||
"AND SUB": "AND SUB",
|
||||
"OR SUB": "OR SUB",
|
||||
"Today": "Hoje",
|
||||
"Yesterday": "Ontem",
|
||||
"Recent 7 days": "Últimos 7 dias",
|
||||
@@ -1750,6 +1752,7 @@
|
||||
"Remove Query": "Remove Query",
|
||||
"Modify Query Name": "Modify Query Name",
|
||||
"Add Condition": "Add Condition",
|
||||
"Add Sub Condition": "Add Sub Condition",
|
||||
"Remove Condition": "Remove Condition",
|
||||
"No conditions defined. All transactions will match.": "No conditions defined. All transactions will match.",
|
||||
"Unable to retrieve explorer list": "Unable to retrieve explorer list",
|
||||
|
||||
@@ -1517,6 +1517,8 @@
|
||||
"WHERE": "WHERE",
|
||||
"AND": "AND",
|
||||
"OR": "OR",
|
||||
"AND SUB": "AND SUB",
|
||||
"OR SUB": "OR SUB",
|
||||
"Today": "Сегодня",
|
||||
"Yesterday": "Вчера",
|
||||
"Recent 7 days": "Последние 7 дней",
|
||||
@@ -1750,6 +1752,7 @@
|
||||
"Remove Query": "Удалить запрос",
|
||||
"Modify Query Name": "Изменить название запроса",
|
||||
"Add Condition": "Добавить условие",
|
||||
"Add Sub Condition": "Add Sub Condition",
|
||||
"Remove Condition": "Удалить условие",
|
||||
"No conditions defined. All transactions will match.": "Нет условий. Подходят все транзакции.",
|
||||
"Unable to retrieve explorer list": "Не возможно получить список исследований",
|
||||
|
||||
@@ -1517,6 +1517,8 @@
|
||||
"WHERE": "KJER",
|
||||
"AND": "IN",
|
||||
"OR": "ALI",
|
||||
"AND SUB": "AND SUB",
|
||||
"OR SUB": "OR SUB",
|
||||
"Today": "Danes",
|
||||
"Yesterday": "Včeraj",
|
||||
"Recent 7 days": "Zadnjih 7 dni",
|
||||
@@ -1750,6 +1752,7 @@
|
||||
"Remove Query": "Odstrani poizvedbo",
|
||||
"Modify Query Name": "Spremeni ime poizvedbe",
|
||||
"Add Condition": "Dodaj pogoj",
|
||||
"Add Sub Condition": "Add Sub Condition",
|
||||
"Remove Condition": "Odstrani pogoj",
|
||||
"No conditions defined. All transactions will match.": "Ni določenih pogojev. Prikazane bodo vse transakcije.",
|
||||
"Unable to retrieve explorer list": "Seznama raziskovanj ni mogoče pridobiti",
|
||||
|
||||
@@ -1517,6 +1517,8 @@
|
||||
"WHERE": "எங்கே",
|
||||
"AND": "AND",
|
||||
"OR": "OR",
|
||||
"AND SUB": "AND SUB",
|
||||
"OR SUB": "OR SUB",
|
||||
"Today": "இன்று",
|
||||
"Yesterday": "நேற்று",
|
||||
"Recent 7 days": "சமீபத்திய 7 நாட்கள்",
|
||||
@@ -1750,6 +1752,7 @@
|
||||
"Remove Query": "வினவல் நீக்கு",
|
||||
"Modify Query Name": "வினவல் பெயரை மாற்று",
|
||||
"Add Condition": "நிபந்தனை சேர்",
|
||||
"Add Sub Condition": "Add Sub Condition",
|
||||
"Remove Condition": "நிபந்தனை நீக்கு",
|
||||
"No conditions defined. All transactions will match.": "நிபந்தனைகள் வரையறுக்கப்படவில்லை. அனைத்து பரிவர்த்தனைகளும் பொருந்தும்.",
|
||||
"Unable to retrieve explorer list": "ஆய்வுக்கருவி பட்டியல் பெற முடியவில்லை",
|
||||
|
||||
@@ -1517,6 +1517,8 @@
|
||||
"WHERE": "WHERE",
|
||||
"AND": "AND",
|
||||
"OR": "OR",
|
||||
"AND SUB": "AND SUB",
|
||||
"OR SUB": "OR SUB",
|
||||
"Today": "วันนี้",
|
||||
"Yesterday": "เมื่อวาน",
|
||||
"Recent 7 days": "7 วันที่ผ่านมา",
|
||||
@@ -1750,6 +1752,7 @@
|
||||
"Remove Query": "Remove Query",
|
||||
"Modify Query Name": "Modify Query Name",
|
||||
"Add Condition": "Add Condition",
|
||||
"Add Sub Condition": "Add Sub Condition",
|
||||
"Remove Condition": "Remove Condition",
|
||||
"No conditions defined. All transactions will match.": "No conditions defined. All transactions will match.",
|
||||
"Unable to retrieve explorer list": "Unable to retrieve explorer list",
|
||||
|
||||
@@ -1517,6 +1517,8 @@
|
||||
"WHERE": "WHERE",
|
||||
"AND": "AND",
|
||||
"OR": "OR",
|
||||
"AND SUB": "AND SUB",
|
||||
"OR SUB": "OR SUB",
|
||||
"Today": "Bugün",
|
||||
"Yesterday": "Dün",
|
||||
"Recent 7 days": "Son 7 gün",
|
||||
@@ -1750,6 +1752,7 @@
|
||||
"Remove Query": "Remove Query",
|
||||
"Modify Query Name": "Modify Query Name",
|
||||
"Add Condition": "Add Condition",
|
||||
"Add Sub Condition": "Add Sub Condition",
|
||||
"Remove Condition": "Remove Condition",
|
||||
"No conditions defined. All transactions will match.": "No conditions defined. All transactions will match.",
|
||||
"Unable to retrieve explorer list": "Unable to retrieve explorer list",
|
||||
|
||||
@@ -1517,6 +1517,8 @@
|
||||
"WHERE": "WHERE",
|
||||
"AND": "AND",
|
||||
"OR": "OR",
|
||||
"AND SUB": "AND SUB",
|
||||
"OR SUB": "OR SUB",
|
||||
"Today": "Сьогодні",
|
||||
"Yesterday": "Вчора",
|
||||
"Recent 7 days": "Останні 7 днів",
|
||||
@@ -1750,6 +1752,7 @@
|
||||
"Remove Query": "Remove Query",
|
||||
"Modify Query Name": "Modify Query Name",
|
||||
"Add Condition": "Add Condition",
|
||||
"Add Sub Condition": "Add Sub Condition",
|
||||
"Remove Condition": "Remove Condition",
|
||||
"No conditions defined. All transactions will match.": "No conditions defined. All transactions will match.",
|
||||
"Unable to retrieve explorer list": "Unable to retrieve explorer list",
|
||||
|
||||
@@ -1517,6 +1517,8 @@
|
||||
"WHERE": "WHERE",
|
||||
"AND": "AND",
|
||||
"OR": "OR",
|
||||
"AND SUB": "AND SUB",
|
||||
"OR SUB": "OR SUB",
|
||||
"Today": "Hôm nay",
|
||||
"Yesterday": "Hôm qua",
|
||||
"Recent 7 days": "7 ngày gần đây",
|
||||
@@ -1750,6 +1752,7 @@
|
||||
"Remove Query": "Remove Query",
|
||||
"Modify Query Name": "Modify Query Name",
|
||||
"Add Condition": "Add Condition",
|
||||
"Add Sub Condition": "Add Sub Condition",
|
||||
"Remove Condition": "Remove Condition",
|
||||
"No conditions defined. All transactions will match.": "No conditions defined. All transactions will match.",
|
||||
"Unable to retrieve explorer list": "Unable to retrieve explorer list",
|
||||
|
||||
@@ -1517,6 +1517,8 @@
|
||||
"WHERE": "条件",
|
||||
"AND": "与",
|
||||
"OR": "或",
|
||||
"AND SUB": "与子条件",
|
||||
"OR SUB": "或子条件",
|
||||
"Today": "今天",
|
||||
"Yesterday": "昨天",
|
||||
"Recent 7 days": "最近7天",
|
||||
@@ -1750,6 +1752,7 @@
|
||||
"Remove Query": "移除查询",
|
||||
"Modify Query Name": "修改查询名称",
|
||||
"Add Condition": "添加条件",
|
||||
"Add Sub Condition": "添加子条件",
|
||||
"Remove Condition": "移除条件",
|
||||
"No conditions defined. All transactions will match.": "没有定义条件。所有交易都会匹配。",
|
||||
"Unable to retrieve explorer list": "无法获取探索列表",
|
||||
|
||||
@@ -1517,6 +1517,8 @@
|
||||
"WHERE": "條件",
|
||||
"AND": "且",
|
||||
"OR": "或",
|
||||
"AND SUB": "且子條件",
|
||||
"OR SUB": "或子條件",
|
||||
"Today": "今天",
|
||||
"Yesterday": "昨天",
|
||||
"Recent 7 days": "最近7天",
|
||||
@@ -1750,6 +1752,7 @@
|
||||
"Remove Query": "移除查詢",
|
||||
"Modify Query Name": "修改查詢名稱",
|
||||
"Add Condition": "新增條件",
|
||||
"Add Sub Condition": "新增子條件",
|
||||
"Remove Condition": "移除條件",
|
||||
"No conditions defined. All transactions will match.": "沒有定義條件。所有交易都符合。",
|
||||
"Unable to retrieve explorer list": "無法取得探索清單",
|
||||
|
||||
+126
-9
@@ -4,7 +4,9 @@ import { AccountType } from '@/core/account.ts';
|
||||
import { TransactionType } from '@/core/transaction.ts';
|
||||
import { ChartSortingType } from '@/core/statistics.ts';
|
||||
import {
|
||||
type TransactionExplorerSubConditionStartRelation,
|
||||
TransactionExplorerConditionRelation,
|
||||
TransactionExplorerSubConditionStartRelationPlaceholder,
|
||||
TransactionExplorerConditionRelationPriority,
|
||||
TransactionExplorerConditionFieldType,
|
||||
TransactionExplorerConditionField,
|
||||
@@ -339,6 +341,10 @@ export class TransactionExplorerQuery {
|
||||
);
|
||||
}
|
||||
|
||||
public addSubConditionEnd(): TransactionExplorerConditionWithRelation {
|
||||
return new TransactionExplorerConditionWithRelation(new TransactionExplorerUndefinedCondition(), TransactionExplorerConditionRelation.SubEnd);
|
||||
}
|
||||
|
||||
public match(transaction: TransactionInsightDataItem): boolean {
|
||||
if (!this.conditions || this.conditions.length < 1) {
|
||||
return true;
|
||||
@@ -434,7 +440,7 @@ export class TransactionExplorerQuery {
|
||||
return finalTokens;
|
||||
}
|
||||
|
||||
const operatorStack: TransactionExplorerConditionRelation[] = [];
|
||||
const operatorStack: (TransactionExplorerConditionRelation | TransactionExplorerSubConditionStartRelation)[] = [];
|
||||
const firstCondition = this.conditions[0] as TransactionExplorerConditionWithRelation;
|
||||
|
||||
if (firstCondition.relation !== TransactionExplorerConditionRelation.First) {
|
||||
@@ -452,10 +458,52 @@ export class TransactionExplorerQuery {
|
||||
throw new Error('only the first condition can have relation "first"');
|
||||
}
|
||||
|
||||
const currentOperator = item.relation;
|
||||
if (item.relation === TransactionExplorerConditionRelation.SubEnd) {
|
||||
while (operatorStack.length > 0) {
|
||||
const topOperator = operatorStack.pop();
|
||||
|
||||
if (topOperator === TransactionExplorerSubConditionStartRelationPlaceholder) {
|
||||
break;
|
||||
}
|
||||
|
||||
const isAndOrOperator = topOperator === TransactionExplorerConditionRelation.And || topOperator === TransactionExplorerConditionRelation.Or;
|
||||
|
||||
if (isAndOrOperator) {
|
||||
finalTokens.push(topOperator);
|
||||
} else {
|
||||
throw new Error('invalid operator in stack');
|
||||
}
|
||||
}
|
||||
} else { // And, Or, AndSub, OrSub
|
||||
let currentOperator: TransactionExplorerConditionRelation.And | TransactionExplorerConditionRelation.Or;
|
||||
let startNewSubCondition = false;
|
||||
|
||||
switch (item.relation) {
|
||||
case TransactionExplorerConditionRelation.AndSub:
|
||||
currentOperator = TransactionExplorerConditionRelation.And;
|
||||
startNewSubCondition = true;
|
||||
break;
|
||||
case TransactionExplorerConditionRelation.OrSub:
|
||||
currentOperator = TransactionExplorerConditionRelation.Or;
|
||||
startNewSubCondition = true;
|
||||
break;
|
||||
case TransactionExplorerConditionRelation.And:
|
||||
currentOperator = item.relation;
|
||||
break;
|
||||
case TransactionExplorerConditionRelation.Or:
|
||||
currentOperator = item.relation;
|
||||
break;
|
||||
default:
|
||||
throw new Error('invalid operator in stack');
|
||||
}
|
||||
|
||||
while (operatorStack.length > 0) {
|
||||
const topOperator = operatorStack[operatorStack.length - 1];
|
||||
|
||||
if (topOperator === TransactionExplorerSubConditionStartRelationPlaceholder) {
|
||||
break;
|
||||
}
|
||||
|
||||
const isAndOrOperator = topOperator === TransactionExplorerConditionRelation.And || topOperator === TransactionExplorerConditionRelation.Or;
|
||||
|
||||
if (isAndOrOperator && TransactionExplorerConditionRelationPriority[topOperator] >= TransactionExplorerConditionRelationPriority[currentOperator]) {
|
||||
@@ -467,8 +515,14 @@ export class TransactionExplorerQuery {
|
||||
}
|
||||
|
||||
operatorStack.push(currentOperator);
|
||||
|
||||
if (startNewSubCondition) {
|
||||
operatorStack.push(TransactionExplorerSubConditionStartRelationPlaceholder);
|
||||
}
|
||||
|
||||
finalTokens.push(item.condition);
|
||||
}
|
||||
}
|
||||
|
||||
while (operatorStack.length > 0) {
|
||||
const topOperator = operatorStack.pop();
|
||||
@@ -483,6 +537,25 @@ export class TransactionExplorerQuery {
|
||||
return finalTokens;
|
||||
}
|
||||
|
||||
public getConditionNestingDepths(): number[] {
|
||||
const depths: number[] = [];
|
||||
let depth = 0;
|
||||
|
||||
for (const item of this.conditions) {
|
||||
if (item.relation === TransactionExplorerConditionRelation.SubEnd) {
|
||||
depth--;
|
||||
depths.push(depth);
|
||||
} else if (item.relation === TransactionExplorerConditionRelation.AndSub || item.relation === TransactionExplorerConditionRelation.OrSub) {
|
||||
depth++;
|
||||
depths.push(depth);
|
||||
} else {
|
||||
depths.push(depth);
|
||||
}
|
||||
}
|
||||
|
||||
return depths;
|
||||
}
|
||||
|
||||
public clone(newId: string): TransactionExplorerQuery {
|
||||
const clonedConditions: TransactionExplorerConditionWithRelation[] = [];
|
||||
|
||||
@@ -527,6 +600,7 @@ export class TransactionExplorerQuery {
|
||||
const id: string = idFieldValue;
|
||||
const name: string = nameFieldValue;
|
||||
const conditions: TransactionExplorerConditionWithRelation[] = [];
|
||||
let conditionDepth = 0;
|
||||
|
||||
for (const [item, index] of itemAndIndex(conditionsFieldValue)) {
|
||||
const condition = TransactionExplorerConditionWithRelation.parse(item);
|
||||
@@ -541,9 +615,20 @@ export class TransactionExplorerQuery {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (condition.relation === TransactionExplorerConditionRelation.AndSub ||
|
||||
condition.relation === TransactionExplorerConditionRelation.OrSub) {
|
||||
conditionDepth++;
|
||||
} else if (condition.relation === TransactionExplorerConditionRelation.SubEnd) {
|
||||
conditionDepth--;
|
||||
}
|
||||
|
||||
conditions.push(condition);
|
||||
}
|
||||
|
||||
if (conditionDepth !== 0) {
|
||||
return null; // unbalanced parentheses
|
||||
}
|
||||
|
||||
return new TransactionExplorerQuery(id, name, conditions);
|
||||
}
|
||||
}
|
||||
@@ -609,6 +694,12 @@ export class TransactionExplorerConditionWithRelation {
|
||||
}
|
||||
|
||||
public toJsonObject(): unknown {
|
||||
if (this.relation === TransactionExplorerConditionRelation.SubEnd) {
|
||||
return {
|
||||
relation: this.relation
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
condition: {
|
||||
field: this.condition.field,
|
||||
@@ -620,12 +711,21 @@ export class TransactionExplorerConditionWithRelation {
|
||||
}
|
||||
|
||||
public static parse(data: unknown): TransactionExplorerConditionWithRelation | null {
|
||||
if (typeof data !== 'object' || !data || !('condition' in data) || !('relation' in data)) {
|
||||
if (typeof data !== 'object' || !data || !('relation' in data)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const relation = data['relation'];
|
||||
let condition: TransactionExplorerCondition | null = null;
|
||||
|
||||
if (relation === TransactionExplorerConditionRelation.First ||
|
||||
relation === TransactionExplorerConditionRelation.And || relation === TransactionExplorerConditionRelation.Or ||
|
||||
relation === TransactionExplorerConditionRelation.AndSub || relation === TransactionExplorerConditionRelation.OrSub) {
|
||||
if (!('condition' in data)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const conditionObject = data['condition'];
|
||||
const relation = data['relation'];
|
||||
|
||||
if (typeof conditionObject !== 'object' || !conditionObject || !('field' in conditionObject) || !('operator' in conditionObject) || !('value' in conditionObject) || typeof relation !== 'string') {
|
||||
return null;
|
||||
@@ -635,8 +735,6 @@ export class TransactionExplorerConditionWithRelation {
|
||||
const conditionOperator = conditionObject['operator'] as TransactionExplorerConditionOperatorType;
|
||||
const conditionValue = conditionObject['value'];
|
||||
|
||||
let condition: TransactionExplorerCondition | null = null;
|
||||
|
||||
switch (conditionField) {
|
||||
case TransactionExplorerConditionField.TransactionType.value:
|
||||
if (conditionOperator === TransactionExplorerConditionOperatorType.In && Array.isArray(conditionValue)) {
|
||||
@@ -691,12 +789,13 @@ export class TransactionExplorerConditionWithRelation {
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (condition === null) {
|
||||
} else if (relation === TransactionExplorerConditionRelation.SubEnd) {
|
||||
condition = new TransactionExplorerUndefinedCondition();
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (relation !== TransactionExplorerConditionRelation.First && relation !== TransactionExplorerConditionRelation.And && relation !== TransactionExplorerConditionRelation.Or) {
|
||||
if (condition === null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -714,6 +813,24 @@ export interface TransactionExplorerCondition<T = TransactionExplorerConditionFi
|
||||
toExpression(allCategoriesMap: Record<string, TransactionCategory>, allAccountsMap: Record<string, Account>, allTagsMap: Record<string, TransactionTag>): string;
|
||||
}
|
||||
|
||||
export class TransactionExplorerUndefinedCondition implements TransactionExplorerCondition {
|
||||
public readonly field = TransactionExplorerConditionFieldType.Undefined;
|
||||
public readonly operator = TransactionExplorerConditionOperatorType.Equals;
|
||||
public value = '';
|
||||
|
||||
public getValueForStore(): string {
|
||||
return this.value;
|
||||
}
|
||||
|
||||
public match(transaction: TransactionInsightDataItem): boolean {
|
||||
return !!transaction;
|
||||
}
|
||||
|
||||
public toExpression(): string {
|
||||
return '';
|
||||
}
|
||||
}
|
||||
|
||||
export class TransactionExplorerTransactionTypeCondition implements TransactionExplorerCondition<TransactionExplorerConditionFieldType.TransactionType, number[]> {
|
||||
public static readonly supportedOperators: PartialRecord<TransactionExplorerConditionOperatorType, true> = {
|
||||
[TransactionExplorerConditionOperatorType.In]: true
|
||||
|
||||
@@ -98,11 +98,13 @@
|
||||
|
||||
<div v-else-if="element.conditions && element.conditions.length > 0 && !showExpression[element.id]">
|
||||
<div :key="conditionIndex" v-for="(conditionWithRelation, conditionIndex) in element.conditions">
|
||||
<div class="d-flex overflow-x-auto align-center gap-2 mb-4">
|
||||
<div class="d-flex overflow-x-auto align-center gap-2 mb-4"
|
||||
:style="getConditionStyle(element, conditionIndex)"
|
||||
v-if="conditionWithRelation.relation !== TransactionExplorerConditionRelation.SubEnd">
|
||||
<v-select
|
||||
disabled
|
||||
class="flex-0-0"
|
||||
width="120px"
|
||||
width="140px"
|
||||
density="compact"
|
||||
item-title="displayName"
|
||||
item-value="value"
|
||||
@@ -113,16 +115,19 @@
|
||||
|
||||
<v-select
|
||||
class="flex-0-0"
|
||||
width="120px"
|
||||
width="140px"
|
||||
density="compact"
|
||||
item-title="displayName"
|
||||
item-value="value"
|
||||
:disabled="loading || disabled || !!editingQuery"
|
||||
:items="[
|
||||
{ value: TransactionExplorerConditionRelation.And, displayName: tt('AND') },
|
||||
{ value: TransactionExplorerConditionRelation.Or, displayName: tt('OR') }
|
||||
{ value: TransactionExplorerConditionRelation.Or, displayName: tt('OR') },
|
||||
{ value: TransactionExplorerConditionRelation.AndSub, displayName: tt('AND SUB') },
|
||||
{ value: TransactionExplorerConditionRelation.OrSub, displayName: tt('OR SUB') }
|
||||
]"
|
||||
v-model="conditionWithRelation.relation"
|
||||
:model-value="conditionWithRelation.relation"
|
||||
@update:model-value="updateItemRelation(element, conditionIndex, $event)"
|
||||
v-else-if="conditionIndex >= 1"
|
||||
/>
|
||||
|
||||
@@ -335,6 +340,16 @@
|
||||
<v-tooltip activator="parent">{{ tt('Remove Condition') }}</v-tooltip>
|
||||
</v-btn>
|
||||
</div>
|
||||
<div class="d-flex overflow-x-auto align-center gap-2 mb-4"
|
||||
:style="getConditionStyle(element, conditionIndex)"
|
||||
v-if="conditionWithRelation.relation === TransactionExplorerConditionRelation.SubEnd">
|
||||
<v-btn class="px-2" density="comfortable" color="primary" variant="text" size="small"
|
||||
:prepend-icon="mdiPlus"
|
||||
:disabled="loading || disabled || !!editingQuery"
|
||||
@click="addSubCondition(element, conditionIndex)">
|
||||
{{ tt('Add Sub Condition') }}
|
||||
</v-btn>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div v-else-if="element.conditions && element.conditions.length > 0 && showExpression[element.id]">
|
||||
@@ -541,6 +556,25 @@ function getFilteredTransactionCategoriesDisplayContent(filterTransactionCategor
|
||||
return joinMultiText(selectedCategoryNames);
|
||||
}
|
||||
|
||||
function getConditionStyle(query: TransactionExplorerQuery, conditionIndex: number): Record<string, string> {
|
||||
const style: Record<string, string> = {};
|
||||
const depths = query.getConditionNestingDepths();
|
||||
const item = query.conditions[conditionIndex];
|
||||
let depth = 0;
|
||||
|
||||
if (item && item.relation === TransactionExplorerConditionRelation.SubEnd) {
|
||||
depth = depths[conditionIndex - 1] ?? 0;
|
||||
} else {
|
||||
depth = depths[conditionIndex] ?? 0;
|
||||
}
|
||||
|
||||
if (depth > 0) {
|
||||
style['margin-inline-start'] = (depth * 1.5) + 'rem';
|
||||
}
|
||||
|
||||
return style;
|
||||
}
|
||||
|
||||
function addQuery(): void {
|
||||
queries.value.push(TransactionExplorerQuery.create(generateRandomUUID()));
|
||||
}
|
||||
@@ -584,16 +618,88 @@ function addCondition(query: TransactionExplorerQuery): void {
|
||||
query.conditions.push(newCondition);
|
||||
}
|
||||
|
||||
function addSubCondition(query: TransactionExplorerQuery, subEndIndex: number): void {
|
||||
const newCondition = query.addNewCondition(TransactionExplorerConditionField.TransactionType, false);
|
||||
query.conditions.splice(subEndIndex, 0, newCondition);
|
||||
}
|
||||
|
||||
function removeCondition(query: TransactionExplorerQuery, conditionIndex: number): void {
|
||||
const item = query.conditions[conditionIndex];
|
||||
|
||||
if (!item || item.relation === TransactionExplorerConditionRelation.SubEnd) {
|
||||
return;
|
||||
}
|
||||
|
||||
query.conditions.splice(conditionIndex, 1);
|
||||
|
||||
if (conditionIndex === 0 && query.conditions.length > 0) {
|
||||
const newFirstCondition = query.conditions[0];
|
||||
|
||||
if (newFirstCondition) {
|
||||
if (newFirstCondition.relation === TransactionExplorerConditionRelation.AndSub || newFirstCondition.relation === TransactionExplorerConditionRelation.OrSub) {
|
||||
removeSubCondition(query, conditionIndex + 1);
|
||||
}
|
||||
|
||||
newFirstCondition.relation = TransactionExplorerConditionRelation.First;
|
||||
}
|
||||
}
|
||||
|
||||
const oldStartSubCondition = item.relation === TransactionExplorerConditionRelation.AndSub || item.relation === TransactionExplorerConditionRelation.OrSub;
|
||||
|
||||
if (oldStartSubCondition && conditionIndex < query.conditions.length && query.conditions[conditionIndex]) {
|
||||
const nextItem = query.conditions[conditionIndex];
|
||||
|
||||
if (nextItem.relation === TransactionExplorerConditionRelation.SubEnd) {
|
||||
query.conditions.splice(conditionIndex, 1);
|
||||
} else if (nextItem.relation === TransactionExplorerConditionRelation.AndSub || nextItem.relation === TransactionExplorerConditionRelation.OrSub) {
|
||||
nextItem.relation = item.relation;
|
||||
removeSubCondition(query, conditionIndex);
|
||||
} else {
|
||||
nextItem.relation = item.relation;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function removeSubCondition(query: TransactionExplorerQuery, conditionIndex: number): void {
|
||||
let depth = 1;
|
||||
|
||||
for (let i = conditionIndex + 1; i < query.conditions.length; i++) {
|
||||
const currentCondition = query.conditions[i];
|
||||
|
||||
if (!currentCondition) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (currentCondition.relation === TransactionExplorerConditionRelation.AndSub || currentCondition.relation === TransactionExplorerConditionRelation.OrSub) {
|
||||
depth++;
|
||||
} else if (currentCondition.relation === TransactionExplorerConditionRelation.SubEnd) {
|
||||
depth--;
|
||||
|
||||
if (depth === 0) {
|
||||
query.conditions.splice(i, 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function updateItemRelation(query: TransactionExplorerQuery, conditionIndex: number, value: TransactionExplorerConditionRelation): void {
|
||||
const item = query.conditions[conditionIndex];
|
||||
|
||||
if (!item || item.relation === TransactionExplorerConditionRelation.SubEnd) {
|
||||
return;
|
||||
}
|
||||
|
||||
const oldStartSubCondition = item.relation === TransactionExplorerConditionRelation.AndSub || item.relation === TransactionExplorerConditionRelation.OrSub;
|
||||
const newStartSubCondition = value === TransactionExplorerConditionRelation.AndSub || value === TransactionExplorerConditionRelation.OrSub;
|
||||
|
||||
item.relation = value;
|
||||
|
||||
if (!oldStartSubCondition && newStartSubCondition) {
|
||||
query.conditions.splice(conditionIndex + 1, 0, query.addSubConditionEnd());
|
||||
} else if (oldStartSubCondition && !newStartSubCondition) {
|
||||
removeSubCondition(query, conditionIndex);
|
||||
}
|
||||
}
|
||||
|
||||
function updateConditionField(query: TransactionExplorerQuery, conditionIndex: number, newField: TransactionExplorerConditionField | undefined): void {
|
||||
|
||||
Reference in New Issue
Block a user