@actual-app/api 26.2.0-nightly.20260112 → 26.2.0-nightly.20260114
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/@types/loot-core/src/server/aql/schema/index.d.ts +14 -0
- package/@types/loot-core/src/server/budgetfiles/app.d.ts +1 -3
- package/@types/loot-core/src/server/cloud-storage.d.ts +0 -1
- package/@types/loot-core/src/server/dashboard/app.d.ts +25 -4
- package/@types/loot-core/src/server/db/types/index.d.ts +6 -0
- package/@types/loot-core/src/server/main-app.d.ts +1 -1
- package/@types/loot-core/src/types/models/dashboard.d.ts +8 -2
- package/@types/loot-core/src/types/prefs.d.ts +1 -1
- package/@types/migrations/1765518577215_multiple_dashboards.d.ts +1 -0
- package/dist/app/bundle.api.js +114 -59
- package/dist/index.js +1 -0
- package/dist/migrations/1765518577215_multiple_dashboards.js +29 -0
- package/dist/package.json +1 -1
- package/dist/utils.js +1 -0
- package/package.json +1 -1
|
@@ -383,10 +383,24 @@ export declare const schema: {
|
|
|
383
383
|
type: string;
|
|
384
384
|
};
|
|
385
385
|
};
|
|
386
|
+
dashboard_pages: {
|
|
387
|
+
id: {
|
|
388
|
+
type: string;
|
|
389
|
+
};
|
|
390
|
+
name: {
|
|
391
|
+
type: string;
|
|
392
|
+
};
|
|
393
|
+
tombstone: {
|
|
394
|
+
type: string;
|
|
395
|
+
};
|
|
396
|
+
};
|
|
386
397
|
dashboard: {
|
|
387
398
|
id: {
|
|
388
399
|
type: string;
|
|
389
400
|
};
|
|
401
|
+
dashboard_page_id: {
|
|
402
|
+
type: string;
|
|
403
|
+
};
|
|
390
404
|
type: {
|
|
391
405
|
type: string;
|
|
392
406
|
};
|
|
@@ -6,7 +6,6 @@ export type BudgetFileHandlers = {
|
|
|
6
6
|
'unique-budget-name': typeof handleUniqueBudgetName;
|
|
7
7
|
'get-budgets': typeof getBudgets;
|
|
8
8
|
'get-remote-files': typeof getRemoteFiles;
|
|
9
|
-
'get-user-file-info': typeof getUserFileInfo;
|
|
10
9
|
'reset-budget-cache': typeof resetBudgetCache;
|
|
11
10
|
'upload-budget': typeof uploadBudget;
|
|
12
11
|
'download-budget': typeof downloadBudget;
|
|
@@ -35,7 +34,7 @@ export declare const app: {
|
|
|
35
34
|
handlers: BudgetFileHandlers;
|
|
36
35
|
services: (() => () => void)[];
|
|
37
36
|
unlistenServices: (() => void)[];
|
|
38
|
-
method<Name extends "load-budget" | "validate-budget-name" | "unique-budget-name" | "get-budgets" | "get-remote-files" | "
|
|
37
|
+
method<Name extends "load-budget" | "validate-budget-name" | "unique-budget-name" | "get-budgets" | "get-remote-files" | "reset-budget-cache" | "upload-budget" | "download-budget" | "sync-budget" | "create-demo-budget" | "close-budget" | "delete-budget" | "duplicate-budget" | "create-budget" | "import-budget" | "export-budget" | "upload-file-web" | "backups-get" | "backup-load" | "backup-make" | "get-last-opened-backup">(name: Name, func: BudgetFileHandlers[Name]): void;
|
|
39
38
|
service(func: () => () => void): void;
|
|
40
39
|
combine(...apps: any[]): void;
|
|
41
40
|
startServices(): void;
|
|
@@ -52,7 +51,6 @@ declare function handleUniqueBudgetName({ name }: {
|
|
|
52
51
|
}): Promise<string>;
|
|
53
52
|
declare function getBudgets(): Promise<Budget[]>;
|
|
54
53
|
declare function getRemoteFiles(): Promise<cloudStorage.RemoteFile[]>;
|
|
55
|
-
declare function getUserFileInfo(fileId: string): Promise<cloudStorage.RemoteFile>;
|
|
56
54
|
declare function resetBudgetCache(): Promise<void>;
|
|
57
55
|
declare function uploadBudget({ id }?: {
|
|
58
56
|
id?: Budget['id'];
|
|
@@ -35,7 +35,6 @@ export declare function upload(): Promise<void>;
|
|
|
35
35
|
export declare function possiblyUpload(): Promise<void>;
|
|
36
36
|
export declare function removeFile(fileId: any): Promise<void>;
|
|
37
37
|
export declare function listRemoteFiles(): Promise<RemoteFile[]>;
|
|
38
|
-
export declare function getRemoteFile(fileId: string): Promise<RemoteFile | null>;
|
|
39
38
|
export declare function download(cloudFileId: any): Promise<{
|
|
40
39
|
id: any;
|
|
41
40
|
}>;
|
|
@@ -1,12 +1,28 @@
|
|
|
1
1
|
import { type Widget } from '../../types/models';
|
|
2
2
|
import { type EverythingButIdOptional } from '../../types/util';
|
|
3
|
+
declare function getDashboardPages(): Promise<unknown[]>;
|
|
4
|
+
declare function createDashboardPage({ name }: {
|
|
5
|
+
name: string;
|
|
6
|
+
}): Promise<string>;
|
|
7
|
+
declare function deleteDashboardPage(id: string): Promise<void>;
|
|
8
|
+
declare function renameDashboardPage({ id, name }: {
|
|
9
|
+
id: string;
|
|
10
|
+
name: string;
|
|
11
|
+
}): Promise<void>;
|
|
3
12
|
declare function updateDashboard(widgets: EverythingButIdOptional<Omit<Widget, 'tombstone'>>[]): Promise<void>;
|
|
4
13
|
declare function updateDashboardWidget(widget: EverythingButIdOptional<Omit<Widget, 'tombstone'>>): Promise<void>;
|
|
5
|
-
declare function resetDashboard(): Promise<void>;
|
|
6
|
-
declare function addDashboardWidget(widget: Omit<Widget, 'id' | 'x' | 'y' | 'tombstone'> & Partial<Pick<Widget, 'x' | 'y'>>
|
|
14
|
+
declare function resetDashboard(id: string): Promise<void>;
|
|
15
|
+
declare function addDashboardWidget(widget: Omit<Widget, 'id' | 'x' | 'y' | 'tombstone'> & Partial<Pick<Widget, 'x' | 'y'>> & {
|
|
16
|
+
dashboard_page_id: string;
|
|
17
|
+
}): Promise<void>;
|
|
7
18
|
declare function removeDashboardWidget(widgetId: string): Promise<void>;
|
|
8
|
-
declare function
|
|
19
|
+
declare function copyDashboardWidget({ widgetId, targetDashboardPageId, }: {
|
|
20
|
+
widgetId: string;
|
|
21
|
+
targetDashboardPageId: string;
|
|
22
|
+
}): Promise<void>;
|
|
23
|
+
declare function importDashboard({ filepath, dashboardPageId, }: {
|
|
9
24
|
filepath: string;
|
|
25
|
+
dashboardPageId: string;
|
|
10
26
|
}): Promise<{
|
|
11
27
|
status: "ok";
|
|
12
28
|
error?: undefined;
|
|
@@ -25,11 +41,16 @@ declare function importDashboard({ filepath }: {
|
|
|
25
41
|
message?: undefined;
|
|
26
42
|
}>;
|
|
27
43
|
export type DashboardHandlers = {
|
|
44
|
+
'dashboard_pages-get': typeof getDashboardPages;
|
|
45
|
+
'dashboard-create': typeof createDashboardPage;
|
|
46
|
+
'dashboard-delete': typeof deleteDashboardPage;
|
|
47
|
+
'dashboard-rename': typeof renameDashboardPage;
|
|
28
48
|
'dashboard-update': typeof updateDashboard;
|
|
29
49
|
'dashboard-update-widget': typeof updateDashboardWidget;
|
|
30
50
|
'dashboard-reset': typeof resetDashboard;
|
|
31
51
|
'dashboard-add-widget': typeof addDashboardWidget;
|
|
32
52
|
'dashboard-remove-widget': typeof removeDashboardWidget;
|
|
53
|
+
'dashboard-copy-widget': typeof copyDashboardWidget;
|
|
33
54
|
'dashboard-import': typeof importDashboard;
|
|
34
55
|
};
|
|
35
56
|
export declare const app: {
|
|
@@ -42,7 +63,7 @@ export declare const app: {
|
|
|
42
63
|
handlers: DashboardHandlers;
|
|
43
64
|
services: (() => () => void)[];
|
|
44
65
|
unlistenServices: (() => void)[];
|
|
45
|
-
method<Name extends "dashboard-update" | "dashboard-update-widget" | "dashboard-reset" | "dashboard-add-widget" | "dashboard-remove-widget" | "dashboard-import">(name: Name, func: DashboardHandlers[Name]): void;
|
|
66
|
+
method<Name extends "dashboard_pages-get" | "dashboard-create" | "dashboard-delete" | "dashboard-rename" | "dashboard-update" | "dashboard-update-widget" | "dashboard-reset" | "dashboard-add-widget" | "dashboard-remove-widget" | "dashboard-copy-widget" | "dashboard-import">(name: Name, func: DashboardHandlers[Name]): void;
|
|
46
67
|
service(func: () => () => void): void;
|
|
47
68
|
combine(...apps: any[]): void;
|
|
48
69
|
startServices(): void;
|
|
@@ -193,8 +193,14 @@ export type DbCustomReport = {
|
|
|
193
193
|
sort_by: string;
|
|
194
194
|
tombstone: 1 | 0;
|
|
195
195
|
};
|
|
196
|
+
export type DbDashboardPage = {
|
|
197
|
+
id: string;
|
|
198
|
+
name: string;
|
|
199
|
+
tombstone: 1 | 0;
|
|
200
|
+
};
|
|
196
201
|
export type DbDashboard = {
|
|
197
202
|
id: string;
|
|
203
|
+
dashboard_page_id: string;
|
|
198
204
|
type: string;
|
|
199
205
|
width: number;
|
|
200
206
|
height: number;
|
|
@@ -9,7 +9,7 @@ export declare const app: {
|
|
|
9
9
|
handlers: Handlers;
|
|
10
10
|
services: (() => () => void)[];
|
|
11
11
|
unlistenServices: (() => void)[];
|
|
12
|
-
method<Name extends "sync" | "load-budget" | "undo" | "redo" | "make-filters-from-conditions" | "query" | "get-server-version" | "get-server-url" | "set-server-url" | "app-focused" | "api/batch-budget-start" | "api/batch-budget-end" | "api/load-budget" | "api/download-budget" | "api/get-budgets" | "api/start-import" | "api/finish-import" | "api/abort-import" | "api/query" | "api/budget-months" | "api/budget-month" | "api/budget-set-amount" | "api/budget-set-carryover" | "api/budget-hold-for-next-month" | "api/budget-reset-hold" | "api/transactions-export" | "api/transactions-import" | "api/transactions-add" | "api/transactions-get" | "api/transaction-update" | "api/transaction-delete" | "api/sync" | "api/bank-sync" | "api/accounts-get" | "api/account-create" | "api/account-update" | "api/account-close" | "api/account-reopen" | "api/account-delete" | "api/account-balance" | "api/categories-get" | "api/category-groups-get" | "api/category-group-create" | "api/category-group-update" | "api/category-group-delete" | "api/category-create" | "api/category-update" | "api/category-delete" | "api/payees-get" | "api/common-payees-get" | "api/payee-create" | "api/payee-update" | "api/payee-delete" | "api/payees-merge" | "api/rules-get" | "api/payee-rules-get" | "api/rule-create" | "api/rule-update" | "api/rule-delete" | "api/schedule-create" | "api/schedule-update" | "api/schedule-delete" | "api/schedules-get" | "api/get-id-by-name" | "api/get-server-version" | "budget/budget-amount" | "budget/copy-previous-month" | "budget/copy-single-month" | "budget/set-zero" | "budget/set-3month-avg" | "budget/set-6month-avg" | "budget/set-12month-avg" | "budget/set-n-month-avg" | "budget/check-templates" | "budget/apply-goal-template" | "budget/apply-multiple-templates" | "budget/overwrite-goal-template" | "budget/apply-single-template" | "budget/cleanup-goal-template" | "budget/hold-for-next-month" | "budget/reset-hold" | "budget/cover-overspending" | "budget/transfer-available" | "budget/cover-overbudgeted" | "budget/transfer-category" | "budget/set-carryover" | "budget/reset-income-carryover" | "get-categories" | "get-budget-bounds" | "envelope-budget-month" | "tracking-budget-month" | "category-create" | "category-update" | "category-move" | "category-delete" | "get-category-groups" | "category-group-create" | "category-group-update" | "category-group-move" | "category-group-delete" | "must-category-transfer" | "budget/get-category-automations" | "budget/set-category-automations" | "budget/store-note-templates" | "budget/render-note-templates" | "dashboard-update" | "dashboard-update-widget" | "dashboard-reset" | "dashboard-add-widget" | "dashboard-remove-widget" | "dashboard-import" | "filter-create" | "filter-update" | "filter-delete" | "notes-save" | "notes-save-undoable" | "preferences/save" | "preferences/get" | "save-global-prefs" | "load-global-prefs" | "save-prefs" | "load-prefs" | "save-server-prefs" | "report/create" | "report/update" | "report/delete" | "rule-validate" | "rule-add" | "rule-update" | "rule-delete" | "rule-delete-all" | "rule-apply-actions" | "rule-add-payee-rename" | "rules-get" | "rule-get" | "rules-run" | "schedule/create" | "schedule/update" | "schedule/delete" | "schedule/skip-next-date" | "schedule/post-transaction" | "schedule/force-run-service" | "schedule/discover" | "schedule/get-upcoming-dates" | "transactions-batch-update" | "transaction-add" | "transaction-update" | "transaction-delete" | "transactions-parse-file" | "transactions-export" | "transactions-export-query" | "transactions-merge" | "get-earliest-transaction" | "get-latest-transaction" | "users-get" | "user-delete-all" | "user-add" | "user-update" | "access-add" | "access-delete-all" | "access-get-available-users" | "transfer-ownership" | "owner-created" | "tools/fix-split-transactions" | "account-update" | "accounts-get" | "account-balance" | "account-properties" | "gocardless-accounts-link" | "simplefin-accounts-link" | "pluggyai-accounts-link" | "account-create" | "account-close" | "account-reopen" | "account-move" | "secret-set" | "secret-check" | "gocardless-poll-web-token" | "gocardless-poll-web-token-stop" | "gocardless-status" | "simplefin-status" | "pluggyai-status" | "simplefin-accounts" | "pluggyai-accounts" | "gocardless-get-banks" | "gocardless-create-web-token" | "accounts-bank-sync" | "simplefin-batch-sync" | "transactions-import" | "account-unlink" | "payee-create" | "common-payees-get" | "payees-get" | "payees-get-orphaned" | "payees-get-rule-counts" | "payees-merge" | "payees-batch-change" | "payees-check-orphaned" | "payees-get-rules" | "get-cell" | "get-cell-names" | "create-query" | "sync-reset" | "sync-repair" | "validate-budget-name" | "unique-budget-name" | "get-budgets" | "get-remote-files" | "
|
|
12
|
+
method<Name extends "sync" | "load-budget" | "undo" | "redo" | "make-filters-from-conditions" | "query" | "get-server-version" | "get-server-url" | "set-server-url" | "app-focused" | "api/batch-budget-start" | "api/batch-budget-end" | "api/load-budget" | "api/download-budget" | "api/get-budgets" | "api/start-import" | "api/finish-import" | "api/abort-import" | "api/query" | "api/budget-months" | "api/budget-month" | "api/budget-set-amount" | "api/budget-set-carryover" | "api/budget-hold-for-next-month" | "api/budget-reset-hold" | "api/transactions-export" | "api/transactions-import" | "api/transactions-add" | "api/transactions-get" | "api/transaction-update" | "api/transaction-delete" | "api/sync" | "api/bank-sync" | "api/accounts-get" | "api/account-create" | "api/account-update" | "api/account-close" | "api/account-reopen" | "api/account-delete" | "api/account-balance" | "api/categories-get" | "api/category-groups-get" | "api/category-group-create" | "api/category-group-update" | "api/category-group-delete" | "api/category-create" | "api/category-update" | "api/category-delete" | "api/payees-get" | "api/common-payees-get" | "api/payee-create" | "api/payee-update" | "api/payee-delete" | "api/payees-merge" | "api/rules-get" | "api/payee-rules-get" | "api/rule-create" | "api/rule-update" | "api/rule-delete" | "api/schedule-create" | "api/schedule-update" | "api/schedule-delete" | "api/schedules-get" | "api/get-id-by-name" | "api/get-server-version" | "budget/budget-amount" | "budget/copy-previous-month" | "budget/copy-single-month" | "budget/set-zero" | "budget/set-3month-avg" | "budget/set-6month-avg" | "budget/set-12month-avg" | "budget/set-n-month-avg" | "budget/check-templates" | "budget/apply-goal-template" | "budget/apply-multiple-templates" | "budget/overwrite-goal-template" | "budget/apply-single-template" | "budget/cleanup-goal-template" | "budget/hold-for-next-month" | "budget/reset-hold" | "budget/cover-overspending" | "budget/transfer-available" | "budget/cover-overbudgeted" | "budget/transfer-category" | "budget/set-carryover" | "budget/reset-income-carryover" | "get-categories" | "get-budget-bounds" | "envelope-budget-month" | "tracking-budget-month" | "category-create" | "category-update" | "category-move" | "category-delete" | "get-category-groups" | "category-group-create" | "category-group-update" | "category-group-move" | "category-group-delete" | "must-category-transfer" | "budget/get-category-automations" | "budget/set-category-automations" | "budget/store-note-templates" | "budget/render-note-templates" | "dashboard_pages-get" | "dashboard-create" | "dashboard-delete" | "dashboard-rename" | "dashboard-update" | "dashboard-update-widget" | "dashboard-reset" | "dashboard-add-widget" | "dashboard-remove-widget" | "dashboard-copy-widget" | "dashboard-import" | "filter-create" | "filter-update" | "filter-delete" | "notes-save" | "notes-save-undoable" | "preferences/save" | "preferences/get" | "save-global-prefs" | "load-global-prefs" | "save-prefs" | "load-prefs" | "save-server-prefs" | "report/create" | "report/update" | "report/delete" | "rule-validate" | "rule-add" | "rule-update" | "rule-delete" | "rule-delete-all" | "rule-apply-actions" | "rule-add-payee-rename" | "rules-get" | "rule-get" | "rules-run" | "schedule/create" | "schedule/update" | "schedule/delete" | "schedule/skip-next-date" | "schedule/post-transaction" | "schedule/force-run-service" | "schedule/discover" | "schedule/get-upcoming-dates" | "transactions-batch-update" | "transaction-add" | "transaction-update" | "transaction-delete" | "transactions-parse-file" | "transactions-export" | "transactions-export-query" | "transactions-merge" | "get-earliest-transaction" | "get-latest-transaction" | "users-get" | "user-delete-all" | "user-add" | "user-update" | "access-add" | "access-delete-all" | "access-get-available-users" | "transfer-ownership" | "owner-created" | "tools/fix-split-transactions" | "account-update" | "accounts-get" | "account-balance" | "account-properties" | "gocardless-accounts-link" | "simplefin-accounts-link" | "pluggyai-accounts-link" | "account-create" | "account-close" | "account-reopen" | "account-move" | "secret-set" | "secret-check" | "gocardless-poll-web-token" | "gocardless-poll-web-token-stop" | "gocardless-status" | "simplefin-status" | "pluggyai-status" | "simplefin-accounts" | "pluggyai-accounts" | "gocardless-get-banks" | "gocardless-create-web-token" | "accounts-bank-sync" | "simplefin-batch-sync" | "transactions-import" | "account-unlink" | "payee-create" | "common-payees-get" | "payees-get" | "payees-get-orphaned" | "payees-get-rule-counts" | "payees-merge" | "payees-batch-change" | "payees-check-orphaned" | "payees-get-rules" | "get-cell" | "get-cell-names" | "create-query" | "sync-reset" | "sync-repair" | "validate-budget-name" | "unique-budget-name" | "get-budgets" | "get-remote-files" | "reset-budget-cache" | "upload-budget" | "download-budget" | "sync-budget" | "create-demo-budget" | "close-budget" | "delete-budget" | "duplicate-budget" | "create-budget" | "import-budget" | "export-budget" | "upload-file-web" | "backups-get" | "backup-load" | "backup-make" | "get-last-opened-backup" | "key-make" | "key-test" | "tags-get" | "tags-create" | "tags-delete" | "tags-delete-all" | "tags-update" | "tags-find" | "get-did-bootstrap" | "subscribe-needs-bootstrap" | "subscribe-bootstrap" | "subscribe-get-login-methods" | "subscribe-get-user" | "subscribe-change-password" | "subscribe-sign-in" | "subscribe-sign-out" | "subscribe-set-token" | "enable-openid" | "get-openid-config" | "enable-password">(name: Name, func: Handlers[Name]): void;
|
|
13
13
|
service(func: () => () => void): void;
|
|
14
14
|
combine(...apps: any[]): void;
|
|
15
15
|
startServices(): void;
|
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
import { type CustomReportEntity } from './reports';
|
|
2
2
|
import { type RuleConditionEntity } from './rule';
|
|
3
|
+
export type DashboardEntity = {
|
|
4
|
+
id: string;
|
|
5
|
+
name: string;
|
|
6
|
+
tombstone: boolean;
|
|
7
|
+
};
|
|
3
8
|
export type TimeFrame = {
|
|
4
9
|
start: string;
|
|
5
10
|
end: string;
|
|
@@ -7,6 +12,7 @@ export type TimeFrame = {
|
|
|
7
12
|
};
|
|
8
13
|
type AbstractWidget<T extends string, Meta extends Record<string, unknown> | null = null> = {
|
|
9
14
|
id: string;
|
|
15
|
+
dashboard_page_id: string;
|
|
10
16
|
type: T;
|
|
11
17
|
x: number;
|
|
12
18
|
y: number;
|
|
@@ -48,7 +54,7 @@ export type CrossoverWidget = AbstractWidget<'crossover-card', {
|
|
|
48
54
|
timeFrame?: TimeFrame;
|
|
49
55
|
safeWithdrawalRate?: number;
|
|
50
56
|
estimatedReturn?: number | null;
|
|
51
|
-
projectionType?: '
|
|
57
|
+
projectionType?: 'hampel' | 'median' | 'mean';
|
|
52
58
|
showHiddenCategories?: boolean;
|
|
53
59
|
expenseAdjustmentFactor?: number;
|
|
54
60
|
} | null>;
|
|
@@ -58,7 +64,7 @@ export type MarkdownWidget = AbstractWidget<'markdown-card', {
|
|
|
58
64
|
}>;
|
|
59
65
|
type SpecializedWidget = NetWorthWidget | CashFlowWidget | SpendingWidget | CrossoverWidget | MarkdownWidget | SummaryWidget | CalendarWidget | FormulaWidget;
|
|
60
66
|
export type Widget = SpecializedWidget | CustomReportWidget;
|
|
61
|
-
export type NewWidget = Omit<Widget, 'id' | 'tombstone'>;
|
|
67
|
+
export type NewWidget = Omit<Widget, 'id' | 'tombstone' | 'dashboard_page_id'>;
|
|
62
68
|
export type ExportImportCustomReportWidget = Omit<CustomReportWidget, 'id' | 'meta' | 'tombstone'> & {
|
|
63
69
|
meta: Omit<CustomReportEntity, 'tombstone'>;
|
|
64
70
|
};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export type FeatureFlag = 'goalTemplatesEnabled' | 'goalTemplatesUIEnabled' | 'actionTemplating' | 'formulaMode' | 'currency' | 'crossoverReport'
|
|
1
|
+
export type FeatureFlag = 'goalTemplatesEnabled' | 'goalTemplatesUIEnabled' | 'actionTemplating' | 'formulaMode' | 'currency' | 'crossoverReport';
|
|
2
2
|
/**
|
|
3
3
|
* Cross-device preferences. These sync across devices when they are changed.
|
|
4
4
|
*/
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export default function runMigration(db: any): Promise<void>;
|
package/dist/app/bundle.api.js
CHANGED
|
@@ -14365,8 +14365,14 @@ const schema = {
|
|
|
14365
14365
|
goal: f("integer"),
|
|
14366
14366
|
long_goal: f("integer")
|
|
14367
14367
|
},
|
|
14368
|
+
dashboard_pages: {
|
|
14369
|
+
id: f("id"),
|
|
14370
|
+
name: f("string"),
|
|
14371
|
+
tombstone: f("boolean")
|
|
14372
|
+
},
|
|
14368
14373
|
dashboard: {
|
|
14369
14374
|
id: f("id"),
|
|
14375
|
+
dashboard_page_id: f("id", { ref: "dashboard_pages" }),
|
|
14370
14376
|
type: f("string", { required: true }),
|
|
14371
14377
|
width: f("integer", { required: true }),
|
|
14372
14378
|
height: f("integer", { required: true }),
|
|
@@ -59696,33 +59702,6 @@ async function listRemoteFiles() {
|
|
|
59696
59702
|
hasKey: hasKey(file.encryptKeyId)
|
|
59697
59703
|
})).filter(Boolean);
|
|
59698
59704
|
}
|
|
59699
|
-
async function getRemoteFile(fileId) {
|
|
59700
|
-
const userToken = await getItem("user-token");
|
|
59701
|
-
if (!userToken) {
|
|
59702
|
-
return null;
|
|
59703
|
-
}
|
|
59704
|
-
let res;
|
|
59705
|
-
try {
|
|
59706
|
-
res = await fetchJSON(getServer().SYNC_SERVER + "/get-user-file-info", {
|
|
59707
|
-
headers: {
|
|
59708
|
-
"X-ACTUAL-TOKEN": userToken,
|
|
59709
|
-
"X-ACTUAL-FILE-ID": fileId
|
|
59710
|
-
}
|
|
59711
|
-
});
|
|
59712
|
-
}
|
|
59713
|
-
catch (e) {
|
|
59714
|
-
logger.log("Unexpected error fetching file from server", e);
|
|
59715
|
-
return null;
|
|
59716
|
-
}
|
|
59717
|
-
if (res.status === "error") {
|
|
59718
|
-
logger.log("Error fetching file from server", res);
|
|
59719
|
-
return null;
|
|
59720
|
-
}
|
|
59721
|
-
return {
|
|
59722
|
-
...res.data,
|
|
59723
|
-
hasKey: hasKey(res.data.encryptKeyId)
|
|
59724
|
-
};
|
|
59725
|
-
}
|
|
59726
59705
|
async function download(cloudFileId) {
|
|
59727
59706
|
const userToken = await getItem("user-token");
|
|
59728
59707
|
const syncServer = getServer().SYNC_SERVER;
|
|
@@ -102004,7 +101983,7 @@ function getHasTransactionsQuery(schedules) {
|
|
|
102004
101983
|
function recurConfigToRSchedule(config2) {
|
|
102005
101984
|
const base = {
|
|
102006
101985
|
start: parseDate$1(config2.start),
|
|
102007
|
-
// @ts-
|
|
101986
|
+
// @ts-expect-error: issues with https://gitlab.com/john.carroll.p/rschedule/-/issues/86
|
|
102008
101987
|
frequency: config2.frequency.toUpperCase(),
|
|
102009
101988
|
byHourOfDay: [12]
|
|
102010
101989
|
};
|
|
@@ -121495,7 +121474,7 @@ function requireMd5() {
|
|
|
121495
121474
|
}
|
|
121496
121475
|
var md5Exports = requireMd5();
|
|
121497
121476
|
const md5 = /* @__PURE__ */ getDefaultExportFromCjs(md5Exports);
|
|
121498
|
-
async function runMigration$
|
|
121477
|
+
async function runMigration$4(db2) {
|
|
121499
121478
|
function getValue(node2) {
|
|
121500
121479
|
return node2.expr != null ? node2.expr : node2.cachedValue;
|
|
121501
121480
|
}
|
|
@@ -121592,7 +121571,7 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
|
|
|
121592
121571
|
VACUUM;
|
|
121593
121572
|
`);
|
|
121594
121573
|
}
|
|
121595
|
-
async function runMigration$
|
|
121574
|
+
async function runMigration$3(db2) {
|
|
121596
121575
|
const categories = await db2.runQuery("SELECT id FROM categories WHERE tombstone = 0", [], true);
|
|
121597
121576
|
const customReports = await db2.runQuery("SELECT id, selected_categories, conditions FROM custom_reports WHERE tombstone = 0 AND selected_categories IS NOT NULL", [], true);
|
|
121598
121577
|
for (const report of customReports) {
|
|
@@ -121878,7 +121857,7 @@ const DEFAULT_DASHBOARD_STATE = [
|
|
|
121878
121857
|
}
|
|
121879
121858
|
}
|
|
121880
121859
|
];
|
|
121881
|
-
async function runMigration$
|
|
121860
|
+
async function runMigration$2(db2) {
|
|
121882
121861
|
db2.transaction(() => {
|
|
121883
121862
|
const reports = db2.runQuery("SELECT id FROM custom_reports WHERE tombstone = 0 ORDER BY name COLLATE NOCASE ASC", [], true);
|
|
121884
121863
|
db2.execQuery(`
|
|
@@ -121943,7 +121922,7 @@ const SYNCED_PREF_KEYS = [
|
|
|
121943
121922
|
"budgetType",
|
|
121944
121923
|
/^flags\./
|
|
121945
121924
|
];
|
|
121946
|
-
async function runMigration(db2, { fs: fs2, fileId }) {
|
|
121925
|
+
async function runMigration$1(db2, { fs: fs2, fileId }) {
|
|
121947
121926
|
await db2.execQuery(`
|
|
121948
121927
|
CREATE TABLE preferences
|
|
121949
121928
|
(id TEXT PRIMARY KEY,
|
|
@@ -121969,12 +121948,34 @@ async function runMigration(db2, { fs: fs2, fileId }) {
|
|
|
121969
121948
|
catch {
|
|
121970
121949
|
}
|
|
121971
121950
|
}
|
|
121951
|
+
async function runMigration(db2) {
|
|
121952
|
+
db2.transaction(() => {
|
|
121953
|
+
db2.execQuery(`
|
|
121954
|
+
CREATE TABLE dashboard_pages
|
|
121955
|
+
(id TEXT PRIMARY KEY,
|
|
121956
|
+
name TEXT,
|
|
121957
|
+
tombstone INTEGER DEFAULT 0);
|
|
121958
|
+
`);
|
|
121959
|
+
db2.execQuery(`
|
|
121960
|
+
ALTER TABLE dashboard ADD COLUMN dashboard_page_id TEXT;
|
|
121961
|
+
`);
|
|
121962
|
+
const defaultDashboardId = v4();
|
|
121963
|
+
db2.runQuery(`INSERT INTO dashboard_pages (id, name) VALUES (?, ?)`, [
|
|
121964
|
+
defaultDashboardId,
|
|
121965
|
+
"Main"
|
|
121966
|
+
]);
|
|
121967
|
+
db2.runQuery(`UPDATE dashboard SET dashboard_page_id = ?`, [
|
|
121968
|
+
defaultDashboardId
|
|
121969
|
+
]);
|
|
121970
|
+
});
|
|
121971
|
+
}
|
|
121972
121972
|
let MIGRATIONS_DIR = migrationsPath;
|
|
121973
121973
|
const javascriptMigrations = {
|
|
121974
|
-
1632571489012: runMigration$
|
|
121975
|
-
1722717601e3: runMigration$
|
|
121976
|
-
1722804019e3: runMigration$
|
|
121977
|
-
1723665565e3: runMigration
|
|
121974
|
+
1632571489012: runMigration$4,
|
|
121975
|
+
1722717601e3: runMigration$3,
|
|
121976
|
+
1722804019e3: runMigration$2,
|
|
121977
|
+
1723665565e3: runMigration$1,
|
|
121978
|
+
1765518577215: runMigration
|
|
121978
121979
|
};
|
|
121979
121980
|
function getMigrationId(name) {
|
|
121980
121981
|
return parseInt(name.match(/^(\d)+/)[0]);
|
|
@@ -122277,7 +122278,6 @@ app$d.method("validate-budget-name", handleValidateBudgetName);
|
|
|
122277
122278
|
app$d.method("unique-budget-name", handleUniqueBudgetName);
|
|
122278
122279
|
app$d.method("get-budgets", getBudgets);
|
|
122279
122280
|
app$d.method("get-remote-files", getRemoteFiles);
|
|
122280
|
-
app$d.method("get-user-file-info", getUserFileInfo);
|
|
122281
122281
|
app$d.method("reset-budget-cache", mutator(resetBudgetCache));
|
|
122282
122282
|
app$d.method("upload-budget", uploadBudget);
|
|
122283
122283
|
app$d.method("download-budget", downloadBudget);
|
|
@@ -122332,9 +122332,6 @@ async function getBudgets() {
|
|
|
122332
122332
|
async function getRemoteFiles() {
|
|
122333
122333
|
return listRemoteFiles();
|
|
122334
122334
|
}
|
|
122335
|
-
async function getUserFileInfo(fileId) {
|
|
122336
|
-
return getRemoteFile(fileId);
|
|
122337
|
-
}
|
|
122338
122335
|
async function resetBudgetCache() {
|
|
122339
122336
|
await loadUserBudgets(db$1);
|
|
122340
122337
|
get$3().recomputeAll();
|
|
@@ -124461,6 +124458,19 @@ app$c.method("report/delete", mutator(undoable(deleteReport)));
|
|
|
124461
124458
|
function isExportedCustomReportWidget(widget) {
|
|
124462
124459
|
return widget.type === "custom-report";
|
|
124463
124460
|
}
|
|
124461
|
+
function isWidgetType(type2) {
|
|
124462
|
+
return [
|
|
124463
|
+
"net-worth-card",
|
|
124464
|
+
"cash-flow-card",
|
|
124465
|
+
"spending-card",
|
|
124466
|
+
"crossover-card",
|
|
124467
|
+
"markdown-card",
|
|
124468
|
+
"summary-card",
|
|
124469
|
+
"calendar-card",
|
|
124470
|
+
"formula-card",
|
|
124471
|
+
"custom-report"
|
|
124472
|
+
].includes(type2);
|
|
124473
|
+
}
|
|
124464
124474
|
const exportModel = {
|
|
124465
124475
|
validate(dashboard) {
|
|
124466
124476
|
requiredFields("Dashboard", dashboard, ["version", "widgets"]);
|
|
@@ -124488,17 +124498,7 @@ const exportModel = {
|
|
|
124488
124498
|
if (!Number.isInteger(widget.height)) {
|
|
124489
124499
|
throw new ValidationError(`Invalid widget.${idx}.height data-type for value ${widget.height}.`);
|
|
124490
124500
|
}
|
|
124491
|
-
if (!
|
|
124492
|
-
"net-worth-card",
|
|
124493
|
-
"cash-flow-card",
|
|
124494
|
-
"spending-card",
|
|
124495
|
-
"crossover-card",
|
|
124496
|
-
"custom-report",
|
|
124497
|
-
"markdown-card",
|
|
124498
|
-
"summary-card",
|
|
124499
|
-
"calendar-card",
|
|
124500
|
-
"formula-card"
|
|
124501
|
-
].includes(widget.type)) {
|
|
124501
|
+
if (!isWidgetType(widget.type)) {
|
|
124502
124502
|
throw new ValidationError(`Invalid widget.${idx}.type value ${widget.type}.`);
|
|
124503
124503
|
}
|
|
124504
124504
|
if (isExportedCustomReportWidget(widget)) {
|
|
@@ -124507,6 +124507,28 @@ const exportModel = {
|
|
|
124507
124507
|
});
|
|
124508
124508
|
}
|
|
124509
124509
|
};
|
|
124510
|
+
async function getDashboardPages() {
|
|
124511
|
+
return all("SELECT * FROM dashboard_pages WHERE tombstone = 0");
|
|
124512
|
+
}
|
|
124513
|
+
async function createDashboardPage({ name }) {
|
|
124514
|
+
const id2 = v4();
|
|
124515
|
+
await insertWithSchema("dashboard_pages", { id: id2, name });
|
|
124516
|
+
return id2;
|
|
124517
|
+
}
|
|
124518
|
+
async function deleteDashboardPage(id2) {
|
|
124519
|
+
const res = await first$2("SELECT count(*) as c FROM dashboard_pages WHERE tombstone = 0");
|
|
124520
|
+
if ((res?.c ?? 0) <= 1) {
|
|
124521
|
+
throw new Error("Cannot delete the last dashboard page");
|
|
124522
|
+
}
|
|
124523
|
+
const deleting_widgets = await all("SELECT id FROM dashboard WHERE dashboard_page_id = ? AND tombstone = 0", [id2]);
|
|
124524
|
+
await batchMessages(async () => {
|
|
124525
|
+
await delete_("dashboard_pages", id2);
|
|
124526
|
+
await Promise.all(deleting_widgets.map(({ id: id22 }) => delete_("dashboard", id22)));
|
|
124527
|
+
});
|
|
124528
|
+
}
|
|
124529
|
+
async function renameDashboardPage({ id: id2, name }) {
|
|
124530
|
+
await updateWithSchema("dashboard_pages", { id: id2, name });
|
|
124531
|
+
}
|
|
124510
124532
|
async function updateDashboard(widgets) {
|
|
124511
124533
|
const { data: dbWidgets } = await aqlQuery(q("dashboard").filter({ id: { $oneof: widgets.map(({ id: id2 }) => id2) } }).select("*"));
|
|
124512
124534
|
const dbWidgetMap = new Map(dbWidgets.map((widget) => [widget.id, widget]));
|
|
@@ -124515,19 +124537,20 @@ async function updateDashboard(widgets) {
|
|
|
124515
124537
|
async function updateDashboardWidget(widget) {
|
|
124516
124538
|
await updateWithSchema("dashboard", widget);
|
|
124517
124539
|
}
|
|
124518
|
-
async function resetDashboard() {
|
|
124540
|
+
async function resetDashboard(id2) {
|
|
124519
124541
|
await batchMessages(async () => {
|
|
124542
|
+
const widgets = await selectWithSchema("dashboard", "SELECT id FROM dashboard WHERE dashboard_page_id = ? AND tombstone = 0", [id2]);
|
|
124520
124543
|
await Promise.all([
|
|
124521
|
-
// Delete all widgets
|
|
124522
|
-
|
|
124544
|
+
// Delete all widgets for this dashboard
|
|
124545
|
+
...widgets.map(({ id: id22 }) => delete_("dashboard", id22)),
|
|
124523
124546
|
// Insert the default state
|
|
124524
|
-
...DEFAULT_DASHBOARD_STATE.map((widget) => insertWithSchema("dashboard", widget))
|
|
124547
|
+
...DEFAULT_DASHBOARD_STATE.map((widget) => insertWithSchema("dashboard", { ...widget, dashboard_page_id: id2 }))
|
|
124525
124548
|
]);
|
|
124526
124549
|
});
|
|
124527
124550
|
}
|
|
124528
124551
|
async function addDashboardWidget(widget) {
|
|
124529
124552
|
if (!("x" in widget) && !("y" in widget)) {
|
|
124530
|
-
const data = await first$2("SELECT x, y, width, height FROM dashboard WHERE tombstone = 0 ORDER BY y DESC, x DESC");
|
|
124553
|
+
const data = await first$2("SELECT x, y, width, height FROM dashboard WHERE dashboard_page_id = ? AND tombstone = 0 ORDER BY y DESC, x DESC", [widget.dashboard_page_id]);
|
|
124531
124554
|
if (!data) {
|
|
124532
124555
|
widget.x = 0;
|
|
124533
124556
|
widget.y = 0;
|
|
@@ -124538,12 +124561,37 @@ async function addDashboardWidget(widget) {
|
|
|
124538
124561
|
widget.y = data.y + (xBoundaryCheck > 12 ? data.height : 0);
|
|
124539
124562
|
}
|
|
124540
124563
|
}
|
|
124541
|
-
|
|
124564
|
+
const { dashboard_page_id, ...widgetWithoutDashboardPageId } = widget;
|
|
124565
|
+
await insertWithSchema("dashboard", {
|
|
124566
|
+
...widgetWithoutDashboardPageId,
|
|
124567
|
+
dashboard_page_id
|
|
124568
|
+
});
|
|
124542
124569
|
}
|
|
124543
124570
|
async function removeDashboardWidget(widgetId) {
|
|
124544
124571
|
await delete_("dashboard", widgetId);
|
|
124545
124572
|
}
|
|
124546
|
-
async function
|
|
124573
|
+
async function copyDashboardWidget({ widgetId, targetDashboardPageId }) {
|
|
124574
|
+
const widget = await first$2("SELECT * FROM dashboard WHERE id = ? AND tombstone = 0", [widgetId]);
|
|
124575
|
+
if (!widget) {
|
|
124576
|
+
throw new Error(`Widget not found: ${widgetId}`);
|
|
124577
|
+
}
|
|
124578
|
+
await batchMessages(async () => {
|
|
124579
|
+
if (isWidgetType(widget.type)) {
|
|
124580
|
+
const newWidget = {
|
|
124581
|
+
type: widget.type,
|
|
124582
|
+
width: widget.width,
|
|
124583
|
+
height: widget.height,
|
|
124584
|
+
meta: widget.meta ? JSON.parse(widget.meta) : {},
|
|
124585
|
+
dashboard_page_id: targetDashboardPageId
|
|
124586
|
+
};
|
|
124587
|
+
await addDashboardWidget(newWidget);
|
|
124588
|
+
}
|
|
124589
|
+
else {
|
|
124590
|
+
throw new Error(`Unsupported widget type: ${widget.type}`);
|
|
124591
|
+
}
|
|
124592
|
+
});
|
|
124593
|
+
}
|
|
124594
|
+
async function importDashboard({ filepath, dashboardPageId }) {
|
|
124547
124595
|
try {
|
|
124548
124596
|
if (!await exists(filepath)) {
|
|
124549
124597
|
throw new Error(`File not found at the provided path: ${filepath}`);
|
|
@@ -124553,10 +124601,11 @@ async function importDashboard({ filepath }) {
|
|
|
124553
124601
|
exportModel.validate(parsedContent);
|
|
124554
124602
|
const customReportIds = await all("SELECT id from custom_reports");
|
|
124555
124603
|
const customReportIdSet = new Set(customReportIds.map(({ id: id2 }) => id2));
|
|
124604
|
+
const existingWidgets = await selectWithSchema("dashboard", "SELECT id FROM dashboard WHERE dashboard_page_id = ? AND tombstone = 0", [dashboardPageId]);
|
|
124556
124605
|
await batchMessages(async () => {
|
|
124557
124606
|
await Promise.all([
|
|
124558
124607
|
// Delete all widgets
|
|
124559
|
-
|
|
124608
|
+
...existingWidgets.map(({ id: id2 }) => delete_("dashboard", id2)),
|
|
124560
124609
|
// Insert new widgets
|
|
124561
124610
|
...parsedContent.widgets.map((widget) => insertWithSchema("dashboard", {
|
|
124562
124611
|
type: widget.type,
|
|
@@ -124564,6 +124613,7 @@ async function importDashboard({ filepath }) {
|
|
|
124564
124613
|
height: widget.height,
|
|
124565
124614
|
x: widget.x,
|
|
124566
124615
|
y: widget.y,
|
|
124616
|
+
dashboard_page_id: dashboardPageId,
|
|
124567
124617
|
meta: isExportedCustomReportWidget(widget) ? { id: widget.meta.id } : widget.meta
|
|
124568
124618
|
})),
|
|
124569
124619
|
// Insert new custom reports
|
|
@@ -124597,11 +124647,16 @@ async function importDashboard({ filepath }) {
|
|
|
124597
124647
|
}
|
|
124598
124648
|
}
|
|
124599
124649
|
const app$b = createApp();
|
|
124650
|
+
app$b.method("dashboard_pages-get", getDashboardPages);
|
|
124651
|
+
app$b.method("dashboard-create", mutator(undoable(createDashboardPage)));
|
|
124652
|
+
app$b.method("dashboard-delete", mutator(undoable(deleteDashboardPage)));
|
|
124653
|
+
app$b.method("dashboard-rename", mutator(undoable(renameDashboardPage)));
|
|
124600
124654
|
app$b.method("dashboard-update", mutator(undoable(updateDashboard)));
|
|
124601
124655
|
app$b.method("dashboard-update-widget", mutator(undoable(updateDashboardWidget)));
|
|
124602
124656
|
app$b.method("dashboard-reset", mutator(undoable(resetDashboard)));
|
|
124603
124657
|
app$b.method("dashboard-add-widget", mutator(undoable(addDashboardWidget)));
|
|
124604
124658
|
app$b.method("dashboard-remove-widget", mutator(undoable(removeDashboardWidget)));
|
|
124659
|
+
app$b.method("dashboard-copy-widget", mutator(undoable(copyDashboardWidget)));
|
|
124605
124660
|
app$b.method("dashboard-import", mutator(undoable(importDashboard)));
|
|
124606
124661
|
const app$a = createApp();
|
|
124607
124662
|
app$a.method("key-make", keyMake);
|
package/dist/index.js
CHANGED
|
@@ -39,6 +39,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
39
39
|
exports.utils = exports.internal = void 0;
|
|
40
40
|
exports.init = init;
|
|
41
41
|
exports.shutdown = shutdown;
|
|
42
|
+
// oxlint-disable-next-line typescript/ban-ts-comment
|
|
42
43
|
// @ts-ignore: bundle not available until we build it
|
|
43
44
|
const bundle = __importStar(require("./app/bundle.api.js"));
|
|
44
45
|
const injected = __importStar(require("./injected"));
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.default = runMigration;
|
|
4
|
+
const uuid_1 = require("uuid");
|
|
5
|
+
async function runMigration(db) {
|
|
6
|
+
db.transaction(() => {
|
|
7
|
+
// 1. Create dashboards table
|
|
8
|
+
db.execQuery(`
|
|
9
|
+
CREATE TABLE dashboard_pages
|
|
10
|
+
(id TEXT PRIMARY KEY,
|
|
11
|
+
name TEXT,
|
|
12
|
+
tombstone INTEGER DEFAULT 0);
|
|
13
|
+
`);
|
|
14
|
+
// 2. Add dashboard_page_id to dashboard (widgets) table
|
|
15
|
+
db.execQuery(`
|
|
16
|
+
ALTER TABLE dashboard ADD COLUMN dashboard_page_id TEXT;
|
|
17
|
+
`);
|
|
18
|
+
// 3. Create a default dashboard
|
|
19
|
+
const defaultDashboardId = (0, uuid_1.v4)();
|
|
20
|
+
db.runQuery(`INSERT INTO dashboard_pages (id, name) VALUES (?, ?)`, [
|
|
21
|
+
defaultDashboardId,
|
|
22
|
+
'Main',
|
|
23
|
+
]);
|
|
24
|
+
// 4. Migrate existing widgets to the default dashboard
|
|
25
|
+
db.runQuery(`UPDATE dashboard SET dashboard_page_id = ?`, [
|
|
26
|
+
defaultDashboardId,
|
|
27
|
+
]);
|
|
28
|
+
});
|
|
29
|
+
}
|
package/dist/package.json
CHANGED
package/dist/utils.js
CHANGED
|
@@ -34,6 +34,7 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
34
34
|
})();
|
|
35
35
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
36
|
exports.integerToAmount = exports.amountToInteger = void 0;
|
|
37
|
+
// oxlint-disable-next-line typescript/ban-ts-comment
|
|
37
38
|
// @ts-ignore: bundle not available until we build it
|
|
38
39
|
const bundle = __importStar(require("./app/bundle.api.js"));
|
|
39
40
|
exports.amountToInteger = bundle.lib.amountToInteger;
|