diff --git a/resources/js/components/automation-rules/automation-rules-dialog.tsx b/resources/js/components/automation-rules/automation-rules-dialog.tsx index 86dfb91c..87835ad9 100644 --- a/resources/js/components/automation-rules/automation-rules-dialog.tsx +++ b/resources/js/components/automation-rules/automation-rules-dialog.tsx @@ -19,7 +19,6 @@ import { useMemo, useState } from 'react'; import { CreateAutomationRuleDialog } from '@/components/automation-rules/create-automation-rule-dialog'; import { DeleteAutomationRuleDialog } from '@/components/automation-rules/delete-automation-rule-dialog'; import { EditAutomationRuleDialog } from '@/components/automation-rules/edit-automation-rule-dialog'; -import { LabelBadges } from '@/components/shared/label-combobox'; import { Badge } from '@/components/ui/badge'; import { Button } from '@/components/ui/button'; import { @@ -52,10 +51,8 @@ import { TableHeader, TableRow, } from '@/components/ui/table'; -import { useEncryptionKey } from '@/contexts/encryption-key-context'; import { type AutomationRule, getRuleActions } from '@/types/automation-rule'; import { type Category, getCategoryColorClasses } from '@/types/category'; -import { type Label } from '@/types/label'; import { __ } from '@/utils/i18n'; interface AutomationRulesDialogProps { @@ -66,11 +63,9 @@ interface AutomationRulesDialogProps { function AutomationRuleActions({ rule, categories, - labels, }: { rule: AutomationRule; categories: Category[]; - labels: Label[]; }) { const [editOpen, setEditOpen] = useState(false); const [deleteOpen, setDeleteOpen] = useState(false); @@ -105,7 +100,6 @@ function AutomationRuleActions({ @@ -121,11 +115,9 @@ function AutomationRuleActions({ function AutomationRuleRow({ row, categories, - labels, }: { row: Row; categories: Category[]; - labels: Label[]; }) { const rule = row.original; const [editOpen, setEditOpen] = useState(false); @@ -171,7 +163,6 @@ function AutomationRuleRow({ @@ -188,14 +179,12 @@ export function AutomationRulesDialog({ open, onOpenChange, }: AutomationRulesDialogProps) { - const { isKeySet } = useEncryptionKey(); const { automationRules: rawRules } = usePage<{ automationRules: AutomationRule[]; }>().props; - // Get categories and labels from globally shared Inertia data + // Get categories from globally shared Inertia data const categories = usePage().props.categories as Category[]; - const labels = usePage().props.labels as Label[]; const rules = useMemo( () => rawRules.map((rule) => ({ @@ -207,29 +196,13 @@ export function AutomationRulesDialog({ })), [rawRules], ); - const [sorting, setSorting] = useState([ - { - id: 'priority', - desc: false, - }, - ]); + const [sorting, setSorting] = useState([]); const [columnFilters, setColumnFilters] = useState([]); const [columnVisibility, setColumnVisibility] = useState( {}, ); const columns: ColumnDef[] = [ - { - accessorKey: 'priority', - header: __('Priority'), - cell: ({ row }) => { - return ( -
- {row.getValue('priority')} -
- ); - }, - }, { accessorKey: 'title', header: __('Title'), @@ -265,14 +238,6 @@ export function AutomationRulesDialog({ {actions.category.name} )} - {actions.hasLabels && actions.labels && ( - - )} - {actions.hasNote && ( - - + note - - )} ); } @@ -294,13 +259,9 @@ export function AutomationRulesDialog({ ); } - if (actions.type === 'labels' && actions.labels) { - return ; - } - return ( - {__('Add note')} + {__('No action set')} ); }, @@ -312,7 +273,6 @@ export function AutomationRulesDialog({ ), }, @@ -362,11 +322,7 @@ export function AutomationRulesDialog({ } className="max-w-sm" /> - +
@@ -400,7 +356,6 @@ export function AutomationRulesDialog({ key={row.id} row={row} categories={categories} - labels={labels} /> )) ) : ( diff --git a/resources/js/components/automation-rules/create-automation-rule-dialog.tsx b/resources/js/components/automation-rules/create-automation-rule-dialog.tsx index 0b114312..4bc68778 100644 --- a/resources/js/components/automation-rules/create-automation-rule-dialog.tsx +++ b/resources/js/components/automation-rules/create-automation-rule-dialog.tsx @@ -1,7 +1,6 @@ import { store } from '@/actions/App/Http/Controllers/Settings/AutomationRuleController'; import { RuleBuilder } from '@/components/automation-rules/rule-builder'; import { CategoryCombobox } from '@/components/shared/category-combobox'; -import { LabelCombobox } from '@/components/shared/label-combobox'; import { Button } from '@/components/ui/button'; import { CreateButton } from '@/components/ui/create-button'; import { @@ -21,33 +20,28 @@ import { type RuleStructure, } from '@/lib/rule-builder-utils'; import type { Category } from '@/types/category'; -import type { Label } from '@/types/label'; import { __ } from '@/utils/i18n'; import { router } from '@inertiajs/react'; import { useState } from 'react'; interface CreateAutomationRuleDialogProps { categories: Category[]; - labels: Label[]; disabled?: boolean; onSuccess?: () => void; } export function CreateAutomationRuleDialog({ categories, - labels, disabled = false, onSuccess, }: CreateAutomationRuleDialogProps) { const [open, setOpen] = useState(false); const [title, setTitle] = useState(''); - const [priority, setPriority] = useState('10'); const [ruleStructure, setRuleStructure] = useState({ groups: [createEmptyGroup()], groupOperator: 'or', }); const [categoryId, setCategoryId] = useState(''); - const [selectedLabelIds, setSelectedLabelIds] = useState([]); const [isSubmitting, setIsSubmitting] = useState(false); const [errors, setErrors] = useState>({}); @@ -68,10 +62,10 @@ export function CreateAutomationRuleDialog({ return; } - if (!categoryId && selectedLabelIds.length === 0) { + if (!categoryId) { setErrors((prev) => ({ ...prev, - action_category_id: 'At least one action is required', + action_category_id: 'A category is required', })); return; } @@ -85,13 +79,12 @@ export function CreateAutomationRuleDialog({ store().url, { title: title.trim(), - priority: parseInt(priority, 10), + priority: 0, rules_json: JSON.stringify(jsonLogic), - action_category_id: categoryId || null, + action_category_id: categoryId, action_note: null, action_note_iv: null, - action_label_ids: - selectedLabelIds.length > 0 ? selectedLabelIds : null, + action_label_ids: null, }, { preserveState: true, @@ -99,13 +92,11 @@ export function CreateAutomationRuleDialog({ onSuccess: () => { setOpen(false); setTitle(''); - setPriority('10'); setRuleStructure({ groups: [createEmptyGroup()], groupOperator: 'and', }); setCategoryId(''); - setSelectedLabelIds([]); setErrors({}); onSuccess?.(); }, @@ -135,7 +126,7 @@ export function CreateAutomationRuleDialog({ {__('Create Automation Rule')} {__( - 'Create a rule to automatically categorize transactions\n and add labels.', + 'Create a rule to automatically categorize transactions.', )} @@ -157,30 +148,6 @@ export function CreateAutomationRuleDialog({ )}
-
- - {__('Priority')} - - setPriority(e.target.value)} - placeholder="10" - required - /> - -

- {__('Lower numbers execute first')} -

- {errors.priority && ( -

- {errors.priority} -

- )} -
-

{__('Actions')}

-

- {__('At least one action is required')} -

@@ -202,40 +166,18 @@ export function CreateAutomationRuleDialog({ value={categoryId} onValueChange={setCategoryId} categories={categories} - placeholder={__( - 'Select a category (optional)', - )} + placeholder={__('Select a category')} showUncategorized={false} data-testid="action-category-select" />
-
- {__('Add Labels')} -
- -
-
- {errors.action_category_id && (

{errors.action_category_id}

)} - {(errors['action_label_ids.0'] || - errors.action_label_ids) && ( -

- {errors['action_label_ids.0'] || - errors.action_label_ids} -

- )}
diff --git a/resources/js/components/automation-rules/edit-automation-rule-dialog.tsx b/resources/js/components/automation-rules/edit-automation-rule-dialog.tsx index ee123f22..b5b638e9 100644 --- a/resources/js/components/automation-rules/edit-automation-rule-dialog.tsx +++ b/resources/js/components/automation-rules/edit-automation-rule-dialog.tsx @@ -1,7 +1,6 @@ import { update } from '@/actions/App/Http/Controllers/Settings/AutomationRuleController'; import { RuleBuilder } from '@/components/automation-rules/rule-builder'; import { CategoryCombobox } from '@/components/shared/category-combobox'; -import { LabelCombobox } from '@/components/shared/label-combobox'; import { Button } from '@/components/ui/button'; import { Dialog, @@ -21,7 +20,6 @@ import { } from '@/lib/rule-builder-utils'; import type { AutomationRule } from '@/types/automation-rule'; import type { Category } from '@/types/category'; -import type { Label as LabelType } from '@/types/label'; import { __ } from '@/utils/i18n'; import { router } from '@inertiajs/react'; import { useEffect, useState } from 'react'; @@ -29,7 +27,6 @@ import { useEffect, useState } from 'react'; interface EditAutomationRuleDialogProps { rule: AutomationRule; categories: Category[]; - labels: LabelType[]; open: boolean; onOpenChange: (open: boolean) => void; onSuccess?: () => void; @@ -38,31 +35,26 @@ interface EditAutomationRuleDialogProps { export function EditAutomationRuleDialog({ rule, categories, - labels, open, onOpenChange, onSuccess, }: EditAutomationRuleDialogProps) { const [title, setTitle] = useState(''); - const [priority, setPriority] = useState('0'); const [ruleStructure, setRuleStructure] = useState({ groups: [createEmptyGroup()], groupOperator: 'and', }); const [categoryId, setCategoryId] = useState(''); - const [selectedLabelIds, setSelectedLabelIds] = useState([]); const [isSubmitting, setIsSubmitting] = useState(false); const [errors, setErrors] = useState>({}); useEffect(() => { if (rule && open) { setTitle(rule.title); - setPriority(String(rule.priority)); setRuleStructure(parseJsonLogic(rule.rules_json)); setCategoryId( rule.action_category_id ? String(rule.action_category_id) : '', ); - setSelectedLabelIds(rule.labels?.map((l) => l.id) || []); } }, [rule, open]); @@ -83,10 +75,10 @@ export function EditAutomationRuleDialog({ return; } - if (!categoryId && selectedLabelIds.length === 0) { + if (!categoryId) { setErrors((prev) => ({ ...prev, - action_category_id: 'At least one action is required', + action_category_id: 'A category is required', })); return; } @@ -100,13 +92,12 @@ export function EditAutomationRuleDialog({ update(rule.id).url, { title: title.trim(), - priority: parseInt(priority, 10), + priority: rule.priority, rules_json: JSON.stringify(jsonLogic), - action_category_id: categoryId || null, + action_category_id: categoryId, action_note: null, action_note_iv: null, - action_label_ids: - selectedLabelIds.length > 0 ? selectedLabelIds : null, + action_label_ids: null, }, { preserveState: true, @@ -137,7 +128,7 @@ export function EditAutomationRuleDialog({ {__('Edit Automation Rule')} {__( - 'Update the rule to automatically categorize transactions\n and add labels.', + 'Update the rule to automatically categorize transactions.', )} @@ -159,28 +150,6 @@ export function EditAutomationRuleDialog({ )}
-
- - setPriority(e.target.value)} - placeholder="0" - required - /> - -

- {__('Lower numbers execute first')} -

- {errors.priority && ( -

- {errors.priority} -

- )} -
-

{__('Actions')}

-

- {__('At least one action is required')} -

-
- - -
- {errors.action_category_id && (

{errors.action_category_id}

)} - {(errors['action_label_ids.0'] || - errors.action_label_ids) && ( -

- {errors['action_label_ids.0'] || - errors.action_label_ids} -

- )}
diff --git a/resources/js/components/automation-rules/rule-builder.tsx b/resources/js/components/automation-rules/rule-builder.tsx index 50366081..5fc4ce0e 100644 --- a/resources/js/components/automation-rules/rule-builder.tsx +++ b/resources/js/components/automation-rules/rule-builder.tsx @@ -272,12 +272,7 @@ function ConditionRow({ condition.operator !== 'is_empty' && condition.operator !== 'is_not_empty'; - const inputType = - fieldConfig?.type === 'number' - ? 'number' - : fieldConfig?.type === 'date' - ? 'date' - : 'text'; + const inputType = fieldConfig?.type === 'number' ? 'number' : 'text'; return (
@@ -331,7 +326,7 @@ function ConditionRow({ size="sm" onClick={onRemove} disabled={!canRemove} - className="self-end sm:self-auto" + className={`self-end sm:self-auto${!canRemove ? 'opacity-30' : ''}`} > diff --git a/resources/js/components/transactions/transaction-actions-menu.tsx b/resources/js/components/transactions/transaction-actions-menu.tsx index acdd990e..a44f3233 100644 --- a/resources/js/components/transactions/transaction-actions-menu.tsx +++ b/resources/js/components/transactions/transaction-actions-menu.tsx @@ -15,6 +15,7 @@ import { } from '@/components/ui/tooltip'; import { useEncryptionKey } from '@/contexts/encryption-key-context'; import { useReEvaluateAllTransactions } from '@/hooks/use-re-evaluate-all-transactions'; + import { type Account, type Bank } from '@/types/account'; import { type AutomationRule } from '@/types/automation-rule'; import { type Category } from '@/types/category'; @@ -73,13 +74,6 @@ export function TransactionActionsMenu({ }; const handleReEvaluateAll = async () => { - if (!isKeySet) { - toast.error( - 'Please unlock your encryption key to re-evaluate transactions', - ); - return; - } - if (!transactions.length) { toast.error('No transactions to re-evaluate'); return; @@ -199,11 +193,7 @@ export function TransactionActionsMenu({ {__('Re-evaluate All Expenses')} diff --git a/resources/js/components/transactions/transaction-list.tsx b/resources/js/components/transactions/transaction-list.tsx index a3e4ab92..745fffaf 100644 --- a/resources/js/components/transactions/transaction-list.tsx +++ b/resources/js/components/transactions/transaction-list.tsx @@ -59,7 +59,6 @@ import { consoleDebug } from '@/lib/debug'; import { db } from '@/lib/dexie-db'; import { getStoredKey } from '@/lib/key-storage'; import { evaluateRules } from '@/lib/rule-engine'; -import { appendNoteIfNotPresent } from '@/lib/utils'; import { transactionSyncService } from '@/services/transaction-sync'; import { type Account, type Bank } from '@/types/account'; import { type AutomationRule } from '@/types/automation-rule'; @@ -846,18 +845,6 @@ export function TransactionList({ setIsReEvaluating(true); try { - const keyString = getStoredKey(); - if (!keyString || !isKeySet) { - consoleDebug('❌ Encryption key not set'); - console.error('Encryption key not set'); - toast.error( - 'Please unlock your encryption key to re-evaluate rules', - ); - return; - } - consoleDebug('✓ Encryption key found'); - - const key = await importKey(keyString); consoleDebug( `Found ${automationRules.length} automation rules`, ); @@ -874,7 +861,7 @@ export function TransactionList({ categories, accounts, banks, - key, + null, ); consoleDebug('Rule evaluation result:', result); @@ -884,27 +871,6 @@ export function TransactionList({ let finalNotes = transaction.notes; let finalNotesIv = transaction.notes_iv; - if (result.note && result.noteIv) { - consoleDebug('Adding note from rule'); - const decryptedRuleNote = await decrypt( - result.note, - key, - result.noteIv, - ); - const combinedNote = appendNoteIfNotPresent( - transaction.decryptedNotes, - decryptedRuleNote, - ); - - if (combinedNote !== transaction.decryptedNotes) { - finalNotes = combinedNote; - finalNotesIv = null; - consoleDebug('Combined notes with rule note'); - } else { - consoleDebug('Rule note already present, skipping'); - } - } - const updateData = { category_id: result.categoryId, notes: finalNotes, @@ -923,16 +889,7 @@ export function TransactionList({ null : null; - let decryptedNotes = transaction.decryptedNotes; - if (finalNotes && !finalNotesIv) { - decryptedNotes = finalNotes; - } else if (finalNotes && finalNotesIv) { - decryptedNotes = await decrypt( - finalNotes, - key, - finalNotesIv, - ); - } + const decryptedNotes = transaction.decryptedNotes; const updatedTransaction = { ...transaction, @@ -961,14 +918,7 @@ export function TransactionList({ consoleDebug('=== Re-evaluation complete ==='); } }, - [ - isKeySet, - categories, - accounts, - banks, - updateTransaction, - automationRules, - ], + [categories, accounts, banks, updateTransaction, automationRules], ); async function handleBulkReEvaluateRules() { @@ -983,18 +933,6 @@ export function TransactionList({ setIsReEvaluating(true); try { - const keyString = getStoredKey(); - if (!keyString || !isKeySet) { - consoleDebug('❌ Encryption key not set'); - console.error('Encryption key not set'); - toast.error( - 'Please unlock your encryption key to re-evaluate rules', - ); - return; - } - consoleDebug('✓ Encryption key found'); - - const key = await importKey(keyString); consoleDebug(`Found ${automationRules.length} automation rules`); if (automationRules.length === 0) { @@ -1031,36 +969,15 @@ export function TransactionList({ categories, accounts, banks, - key, + null, ); consoleDebug('Rule evaluation result:', result); if (result) { consoleDebug('✓ Rule matched! Applying changes...'); - let finalNotes = transaction.notes; - let finalNotesIv = transaction.notes_iv; - - if (result.note && result.noteIv) { - consoleDebug('Adding note from rule'); - const decryptedRuleNote = await decrypt( - result.note, - key, - result.noteIv, - ); - const combinedNote = appendNoteIfNotPresent( - transaction.decryptedNotes, - decryptedRuleNote, - ); - - if (combinedNote !== transaction.decryptedNotes) { - finalNotes = combinedNote; - finalNotesIv = null; - consoleDebug('Combined notes with rule note'); - } else { - consoleDebug('Rule note already present, skipping'); - } - } + const finalNotes = transaction.notes; + const finalNotesIv = transaction.notes_iv; const updateData = { category_id: result.categoryId, @@ -1080,16 +997,7 @@ export function TransactionList({ null : null; - let decryptedNotes = transaction.decryptedNotes; - if (finalNotes && !finalNotesIv) { - decryptedNotes = finalNotes; - } else if (finalNotes && finalNotesIv) { - decryptedNotes = await decrypt( - finalNotes, - key, - finalNotesIv, - ); - } + const decryptedNotes = transaction.decryptedNotes; updates.push({ transaction, diff --git a/resources/js/components/ui/amount-display.tsx b/resources/js/components/ui/amount-display.tsx index 8cf3f6b2..c0df8d03 100644 --- a/resources/js/components/ui/amount-display.tsx +++ b/resources/js/components/ui/amount-display.tsx @@ -1,4 +1,5 @@ import { useEncryptionKey } from '@/contexts/encryption-key-context'; +import { useLocale } from '@/hooks/use-locale'; import { cn } from '@/lib/utils'; import { useEffect, useMemo, useState } from 'react'; @@ -55,6 +56,7 @@ export function AmountDisplay({ highlightPositive = false, }: AmountDisplayProps) { const { isKeySet } = useEncryptionKey(); + const locale = useLocale(); const [amount, setAmount] = useState(amountInCents / 100); const isPositive = amountInCents > 0 @@ -73,13 +75,13 @@ export function AmountDisplay({ }, [amountInCents, shouldHideAmount]); const formatted = useMemo(() => { - return new Intl.NumberFormat('en-US', { + return new Intl.NumberFormat(locale, { style: 'currency', currency: currencyCode, minimumFractionDigits, maximumFractionDigits, }).format(amount); - }, [amount, currencyCode, minimumFractionDigits, maximumFractionDigits]); + }, [amount, currencyCode, minimumFractionDigits, maximumFractionDigits, locale]); const getBackgroundClass = (shouldHideAmount: boolean) => { if (!highlightPositive && !shouldHideAmount) return ''; diff --git a/resources/js/hooks/use-re-evaluate-all-transactions.tsx b/resources/js/hooks/use-re-evaluate-all-transactions.tsx index 06420f4d..f9be5cb9 100644 --- a/resources/js/hooks/use-re-evaluate-all-transactions.tsx +++ b/resources/js/hooks/use-re-evaluate-all-transactions.tsx @@ -1,7 +1,4 @@ -import { decrypt, importKey } from '@/lib/crypto'; -import { getStoredKey } from '@/lib/key-storage'; import { evaluateRules } from '@/lib/rule-engine'; -import { appendNoteIfNotPresent } from '@/lib/utils'; import { transactionSyncService } from '@/services/transaction-sync'; import type { Account, Bank } from '@/types/account'; import type { AutomationRule } from '@/types/automation-rule'; @@ -34,14 +31,6 @@ export function useReEvaluateAllTransactions() { return; } - const keyString = getStoredKey(); - if (!keyString) { - toast.error('Please unlock your encryption key'); - return; - } - - const key = await importKey(keyString); - if (!automationRules.length) { toast.error('No automation rules found'); return; @@ -71,34 +60,14 @@ export function useReEvaluateAllTransactions() { categories, accounts, banks, - key, + null, ); if (result) { - let finalNotes = transaction.notes; - let finalNotesIv = transaction.notes_iv; - - if (result.note && result.noteIv) { - const decryptedRuleNote = await decrypt( - result.note, - key, - result.noteIv, - ); - const combinedNote = appendNoteIfNotPresent( - transaction.decryptedNotes, - decryptedRuleNote, - ); - - if (combinedNote !== transaction.decryptedNotes) { - finalNotes = combinedNote; - finalNotesIv = null; - } - } - await transactionSyncService.update(transaction.id, { category_id: result.categoryId, - notes: finalNotes, - notes_iv: finalNotesIv, + notes: transaction.notes, + notes_iv: transaction.notes_iv, }); successCount++; diff --git a/resources/js/lib/rule-builder-utils.ts b/resources/js/lib/rule-builder-utils.ts index da3bfeaf..bae67cb3 100644 --- a/resources/js/lib/rule-builder-utils.ts +++ b/resources/js/lib/rule-builder-utils.ts @@ -1,4 +1,4 @@ -export type FieldType = 'string' | 'number' | 'date' | 'nullable'; +export type FieldType = 'string' | 'number'; export type Operator = | 'contains' @@ -35,21 +35,11 @@ export const FIELD_CONFIG: Record< type: 'string', operators: ['contains', 'equals'], }, - notes: { - label: 'Notes', - type: 'nullable', - operators: ['contains', 'equals', 'is_empty', 'is_not_empty'], - }, amount: { label: 'Amount', type: 'number', operators: ['equals', 'greater_than', 'less_than'], }, - transaction_date: { - label: 'Transaction Date', - type: 'date', - operators: ['equals'], - }, bank_name: { label: 'Bank Name', type: 'string', @@ -62,7 +52,7 @@ export const FIELD_CONFIG: Record< }, category: { label: 'Category', - type: 'nullable', + type: 'string', operators: ['equals', 'is_empty', 'is_not_empty'], }, }; diff --git a/resources/js/lib/rule-engine.ts b/resources/js/lib/rule-engine.ts index a34a957c..157fc2b5 100644 --- a/resources/js/lib/rule-engine.ts +++ b/resources/js/lib/rule-engine.ts @@ -102,7 +102,7 @@ export async function prepareTransactionData( accounts: Account[], banks: Bank[], categories: Category[], - encryptionKey: CryptoKey, + encryptionKey: CryptoKey | null, ): Promise { const account = accounts.find((a) => a.id === transaction.account_id); const bank = account?.bank?.id @@ -136,7 +136,7 @@ export async function evaluateRules( categories: Category[], accounts: Account[], banks: Bank[], - encryptionKey: CryptoKey, + encryptionKey: CryptoKey | null, ): Promise { const sortedRules = [...rules].sort((a, b) => a.priority - b.priority); @@ -201,7 +201,7 @@ export async function evaluateRulesForTransactions( categories: Category[], accounts: Account[], banks: Bank[], - encryptionKey: CryptoKey, + encryptionKey: CryptoKey | null, ): Promise> { const results = new Map(); @@ -237,7 +237,7 @@ export async function evaluateRulesForNewTransaction( categories: Category[], accounts: Account[], banks: Bank[], - encryptionKey: CryptoKey, + encryptionKey: CryptoKey | null, ): Promise { if (!rules || !categories || !accounts || !banks) { consoleDebug( diff --git a/resources/js/pages/settings/automation-rules.tsx b/resources/js/pages/settings/automation-rules.tsx index 92342a72..b12be01c 100644 --- a/resources/js/pages/settings/automation-rules.tsx +++ b/resources/js/pages/settings/automation-rules.tsx @@ -21,7 +21,6 @@ import { CreateAutomationRuleDialog } from '@/components/automation-rules/create import { DeleteAutomationRuleDialog } from '@/components/automation-rules/delete-automation-rule-dialog'; import { EditAutomationRuleDialog } from '@/components/automation-rules/edit-automation-rule-dialog'; import HeadingSmall from '@/components/heading-small'; -import { LabelBadges } from '@/components/shared/label-combobox'; import { Badge } from '@/components/ui/badge'; import { Button } from '@/components/ui/button'; import { @@ -47,13 +46,11 @@ import { TableHeader, TableRow, } from '@/components/ui/table'; -import { useEncryptionKey } from '@/contexts/encryption-key-context'; import AppLayout from '@/layouts/app-layout'; import SettingsLayout from '@/layouts/settings/layout'; import { type BreadcrumbItem } from '@/types'; import { type AutomationRule, getRuleActions } from '@/types/automation-rule'; import { type Category, getCategoryColorClasses } from '@/types/category'; -import { type Label } from '@/types/label'; import { __ } from '@/utils/i18n'; const breadcrumbs: BreadcrumbItem[] = [ @@ -66,11 +63,9 @@ const breadcrumbs: BreadcrumbItem[] = [ function AutomationRuleActions({ rule, categories, - labels, }: { rule: AutomationRule; categories: Category[]; - labels: Label[]; }) { const [editOpen, setEditOpen] = useState(false); const [deleteOpen, setDeleteOpen] = useState(false); @@ -105,7 +100,6 @@ function AutomationRuleActions({ @@ -121,11 +115,9 @@ function AutomationRuleActions({ function AutomationRuleRow({ row, categories, - labels, }: { row: Row; categories: Category[]; - labels: Label[]; }) { const rule = row.original; const [editOpen, setEditOpen] = useState(false); @@ -171,7 +163,6 @@ function AutomationRuleRow({ @@ -185,14 +176,12 @@ function AutomationRuleRow({ } export default function AutomationRules() { - const { isKeySet } = useEncryptionKey(); const { automationRules: rawRules } = usePage<{ automationRules: AutomationRule[]; }>().props; - // Get categories and labels from globally shared Inertia data + // Get categories from globally shared Inertia data const categories = usePage().props.categories as Category[]; - const labels = usePage().props.labels as Label[]; const rules = useMemo( () => rawRules.map((rule) => ({ @@ -204,29 +193,13 @@ export default function AutomationRules() { })), [rawRules], ); - const [sorting, setSorting] = useState([ - { - id: 'priority', - desc: false, - }, - ]); + const [sorting, setSorting] = useState([]); const [columnFilters, setColumnFilters] = useState([]); const [columnVisibility, setColumnVisibility] = useState( {}, ); const columns: ColumnDef[] = [ - { - accessorKey: 'priority', - header: __('Priority'), - cell: ({ row }) => { - return ( -
- {row.getValue('priority')} -
- ); - }, - }, { accessorKey: 'title', header: __('Title'), @@ -262,14 +235,6 @@ export default function AutomationRules() { {actions.category.name} )} - {actions.hasLabels && actions.labels && ( - - )} - {actions.hasNote && ( - - + note - - )}
); } @@ -291,13 +256,9 @@ export default function AutomationRules() { ); } - if (actions.type === 'labels' && actions.labels) { - return ; - } - return ( - {__('Add note')} + {__('No action set')} ); }, @@ -309,7 +270,6 @@ export default function AutomationRules() { ), }, @@ -362,8 +322,6 @@ export default function AutomationRules() { />
@@ -405,7 +363,6 @@ export default function AutomationRules() { key={row.id} row={row} categories={categories} - labels={labels} /> )) ) : ( diff --git a/tests/Browser/AutomationRuleBuilderTest.php b/tests/Browser/AutomationRuleBuilderTest.php index 6dedd9c1..d01ad5d3 100644 --- a/tests/Browser/AutomationRuleBuilderTest.php +++ b/tests/Browser/AutomationRuleBuilderTest.php @@ -27,7 +27,6 @@ it('can create an automation rule with visual builder', function () { ->click('button:has-text("Create Rule")') ->wait(0.5) ->fill('title', 'Test Rule') - ->fill('priority', '10') ->assertSee('Conditions') ->assertSee('Description') ->fill('input[placeholder="Value"]', 'grocery') @@ -42,7 +41,7 @@ it('can create an automation rule with visual builder', function () { $this->assertDatabaseHas('automation_rules', [ 'user_id' => $user->id, 'title' => 'Test Rule', - 'priority' => 10, + 'priority' => 0, ]); }); @@ -62,7 +61,6 @@ it('can add multiple conditions to a group', function () { ->click('button:has-text("Create Rule")') ->wait(0.5) ->fill('title', 'Multi-Condition Rule') - ->fill('priority', '5') ->fill('input[placeholder="Value"]', 'grocery') ->click('Add Condition') ->wait(0.5) @@ -100,7 +98,6 @@ it('can add multiple groups', function () { ->click('button:has-text("Create Rule")') ->wait(0.5) ->fill('title', 'Multi-Group Rule') - ->fill('priority', '3') ->fill('input[placeholder="Value"]', 'grocery') ->click('Add Group') ->wait(0.5) @@ -138,7 +135,6 @@ it('can select different field types and operators', function () { ->click('button:has-text("Create Rule")') ->wait(0.5) ->fill('title', 'Amount Rule') - ->fill('priority', '1') ->click('button:has-text("Description")') ->wait(0.5) ->click('[role="option"]:has-text("Amount")') @@ -179,7 +175,6 @@ it('can edit an existing rule with visual builder', function () { ->click('button:has-text("Create Rule")') ->wait(0.5) ->fill('title', 'Original Rule') - ->fill('priority', '5') ->fill('input[placeholder="Value"]', 'grocery') ->click('[data-testid="action-category-select"]') ->wait(0.5) @@ -222,7 +217,6 @@ it('validates that at least one condition is required', function () { ->click('button:has-text("Create Rule")') ->wait(0.5) ->fill('title', 'Invalid Rule') - ->fill('priority', '1') ->click('[data-testid="action-category-select"]') ->wait(0.5) ->click('Entertainment') @@ -252,7 +246,6 @@ it('can toggle group operators between AND and OR', function () { ->click('button:has-text("Create Rule")') ->wait(0.5) ->fill('title', 'OR Rule') - ->fill('priority', '1') ->fill('input[placeholder="Value"]', 'test') ->click('Add Condition') ->wait(0.5) @@ -293,7 +286,6 @@ it('can use is empty operator for nullable fields', function () { ->click('button:has-text("Create Rule")') ->wait(0.5) ->fill('title', 'Empty Category Rule') - ->fill('priority', '1') ->click('button:has-text("Description")') ->wait(0.5) ->click('[role="option"]:has-text("Category")')