mirror of
https://github.com/actualbudget/actual.git
synced 2026-03-11 20:44:32 -05:00
Compare commits
4 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
05e2cbede1 | ||
|
|
fd42689f00 | ||
|
|
dd58376aa9 | ||
|
|
3c1f98daf1 |
@@ -36,6 +36,16 @@ fi
|
|||||||
|
|
||||||
yarn workspace loot-core build:node
|
yarn workspace loot-core build:node
|
||||||
|
|
||||||
|
# Get translations
|
||||||
|
echo "Updating translations..."
|
||||||
|
if ! [ -d packages/desktop-client/locale ]; then
|
||||||
|
git clone https://github.com/actualbudget/translations packages/desktop-client/locale
|
||||||
|
fi
|
||||||
|
pushd packages/desktop-client/locale > /dev/null
|
||||||
|
git pull
|
||||||
|
popd > /dev/null
|
||||||
|
packages/desktop-client/bin/remove-untranslated-languages
|
||||||
|
|
||||||
yarn workspace @actual-app/web build --mode=desktop # electron specific build
|
yarn workspace @actual-app/web build --mode=desktop # electron specific build
|
||||||
|
|
||||||
yarn workspace desktop-electron update-client
|
yarn workspace desktop-electron update-client
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@actual-app/api",
|
"name": "@actual-app/api",
|
||||||
"version": "25.2.0",
|
"version": "25.2.1",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"description": "An API for Actual",
|
"description": "An API for Actual",
|
||||||
"engines": {
|
"engines": {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@actual-app/web",
|
"name": "@actual-app/web",
|
||||||
"version": "25.2.0",
|
"version": "25.2.1",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"files": [
|
"files": [
|
||||||
"build"
|
"build"
|
||||||
|
|||||||
@@ -36,33 +36,43 @@ export const defaultReport: CustomReportEntity = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const balanceTypeOptions = [
|
const balanceTypeOptions = [
|
||||||
{ description: t('Payment'), format: 'totalDebts' as const },
|
{ description: t('Payment'), key: 'Payment', format: 'totalDebts' as const },
|
||||||
{ description: t('Deposit'), format: 'totalAssets' as const },
|
{ description: t('Deposit'), key: 'Deposit', format: 'totalAssets' as const },
|
||||||
{ description: t('Net'), format: 'totalTotals' as const },
|
{ description: t('Net'), key: 'Net', format: 'totalTotals' as const },
|
||||||
{ description: t('Net Payment'), format: 'netDebts' as const },
|
{
|
||||||
{ description: t('Net Deposit'), format: 'netAssets' as const },
|
description: t('Net Payment'),
|
||||||
|
key: 'Net Payment',
|
||||||
|
format: 'netDebts' as const,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
description: t('Net Deposit'),
|
||||||
|
key: 'Net Deposit',
|
||||||
|
format: 'netAssets' as const,
|
||||||
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
const groupByOptions = [
|
const groupByOptions = [
|
||||||
{ description: 'Category' },
|
{ description: t('Category'), key: 'Category' },
|
||||||
{ description: 'Group' },
|
{ description: t('Group'), key: 'Group' },
|
||||||
{ description: 'Payee' },
|
{ description: t('Payee'), key: 'Payee' },
|
||||||
{ description: 'Account' },
|
{ description: t('Account'), key: 'Account' },
|
||||||
{ description: 'Interval' },
|
{ description: t('Interval'), key: 'Interval' },
|
||||||
];
|
];
|
||||||
|
|
||||||
const sortByOptions: {
|
const sortByOptions: {
|
||||||
description: string;
|
description: string;
|
||||||
|
key: string;
|
||||||
format: sortByOpType;
|
format: sortByOpType;
|
||||||
}[] = [
|
}[] = [
|
||||||
{ description: t('Ascending'), format: 'asc' as const },
|
{ description: t('Ascending'), key: 'Ascending', format: 'asc' as const },
|
||||||
{ description: t('Descending'), format: 'desc' as const },
|
{ description: t('Descending'), key: 'Descending', format: 'desc' as const },
|
||||||
{ description: t('Name'), format: 'name' as const },
|
{ description: t('Name'), key: 'Name', format: 'name' as const },
|
||||||
{ description: t('Budget'), format: 'budget' as const },
|
{ description: t('Budget'), key: 'Budget', format: 'budget' as const },
|
||||||
];
|
];
|
||||||
|
|
||||||
export type dateRangeProps = {
|
export type dateRangeProps = {
|
||||||
description: string;
|
description: string;
|
||||||
|
key: string;
|
||||||
name: number | string;
|
name: number | string;
|
||||||
type?: string;
|
type?: string;
|
||||||
Daily: boolean;
|
Daily: boolean;
|
||||||
@@ -74,6 +84,7 @@ export type dateRangeProps = {
|
|||||||
const dateRangeOptions: dateRangeProps[] = [
|
const dateRangeOptions: dateRangeProps[] = [
|
||||||
{
|
{
|
||||||
description: t('This week'),
|
description: t('This week'),
|
||||||
|
key: 'This week',
|
||||||
name: 0,
|
name: 0,
|
||||||
type: 'Week',
|
type: 'Week',
|
||||||
Daily: true,
|
Daily: true,
|
||||||
@@ -83,6 +94,7 @@ const dateRangeOptions: dateRangeProps[] = [
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
description: t('Last week'),
|
description: t('Last week'),
|
||||||
|
key: 'Last week',
|
||||||
name: 1,
|
name: 1,
|
||||||
type: 'Week',
|
type: 'Week',
|
||||||
Daily: true,
|
Daily: true,
|
||||||
@@ -92,6 +104,7 @@ const dateRangeOptions: dateRangeProps[] = [
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
description: t('This month'),
|
description: t('This month'),
|
||||||
|
key: 'This month',
|
||||||
name: 0,
|
name: 0,
|
||||||
type: 'Month',
|
type: 'Month',
|
||||||
Daily: true,
|
Daily: true,
|
||||||
@@ -101,6 +114,7 @@ const dateRangeOptions: dateRangeProps[] = [
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
description: t('Last month'),
|
description: t('Last month'),
|
||||||
|
key: 'Last month',
|
||||||
name: 1,
|
name: 1,
|
||||||
type: 'Month',
|
type: 'Month',
|
||||||
Daily: true,
|
Daily: true,
|
||||||
@@ -110,6 +124,7 @@ const dateRangeOptions: dateRangeProps[] = [
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
description: t('Last 3 months'),
|
description: t('Last 3 months'),
|
||||||
|
key: 'Last 3 months',
|
||||||
name: 3,
|
name: 3,
|
||||||
type: 'Month',
|
type: 'Month',
|
||||||
Daily: true,
|
Daily: true,
|
||||||
@@ -119,6 +134,7 @@ const dateRangeOptions: dateRangeProps[] = [
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
description: t('Last 6 months'),
|
description: t('Last 6 months'),
|
||||||
|
key: 'Last 6 months',
|
||||||
name: 6,
|
name: 6,
|
||||||
type: 'Month',
|
type: 'Month',
|
||||||
Daily: false,
|
Daily: false,
|
||||||
@@ -128,6 +144,7 @@ const dateRangeOptions: dateRangeProps[] = [
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
description: t('Last 12 months'),
|
description: t('Last 12 months'),
|
||||||
|
key: 'Last 12 months',
|
||||||
name: 12,
|
name: 12,
|
||||||
type: 'Month',
|
type: 'Month',
|
||||||
Daily: false,
|
Daily: false,
|
||||||
@@ -137,6 +154,7 @@ const dateRangeOptions: dateRangeProps[] = [
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
description: t('Year to date'),
|
description: t('Year to date'),
|
||||||
|
key: 'Year to date',
|
||||||
name: 'yearToDate',
|
name: 'yearToDate',
|
||||||
type: 'Month',
|
type: 'Month',
|
||||||
Daily: false,
|
Daily: false,
|
||||||
@@ -146,6 +164,7 @@ const dateRangeOptions: dateRangeProps[] = [
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
description: t('Last year'),
|
description: t('Last year'),
|
||||||
|
key: 'Last year',
|
||||||
name: 'lastYear',
|
name: 'lastYear',
|
||||||
type: 'Month',
|
type: 'Month',
|
||||||
Daily: false,
|
Daily: false,
|
||||||
@@ -155,6 +174,7 @@ const dateRangeOptions: dateRangeProps[] = [
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
description: t('All time'),
|
description: t('All time'),
|
||||||
|
key: 'All time',
|
||||||
name: 'allTime',
|
name: 'allTime',
|
||||||
type: 'Month',
|
type: 'Month',
|
||||||
Daily: false,
|
Daily: false,
|
||||||
@@ -166,6 +186,7 @@ const dateRangeOptions: dateRangeProps[] = [
|
|||||||
|
|
||||||
type intervalOptionsProps = {
|
type intervalOptionsProps = {
|
||||||
description: string;
|
description: string;
|
||||||
|
key: string;
|
||||||
name: 'Day' | 'Week' | 'Month' | 'Year';
|
name: 'Day' | 'Week' | 'Month' | 'Year';
|
||||||
format: string;
|
format: string;
|
||||||
range:
|
range:
|
||||||
@@ -178,12 +199,14 @@ type intervalOptionsProps = {
|
|||||||
const intervalOptions: intervalOptionsProps[] = [
|
const intervalOptions: intervalOptionsProps[] = [
|
||||||
{
|
{
|
||||||
description: t('Daily'),
|
description: t('Daily'),
|
||||||
|
key: 'Daily',
|
||||||
name: 'Day',
|
name: 'Day',
|
||||||
format: 'yy-MM-dd',
|
format: 'yy-MM-dd',
|
||||||
range: 'dayRangeInclusive',
|
range: 'dayRangeInclusive',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
description: t('Weekly'),
|
description: t('Weekly'),
|
||||||
|
key: 'Weekly',
|
||||||
name: 'Week',
|
name: 'Week',
|
||||||
format: 'yy-MM-dd',
|
format: 'yy-MM-dd',
|
||||||
range: 'weekRangeInclusive',
|
range: 'weekRangeInclusive',
|
||||||
@@ -191,6 +214,7 @@ const intervalOptions: intervalOptionsProps[] = [
|
|||||||
//{ value: 3, description: 'Fortnightly', name: 3},
|
//{ value: 3, description: 'Fortnightly', name: 3},
|
||||||
{
|
{
|
||||||
description: t('Monthly'),
|
description: t('Monthly'),
|
||||||
|
key: 'Monthly',
|
||||||
name: 'Month',
|
name: 'Month',
|
||||||
// eslint-disable-next-line rulesdir/typography
|
// eslint-disable-next-line rulesdir/typography
|
||||||
format: "MMM ''yy",
|
format: "MMM ''yy",
|
||||||
@@ -198,6 +222,7 @@ const intervalOptions: intervalOptionsProps[] = [
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
description: t('Yearly'),
|
description: t('Yearly'),
|
||||||
|
key: 'Yearly',
|
||||||
name: 'Year',
|
name: 'Year',
|
||||||
format: 'yyyy',
|
format: 'yyyy',
|
||||||
range: 'yearRangeInclusive',
|
range: 'yearRangeInclusive',
|
||||||
@@ -205,36 +230,29 @@ const intervalOptions: intervalOptionsProps[] = [
|
|||||||
];
|
];
|
||||||
|
|
||||||
export const ReportOptions = {
|
export const ReportOptions = {
|
||||||
groupBy: groupByOptions.map(item => item.description),
|
groupBy: groupByOptions,
|
||||||
|
groupByItems: new Set(groupByOptions.map(item => item.key)),
|
||||||
balanceType: balanceTypeOptions,
|
balanceType: balanceTypeOptions,
|
||||||
balanceTypeMap: new Map(
|
balanceTypeMap: new Map(
|
||||||
balanceTypeOptions.map(item => [item.description, item.format]),
|
balanceTypeOptions.map(item => [item.key, item.format]),
|
||||||
),
|
),
|
||||||
sortBy: sortByOptions,
|
sortBy: sortByOptions,
|
||||||
sortByMap: new Map(
|
sortByMap: new Map(sortByOptions.map(item => [item.key, item.format])),
|
||||||
sortByOptions.map(item => [item.description, item.format]),
|
|
||||||
),
|
|
||||||
dateRange: dateRangeOptions,
|
dateRange: dateRangeOptions,
|
||||||
dateRangeMap: new Map(
|
dateRangeMap: new Map(dateRangeOptions.map(item => [item.key, item.name])),
|
||||||
dateRangeOptions.map(item => [item.description, item.name]),
|
dateRangeType: new Map(dateRangeOptions.map(item => [item.key, item.type])),
|
||||||
),
|
|
||||||
dateRangeType: new Map(
|
|
||||||
dateRangeOptions.map(item => [item.description, item.type]),
|
|
||||||
),
|
|
||||||
interval: intervalOptions,
|
interval: intervalOptions,
|
||||||
intervalMap: new Map<string, 'Day' | 'Week' | 'Month' | 'Year'>(
|
intervalMap: new Map<string, 'Day' | 'Week' | 'Month' | 'Year'>(
|
||||||
intervalOptions.map(item => [item.description, item.name]),
|
intervalOptions.map(item => [item.key, item.name]),
|
||||||
),
|
|
||||||
intervalFormat: new Map(
|
|
||||||
intervalOptions.map(item => [item.description, item.format]),
|
|
||||||
),
|
),
|
||||||
|
intervalFormat: new Map(intervalOptions.map(item => [item.key, item.format])),
|
||||||
intervalRange: new Map<
|
intervalRange: new Map<
|
||||||
string,
|
string,
|
||||||
| 'dayRangeInclusive'
|
| 'dayRangeInclusive'
|
||||||
| 'weekRangeInclusive'
|
| 'weekRangeInclusive'
|
||||||
| 'rangeInclusive'
|
| 'rangeInclusive'
|
||||||
| 'yearRangeInclusive'
|
| 'yearRangeInclusive'
|
||||||
>(intervalOptions.map(item => [item.description, item.range])),
|
>(intervalOptions.map(item => [item.key, item.range])),
|
||||||
};
|
};
|
||||||
|
|
||||||
export type QueryDataEntity = {
|
export type QueryDataEntity = {
|
||||||
|
|||||||
@@ -156,7 +156,7 @@ export function ReportSidebar({
|
|||||||
const rangeOptions = useMemo(() => {
|
const rangeOptions = useMemo(() => {
|
||||||
const options: SelectOption[] = ReportOptions.dateRange
|
const options: SelectOption[] = ReportOptions.dateRange
|
||||||
.filter(f => f[customReportItems.interval as keyof dateRangeProps])
|
.filter(f => f[customReportItems.interval as keyof dateRangeProps])
|
||||||
.map(option => [option.description, option.description]);
|
.map(option => [option.key, option.description]);
|
||||||
|
|
||||||
// Append separator if necessary
|
// Append separator if necessary
|
||||||
if (dateRangeLine > 0) {
|
if (dateRangeLine > 0) {
|
||||||
@@ -230,7 +230,10 @@ export function ReportSidebar({
|
|||||||
<Select
|
<Select
|
||||||
value={customReportItems.groupBy}
|
value={customReportItems.groupBy}
|
||||||
onChange={e => onChangeSplit(e)}
|
onChange={e => onChangeSplit(e)}
|
||||||
options={ReportOptions.groupBy.map(option => [option, option])}
|
options={ReportOptions.groupBy.map(option => [
|
||||||
|
option.key,
|
||||||
|
option.description,
|
||||||
|
])}
|
||||||
disabledKeys={disabledItems('split')}
|
disabledKeys={disabledItems('split')}
|
||||||
/>
|
/>
|
||||||
</View>
|
</View>
|
||||||
@@ -249,7 +252,7 @@ export function ReportSidebar({
|
|||||||
value={customReportItems.balanceType}
|
value={customReportItems.balanceType}
|
||||||
onChange={e => onChangeBalanceType(e)}
|
onChange={e => onChangeBalanceType(e)}
|
||||||
options={ReportOptions.balanceType.map(option => [
|
options={ReportOptions.balanceType.map(option => [
|
||||||
option.description,
|
option.key,
|
||||||
option.description,
|
option.description,
|
||||||
])}
|
])}
|
||||||
disabledKeys={disabledItems('type')}
|
disabledKeys={disabledItems('type')}
|
||||||
@@ -274,14 +277,14 @@ export function ReportSidebar({
|
|||||||
if (
|
if (
|
||||||
ReportOptions.dateRange
|
ReportOptions.dateRange
|
||||||
.filter(d => !d[e as keyof dateRangeProps])
|
.filter(d => !d[e as keyof dateRangeProps])
|
||||||
.map(int => int.description)
|
.map(int => int.key)
|
||||||
.includes(customReportItems.dateRange)
|
.includes(customReportItems.dateRange)
|
||||||
) {
|
) {
|
||||||
onSelectRange(defaultsList.intervalRange.get(e) || '');
|
onSelectRange(defaultsList.intervalRange.get(e) || '');
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
options={ReportOptions.interval.map(option => [
|
options={ReportOptions.interval.map(option => [
|
||||||
option.description,
|
option.key,
|
||||||
option.description,
|
option.description,
|
||||||
])}
|
])}
|
||||||
disabledKeys={[]}
|
disabledKeys={[]}
|
||||||
|
|||||||
@@ -5,18 +5,22 @@ import { type sortByOpType } from 'loot-core/types/models';
|
|||||||
const intervalOptions = [
|
const intervalOptions = [
|
||||||
{
|
{
|
||||||
description: t('Daily'),
|
description: t('Daily'),
|
||||||
|
key: 'Daily',
|
||||||
defaultRange: 'This month',
|
defaultRange: 'This month',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
description: t('Weekly'),
|
description: t('Weekly'),
|
||||||
|
key: 'Weekly',
|
||||||
defaultRange: 'Last 3 months',
|
defaultRange: 'Last 3 months',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
description: t('Monthly'),
|
description: t('Monthly'),
|
||||||
|
key: 'Monthly',
|
||||||
defaultRange: 'Last 6 months',
|
defaultRange: 'Last 6 months',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
description: t('Yearly'),
|
description: t('Yearly'),
|
||||||
|
key: 'Yearly',
|
||||||
defaultRange: 'Year to date',
|
defaultRange: 'Year to date',
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
@@ -215,6 +219,6 @@ export const defaultsList = {
|
|||||||
modeOptions.map(item => [item.description, item.defaultGraph]),
|
modeOptions.map(item => [item.description, item.defaultGraph]),
|
||||||
),
|
),
|
||||||
intervalRange: new Map(
|
intervalRange: new Map(
|
||||||
intervalOptions.map(item => [item.description, item.defaultRange]),
|
intervalOptions.map(item => [item.key, item.defaultRange]),
|
||||||
),
|
),
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -524,7 +524,7 @@ function CustomReportInner({ report: initialReport }: CustomReportInnerProps) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const defaultItems = (item: string) => {
|
const defaultItems = (item: string) => {
|
||||||
const chooseGraph = ReportOptions.groupBy.includes(item) ? graphType : item;
|
const chooseGraph = ReportOptions.groupByItems.has(item) ? graphType : item;
|
||||||
if (
|
if (
|
||||||
(disabledGraphList(mode, chooseGraph, 'disabledSplit') || []).includes(
|
(disabledGraphList(mode, chooseGraph, 'disabledSplit') || []).includes(
|
||||||
groupBy,
|
groupBy,
|
||||||
|
|||||||
@@ -59,7 +59,7 @@ export function LanguageSettings() {
|
|||||||
variant="external"
|
variant="external"
|
||||||
to={
|
to={
|
||||||
'https://hosted.weblate.org/projects/actualbudget/actual/' +
|
'https://hosted.weblate.org/projects/actualbudget/actual/' +
|
||||||
language
|
(language ?? '')
|
||||||
}
|
}
|
||||||
linkColor="purple"
|
linkColor="purple"
|
||||||
>
|
>
|
||||||
|
|||||||
@@ -77,5 +77,9 @@ export const setI18NextLanguage = (language: string) => {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (language === i18n.language) {
|
||||||
|
return; // language is already set
|
||||||
|
}
|
||||||
|
|
||||||
i18n.changeLanguage(language || 'en');
|
i18n.changeLanguage(language || 'en');
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
"author": "Actual",
|
"author": "Actual",
|
||||||
"productName": "Actual",
|
"productName": "Actual",
|
||||||
"description": "A simple and powerful personal finance system",
|
"description": "A simple and powerful personal finance system",
|
||||||
"version": "25.2.0",
|
"version": "25.2.1",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"clean": "rm -rf dist",
|
"clean": "rm -rf dist",
|
||||||
"update-client": "bin/update-client",
|
"update-client": "bin/update-client",
|
||||||
|
|||||||
6
upcoming-release-notes/4303.md
Normal file
6
upcoming-release-notes/4303.md
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
---
|
||||||
|
category: Bugfix
|
||||||
|
authors: [jfdoming]
|
||||||
|
---
|
||||||
|
|
||||||
|
Fix crashes on reports page with translations enabled
|
||||||
6
upcoming-release-notes/4312.md
Normal file
6
upcoming-release-notes/4312.md
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
---
|
||||||
|
category: Bugfix
|
||||||
|
authors: [matt-fidd]
|
||||||
|
---
|
||||||
|
|
||||||
|
Fix broken Weblate URL in settings if the language option has never been set
|
||||||
6
upcoming-release-notes/4317.md
Normal file
6
upcoming-release-notes/4317.md
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
---
|
||||||
|
category: Bugfix
|
||||||
|
authors: [MikesGlitch]
|
||||||
|
---
|
||||||
|
|
||||||
|
Fix Electron language support
|
||||||
Reference in New Issue
Block a user