Skip to content

Commit

Permalink
Merge pull request #62 from ya-erm/dev
Browse files Browse the repository at this point in the history
Version 2.8.5
  • Loading branch information
ya-erm authored May 7, 2024
2 parents 86b84e6 + d857878 commit c45cd60
Show file tree
Hide file tree
Showing 18 changed files with 3,612 additions and 2,707 deletions.
5,898 changes: 3,319 additions & 2,579 deletions package-lock.json

Large diffs are not rendered by default.

50 changes: 25 additions & 25 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "client",
"version": "2.8.4",
"version": "2.8.5",
"private": true,
"scripts": {
"dev": "vite dev",
Expand All @@ -19,41 +19,41 @@
"generate": "npm run generate:icons && npm run generate:prisma"
},
"devDependencies": {
"@iconify/json": "^2.2.176",
"@iconify/json": "^2.2.205",
"@iconify/svelte": "^3.1.6",
"@iconify/utils": "^2.1.20",
"@playwright/test": "^1.41.1",
"@sveltejs/adapter-auto": "^3.1.1",
"@iconify/utils": "^2.1.23",
"@playwright/test": "^1.43.1",
"@sveltejs/adapter-auto": "^3.2.0",
"@sveltejs/adapter-node": "^4.0.1",
"@sveltejs/kit": "^2.5.2",
"@sveltejs/kit": "^2.5.7",
"@types/bcrypt": "^5.0.2",
"@types/uuid": "^9.0.8",
"@typescript-eslint/eslint-plugin": "^6.20.0",
"@typescript-eslint/parser": "^6.20.0",
"@vite-pwa/sveltekit": "^0.3.0",
"autoprefixer": "^10.4.17",
"dotenv": "^16.4.1",
"eslint": "^8.56.0",
"@typescript-eslint/eslint-plugin": "^6.21.0",
"@typescript-eslint/parser": "^6.21.0",
"@vite-pwa/sveltekit": "^0.5.0",
"autoprefixer": "^10.4.19",
"dotenv": "^16.4.5",
"eslint": "^8.57.0",
"eslint-config-prettier": "^9.1.0",
"eslint-plugin-svelte": "^2.35.1",
"prettier": "^3.2.4",
"prettier-plugin-svelte": "^3.1.2",
"prisma": "^5.8.1",
"svelte": "^4.2.9",
"svelte-check": "^3.6.3",
"eslint-plugin-svelte": "^2.38.0",
"prettier": "^3.2.5",
"prettier-plugin-svelte": "^3.2.3",
"prisma": "^5.13.0",
"svelte": "^4.2.15",
"svelte-check": "^3.7.0",
"svelte-i18n": "^4.0.0",
"svelte-preprocess": "^5.1.3",
"svelte-preprocess": "^5.1.4",
"tslib": "^2.6.2",
"typescript": "^5.3.3",
"vite": "^5.0.13"
"typescript": "^5.4.5",
"vite": "^5.2.10"
},
"dependencies": {
"@prisma/client": "^5.8.1",
"@vercel/analytics": "^1.1.2",
"@prisma/client": "^5.13.0",
"@vercel/analytics": "^1.2.2",
"bcrypt": "^5.1.1",
"dayjs": "^1.11.10",
"dayjs": "^1.11.11",
"idb": "^8.0.0",
"svelte-dnd-action": "^0.9.38",
"svelte-dnd-action": "^0.9.43",
"timezones-list": "^3.0.3",
"uuid": "^9.0.1"
},
Expand Down
68 changes: 54 additions & 14 deletions src/lib/data/operations.ts
Original file line number Diff line number Diff line change
@@ -1,20 +1,28 @@
import dayjs from 'dayjs';
import { derived, type Readable } from 'svelte/store';
import { derived, get } from 'svelte/store';

import { translate } from '$lib/translate';
import { showErrorToast } from '$lib/ui/toasts';
import { Logger } from '$lib/utils/logger';

import { store } from '$lib/store';
import { accountsService, accountsStore } from './accounts';
import { categoriesStore, SYSTEM_CATEGORY_TRANSFER_IN, SYSTEM_CATEGORY_TRANSFER_OUT } from './categories';
import {
SYSTEM_CATEGORY_TRANSFER_IN,
SYSTEM_CATEGORY_TRANSFER_OUT,
categoriesService,
categoriesStore,
} from './categories';
import { $initialized } from './initialized';
import type { Transaction, TransactionViewModel } from './interfaces';
import { operationTagsStore } from './operationTags';
import { operationTagsService, operationTagsStore } from './operationTags';
import { BaseService } from './service';

const logger = new Logger('OperationsService', { disabled: false });

export class OperationsService extends BaseService<Transaction> {
private _operations: Readable<TransactionViewModel[]>;
private _operations = store<TransactionViewModel[]>([]);
private _errorToastShown = false;

get $operations() {
return this._operations;
Expand All @@ -25,28 +33,51 @@ export class OperationsService extends BaseService<Transaction> {

accountsService.deleteAccountOperations = this.deleteTransactionsByAccount;

this._operations = derived(
derived(
[this.$items, $initialized, accountsStore, categoriesStore, operationTagsStore],
([transactions, initialized, accounts, _categories, tags]) => {
if (!initialized) return [];
if (!initialized) return null;

const categories = _categories.concat(SYSTEM_CATEGORY_TRANSFER_IN, SYSTEM_CATEGORY_TRANSFER_OUT);

const warnings: Array<unknown> = [];

function findAccount(id: string) {
const account = accounts.find((account) => account.id === id);
if (!account) throw new Error(`Account ${id} not found`);
if (!account) {
const deletedAccount = accountsService.deletedItems.find((account) => account.id === id);
if (!deletedAccount) {
throw new Error(`Account ${id} not found`);
}
warnings.push(`Account "${deletedAccount.name}" ${id} is deleted`);
return deletedAccount;
}
return account;
}

function findCategory(id: string) {
const category = categories.find((category) => category.id === id);
if (!category) throw new Error(`Category ${id} not found`);
if (!category) {
const deletedCategory = categoriesService.deletedItems.find((category) => category.id === id);
if (!deletedCategory) {
throw new Error(`Category ${id} not found`);
}
warnings.push(`Category "${deletedCategory.name}" ${id} is deleted`);
return deletedCategory;
}
return category;
}

function findTag(id: string) {
const tag = tags.find((tag) => tag.id === id);
if (!tag) throw new Error(`Tag ${id} not found`);
if (!tag) {
const deletedTag = operationTagsService.deletedItems.find((tag) => tag.id === id);
if (!deletedTag) {
throw new Error(`Tag ${id} not found`);
}
warnings.push(`Tag "${deletedTag.name}" ${id} is deleted`);
return deletedTag;
}
return tag;
}

Expand All @@ -56,7 +87,9 @@ export class OperationsService extends BaseService<Transaction> {

const items = transactions
.map((transaction) => {
const linkedTransaction = transactions.find((t) => t.id === transaction.linkedTransactionId);
const linkedTransaction = transaction.linkedTransactionId
? transactions.find((t) => t.id === transaction.linkedTransactionId)
: undefined;

try {
const viewModel: TransactionViewModel = {
Expand All @@ -80,14 +113,21 @@ export class OperationsService extends BaseService<Transaction> {
})
.filter((x) => x !== null);

if (problems.length) {
logger.error('Data load problems:', problems);
showErrorToast(`Data loaded with ${problems.length} problem(s)`);
const problemsCount = problems.length + warnings.length;
if (problemsCount) {
logger.error('Data load problems:', problems, warnings);
if (!this._errorToastShown) {
const $translate = get(translate);
showErrorToast($translate('common.data_problems', { values: { count: problemsCount } }));
this._errorToastShown = true;
}
}

return items;
},
);
).subscribe((items) => {
if (items) this._operations.set(items);
});
}

deleteTransactionsByAccount(accountId: string): void {
Expand Down
35 changes: 29 additions & 6 deletions src/lib/data/service.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { store } from '$lib/store';
import { derived, type Readable } from 'svelte/store';

import type {
Account,
Expand All @@ -23,23 +24,37 @@ export class BaseService<T extends EntityType> implements Initialisable, Journal
private _name: string;
private _journalKey: keyof JournalOperation;
private _storageName: StorageName;
private _items = store<T[]>([]);
private _items = store<{
active: T[];
deleted: T[];
}>({
active: [],
deleted: [],
});
private _activeItems: Readable<T[]>;

/** Constructor */
constructor(serviceName: string, storageName: StorageName, journalOperationKey: keyof JournalOperation) {
this._name = serviceName;
this._storageName = storageName;
this._journalKey = journalOperationKey;

this._activeItems = derived(this._items, ({ active }) => active);
}

/** List of all items */
public get items() {
return this._items.value;
return this._items.value.active;
}

/** Readable store of all items */
protected get $items() {
return this._items.readable;
return this._activeItems;
}

/** List of deleted items */
public get deletedItems() {
return this._items.value.deleted;
}

/** Service name */
Expand All @@ -57,7 +72,10 @@ export class BaseService<T extends EntityType> implements Initialisable, Journal
const db = await useDB();
const member = membersService.getSelectedMember();
const allItems = (await db.getAllFromIndex(this._storageName, 'by-owner', member.uuid)) as unknown as T[];
this._items.set(allItems.filter((x) => !x.deleted));
this._items.set({
active: allItems.filter((x) => !x.deleted),
deleted: allItems.filter((x) => x.deleted),
});
}

/** Save one item to local DB */
Expand All @@ -80,9 +98,14 @@ export class BaseService<T extends EntityType> implements Initialisable, Journal

this._items.update((prev) => {
const dict = new Map<string, T>();
prev.forEach((item) => dict.set(item.id, item));
prev.active.forEach((item) => dict.set(item.id, item));
prev.deleted.forEach((item) => dict.set(item.id, item));
items.forEach((item) => dict.set(item.id, item));
return Array.from(dict.values()).filter((x) => !x.deleted);
const allItems = Array.from(dict.values());
return {
active: allItems.filter((x) => !x.deleted),
deleted: allItems.filter((x) => x.deleted),
};
});

if (saveToDB) {
Expand Down
1 change: 1 addition & 0 deletions src/lib/translate/en.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ export const enDict: Dictionary = {
'common.count': '{count} pcs.',
'common.show': 'Show',
'common.hide': 'Hide',
'common.data_problems': 'Data storage initialization finished with {count, plural, =1 {# error} other {# errors}}',
// Timezones
'timezones.select_time_zone': 'Select time zone',
'timezones.current_time_zone': 'Current time zone',
Expand Down
1 change: 1 addition & 0 deletions src/lib/translate/messages.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ export type Messages =
| 'common.count'
| 'common.show'
| 'common.hide'
| 'common.data_problems'
// Timezones
| 'timezones.select_time_zone'
| 'timezones.current_time_zone'
Expand Down
2 changes: 2 additions & 0 deletions src/lib/translate/ru.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ export const ruDict: Dictionary = {
'common.count': '{count} шт.',
'common.show': 'Показать',
'common.hide': 'Скрыть',
'common.data_problems':
'{count, plural, one {Обнаружена # ошибка} few {Обнаружено # ошибки} other {Обнаружено # ошибок}} при инициализации данных',
// Timezones
'timezones.select_time_zone': 'Выберите часовой пояс',
'timezones.current_time_zone': 'Текущий часовой пояс',
Expand Down
7 changes: 6 additions & 1 deletion src/lib/ui/list/ListSwitchItem.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,9 @@
<div class="theme-switch">
<input type="checkbox" bind:checked />
<span>{title}</span>
<Switch bind:checked />
<div class="switch">
<Switch bind:checked />
</div>
</div>
</ListGroupItem>

Expand All @@ -33,4 +35,7 @@
.theme-switch input {
display: none;
}
.switch {
pointer-events: none;
}
</style>
19 changes: 13 additions & 6 deletions src/lib/utils/getSearchParam.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { replaceState } from '$app/navigation';
import { goto } from '$app/navigation';
import type { Page } from '@sveltejs/kit';

export function getNumberSearchParam(page: Page, name: string) {
Expand All @@ -9,12 +9,19 @@ export function getSearchParam(page: Page, name: string) {
return page.url.searchParams.get(name);
}

export async function setSearchParam(page: Page, name: string, value: string) {
page.url.searchParams.set(name, value);
replaceState(page.url, page.state);
export async function setSearchParam(
page: Page,
name: string,
value: string,
{ replace }: { replace: boolean } = { replace: true },
) {
const searchParams = new URLSearchParams(page.url.searchParams);
searchParams.set(name, value);
await goto(`?${searchParams.toString()}`, { replaceState: replace });
}

export async function deleteSearchParam(page: Page, name: string) {
page.url.searchParams.delete(name);
replaceState(page.url, page.state);
const searchParams = new URLSearchParams(page.url.searchParams);
searchParams.delete(name);
await goto(`?${searchParams.toString()}`, { replaceState: true });
}
2 changes: 1 addition & 1 deletion src/routes/accounts/AccountCards.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@

<div class="accounts-container" bind:this={accountsContainerElement}>
<div class="accounts-list" bind:this={accountListElement} on:scroll={handleScroll}>
{#each accounts as account}
{#each accounts as account (account.id)}
<div class="account-card" on:click={() => scrollToCard(account.id)} aria-hidden>
<AccountCard
{account}
Expand Down
Loading

0 comments on commit c45cd60

Please sign in to comment.