mirror of
https://github.com/firefly-iii/firefly-iii.git
synced 2026-05-27 04:58:41 +00:00
Compare commits
16 Commits
develop-20
...
adminlte
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
58b3338f6c | ||
|
|
eee46562be | ||
|
|
0579049b8b | ||
|
|
db73ae39d1 | ||
|
|
972d75dc41 | ||
|
|
7891c24f5c | ||
|
|
7fa4d67a3f | ||
|
|
5e4d6bbdb5 | ||
|
|
3cd030cd69 | ||
|
|
12baa27de9 | ||
|
|
9e60d0ca0d | ||
|
|
b3bf43e6b2 | ||
|
|
8115294582 | ||
|
|
b99c97740d | ||
|
|
e511b55c76 | ||
|
|
9ccb8e8527 |
3
.gitignore
vendored
3
.gitignore
vendored
@@ -28,3 +28,6 @@ public/v1/js/webhooks
|
||||
resources/assets/v2/node_modules
|
||||
resources/assets/v2/build
|
||||
public/v2/i18n
|
||||
|
||||
# ignore v3 build files
|
||||
resources/assets/v3/node_modules
|
||||
|
||||
@@ -22,8 +22,13 @@
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
use Carbon\Carbon;
|
||||
use FireflyIII\Exceptions\FireflyException;
|
||||
|
||||
use FireflyIII\Models\TransactionCurrency;
|
||||
use FireflyIII\Support\Facades\Amount;
|
||||
use FireflyIII\Support\Facades\Steam;
|
||||
use Illuminate\Support\Collection;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use function Safe\mb_ord;
|
||||
use function Safe\preg_match;
|
||||
use function Safe\preg_replace_callback;
|
||||
@@ -32,7 +37,7 @@ if (!function_exists('env_default_when_empty')) {
|
||||
/**
|
||||
* @return null|mixed
|
||||
*/
|
||||
function env_default_when_empty(mixed $value, bool|int|string|null $default = null): mixed
|
||||
function env_default_when_empty(mixed $value, bool | int | string | null $default = null): mixed
|
||||
{
|
||||
if (null === $value) {
|
||||
return $default;
|
||||
@@ -45,6 +50,59 @@ if (!function_exists('env_default_when_empty')) {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (!function_exists('bladeAccountBalance')) {
|
||||
function bladeAccountBalance(\FireflyIII\Models\Account $account): string
|
||||
{
|
||||
/** @var Carbon $date */
|
||||
$date = now();
|
||||
|
||||
// get the date from the current session. If it's in the future, keep `now()`.
|
||||
/** @var Carbon $session */
|
||||
$session = clone session('end', today(config('app.timezone'))->endOfMonth());
|
||||
if ($session->lt($date)) {
|
||||
$date = $session->copy();
|
||||
$date->endOfDay();
|
||||
}
|
||||
Log::debug(sprintf('twig balance: Call finalAccountBalance with date/time "%s"', $date->toIso8601String()));
|
||||
|
||||
// 2025-10-08 replace finalAccountBalance with accountsBalancesOptimized.
|
||||
$info = Steam::accountsBalancesOptimized(new Collection()->push($account), $date)[$account->id];
|
||||
// $info = Steam::finalAccountBalance($account, $date);
|
||||
$currency = Steam::getAccountCurrency($account);
|
||||
$primary = Amount::getPrimaryCurrency();
|
||||
$convertToPrimary = Amount::convertToPrimary();
|
||||
$usePrimary = $convertToPrimary && $primary->id !== $currency->id;
|
||||
$currency ??= $primary;
|
||||
$strings = [];
|
||||
foreach ($info as $key => $balance) {
|
||||
if ('balance' === $key) {
|
||||
// balance in account currency.
|
||||
if (!$usePrimary) {
|
||||
$strings[] = Amount::formatAnything($currency, $balance, false);
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
if ('pc_balance' === $key) {
|
||||
// balance in primary currency.
|
||||
if ($usePrimary) {
|
||||
$strings[] = Amount::formatAnything($primary, $balance, false);
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
// for multi currency accounts.
|
||||
if ($usePrimary && $key !== $primary->code) {
|
||||
$strings[] = Amount::formatAnything(Amount::getTransactionCurrencyByCode($key), $balance, false);
|
||||
}
|
||||
}
|
||||
|
||||
return implode(', ', $strings);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
if (!function_exists('string_is_equal')) {
|
||||
function string_is_equal(string $left, string $right): bool
|
||||
{
|
||||
@@ -64,14 +122,14 @@ if (!function_exists('blade_escape_js')) {
|
||||
return preg_replace_callback(
|
||||
'#[^a-zA-Z0-9,\._]#Su',
|
||||
static function ($matches) {
|
||||
$char = $matches[0];
|
||||
$char = $matches[0];
|
||||
|
||||
/*
|
||||
* A few characters have short escape sequences in JSON and JavaScript.
|
||||
* Escape sequences supported only by JavaScript, not JSON, are omitted.
|
||||
* \" is also supported but omitted, because the resulting string is not HTML safe.
|
||||
*/
|
||||
$short = match ($char) {
|
||||
$short = match ($char) {
|
||||
'\\' => '\\\\',
|
||||
'/' => '\/',
|
||||
"\x08" => '\b',
|
||||
@@ -93,9 +151,9 @@ if (!function_exists('blade_escape_js')) {
|
||||
|
||||
// Split characters outside the BMP into surrogate pairs
|
||||
// https://tools.ietf.org/html/rfc2781.html#section-2.1
|
||||
$u = $codepoint - 0x10_000;
|
||||
$high = 0xD800 | ($u >> 10);
|
||||
$low = 0xDC00 | ($u & 0x3FF);
|
||||
$u = $codepoint - 0x10_000;
|
||||
$high = 0xD800 | ($u >> 10);
|
||||
$low = 0xDC00 | ($u & 0x3FF);
|
||||
|
||||
return \sprintf('\u%04X\u%04X', $high, $low);
|
||||
},
|
||||
|
||||
@@ -118,11 +118,19 @@ class ProcessesUpdatedTransactionGroup
|
||||
|
||||
$all = $group->transactionJournals()->get()->pluck('id')->toArray();
|
||||
|
||||
/** @var Account $sourceAccount */
|
||||
$sourceAccount = $first->transactions()->where('amount', '<', '0')->first()->account;
|
||||
/** @var Account|null $sourceAccount */
|
||||
$sourceAccount = $first->transactions()->where('amount', '<', '0')->first()?->account;
|
||||
|
||||
/** @var Account $destAccount */
|
||||
$destAccount = $first->transactions()->where('amount', '>', '0')->first()->account;
|
||||
/** @var Account|null $destAccount */
|
||||
$destAccount = $first->transactions()->where('amount', '>', '0')->first()?->account;
|
||||
if(null === $destAccount) {
|
||||
Log::warning(sprintf('Group #%d (journal #%d) has no destination account. Break.', $group->id, $first->id));
|
||||
return 0;
|
||||
}
|
||||
if(null === $sourceAccount) {
|
||||
Log::warning(sprintf('Group #%d (journal #%d) has no source account. Break.', $group->id, $first->id));
|
||||
return 0;
|
||||
}
|
||||
|
||||
$type = $first->transactionType->type;
|
||||
$effect = 0;
|
||||
|
||||
@@ -23,7 +23,9 @@ declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Providers;
|
||||
|
||||
use FireflyIII\Models\Account;
|
||||
use Illuminate\Support\Facades\Blade;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Illuminate\Support\Facades\Response;
|
||||
use Illuminate\Support\Facades\Route;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
@@ -57,6 +59,24 @@ class AppServiceProvider extends ServiceProvider
|
||||
return response()->json($value)->withHeaders($headers);
|
||||
});
|
||||
|
||||
// blade extension for active menu link
|
||||
Blade::directive('menuItemActive', function (string $route): string {
|
||||
$name = Route::getCurrentRoute()->getName() ?? '';
|
||||
Log::debug(sprintf('menuItemActive("%s", "%s")', $route, $name));
|
||||
if (str_contains($route, $name)) {
|
||||
return 'active';
|
||||
}
|
||||
|
||||
return '';
|
||||
});
|
||||
|
||||
// blade extension for account balance.
|
||||
Blade::directive('balance', function (string $account): string {
|
||||
var_dump($account);exit;
|
||||
return $account;
|
||||
return 'blablabla';
|
||||
});
|
||||
|
||||
// blade extension
|
||||
Blade::directive('activeXRoutePartial', function (string $route): string {
|
||||
$name = Route::getCurrentRoute()->getName() ?? '';
|
||||
|
||||
@@ -203,6 +203,8 @@ class JournalUpdateService
|
||||
|
||||
/**
|
||||
* Get destination transaction.
|
||||
*
|
||||
* @throws FireflyException
|
||||
*/
|
||||
private function getDestinationTransaction(): Transaction
|
||||
{
|
||||
@@ -211,6 +213,9 @@ class JournalUpdateService
|
||||
$result = $this->transactionJournal->transactions()->where('amount', '>', 0)->first();
|
||||
$this->destinationTransaction = $result;
|
||||
}
|
||||
if(null === $this->destinationTransaction) {
|
||||
throw new FireflyException(sprintf('Destination transaction for transaction group #%d could not be found.', $this->transactionGroup->transaction_group_id ?? 0));
|
||||
}
|
||||
|
||||
return $this->destinationTransaction;
|
||||
}
|
||||
|
||||
@@ -875,4 +875,31 @@ class Steam
|
||||
|
||||
return $return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Will format the amount by the currency related to the given account.
|
||||
*/
|
||||
public function formatAmountBySymbol(string $amount, ?string $symbol = null, ?int $decimalPlaces = null, ?bool $coloured = null): string
|
||||
{
|
||||
if (null === $symbol) {
|
||||
$message = sprintf(
|
||||
'formatAmountBySymbol("%s", %s, %d, %s) was called without a symbol. Please browse to /flush to clear your cache.',
|
||||
$amount,
|
||||
var_export($symbol, true),
|
||||
$decimalPlaces,
|
||||
var_export($coloured, true)
|
||||
);
|
||||
Log::error($message);
|
||||
$currency = Amount::getPrimaryCurrency();
|
||||
}
|
||||
if (null !== $symbol) {
|
||||
$decimalPlaces ??= 2;
|
||||
$coloured ??= true;
|
||||
$currency = new TransactionCurrency();
|
||||
$currency->symbol = $symbol;
|
||||
$currency->decimal_places = $decimalPlaces;
|
||||
}
|
||||
|
||||
return Amount::formatAnything($currency, $amount, $coloured);
|
||||
}
|
||||
}
|
||||
|
||||
27
app/View/Components/Dashboard/Boxes.php
Normal file
27
app/View/Components/Dashboard/Boxes.php
Normal file
@@ -0,0 +1,27 @@
|
||||
<?php
|
||||
|
||||
namespace FireflyIII\View\Components\Dashboard;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use Closure;
|
||||
use Illuminate\Contracts\View\View;
|
||||
use Illuminate\View\Component;
|
||||
|
||||
class Boxes extends Component
|
||||
{
|
||||
/**
|
||||
* Create a new component instance.
|
||||
*/
|
||||
public function __construct(public Carbon $start, public Carbon $end)
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the view / contents that represent the component.
|
||||
*/
|
||||
public function render(): View|Closure|string
|
||||
{
|
||||
return view('components.dashboard.boxes');
|
||||
}
|
||||
}
|
||||
27
app/View/Components/Generic/Amount.php
Normal file
27
app/View/Components/Generic/Amount.php
Normal file
@@ -0,0 +1,27 @@
|
||||
<?php
|
||||
|
||||
namespace FireflyIII\View\Components\Generic;
|
||||
|
||||
use Closure;
|
||||
use Illuminate\Contracts\View\View;
|
||||
use Illuminate\View\Component;
|
||||
|
||||
class Amount extends Component
|
||||
{
|
||||
|
||||
/**
|
||||
* Create a new component instance.
|
||||
*/
|
||||
public function __construct(public array $transaction)
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the view / contents that represent the component.
|
||||
*/
|
||||
public function render(): View|Closure|string
|
||||
{
|
||||
return view('components.generic.amount');
|
||||
}
|
||||
}
|
||||
26
app/View/Components/Layout/CreateMenu.php
Normal file
26
app/View/Components/Layout/CreateMenu.php
Normal file
@@ -0,0 +1,26 @@
|
||||
<?php
|
||||
|
||||
namespace FireflyIII\View\Components\Layout;
|
||||
|
||||
use Closure;
|
||||
use Illuminate\Contracts\View\View;
|
||||
use Illuminate\View\Component;
|
||||
|
||||
class CreateMenu extends Component
|
||||
{
|
||||
/**
|
||||
* Create a new component instance.
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the view / contents that represent the component.
|
||||
*/
|
||||
public function render(): View|Closure|string
|
||||
{
|
||||
return view('components.layout.create-menu');
|
||||
}
|
||||
}
|
||||
26
app/View/Components/Layout/FavIcons.php
Normal file
26
app/View/Components/Layout/FavIcons.php
Normal file
@@ -0,0 +1,26 @@
|
||||
<?php
|
||||
|
||||
namespace FireflyIII\View\Components\Layout;
|
||||
|
||||
use Closure;
|
||||
use Illuminate\Contracts\View\View;
|
||||
use Illuminate\View\Component;
|
||||
|
||||
class FavIcons extends Component
|
||||
{
|
||||
/**
|
||||
* Create a new component instance.
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the view / contents that represent the component.
|
||||
*/
|
||||
public function render(): View|Closure|string
|
||||
{
|
||||
return view('components.layout.fav-icons');
|
||||
}
|
||||
}
|
||||
26
app/View/Components/Layout/Sidebar.php
Normal file
26
app/View/Components/Layout/Sidebar.php
Normal file
@@ -0,0 +1,26 @@
|
||||
<?php
|
||||
|
||||
namespace FireflyIII\View\Components\Layout;
|
||||
|
||||
use Closure;
|
||||
use Illuminate\Contracts\View\View;
|
||||
use Illuminate\View\Component;
|
||||
|
||||
class Sidebar extends Component
|
||||
{
|
||||
/**
|
||||
* Create a new component instance.
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the view / contents that represent the component.
|
||||
*/
|
||||
public function render(): View|Closure|string
|
||||
{
|
||||
return view('components.layout.sidebar');
|
||||
}
|
||||
}
|
||||
26
app/View/Components/Layout/TopBoxes.php
Normal file
26
app/View/Components/Layout/TopBoxes.php
Normal file
@@ -0,0 +1,26 @@
|
||||
<?php
|
||||
|
||||
namespace FireflyIII\View\Components\Layout;
|
||||
|
||||
use Closure;
|
||||
use Illuminate\Contracts\View\View;
|
||||
use Illuminate\View\Component;
|
||||
|
||||
class TopBoxes extends Component
|
||||
{
|
||||
/**
|
||||
* Create a new component instance.
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the view / contents that represent the component.
|
||||
*/
|
||||
public function render(): View|Closure|string
|
||||
{
|
||||
return view('components.layout.top-boxes');
|
||||
}
|
||||
}
|
||||
26
app/View/Components/Layout/UserMenu.php
Normal file
26
app/View/Components/Layout/UserMenu.php
Normal file
@@ -0,0 +1,26 @@
|
||||
<?php
|
||||
|
||||
namespace FireflyIII\View\Components\Layout;
|
||||
|
||||
use Closure;
|
||||
use Illuminate\Contracts\View\View;
|
||||
use Illuminate\View\Component;
|
||||
|
||||
class UserMenu extends Component
|
||||
{
|
||||
/**
|
||||
* Create a new component instance.
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the view / contents that represent the component.
|
||||
*/
|
||||
public function render(): View|Closure|string
|
||||
{
|
||||
return view('components.layout.user-menu');
|
||||
}
|
||||
}
|
||||
26
app/View/Components/Lists/GroupsTiny.php
Normal file
26
app/View/Components/Lists/GroupsTiny.php
Normal file
@@ -0,0 +1,26 @@
|
||||
<?php
|
||||
|
||||
namespace FireflyIII\View\Components\Lists;
|
||||
|
||||
use Closure;
|
||||
use Illuminate\Contracts\View\View;
|
||||
use Illuminate\View\Component;
|
||||
|
||||
class GroupsTiny extends Component
|
||||
{
|
||||
/**
|
||||
* Create a new component instance.
|
||||
*/
|
||||
public function __construct(public array $transactions)
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the view / contents that represent the component.
|
||||
*/
|
||||
public function render(): View|Closure|string
|
||||
{
|
||||
return view('components.lists.groups-tiny');
|
||||
}
|
||||
}
|
||||
@@ -49,7 +49,7 @@ return [
|
||||
|
|
||||
*/
|
||||
|
||||
'view' => 'partials/layout/breadcrumbs',
|
||||
'view' => 'partials/layout/breadcrumbs-v3',
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
|
||||
322
package-lock.json
generated
322
package-lock.json
generated
@@ -7,7 +7,8 @@
|
||||
"hasInstallScript": true,
|
||||
"workspaces": [
|
||||
"resources/assets/v1",
|
||||
"resources/assets/v2"
|
||||
"resources/assets/v2",
|
||||
"resources/assets/v3"
|
||||
],
|
||||
"dependencies": {
|
||||
"patch-package": "^8.0.1"
|
||||
@@ -1915,9 +1916,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@oxc-project/types": {
|
||||
"version": "0.130.0",
|
||||
"resolved": "https://registry.npmjs.org/@oxc-project/types/-/types-0.130.0.tgz",
|
||||
"integrity": "sha512-ibD2usx9JRu7f5pu2tMKMI4cpA4NgXJQoYRP4pQ7Pxmn1l6k/53qWtQWZayhYy3X4QZkt90Ot+mJEaeXouio6Q==",
|
||||
"version": "0.132.0",
|
||||
"resolved": "https://registry.npmjs.org/@oxc-project/types/-/types-0.132.0.tgz",
|
||||
"integrity": "sha512-FESMOxil5Se014ui/Eq8fT5uHJo6nIRwH0PfJrZJXs6Gek3ZVFOrpUv3YIZT20m+extU98Hg1Ym72U58rlsxUQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"funding": {
|
||||
@@ -2259,9 +2260,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@rolldown/binding-android-arm64": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@rolldown/binding-android-arm64/-/binding-android-arm64-1.0.1.tgz",
|
||||
"integrity": "sha512-fJI3I0r3C3Oj/zdBCpaCmBRZYf07xpaq4yCfDDoSFm+beWNzbIl26puW8RraUdugoJw/95zerNOn6jasAhzSmg==",
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/@rolldown/binding-android-arm64/-/binding-android-arm64-1.0.2.tgz",
|
||||
"integrity": "sha512-ZS4D1JPGn/MYQN/SYDWftIE/nVsM8j/AFOYEzAoOE2O3NktQOZru+/vYXGbR/qtdLdIfGCP0lcoJiYVzsEz+iQ==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
@@ -2276,9 +2277,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@rolldown/binding-darwin-arm64": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-arm64/-/binding-darwin-arm64-1.0.1.tgz",
|
||||
"integrity": "sha512-cKnAhWEsV7TPcA/5EAteDp6KcJZBQ2G+BqE7zayMMi7kMvwRsbv7WT9aOnn0WNl4SKEIf43vjS31iUPu80nzXg==",
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-arm64/-/binding-darwin-arm64-1.0.2.tgz",
|
||||
"integrity": "sha512-vdFA9+C/rekyGce7WqHs/xoT0ioZEWaOFyZLIV1mEeNFaFDUQrPIo8Vs2GvJ6eetb3rzDUtUBgzto3ExpXJB3w==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
@@ -2293,9 +2294,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@rolldown/binding-darwin-x64": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-x64/-/binding-darwin-x64-1.0.1.tgz",
|
||||
"integrity": "sha512-YKrVwQjIRBPo+5G/u03wGjbdy4q7pyzCe93DK9VJ7zkVmeg8LJ7GbgsiHWdR4xSoe4CAXRD7Bcjgbtr64bkXNg==",
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-x64/-/binding-darwin-x64-1.0.2.tgz",
|
||||
"integrity": "sha512-BewSOwTHazv77DTYiAZXSqqKZ4KP/KonFisDMVU7PImxoWfB2aepnPhd2E4SWz3zDzYgDNbs6jBmTdgNnF02GA==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
@@ -2310,9 +2311,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@rolldown/binding-freebsd-x64": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@rolldown/binding-freebsd-x64/-/binding-freebsd-x64-1.0.1.tgz",
|
||||
"integrity": "sha512-z/oBsREo46SsFqBwYtFe0kpJeBijAT48O/WXLI4suiCLBkr03RTtTJMCzSdDd2znlh8VJizL09XVkQgk8IZonw==",
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/@rolldown/binding-freebsd-x64/-/binding-freebsd-x64-1.0.2.tgz",
|
||||
"integrity": "sha512-m41o7M0YWtUdqk61Tb+jnKb2rN++iRdIASlExkUoKfIAH30DOHCB8fVLzSUpbWHHU8esmEioY62PxzexE8MBuA==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
@@ -2327,9 +2328,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@rolldown/binding-linux-arm-gnueabihf": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-1.0.1.tgz",
|
||||
"integrity": "sha512-ik8q7GM11zxvYxFc2PeDcT6TBvhCQMaUxfph/M5l9sKuTs/Sjg3L+Byw0F7w0ZVLBZmx30P+gG0ECzzN+MFcmQ==",
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-1.0.2.tgz",
|
||||
"integrity": "sha512-jcojB9H7W/jS29pMKWAK1N+fU99vXodHDTatS3b3y/XSOCiHo0kkA74pL3jJmkoQtYpOCxDvaKs1fo2Ij/1X5w==",
|
||||
"cpu": [
|
||||
"arm"
|
||||
],
|
||||
@@ -2344,9 +2345,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@rolldown/binding-linux-arm64-gnu": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.0.1.tgz",
|
||||
"integrity": "sha512-QoSx2EkyrrdZ6kcyE8stqZ62t0Yra8Fs5ia9lOxJrh6TMQJK7gQKmscdTHf7pOXKREKrVwOtJcQG3qVSfc866A==",
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.0.2.tgz",
|
||||
"integrity": "sha512-1jn6qDU5iiOgFgygDzKUuKP0maTi0/f1+sBLgvij/76C77Nm3ts6ufz9Bjg5q5dduxiUIxtq86JIoBvo1xQ4Ig==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
@@ -2361,9 +2362,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@rolldown/binding-linux-arm64-musl": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.0.1.tgz",
|
||||
"integrity": "sha512-uwNwFpwKeNiZawfAWBgg0VIztPTV3ihhh1vV334h9ivnNLorxnQMU6Fz8wG1Zb4Qh9LC1/MkcyT3YlDXG3Rsgg==",
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.0.2.tgz",
|
||||
"integrity": "sha512-QVLO/czFMdoMFSqlX3bcswcJNm/23r+qoa/jgtmFc/qEp6/jXmIkDjF/XIo8dPfGaiwy1xfQn8o77L79GeXFgw==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
@@ -2378,9 +2379,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@rolldown/binding-linux-ppc64-gnu": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@rolldown/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-1.0.1.tgz",
|
||||
"integrity": "sha512-zY1bul7OWr7DFBiJ++wofXvnr8B45ce3QsQUhKrIhXsygAh7bTkwyeM1bi1a2g5C/yC/N8TZyGDEoMfm/l9mpg==",
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/@rolldown/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-1.0.2.tgz",
|
||||
"integrity": "sha512-hgO5Abm0w5UL6FEa2iFnZqo2KlK7TQ5QhV5x09hujBf7t5KzHQ1VmfPuTpqRy/rNlSxua3eWH374xxiVrP+lcA==",
|
||||
"cpu": [
|
||||
"ppc64"
|
||||
],
|
||||
@@ -2395,9 +2396,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@rolldown/binding-linux-s390x-gnu": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@rolldown/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-1.0.1.tgz",
|
||||
"integrity": "sha512-0frlsT/f4Ft6I7SMESTKnF3cZsdicQn1dCMkF/jT9wDLE+gGoiQfv1nmT9e+s7s/fekvvy6tZM2jHvI2tkbJDQ==",
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/@rolldown/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-1.0.2.tgz",
|
||||
"integrity": "sha512-fy8rXxuYEu602abC8MUNaPjYLIFzReOaEIEMKMUa0rFEUxNpVXhs15KSSQ4qlqSaM7B6rcj9rDZgADh/IGDzLQ==",
|
||||
"cpu": [
|
||||
"s390x"
|
||||
],
|
||||
@@ -2412,9 +2413,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@rolldown/binding-linux-x64-gnu": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.0.1.tgz",
|
||||
"integrity": "sha512-XABVmGp9Tg0WspTVvwduTc4fpqy6JnAUrSQe6OuyqD/03nI7r0O9OWUkMIwFrjKAIqolvqoA4ZrJppgwE0Gxmw==",
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.0.2.tgz",
|
||||
"integrity": "sha512-0+bOkiQ779+r1WpoHOWHqncvyySci0vKph+myNDYb+im6meJAzHQXay6oEgnkHuUGouM1LKTZwqKpBow6Kj7CQ==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
@@ -2429,9 +2430,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@rolldown/binding-linux-x64-musl": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-musl/-/binding-linux-x64-musl-1.0.1.tgz",
|
||||
"integrity": "sha512-bV4fzswuzVcKD90o/VM6QqKxnxlDq0g2BISDLNVmxrnhpv1DDbyPhCIjYfvzYLV+MvkKKnQt2Q6AO86SEBULUQ==",
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-musl/-/binding-linux-x64-musl-1.0.2.tgz",
|
||||
"integrity": "sha512-mjSkrzZK5Qsl0a9d1JgILOiuZOSDTVdKENcSXBoqbzSrspLR/4/IRVDo5wd2GgZjNss/viBFJdeq+j7qH2nypw==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
@@ -2446,9 +2447,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@rolldown/binding-openharmony-arm64": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@rolldown/binding-openharmony-arm64/-/binding-openharmony-arm64-1.0.1.tgz",
|
||||
"integrity": "sha512-/Mh0Zhq3OP7fVs0kcQHZP6lZEthMGTaSf8UBQYSFEZDWGXXlEC+nJ6EqenaK2t4LBXMe3A+K/G2BVXXdtOr4PQ==",
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/@rolldown/binding-openharmony-arm64/-/binding-openharmony-arm64-1.0.2.tgz",
|
||||
"integrity": "sha512-1v5vHasdfQAZoEHakBV72LIFAC9JjnymsiKxp+GEr/ma3+NJCPSaYK+qavInOovJkgwFrs7GccX2d6IgDA3Z5w==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
@@ -2463,9 +2464,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@rolldown/binding-wasm32-wasi": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@rolldown/binding-wasm32-wasi/-/binding-wasm32-wasi-1.0.1.tgz",
|
||||
"integrity": "sha512-+1xc9X45l8ufsBAm6Gjvx2qDRIY9lTVt0cgWNcJ+1gdhXvkbxePA60yRTwSTuXL09CMhyJmjpV7E3NoyxbqFQQ==",
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/@rolldown/binding-wasm32-wasi/-/binding-wasm32-wasi-1.0.2.tgz",
|
||||
"integrity": "sha512-mb1VobWn6NheziTk5/WEaR6AKVbrwT5sOi6C7zk3gy/pD1qtJfU1j4PgTo2NJnOtbL9Dl3Aeei8w9jJ7qC2jZQ==",
|
||||
"cpu": [
|
||||
"wasm32"
|
||||
],
|
||||
@@ -2482,9 +2483,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@rolldown/binding-win32-arm64-msvc": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@rolldown/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.0.1.tgz",
|
||||
"integrity": "sha512-1D+UqZdfnuR+Jy1GgMJwi85bD40H21uNmOPRWQhw4oRSuolZ/B5rixZ45DK2KXOTCvmVCecauWgEhbw8bI7tOw==",
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/@rolldown/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.0.2.tgz",
|
||||
"integrity": "sha512-SqKonF56vA/L2yHwHYcEp2P34URpOZ7d1fS635cTkpDnUtEGdUbhI6NzsPdqeSWvAAeGDrxjWjNmibDIdFf9/A==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
@@ -2499,9 +2500,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@rolldown/binding-win32-x64-msvc": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@rolldown/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.0.1.tgz",
|
||||
"integrity": "sha512-INAycaWuhlOK3wk4mRHGsdgwYWmd9cChdPdE9bwWmy6rn9VqVNYNFGhOdXrofXUxwHIncSiPNb8tNm8knDVIeQ==",
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/@rolldown/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.0.2.tgz",
|
||||
"integrity": "sha512-v7qRI7gXLRINcOGXt+7YmAZ6iFuyZVMIoXAxhd8oP+DR9dLfL9GfNIx7PLMxmhZdvq8waUJBQiWN9EKNy+TRBQ==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
@@ -2631,28 +2632,6 @@
|
||||
"@types/node": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/eslint": {
|
||||
"version": "9.6.1",
|
||||
"resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-9.6.1.tgz",
|
||||
"integrity": "sha512-FXx2pKgId/WyYo2jXw63kk7/+TY7u7AziEJxJAnSFzHlqTAS3Ync6SvgYAN/k4/PQpnnVuzoMuVnByKK2qp0ag==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@types/estree": "*",
|
||||
"@types/json-schema": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/eslint-scope": {
|
||||
"version": "3.7.7",
|
||||
"resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.7.tgz",
|
||||
"integrity": "sha512-MzMFlSLBqNF2gcHWO0G1vP/YQyfvrxZ0bF+u7mzUdZ1/xK4A4sru+nraZz5i3iEIk1l1uyicaDVTB4QbbEkAYg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@types/eslint": "*",
|
||||
"@types/estree": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/estree": {
|
||||
"version": "1.0.9",
|
||||
"resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.9.tgz",
|
||||
@@ -3848,6 +3827,22 @@
|
||||
"@popperjs/core": "^2.11.8"
|
||||
}
|
||||
},
|
||||
"node_modules/bootstrap-icons": {
|
||||
"version": "1.13.1",
|
||||
"resolved": "https://registry.npmjs.org/bootstrap-icons/-/bootstrap-icons-1.13.1.tgz",
|
||||
"integrity": "sha512-ijombt4v6bv5CLeXvRWKy7CuM3TRTuPEuGaGKvTV5cz65rQSY8RQ2JcHt6b90cBBAC7s8fsf2EkQDldzCoXUjw==",
|
||||
"funding": [
|
||||
{
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/twbs"
|
||||
},
|
||||
{
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/bootstrap"
|
||||
}
|
||||
],
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/bootstrap-sass": {
|
||||
"version": "3.4.3",
|
||||
"resolved": "https://registry.npmjs.org/bootstrap-sass/-/bootstrap-sass-3.4.3.tgz",
|
||||
@@ -4498,6 +4493,47 @@
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/concurrently": {
|
||||
"version": "9.2.1",
|
||||
"resolved": "https://registry.npmjs.org/concurrently/-/concurrently-9.2.1.tgz",
|
||||
"integrity": "sha512-fsfrO0MxV64Znoy8/l1vVIjjHa29SZyyqPgQBwhiDcaW8wJc2W3XWVOGx4M3oJBnv/zdUZIIp1gDeS98GzP8Ng==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"chalk": "4.1.2",
|
||||
"rxjs": "7.8.2",
|
||||
"shell-quote": "1.8.3",
|
||||
"supports-color": "8.1.1",
|
||||
"tree-kill": "1.2.2",
|
||||
"yargs": "17.7.2"
|
||||
},
|
||||
"bin": {
|
||||
"conc": "dist/bin/concurrently.js",
|
||||
"concurrently": "dist/bin/concurrently.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/open-cli-tools/concurrently?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/concurrently/node_modules/supports-color": {
|
||||
"version": "8.1.1",
|
||||
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz",
|
||||
"integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"has-flag": "^4.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/chalk/supports-color?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/connect-history-api-fallback": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/connect-history-api-fallback/-/connect-history-api-fallback-2.0.0.tgz",
|
||||
@@ -4995,9 +5031,9 @@
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/date-fns": {
|
||||
"version": "4.1.0",
|
||||
"resolved": "https://registry.npmjs.org/date-fns/-/date-fns-4.1.0.tgz",
|
||||
"integrity": "sha512-Ukq0owbQXxa/U3EGtsdVBkR1w7KOQ5gIBqdH2hkvknzZPYvBxb/aa6E8L7tmjFtkwZBu3UXBbjIgPo/Ez4xaNg==",
|
||||
"version": "4.3.0",
|
||||
"resolved": "https://registry.npmjs.org/date-fns/-/date-fns-4.3.0.tgz",
|
||||
"integrity": "sha512-OYcL+3N/jyWbYdFGqoMAhytDgxP9pbYPUUiRCOgn4Fewaadk9l/Wam4Avciiyp2BgkpfQyBV9B+ehnVJych+eQ==",
|
||||
"license": "MIT",
|
||||
"funding": {
|
||||
"type": "github",
|
||||
@@ -8466,6 +8502,12 @@
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/overlayscrollbars": {
|
||||
"version": "2.16.0",
|
||||
"resolved": "https://registry.npmjs.org/overlayscrollbars/-/overlayscrollbars-2.16.0.tgz",
|
||||
"integrity": "sha512-N03oje/q7j93D0aLZtoCdsDSYLmhheSsv8H7oSLE7HhdV9P/bmCURtLV/KbPye7P/bpfyt/obSfDpGUYoJ0OWg==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/p-limit": {
|
||||
"version": "2.3.0",
|
||||
"resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz",
|
||||
@@ -9917,13 +9959,13 @@
|
||||
}
|
||||
},
|
||||
"node_modules/rolldown": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/rolldown/-/rolldown-1.0.1.tgz",
|
||||
"integrity": "sha512-X0KQHljNnEkWNqqiz9zJrGunh1B0HgOxLXvnFpCOcadzcy5qohZ3tqMEUg00vncoRovXuK3ZqCT9KnnKzoInFQ==",
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/rolldown/-/rolldown-1.0.2.tgz",
|
||||
"integrity": "sha512-oZx5zVDtVB44AW3eaifgDml1gWRDZGvjcfdxonE4swNPG98PrrXjaO/KrnUjzlMnztCCRVlUueA1kCXhARGk6g==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@oxc-project/types": "=0.130.0",
|
||||
"@oxc-project/types": "=0.132.0",
|
||||
"@rolldown/pluginutils": "^1.0.0"
|
||||
},
|
||||
"bin": {
|
||||
@@ -9933,21 +9975,21 @@
|
||||
"node": "^20.19.0 || >=22.12.0"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"@rolldown/binding-android-arm64": "1.0.1",
|
||||
"@rolldown/binding-darwin-arm64": "1.0.1",
|
||||
"@rolldown/binding-darwin-x64": "1.0.1",
|
||||
"@rolldown/binding-freebsd-x64": "1.0.1",
|
||||
"@rolldown/binding-linux-arm-gnueabihf": "1.0.1",
|
||||
"@rolldown/binding-linux-arm64-gnu": "1.0.1",
|
||||
"@rolldown/binding-linux-arm64-musl": "1.0.1",
|
||||
"@rolldown/binding-linux-ppc64-gnu": "1.0.1",
|
||||
"@rolldown/binding-linux-s390x-gnu": "1.0.1",
|
||||
"@rolldown/binding-linux-x64-gnu": "1.0.1",
|
||||
"@rolldown/binding-linux-x64-musl": "1.0.1",
|
||||
"@rolldown/binding-openharmony-arm64": "1.0.1",
|
||||
"@rolldown/binding-wasm32-wasi": "1.0.1",
|
||||
"@rolldown/binding-win32-arm64-msvc": "1.0.1",
|
||||
"@rolldown/binding-win32-x64-msvc": "1.0.1"
|
||||
"@rolldown/binding-android-arm64": "1.0.2",
|
||||
"@rolldown/binding-darwin-arm64": "1.0.2",
|
||||
"@rolldown/binding-darwin-x64": "1.0.2",
|
||||
"@rolldown/binding-freebsd-x64": "1.0.2",
|
||||
"@rolldown/binding-linux-arm-gnueabihf": "1.0.2",
|
||||
"@rolldown/binding-linux-arm64-gnu": "1.0.2",
|
||||
"@rolldown/binding-linux-arm64-musl": "1.0.2",
|
||||
"@rolldown/binding-linux-ppc64-gnu": "1.0.2",
|
||||
"@rolldown/binding-linux-s390x-gnu": "1.0.2",
|
||||
"@rolldown/binding-linux-x64-gnu": "1.0.2",
|
||||
"@rolldown/binding-linux-x64-musl": "1.0.2",
|
||||
"@rolldown/binding-openharmony-arm64": "1.0.2",
|
||||
"@rolldown/binding-wasm32-wasi": "1.0.2",
|
||||
"@rolldown/binding-win32-arm64-msvc": "1.0.2",
|
||||
"@rolldown/binding-win32-x64-msvc": "1.0.2"
|
||||
}
|
||||
},
|
||||
"node_modules/run-parallel": {
|
||||
@@ -9974,6 +10016,16 @@
|
||||
"queue-microtask": "^1.2.2"
|
||||
}
|
||||
},
|
||||
"node_modules/rxjs": {
|
||||
"version": "7.8.2",
|
||||
"resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.2.tgz",
|
||||
"integrity": "sha512-dhKf903U/PQZY6boNNtAGdWbG85WAbjT/1xYoZIC7FAY0yWapOBQVsVrDl58W86//e1VpMNBtRV4MaXfdMySFA==",
|
||||
"dev": true,
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"tslib": "^2.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/safe-buffer": {
|
||||
"version": "5.2.1",
|
||||
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
|
||||
@@ -10767,6 +10819,13 @@
|
||||
"node": ">=10.13.0"
|
||||
}
|
||||
},
|
||||
"node_modules/tailwindcss": {
|
||||
"version": "4.3.0",
|
||||
"resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.3.0.tgz",
|
||||
"integrity": "sha512-y6nxMGB1nMW9R6k96e5gdIFzcfL/gTJRNaqGes1YvkLnPVXzWgbqFF2yLC0T8G774n24cx3Pe8XrKoniCOAH+Q==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/tapable": {
|
||||
"version": "2.3.3",
|
||||
"resolved": "https://registry.npmjs.org/tapable/-/tapable-2.3.3.tgz",
|
||||
@@ -11052,6 +11111,16 @@
|
||||
"integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/tree-kill": {
|
||||
"version": "1.2.2",
|
||||
"resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.2.tgz",
|
||||
"integrity": "sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"bin": {
|
||||
"tree-kill": "cli.js"
|
||||
}
|
||||
},
|
||||
"node_modules/tslib": {
|
||||
"version": "2.8.1",
|
||||
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz",
|
||||
@@ -11297,6 +11366,10 @@
|
||||
"resolved": "resources/assets/v2",
|
||||
"link": true
|
||||
},
|
||||
"node_modules/v3": {
|
||||
"resolved": "resources/assets/v3",
|
||||
"link": true
|
||||
},
|
||||
"node_modules/vary": {
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz",
|
||||
@@ -11308,16 +11381,16 @@
|
||||
}
|
||||
},
|
||||
"node_modules/vite": {
|
||||
"version": "8.0.13",
|
||||
"resolved": "https://registry.npmjs.org/vite/-/vite-8.0.13.tgz",
|
||||
"integrity": "sha512-MFtjBYgzmSxmgA4RAfjIyXWpGe1oALnjgUTzzV7QLx/TKxCzjtMH6Fd9/eVK+5Fg1qNoz5VAwsmMs/NofrmJvw==",
|
||||
"version": "8.0.14",
|
||||
"resolved": "https://registry.npmjs.org/vite/-/vite-8.0.14.tgz",
|
||||
"integrity": "sha512-s4BJJ+5y1pYL6Otw51FHhVJQhPnuRinKig64g/1+EUNaJsd3gCKdD31IPFvswUgW9/60QT9oFHbZHbQK5imcxw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"lightningcss": "^1.32.0",
|
||||
"picomatch": "^4.0.4",
|
||||
"postcss": "^8.5.14",
|
||||
"rolldown": "1.0.1",
|
||||
"postcss": "^8.5.15",
|
||||
"rolldown": "1.0.2",
|
||||
"tinyglobby": "^0.2.16"
|
||||
},
|
||||
"bin": {
|
||||
@@ -11616,13 +11689,12 @@
|
||||
"license": "BSD-2-Clause"
|
||||
},
|
||||
"node_modules/webpack": {
|
||||
"version": "5.105.4",
|
||||
"resolved": "https://registry.npmjs.org/webpack/-/webpack-5.105.4.tgz",
|
||||
"integrity": "sha512-jTywjboN9aHxFlToqb0K0Zs9SbBoW4zRUlGzI2tYNxVYcEi/IPpn+Xi4ye5jTLvX2YeLuic/IvxNot+Q1jMoOw==",
|
||||
"version": "5.107.1",
|
||||
"resolved": "https://registry.npmjs.org/webpack/-/webpack-5.107.1.tgz",
|
||||
"integrity": "sha512-mvdIWxj/H6QsfgDdH9djne3a5dYcmEmtsXGESkypaGN5jXjF/b+9KDlmTDQ2TKlFUeA2fI9Y65kihD30JOdB+Q==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@types/eslint-scope": "^3.7.7",
|
||||
"@types/estree": "^1.0.8",
|
||||
"@types/json-schema": "^7.0.15",
|
||||
"@webassemblyjs/ast": "^1.14.1",
|
||||
@@ -11632,21 +11704,20 @@
|
||||
"acorn-import-phases": "^1.0.3",
|
||||
"browserslist": "^4.28.1",
|
||||
"chrome-trace-event": "^1.0.2",
|
||||
"enhanced-resolve": "^5.20.0",
|
||||
"es-module-lexer": "^2.0.0",
|
||||
"enhanced-resolve": "^5.21.4",
|
||||
"es-module-lexer": "^2.1.0",
|
||||
"eslint-scope": "5.1.1",
|
||||
"events": "^3.2.0",
|
||||
"glob-to-regexp": "^0.4.1",
|
||||
"graceful-fs": "^4.2.11",
|
||||
"json-parse-even-better-errors": "^2.3.1",
|
||||
"loader-runner": "^4.3.1",
|
||||
"mime-types": "^2.1.27",
|
||||
"loader-runner": "^4.3.2",
|
||||
"mime-db": "^1.54.0",
|
||||
"neo-async": "^2.6.2",
|
||||
"schema-utils": "^4.3.3",
|
||||
"tapable": "^2.3.0",
|
||||
"terser-webpack-plugin": "^5.3.17",
|
||||
"terser-webpack-plugin": "^5.5.0",
|
||||
"watchpack": "^2.5.1",
|
||||
"webpack-sources": "^3.3.4"
|
||||
"webpack-sources": "^3.4.1"
|
||||
},
|
||||
"bin": {
|
||||
"webpack": "bin/webpack.js"
|
||||
@@ -12010,6 +12081,16 @@
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/webpack/node_modules/mime-db": {
|
||||
"version": "1.54.0",
|
||||
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.54.0.tgz",
|
||||
"integrity": "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 0.6"
|
||||
}
|
||||
},
|
||||
"node_modules/webpack/node_modules/schema-utils": {
|
||||
"version": "4.3.3",
|
||||
"resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.3.3.tgz",
|
||||
@@ -12258,7 +12339,7 @@
|
||||
},
|
||||
"resources/assets/v1": {
|
||||
"dependencies": {
|
||||
"date-fns": "4.1.0",
|
||||
"date-fns": "^4.3.0",
|
||||
"stream-browserify": "^3.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
@@ -12276,7 +12357,7 @@
|
||||
"vue-i18n": "^8",
|
||||
"vue-loader": "^15",
|
||||
"vue-template-compiler": "^2.7",
|
||||
"webpack": "~5.105.4"
|
||||
"webpack": "^5.107.1"
|
||||
}
|
||||
},
|
||||
"resources/assets/v2": {
|
||||
@@ -12292,7 +12373,7 @@
|
||||
"chart.js": "^4",
|
||||
"chartjs-adapter-date-fns": "^3.0.0",
|
||||
"chartjs-chart-sankey": "^0.14.0",
|
||||
"date-fns": "4.1.0",
|
||||
"date-fns": "^4.3.0",
|
||||
"i18next": "^26.0.3",
|
||||
"i18next-chained-backend": "^5.0.0",
|
||||
"i18next-http-backend": "^3.0.1",
|
||||
@@ -12305,7 +12386,22 @@
|
||||
"laravel-vite-plugin": "^3",
|
||||
"patch-package": "^8",
|
||||
"sass": "^1",
|
||||
"vite": "=8.0.13",
|
||||
"vite": "^8.0.14",
|
||||
"vite-plugin-manifest-sri": "^0.2.0"
|
||||
}
|
||||
},
|
||||
"resources/assets/v3": {
|
||||
"dependencies": {
|
||||
"admin-lte": "^4.0.0",
|
||||
"alpinejs": "^3.15.12",
|
||||
"bootstrap-icons": "^1.13.1",
|
||||
"overlayscrollbars": "^2.16.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"concurrently": "^9.0.1",
|
||||
"laravel-vite-plugin": "^3.1",
|
||||
"tailwindcss": "^4.0.0",
|
||||
"vite": "^8.0.0",
|
||||
"vite-plugin-manifest-sri": "^0.2.0"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,7 +4,8 @@
|
||||
},
|
||||
"workspaces": [
|
||||
"resources/assets/v1",
|
||||
"resources/assets/v2"
|
||||
"resources/assets/v2",
|
||||
"resources/assets/v3"
|
||||
],
|
||||
"devDependencies": {
|
||||
"postcss": "^8.5.14"
|
||||
|
||||
0
public/v1/js/.gitkeep
Normal file → Executable file
0
public/v1/js/.gitkeep
Normal file → Executable file
1
public/v1/js/css/app.css
Executable file
1
public/v1/js/css/app.css
Executable file
@@ -0,0 +1 @@
|
||||
|
||||
1
public/v1/js/css/layout.css
Executable file
1
public/v1/js/css/layout.css
Executable file
@@ -0,0 +1 @@
|
||||
|
||||
@@ -22,6 +22,8 @@
|
||||
"/public/v1/js/app_vue.js.LICENSE.txt": "/public/v1/js/app_vue.js.LICENSE.txt",
|
||||
"/public/v1/js/create_transaction.js": "/public/v1/js/create_transaction.js",
|
||||
"/public/v1/js/create_transaction.js.LICENSE.txt": "/public/v1/js/create_transaction.js.LICENSE.txt",
|
||||
"/public/v1/js/css/app.css": "/public/v1/js/css/app.css",
|
||||
"/public/v1/js/css/layout.css": "/public/v1/js/css/layout.css",
|
||||
"/public/v1/js/edit_transaction.js": "/public/v1/js/edit_transaction.js",
|
||||
"/public/v1/js/edit_transaction.js.LICENSE.txt": "/public/v1/js/edit_transaction.js.LICENSE.txt",
|
||||
"/public/v1/js/exchange-rates/index.js": "/public/v1/js/exchange-rates/index.js",
|
||||
@@ -97,6 +99,10 @@
|
||||
"/public/v1/js/ff/transactions/mass/edit-bulk.js": "/public/v1/js/ff/transactions/mass/edit-bulk.js",
|
||||
"/public/v1/js/ff/transactions/mass/edit.js": "/public/v1/js/ff/transactions/mass/edit.js",
|
||||
"/public/v1/js/ff/transactions/show.js": "/public/v1/js/ff/transactions/show.js",
|
||||
"/public/v1/js/js/layout.js": "/public/v1/js/js/layout.js",
|
||||
"/public/v1/js/js/layout.js.LICENSE.txt": "/public/v1/js/js/layout.js.LICENSE.txt",
|
||||
"/public/v1/js/layout.js": "/public/v1/js/layout.js",
|
||||
"/public/v1/js/layout.js.LICENSE.txt": "/public/v1/js/layout.js.LICENSE.txt",
|
||||
"/public/v1/js/lib/Chart.bundle.min.js": "/public/v1/js/lib/Chart.bundle.min.js",
|
||||
"/public/v1/js/lib/accounting.min.js": "/public/v1/js/lib/accounting.min.js",
|
||||
"/public/v1/js/lib/bootstrap-multiselect.js": "/public/v1/js/lib/bootstrap-multiselect.js",
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
"prod": "mix --production"
|
||||
},
|
||||
"dependencies": {
|
||||
"date-fns": "4.1.0",
|
||||
"date-fns": "4.3.0",
|
||||
"stream-browserify": "^3.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
@@ -28,6 +28,6 @@
|
||||
"vue-i18n": "^8",
|
||||
"vue-loader": "^15",
|
||||
"vue-template-compiler": "^2.7",
|
||||
"webpack": "~5.105.4"
|
||||
"webpack": "~5.107.1"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
"laravel-vite-plugin": "^3",
|
||||
"patch-package": "^8",
|
||||
"sass": "^1",
|
||||
"vite": "=8.0.13",
|
||||
"vite": "=8.0.14",
|
||||
"vite-plugin-manifest-sri": "^0.2.0"
|
||||
},
|
||||
"dependencies": {
|
||||
@@ -26,7 +26,7 @@
|
||||
"chart.js": "^4",
|
||||
"chartjs-adapter-date-fns": "^3.0.0",
|
||||
"chartjs-chart-sankey": "^0.14.0",
|
||||
"date-fns": "4.1.0",
|
||||
"date-fns": "4.3.0",
|
||||
"i18next": "^26.0.3",
|
||||
"i18next-chained-backend": "^5.0.0",
|
||||
"i18next-http-backend": "^3.0.1",
|
||||
|
||||
21
resources/assets/v3/css/app.css
Normal file
21
resources/assets/v3/css/app.css
Normal file
@@ -0,0 +1,21 @@
|
||||
/*
|
||||
* app.css
|
||||
* Copyright (c) 2026 james@firefly-iii.org
|
||||
*
|
||||
* This file is part of Firefly III (https://github.com/firefly-iii).
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/** here **/
|
||||
34
resources/assets/v3/js/api/preferences/index.js
Normal file
34
resources/assets/v3/js/api/preferences/index.js
Normal file
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* basic.js
|
||||
* Copyright (c) 2021 james@firefly-iii.org
|
||||
*
|
||||
* This file is part of Firefly III (https://github.com/firefly-iii).
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import {api} from "../../boot/axios";
|
||||
|
||||
export default class Preferences {
|
||||
getByName(name) {
|
||||
return api.get('/api/v1/preferences/' + name);
|
||||
}
|
||||
getByNameNow(name) {
|
||||
return api.get('/api/v1/preferences/' + name);
|
||||
}
|
||||
|
||||
postByName(name, value) {
|
||||
return api.post('/api/v1/preferences', {name: name, data: value});
|
||||
}
|
||||
}
|
||||
28
resources/assets/v3/js/api/preferences/post.js
Normal file
28
resources/assets/v3/js/api/preferences/post.js
Normal file
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
* post.js
|
||||
* Copyright (c) 2022 james@firefly-iii.org
|
||||
*
|
||||
* This file is part of Firefly III (https://github.com/firefly-iii).
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import {api} from "../../boot/axios";
|
||||
|
||||
export default class Post {
|
||||
post(name, value) {
|
||||
let url = '/api/v1/preferences';
|
||||
return api.post(url, {name: name, data: value});
|
||||
}
|
||||
}
|
||||
28
resources/assets/v3/js/api/summary/index.js
Normal file
28
resources/assets/v3/js/api/summary/index.js
Normal file
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
* index.js
|
||||
* Copyright (c) 2023 james@firefly-iii.org
|
||||
*
|
||||
* This file is part of Firefly III (https://github.com/firefly-iii).
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
|
||||
import {api} from "../../boot/axios.js";
|
||||
|
||||
export default class Summary {
|
||||
get(start, end, code) {
|
||||
return api.get('/api/v1/summary/basic', {params: {start: start, end: end, code: code}});
|
||||
}
|
||||
}
|
||||
21
resources/assets/v3/js/app.js
Normal file
21
resources/assets/v3/js/app.js
Normal file
@@ -0,0 +1,21 @@
|
||||
/*
|
||||
* app.js
|
||||
* Copyright (c) 2026 james@firefly-iii.org
|
||||
*
|
||||
* This file is part of Firefly III (https://github.com/firefly-iii).
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
// unused, see the specific pages.
|
||||
40
resources/assets/v3/js/boot/axios.js
Normal file
40
resources/assets/v3/js/boot/axios.js
Normal file
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* axios.js
|
||||
* Copyright (c) 2022 james@firefly-iii.org
|
||||
*
|
||||
* This file is part of Firefly III (https://github.com/firefly-iii).
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import axios from 'axios'
|
||||
|
||||
// Be careful when using SSR for cross-request state pollution
|
||||
// due to creating a Singleton instance here;
|
||||
// If any client changes this (global) instance, it might be a
|
||||
// good idea to move this instance creation inside of the
|
||||
// "export default () => {}" function below (which runs individually
|
||||
// for each client)
|
||||
|
||||
|
||||
// for use inside Vue files (Options API) through this.$axios and this.$api
|
||||
|
||||
|
||||
const url = '/';
|
||||
const api = axios.create({baseURL: url, withCredentials: true});
|
||||
|
||||
axios.defaults.withCredentials = true;
|
||||
axios.defaults.baseURL = url;
|
||||
|
||||
export {api}
|
||||
82
resources/assets/v3/js/boot/bootstrap.js
vendored
Normal file
82
resources/assets/v3/js/boot/bootstrap.js
vendored
Normal file
@@ -0,0 +1,82 @@
|
||||
/*
|
||||
* bootstrap.js
|
||||
* Copyright (c) 2026 james@firefly-iii.org
|
||||
*
|
||||
* This file is part of Firefly III (https://github.com/firefly-iii).
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
// JS
|
||||
import "bootstrap"
|
||||
import "admin-lte"
|
||||
import Alpine from 'alpinejs'
|
||||
import store from "store";
|
||||
import axios from 'axios';
|
||||
import observePlugin from 'store/plugins/observe';
|
||||
import {getFreshVariable} from "v2/src/store/get-fresh-variable.js";
|
||||
import {getVariable} from "v2/src/store/get-variable.js";
|
||||
import {getViewRange} from "v2/src/support/get-viewrange.js";
|
||||
import {loadTranslations} from "v2/src/support/load-translations.js";
|
||||
|
||||
store.addPlugin(observePlugin);
|
||||
|
||||
window.bootstrapped = false;
|
||||
window.store = store;
|
||||
window.Alpine = Alpine
|
||||
|
||||
window.axios = axios;
|
||||
window.axios.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest';
|
||||
|
||||
// always grab the preference "marker" from Firefly III.
|
||||
getFreshVariable('lastActivity').then((serverValue) => {
|
||||
if(null === serverValue) {
|
||||
console.log('Server value is null in getFreshVariable.');
|
||||
throw new Error('401 in getFreshVariable.');
|
||||
}
|
||||
const localValue = store.get('lastActivity');
|
||||
store.set('cacheValid', localValue === serverValue);
|
||||
store.set('lastActivity', serverValue);
|
||||
console.log('Server value: ' + serverValue);
|
||||
console.log('Local value: ' + localValue);
|
||||
console.log('Cache valid: ' + (localValue === serverValue));
|
||||
}).then(() => {
|
||||
Promise.all([
|
||||
getVariable('viewRange'),
|
||||
getVariable('darkMode'),
|
||||
getVariable('locale'),
|
||||
getVariable('language')
|
||||
]).then((values) => {
|
||||
if (!store.get('start') || !store.get('end')) {
|
||||
// calculate new start and end, and store them.
|
||||
const range = getViewRange(values[0], new Date);
|
||||
store.set('start', range.start);
|
||||
store.set('end', range.end);
|
||||
}
|
||||
|
||||
// save local in window.__ something
|
||||
window.__localeId__ = values[2];
|
||||
store.set('language', values[3]);
|
||||
store.set('locale', values[3]);
|
||||
loadTranslations(values[3]).then(() => {
|
||||
const event = new Event('firefly-iii-bootstrapped');
|
||||
document.dispatchEvent(event);
|
||||
window.bootstrapped = true;
|
||||
console.log('Bootstrapped!');
|
||||
});
|
||||
});
|
||||
}).catch((error) => {
|
||||
console.error('Error while bootstrapping: ' + error);
|
||||
});
|
||||
|
||||
190
resources/assets/v3/js/pages/dashboard/boxes.js
Normal file
190
resources/assets/v3/js/pages/dashboard/boxes.js
Normal file
@@ -0,0 +1,190 @@
|
||||
/*
|
||||
* boxes.js
|
||||
* Copyright (c) 2026 james@firefly-iii.org
|
||||
*
|
||||
* This file is part of Firefly III (https://github.com/firefly-iii).
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
|
||||
import Summary from "../../api/summary/index.js";
|
||||
import {format} from "date-fns";
|
||||
import {getVariable} from "../../store/get-variable.js";
|
||||
import formatMoney from "../../util/format-money.js";
|
||||
import {getCacheKey} from "../../support/get-cache-key.js";
|
||||
import {cleanupCache} from "../../support/cleanup-cache.js";
|
||||
|
||||
let afterPromises = false;
|
||||
export default () => ({
|
||||
balanceBox: {amounts: [], subtitles: []},
|
||||
billBox: {paid: [], unpaid: []},
|
||||
leftBox: {left: [], perDay: []},
|
||||
netBox: {net: []},
|
||||
convertToPrimary: false,
|
||||
loading: false,
|
||||
boxData: null,
|
||||
boxOptions: null,
|
||||
eventListeners: {
|
||||
['@convert-to-primary.window'](event){
|
||||
this.convertToPrimary = event.detail;
|
||||
this.accountList = [];
|
||||
console.log('I heard that! (dashboard/boxes)');
|
||||
this.boxData = null;
|
||||
this.loadBoxes();
|
||||
}
|
||||
},
|
||||
|
||||
getFreshData() {
|
||||
const start = new Date(window.store.get('start'));
|
||||
const end = new Date(window.store.get('end'));
|
||||
// TODO cache key is hard coded, problem?
|
||||
const boxesCacheKey = getCacheKey('ds_boxes_data', {convertToPrimary: this.convertToPrimary, start: start, end: end});
|
||||
cleanupCache();
|
||||
|
||||
//const cacheValid = window.store.get('cacheValid');
|
||||
let cachedData = window.store.get(boxesCacheKey);
|
||||
const cacheValid = false; // force refresh
|
||||
|
||||
if (cacheValid && typeof cachedData !== 'undefined') {
|
||||
this.boxData = cachedData;
|
||||
this.generateOptions(this.boxData);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// get stuff
|
||||
let getter = new Summary();
|
||||
getter.get(format(start, 'yyyy-MM-dd'), format(end, 'yyyy-MM-dd'), null).then((response) => {
|
||||
this.boxData = response.data;
|
||||
window.store.set(boxesCacheKey, response.data);
|
||||
this.generateOptions(this.boxData);
|
||||
});
|
||||
},
|
||||
generateOptions(data) {
|
||||
this.balanceBox = {amounts: [], subtitles: []};
|
||||
this.billBox = {paid: [], unpaid: []};
|
||||
this.leftBox = {left: [], perDay: []};
|
||||
this.netBox = {net: []};
|
||||
let subtitles = {};
|
||||
|
||||
// process new content:
|
||||
for (const i in data) {
|
||||
if (data.hasOwnProperty(i)) {
|
||||
const current = data[i];
|
||||
if (!current.hasOwnProperty('key')) {
|
||||
continue;
|
||||
}
|
||||
let key = current.key;
|
||||
// console.log('NOT PRIMARY CURRENCY');
|
||||
if (key.startsWith('balance-in-')) {
|
||||
this.balanceBox.amounts.push(formatMoney(current.monetary_value, current.currency_code));
|
||||
continue;
|
||||
}
|
||||
// spent info is used in subtitle:
|
||||
if (key.startsWith('spent-in-')) {
|
||||
// prep subtitles (for later)
|
||||
if (!subtitles.hasOwnProperty(current.currency_code)) {
|
||||
subtitles[current.currency_code] = '';
|
||||
}
|
||||
// append the amount spent.
|
||||
subtitles[current.currency_code] =
|
||||
subtitles[current.currency_code] +
|
||||
formatMoney(current.monetary_value, current.currency_code);
|
||||
continue;
|
||||
}
|
||||
// earned info is used in subtitle:
|
||||
if (key.startsWith('earned-in-')) {
|
||||
// prep subtitles (for later)
|
||||
if (!subtitles.hasOwnProperty(current.currency_code)) {
|
||||
subtitles[current.currency_code] = '';
|
||||
}
|
||||
// prepend the amount earned.
|
||||
subtitles[current.currency_code] =
|
||||
formatMoney(current.monetary_value, current.currency_code) + ' + ' +
|
||||
subtitles[current.currency_code];
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
if (key.startsWith('bills-unpaid-in-')) {
|
||||
this.billBox.unpaid.push(formatMoney(current.monetary_value, current.currency_code));
|
||||
continue;
|
||||
}
|
||||
if (key.startsWith('bills-paid-in-')) {
|
||||
this.billBox.paid.push(formatMoney(current.monetary_value, current.currency_code));
|
||||
continue;
|
||||
}
|
||||
if (key.startsWith('left-to-spend-in-')) {
|
||||
this.leftBox.left.push(formatMoney(current.monetary_value, current.currency_code));
|
||||
continue;
|
||||
}
|
||||
if (key.startsWith('left-per-day-to-spend-in-')) {
|
||||
this.leftBox.perDay.push(formatMoney(current.monetary_value, current.currency_code));
|
||||
continue;
|
||||
}
|
||||
if (key.startsWith('net-worth-in-')) {
|
||||
this.netBox.net.push(formatMoney(current.monetary_value, current.currency_code));
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
for (let i in subtitles) {
|
||||
if (subtitles.hasOwnProperty(i)) {
|
||||
this.balanceBox.subtitles.push(subtitles[i]);
|
||||
}
|
||||
}
|
||||
this.loading = false;
|
||||
},
|
||||
loadBoxes() {
|
||||
if (true === this.loading) {
|
||||
return;
|
||||
}
|
||||
this.loading = true;
|
||||
if (null === this.boxData) {
|
||||
this.getFreshData();
|
||||
return;
|
||||
}
|
||||
this.generateOptions(this.boxData);
|
||||
this.loading = false;
|
||||
},
|
||||
|
||||
// Getter
|
||||
init() {
|
||||
// console.log('boxes init');
|
||||
// TODO can be replaced by "getVariables"
|
||||
Promise.all([getVariable('viewRange'), getVariable('convert_to_primary', false)]).then((values) => {
|
||||
// console.log('boxes after promises');
|
||||
afterPromises = true;
|
||||
this.convertToPrimary = values[1];
|
||||
this.loadBoxes();
|
||||
});
|
||||
window.store.observe('end', () => {
|
||||
if (!afterPromises) {
|
||||
return;
|
||||
}
|
||||
// console.log('boxes observe end');
|
||||
this.boxData = null;
|
||||
this.loadBoxes();
|
||||
});
|
||||
window.store.observe('convert_to_primary', (newValue) => {
|
||||
if (!afterPromises) {
|
||||
return;
|
||||
}
|
||||
// console.log('boxes observe convertToPrimary');
|
||||
this.convertToPrimary = newValue;
|
||||
this.loadBoxes();
|
||||
});
|
||||
},
|
||||
});
|
||||
65
resources/assets/v3/js/pages/dashboard/dashboard.js
Normal file
65
resources/assets/v3/js/pages/dashboard/dashboard.js
Normal file
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
* dashboard.js
|
||||
* Copyright (c) 2026 james@firefly-iii.org
|
||||
*
|
||||
* This file is part of Firefly III (https://github.com/firefly-iii).
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
// CSS
|
||||
// import "admin-lte/dist/css/adminlte.min.css"
|
||||
// Plus Bootstrap and dependency CSS
|
||||
import "bootstrap-icons/font/bootstrap-icons.css"
|
||||
// import "overlayscrollbars/styles/overlayscrollbars.css"
|
||||
|
||||
|
||||
import '../../boot/bootstrap.js';
|
||||
import sidebar from '../../pages/shared/sidebar.js';
|
||||
import boxes from './boxes.js';
|
||||
|
||||
let index = function () {
|
||||
return {
|
||||
foo2: 'bar2',
|
||||
init() {
|
||||
console.log('init op index')
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
const comps = {
|
||||
index,
|
||||
sidebar,
|
||||
boxes
|
||||
};
|
||||
|
||||
function loadPage(comps) {
|
||||
Object.keys(comps).forEach(comp => {
|
||||
let data = comps[comp]();
|
||||
Alpine.data(comp, () => data);
|
||||
});
|
||||
Alpine.start();
|
||||
}
|
||||
|
||||
// wait for load until bootstrapped event is received.
|
||||
document.addEventListener('firefly-iii-bootstrapped', () => {
|
||||
console.log('Loaded through event listener.');
|
||||
loadPage(comps);
|
||||
});
|
||||
// or is bootstrapped before event is triggered.
|
||||
if (window.bootstrapped) {
|
||||
console.log('Loaded through window variable.');
|
||||
loadPage(comps);
|
||||
}
|
||||
31
resources/assets/v3/js/pages/shared/sidebar.js
Normal file
31
resources/assets/v3/js/pages/shared/sidebar.js
Normal file
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* sidebar.js
|
||||
* Copyright (c) 2026 james@firefly-iii.org
|
||||
*
|
||||
* This file is part of Firefly III (https://github.com/firefly-iii).
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
export default () => ({
|
||||
foo: 'bar',
|
||||
init() {
|
||||
console.log('init op sidebar')
|
||||
},
|
||||
logoutUser(e) {
|
||||
e.preventDefault();
|
||||
document.getElementById('logout-form').submit();
|
||||
console.log('Logout user');
|
||||
}
|
||||
});
|
||||
64
resources/assets/v3/js/store/get-variable.js
Normal file
64
resources/assets/v3/js/store/get-variable.js
Normal file
@@ -0,0 +1,64 @@
|
||||
/*
|
||||
* get-variable.js
|
||||
* Copyright (c) 2023 james@firefly-iii.org
|
||||
*
|
||||
* This file is part of Firefly III (https://github.com/firefly-iii).
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import Get from "../api/preferences/index.js";
|
||||
import Post from "../api/preferences/post.js";
|
||||
|
||||
export function getVariable(name, defaultValue = null) {
|
||||
const validCache = window.store.get('cacheValid');
|
||||
// currently unused, window.X can be used by the blade template
|
||||
// to make things available quicker than if the store has to grab it through the API.
|
||||
// then again, it's not that slow.
|
||||
if (validCache && window.hasOwnProperty(name)) {
|
||||
console.log('Returning "'+name+'" from window: ' + window[name]);
|
||||
return Promise.resolve(window[name]);
|
||||
}
|
||||
// load from store2, if it's present.
|
||||
const fromStore = window.store.get(name);
|
||||
if (validCache && typeof fromStore !== 'undefined') {
|
||||
console.log('Returning "'+name+'" from store: ' + fromStore);
|
||||
return Promise.resolve(fromStore);
|
||||
}
|
||||
let getter = (new Get);
|
||||
|
||||
return getter.getByName(name).then((response) => {
|
||||
console.log('Returning "'+name+'" from server: ' + parseResponse(name, response));
|
||||
return Promise.resolve(parseResponse(name, response));
|
||||
}).catch((error) => {
|
||||
if('' === defaultValue) {
|
||||
// do not try to store empty strings.
|
||||
return Promise.resolve(defaultValue);
|
||||
}
|
||||
// preference does not exist (yet).
|
||||
// POST it and then return it anyway.
|
||||
let poster = (new Post);
|
||||
return poster.post(name, defaultValue).then((response) => {
|
||||
console.log('Returning "'+name+'" from POST: ' + parseResponse(name, response));
|
||||
return Promise.resolve(parseResponse(name, response));
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
export function parseResponse(name, response) {
|
||||
let value = response.data.data.attributes.data;
|
||||
window.store.set(name, value);
|
||||
return value;
|
||||
}
|
||||
|
||||
34
resources/assets/v3/js/support/cleanup-cache.js
Normal file
34
resources/assets/v3/js/support/cleanup-cache.js
Normal file
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* load-translations.js
|
||||
* Copyright (c) 2023 james@firefly-iii.org
|
||||
*
|
||||
* This file is part of Firefly III (https://github.com/firefly-iii).
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import {format} from "date-fns";
|
||||
import store from "store";
|
||||
|
||||
function cleanupCache() {
|
||||
const localValue = store.get('lastActivity');
|
||||
|
||||
store.each(function(value, key) {
|
||||
if(key.startsWith('dcx') && !key.includes(localValue)) {
|
||||
store.remove(key);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
export {cleanupCache};
|
||||
96
resources/assets/v3/js/support/get-cache-key.js
Normal file
96
resources/assets/v3/js/support/get-cache-key.js
Normal file
@@ -0,0 +1,96 @@
|
||||
/*
|
||||
* load-translations.js
|
||||
* Copyright (c) 2023 james@firefly-iii.org
|
||||
*
|
||||
* This file is part of Firefly III (https://github.com/firefly-iii).
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import {format} from "date-fns";
|
||||
import store from "store";
|
||||
//const { createHash } = require('crypto');
|
||||
|
||||
|
||||
|
||||
function getCacheKey(string, params) {
|
||||
const lastActivity = store.get('lastActivity')
|
||||
let newParams = {lastActivity: lastActivity, key: string};
|
||||
|
||||
for (const key in params) {
|
||||
if (params.hasOwnProperty(key)) {
|
||||
if(params[key] === null || params[key] === undefined) {
|
||||
newParams[key] = '';
|
||||
continue;
|
||||
}
|
||||
if(params[key] instanceof Date) {
|
||||
newParams[key] = format(params[key], 'yMMdd');
|
||||
continue;
|
||||
}
|
||||
newParams[key] = params[key];
|
||||
}
|
||||
}
|
||||
return 'dcx_' + md5(JSON.stringify(newParams)).substring(0,12) + lastActivity;
|
||||
}
|
||||
|
||||
// Formatted version of a popular md5 implementation
|
||||
// Original copyright (c) Paul Johnston & Greg Holt.
|
||||
// The function itself is now 42 lines long.
|
||||
|
||||
function md5(inputString) {
|
||||
var hc="0123456789abcdef";
|
||||
function rh(n) {var j,s="";for(j=0;j<=3;j++) s+=hc.charAt((n>>(j*8+4))&0x0F)+hc.charAt((n>>(j*8))&0x0F);return s;}
|
||||
function ad(x,y) {var l=(x&0xFFFF)+(y&0xFFFF);var m=(x>>16)+(y>>16)+(l>>16);return (m<<16)|(l&0xFFFF);}
|
||||
function rl(n,c) {return (n<<c)|(n>>>(32-c));}
|
||||
function cm(q,a,b,x,s,t) {return ad(rl(ad(ad(a,q),ad(x,t)),s),b);}
|
||||
function ff(a,b,c,d,x,s,t) {return cm((b&c)|((~b)&d),a,b,x,s,t);}
|
||||
function gg(a,b,c,d,x,s,t) {return cm((b&d)|(c&(~d)),a,b,x,s,t);}
|
||||
function hh(a,b,c,d,x,s,t) {return cm(b^c^d,a,b,x,s,t);}
|
||||
function ii(a,b,c,d,x,s,t) {return cm(c^(b|(~d)),a,b,x,s,t);}
|
||||
function sb(x) {
|
||||
var i;var nblk=((x.length+8)>>6)+1;var blks=new Array(nblk*16);for(i=0;i<nblk*16;i++) blks[i]=0;
|
||||
for(i=0;i<x.length;i++) blks[i>>2]|=x.charCodeAt(i)<<((i%4)*8);
|
||||
blks[i>>2]|=0x80<<((i%4)*8);blks[nblk*16-2]=x.length*8;return blks;
|
||||
}
|
||||
var i,x=sb(""+inputString),a=1732584193,b=-271733879,c=-1732584194,d=271733878,olda,oldb,oldc,oldd;
|
||||
for(i=0;i<x.length;i+=16) {olda=a;oldb=b;oldc=c;oldd=d;
|
||||
a=ff(a,b,c,d,x[i+ 0], 7, -680876936);d=ff(d,a,b,c,x[i+ 1],12, -389564586);c=ff(c,d,a,b,x[i+ 2],17, 606105819);
|
||||
b=ff(b,c,d,a,x[i+ 3],22,-1044525330);a=ff(a,b,c,d,x[i+ 4], 7, -176418897);d=ff(d,a,b,c,x[i+ 5],12, 1200080426);
|
||||
c=ff(c,d,a,b,x[i+ 6],17,-1473231341);b=ff(b,c,d,a,x[i+ 7],22, -45705983);a=ff(a,b,c,d,x[i+ 8], 7, 1770035416);
|
||||
d=ff(d,a,b,c,x[i+ 9],12,-1958414417);c=ff(c,d,a,b,x[i+10],17, -42063);b=ff(b,c,d,a,x[i+11],22,-1990404162);
|
||||
a=ff(a,b,c,d,x[i+12], 7, 1804603682);d=ff(d,a,b,c,x[i+13],12, -40341101);c=ff(c,d,a,b,x[i+14],17,-1502002290);
|
||||
b=ff(b,c,d,a,x[i+15],22, 1236535329);a=gg(a,b,c,d,x[i+ 1], 5, -165796510);d=gg(d,a,b,c,x[i+ 6], 9,-1069501632);
|
||||
c=gg(c,d,a,b,x[i+11],14, 643717713);b=gg(b,c,d,a,x[i+ 0],20, -373897302);a=gg(a,b,c,d,x[i+ 5], 5, -701558691);
|
||||
d=gg(d,a,b,c,x[i+10], 9, 38016083);c=gg(c,d,a,b,x[i+15],14, -660478335);b=gg(b,c,d,a,x[i+ 4],20, -405537848);
|
||||
a=gg(a,b,c,d,x[i+ 9], 5, 568446438);d=gg(d,a,b,c,x[i+14], 9,-1019803690);c=gg(c,d,a,b,x[i+ 3],14, -187363961);
|
||||
b=gg(b,c,d,a,x[i+ 8],20, 1163531501);a=gg(a,b,c,d,x[i+13], 5,-1444681467);d=gg(d,a,b,c,x[i+ 2], 9, -51403784);
|
||||
c=gg(c,d,a,b,x[i+ 7],14, 1735328473);b=gg(b,c,d,a,x[i+12],20,-1926607734);a=hh(a,b,c,d,x[i+ 5], 4, -378558);
|
||||
d=hh(d,a,b,c,x[i+ 8],11,-2022574463);c=hh(c,d,a,b,x[i+11],16, 1839030562);b=hh(b,c,d,a,x[i+14],23, -35309556);
|
||||
a=hh(a,b,c,d,x[i+ 1], 4,-1530992060);d=hh(d,a,b,c,x[i+ 4],11, 1272893353);c=hh(c,d,a,b,x[i+ 7],16, -155497632);
|
||||
b=hh(b,c,d,a,x[i+10],23,-1094730640);a=hh(a,b,c,d,x[i+13], 4, 681279174);d=hh(d,a,b,c,x[i+ 0],11, -358537222);
|
||||
c=hh(c,d,a,b,x[i+ 3],16, -722521979);b=hh(b,c,d,a,x[i+ 6],23, 76029189);a=hh(a,b,c,d,x[i+ 9], 4, -640364487);
|
||||
d=hh(d,a,b,c,x[i+12],11, -421815835);c=hh(c,d,a,b,x[i+15],16, 530742520);b=hh(b,c,d,a,x[i+ 2],23, -995338651);
|
||||
a=ii(a,b,c,d,x[i+ 0], 6, -198630844);d=ii(d,a,b,c,x[i+ 7],10, 1126891415);c=ii(c,d,a,b,x[i+14],15,-1416354905);
|
||||
b=ii(b,c,d,a,x[i+ 5],21, -57434055);a=ii(a,b,c,d,x[i+12], 6, 1700485571);d=ii(d,a,b,c,x[i+ 3],10,-1894986606);
|
||||
c=ii(c,d,a,b,x[i+10],15, -1051523);b=ii(b,c,d,a,x[i+ 1],21,-2054922799);a=ii(a,b,c,d,x[i+ 8], 6, 1873313359);
|
||||
d=ii(d,a,b,c,x[i+15],10, -30611744);c=ii(c,d,a,b,x[i+ 6],15,-1560198380);b=ii(b,c,d,a,x[i+13],21, 1309151649);
|
||||
a=ii(a,b,c,d,x[i+ 4], 6, -145523070);d=ii(d,a,b,c,x[i+11],10,-1120210379);c=ii(c,d,a,b,x[i+ 2],15, 718787259);
|
||||
b=ii(b,c,d,a,x[i+ 9],21, -343485551);a=ad(a,olda);b=ad(b,oldb);c=ad(c,oldc);d=ad(d,oldd);
|
||||
}
|
||||
return rh(a)+rh(b)+rh(c)+rh(d);
|
||||
}
|
||||
|
||||
|
||||
|
||||
export {getCacheKey};
|
||||
38
resources/assets/v3/js/util/format-money.js
Normal file
38
resources/assets/v3/js/util/format-money.js
Normal file
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* format-money.js
|
||||
* Copyright (c) 2023 james@firefly-iii.org
|
||||
*
|
||||
* This file is part of Firefly III (https://github.com/firefly-iii).
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import {format} from "date-fns";
|
||||
|
||||
export default function (amount, currencyCode) {
|
||||
if( (typeof amount !== 'number' && typeof amount !== 'string') || isNaN(amount)) {
|
||||
console.warn('format-money: amount is not a number:', amount);
|
||||
return '';
|
||||
}
|
||||
if(typeof currencyCode !== 'string' || currencyCode.length !== 3) {
|
||||
console.warn('format-money: currencyCode is not a valid ISO 4217 code:', currencyCode);
|
||||
return '';
|
||||
}
|
||||
let locale = window.__localeId__.replace('_', '-');
|
||||
|
||||
return Intl.NumberFormat(locale, {
|
||||
style: 'currency',
|
||||
currency: currencyCode
|
||||
}).format(amount);
|
||||
}
|
||||
21
resources/assets/v3/package.json
Normal file
21
resources/assets/v3/package.json
Normal file
@@ -0,0 +1,21 @@
|
||||
{
|
||||
"$schema": "https://www.schemastore.org/package.json",
|
||||
"name": "v3",
|
||||
"private": true,
|
||||
"dependencies": {
|
||||
"admin-lte": "^4.0.0",
|
||||
"alpinejs": "^3.15.12"
|
||||
},
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"build": "vite build",
|
||||
"dev": "vite"
|
||||
},
|
||||
"devDependencies": {
|
||||
"concurrently": "^9.0.1",
|
||||
"laravel-vite-plugin": "^3.1",
|
||||
"tailwindcss": "^4.0.0",
|
||||
"vite": "^8.0.0",
|
||||
"vite-plugin-manifest-sri": "^0.2.0"
|
||||
}
|
||||
}
|
||||
99
resources/assets/v3/sass/app.scss
Normal file
99
resources/assets/v3/sass/app.scss
Normal file
@@ -0,0 +1,99 @@
|
||||
/*!
|
||||
* app.scss
|
||||
* Copyright (c) 2026 james@firefly-iii.org
|
||||
*
|
||||
* This file is part of Firefly III (https://github.com/firefly-iii).
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
$color-mode-type: media-query;
|
||||
$link-decoration: none !default;
|
||||
$font-family-sans-serif: "Roboto", sans-serif;
|
||||
|
||||
$danger: #CD5029 !default;
|
||||
$primary: #1E6581 !default;
|
||||
$success: #64B624 !default;
|
||||
|
||||
// admin LTE
|
||||
@use "../../../../node_modules/admin-lte/src/scss/adminlte" with (
|
||||
$color-mode-type: $color-mode-type,
|
||||
$link-decoration: $link-decoration,
|
||||
$font-family-sans-serif: $font-family-sans-serif,
|
||||
$danger: $danger,
|
||||
$primary: $primary,
|
||||
$success: $success
|
||||
);
|
||||
|
||||
//@use '../../../../node_modules/@fortawesome/fontawesome-free/scss/variables' with (
|
||||
// $font-path: "@fortawesome/fontawesome-free/webfonts"
|
||||
//);
|
||||
|
||||
//@use '../../../../node_modules/@fortawesome/fontawesome-free/scss/fontawesome';
|
||||
//@use '../../../../node_modules/@fortawesome/fontawesome-free/scss/fa' as fa;
|
||||
//@use '../../../../node_modules/@fortawesome/fontawesome-free/scss/solid' as fa-solid;
|
||||
//@use '../../../../node_modules/@fortawesome/fontawesome-free/scss/brands' as fa-brands;
|
||||
//@use '../../../../node_modules/@fortawesome/fontawesome-free/scss/regular' as fa-regular;
|
||||
|
||||
|
||||
// some local CSS
|
||||
.skip-links {display: none;}
|
||||
|
||||
/*
|
||||
Remove bottom margin from unstyled lists
|
||||
*/
|
||||
.list-no-margin {margin-bottom: 0;}
|
||||
.list-no-margin li.list-indent {margin-left:1.6em;}
|
||||
|
||||
.hover-footer {
|
||||
overflow-x:hidden;
|
||||
width:100%;
|
||||
text-align:right;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis
|
||||
}
|
||||
.hover-footer:hover {
|
||||
overflow: auto;
|
||||
text-overflow: unset;
|
||||
white-space: normal;
|
||||
}
|
||||
h3.hover-expand {
|
||||
overflow-x: hidden;
|
||||
text-overflow: ellipsis
|
||||
}
|
||||
h3.hover-expand:hover {
|
||||
overflow-x: auto;
|
||||
}
|
||||
|
||||
.form-control {
|
||||
appearance: auto;
|
||||
}
|
||||
|
||||
// edit buttons
|
||||
.hidden-edit-button {
|
||||
cursor: pointer;
|
||||
}
|
||||
td:not(:hover) .hidden-edit-button {
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
// Bootstrap
|
||||
// @import "bootstrap/scss/bootstrap";
|
||||
|
||||
|
||||
// @import "~bootstrap-sass/assets/stylesheets/bootstrap";
|
||||
|
||||
// hover buttons
|
||||
|
||||
|
||||
70
resources/assets/v3/vite.config.js
Normal file
70
resources/assets/v3/vite.config.js
Normal file
@@ -0,0 +1,70 @@
|
||||
/*
|
||||
* vite.config.js
|
||||
* Copyright (c) 2026 james@firefly-iii.org
|
||||
*
|
||||
* This file is part of Firefly III (https://github.com/firefly-iii).
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import {defineConfig} from 'vite';
|
||||
import laravel from 'laravel-vite-plugin';
|
||||
import manifestSRI from 'vite-plugin-manifest-sri';
|
||||
import fs from "fs";
|
||||
|
||||
export default defineConfig(({command, mode, isSsrBuild, isPreview}) => {
|
||||
let https = null;
|
||||
if (command === 'serve') {
|
||||
https = {
|
||||
key: fs.readFileSync(`/vagrant/tls-certificates/wildcard.sd.internal.key`),
|
||||
cert: fs.readFileSync(`/vagrant/tls-certificates/wildcard.sd.internal.crt`),
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
base: './',
|
||||
plugins: [
|
||||
laravel({
|
||||
input: [
|
||||
// CSS for entire app
|
||||
'sass/app.scss',
|
||||
|
||||
// dashboard
|
||||
'js/pages/dashboard/boxes.js',
|
||||
'js/pages/dashboard/dashboard.js'
|
||||
],
|
||||
buildDirectory: '../../../../public/build',
|
||||
// publicDirectory: '../../../public',
|
||||
refresh: true,
|
||||
fonts: [],
|
||||
}),
|
||||
manifestSRI(),
|
||||
],
|
||||
server: {
|
||||
watch: {
|
||||
ignored: ['**/storage/framework/views/**'],
|
||||
usePolling: true,
|
||||
},
|
||||
cors: true,
|
||||
// make sure this IP matches the IP of the dev machine.
|
||||
origin: 'https://192.168.96.169:5173',
|
||||
port: 5173,
|
||||
host: true,
|
||||
// hmr: {
|
||||
// protocol: 'wss',
|
||||
// },
|
||||
https: https,
|
||||
},
|
||||
}
|
||||
});
|
||||
@@ -46,8 +46,10 @@ return [
|
||||
'YTD' => 'YTD',
|
||||
'welcome_back' => 'What\'s playing?',
|
||||
'main_dashboard_page_title' => 'Home',
|
||||
'view_documentation' => 'View documentation',
|
||||
'everything' => 'Everything',
|
||||
'today' => 'today',
|
||||
'organization' => 'Organization',
|
||||
'customRange' => 'Custom range',
|
||||
'date_range' => 'Date range',
|
||||
'apply' => 'Apply',
|
||||
|
||||
187
resources/views/components/dashboard/boxes.blade.php
Normal file
187
resources/views/components/dashboard/boxes.blade.php
Normal file
@@ -0,0 +1,187 @@
|
||||
<div class="row mb-2" x-data="boxes" x-bind="eventListeners">
|
||||
<div class="col-xl-3 col-lg-6 col-md-12 col-sm-12">
|
||||
<div class="small-box text-bg-primary">
|
||||
<div class="inner balance-box">
|
||||
<h4 class="hover-expand">
|
||||
<template x-if="0 === balanceBox.amounts.length">
|
||||
<span> </span>
|
||||
</template>
|
||||
<template x-for="(amount, index) in balanceBox.amounts" :key="index">
|
||||
<span>
|
||||
<span x-text="amount"></span><span
|
||||
:class="{ 'invisible': (balanceBox.amounts.length == index+1) }">, </span>
|
||||
</span>
|
||||
</template>
|
||||
</h4>
|
||||
<template x-if="loading">
|
||||
<p class="d-none d-xs-block">
|
||||
<em class="fa-solid fa-spinner fa-spin"></em>
|
||||
</p>
|
||||
</template>
|
||||
<template x-if="!loading && 0 !== balanceBox.amounts.length">
|
||||
<p class="d-none d-sm-block">
|
||||
<a href="{{ route('reports.report.default', ['allAssetAccounts', $start->format('Ymd'), $end->format('Ymd')]) }}">{{ __('firefly.in_out_period') }}</a>
|
||||
</p>
|
||||
</template>
|
||||
<template x-if="!loading && 0 === balanceBox.amounts.length">
|
||||
<p class="d-none d-sm-block">
|
||||
TODO (no money in or out)
|
||||
</p>
|
||||
</template>
|
||||
</div>
|
||||
<span class="small-box-icon">
|
||||
<i class="fa-solid fa-scale-balanced"></i>
|
||||
</span>
|
||||
|
||||
<div class="small-box-footer hover-footer d-none d-xl-block">
|
||||
<template x-if="0 === balanceBox.subtitles.length">
|
||||
<span> </span>
|
||||
</template>
|
||||
<template x-for="(subtitle, index) in balanceBox.subtitles" :key="index">
|
||||
<span>
|
||||
<span x-text="subtitle"></span><span
|
||||
:class="{ 'invisible': (balanceBox.amounts.length == index+1) }"> & </span>
|
||||
</span>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
<!--end::Small Box Widget 1-->
|
||||
</div>
|
||||
<!--end::Col-->
|
||||
<div class="col-xl-3 col-lg-6 col-md-12 col-sm-12" style="flex-grow: 1;">
|
||||
<!--begin::Small Box Widget 2-->
|
||||
<div class="small-box text-bg-success">
|
||||
<div class="inner">
|
||||
<template x-if="0 === billBox.unpaid.length">
|
||||
<h4> </h4>
|
||||
</template>
|
||||
<template x-if="billBox.unpaid.length > 0">
|
||||
<h4 class="hover-expand">
|
||||
<template x-for="(amount, index) in billBox.unpaid" :key="index">
|
||||
<span>
|
||||
<span x-text="amount"></span><span
|
||||
:class="{ 'invisible': (billBox.unpaid.length == index+1) }">, </span>
|
||||
</span>
|
||||
</template>
|
||||
</h4>
|
||||
</template>
|
||||
<template x-if="loading">
|
||||
<p class="d-none d-sm-block">
|
||||
<em class="fa-solid fa-spinner fa-spin"></em>
|
||||
</p>
|
||||
</template>
|
||||
<template x-if="!loading && billBox.unpaid.length > 0">
|
||||
<p class="d-none d-sm-block"><a href="{{ route('subscriptions.index') }}">{{ __('firefly.bills_to_pay') }}</a></p>
|
||||
</template>
|
||||
<template x-if="0 === billBox.unpaid.length && !loading">
|
||||
<p class="d-none d-sm-block">TODO No subscriptions are waiting to be paid</p>
|
||||
</template>
|
||||
</div>
|
||||
<span class="small-box-icon">
|
||||
<em class="fa-regular fa-calendar"></em>
|
||||
</span>
|
||||
<span class="small-box-footer d-none d-xl-block">
|
||||
<template x-if="0 === billBox.paid.length">
|
||||
<span> </span>
|
||||
</template>
|
||||
<template x-if="billBox.paid.length > 0">
|
||||
<span>
|
||||
{{ __('firefly.paid') }}:
|
||||
<template x-for="(amount, index) in billBox.paid" :key="index">
|
||||
<span>
|
||||
<span x-text="amount"></span><span
|
||||
:class="{ 'invisible': (billBox.paid.length == index+1) }">, </span>
|
||||
</span>
|
||||
</template>
|
||||
</span>
|
||||
</template>
|
||||
</span>
|
||||
</div>
|
||||
<!--end::Small Box Widget 2-->
|
||||
</div>
|
||||
<!--end::Col-->
|
||||
<div class="col-xl-3 col-lg-6 col-md-12 col-sm-12" style="flex-grow: 1;">
|
||||
<!--begin::Small Box Widget 3-->
|
||||
<div class="small-box text-bg-warning">
|
||||
<div class="inner">
|
||||
<h4 class="hover-expand">
|
||||
<template x-if="0 === leftBox.left.length">
|
||||
<span> </span>
|
||||
</template>
|
||||
<template x-for="(amount, index) in leftBox.left" :key="index">
|
||||
<span>
|
||||
<span x-text="amount"></span><span
|
||||
:class="{ 'invisible': (leftBox.left.length == index+1) }">, </span>
|
||||
</span>
|
||||
</template>
|
||||
</h4>
|
||||
|
||||
<template x-if="loading">
|
||||
<p class="d-none d-sm-block">
|
||||
<em class="fa-solid fa-spinner fa-spin"></em>
|
||||
</p>
|
||||
</template>
|
||||
<template x-if="!loading && 0 !== leftBox.left.length">
|
||||
<p class="d-none d-sm-block"><a href="{{ route('budgets.index') }}">{{ __('firefly.left_to_spend') }}</a></p>
|
||||
</template>
|
||||
<template x-if="!loading && 0 === leftBox.left.length">
|
||||
<p class="d-none d-sm-block">TODO no money is budgeted in this period</p>
|
||||
</template>
|
||||
</div>
|
||||
<span class="small-box-icon">
|
||||
<em class="fa-solid fa-money-check-dollar"></em>
|
||||
</span>
|
||||
<span class="small-box-footer d-none d-xl-block">
|
||||
<template x-if="0 !== leftBox.perDay.length">
|
||||
<span>{{ __('firefly.per_day') }}:</span>
|
||||
</template>
|
||||
<template x-if="0 === leftBox.perDay.length">
|
||||
<span> </span>
|
||||
</template>
|
||||
<template x-for="(amount, index) in leftBox.perDay" :key="index">
|
||||
<span>
|
||||
<span x-text="amount"></span><span
|
||||
:class="{ 'invisible': (leftBox.perDay.length == index+1) }">, </span>
|
||||
</span>
|
||||
</template>
|
||||
</span>
|
||||
</div>
|
||||
<!--end::Small Box Widget 3-->
|
||||
</div>
|
||||
<!--end::Col-->
|
||||
<div class="col-xl-3 col-lg-6 col-md-12 col-sm-12" style="flex-grow: 1;">
|
||||
<!--begin::Small Box Widget 4-->
|
||||
<div class="small-box text-bg-danger">
|
||||
<div class="inner">
|
||||
<h4 class="hover-expand">
|
||||
<template x-for="(amount, index) in netBox.net" :key="index">
|
||||
<span>
|
||||
<span x-text="amount"></span><span
|
||||
:class="{ 'invisible': (netBox.net.length == index+1) }">, </span>
|
||||
</span>
|
||||
</template>
|
||||
</h4>
|
||||
|
||||
<template x-if="loading">
|
||||
<p class="d-none d-sm-block">
|
||||
<em class="fa-solid fa-spinner fa-spin"></em>
|
||||
</p>
|
||||
</template>
|
||||
<template x-if="!loading">
|
||||
<p class="d-none d-sm-block">
|
||||
<a href="{{ route('reports.report.default', ['allAssetAccounts','currentYearStart','currentYearEnd']) }}">{{ __('firefly.net_worth') }}</a>
|
||||
</p>
|
||||
</template>
|
||||
</div>
|
||||
<span class="small-box-icon">
|
||||
<i class="fa-solid fa-chart-line"></i>
|
||||
</span>
|
||||
<span class="small-box-footer d-none d-xl-block">
|
||||
|
||||
</span>
|
||||
</div>
|
||||
<!--end::Small Box Widget 4-->
|
||||
</div>
|
||||
<!--end::Col-->
|
||||
</div>
|
||||
<!--end::Row-->
|
||||
116
resources/views/components/generic/amount.blade.php
Normal file
116
resources/views/components/generic/amount.blade.php
Normal file
@@ -0,0 +1,116 @@
|
||||
|
||||
|
||||
|
||||
|
||||
@if(\FireflyIII\Enums\TransactionTypeEnum::DEPOSIT->value === $transaction['transaction_type_type'])
|
||||
{!! \FireflyIII\Support\Facades\Steam::formatAmountBySymbol(bcmul($transaction['amount'],'-1'), $transaction['currency_symbol'], $transaction['currency_decimal_places']) !!}
|
||||
@if(null !== $transaction['foreign_amount'])
|
||||
({!! \FireflyIII\Support\Facades\Steam::formatAmountBySymbol(bcmul($transaction['foreign_amount'], '-1'), $transaction['foreign_currency_symbol'], $transaction['foreign_currency_decimal_places']) !!})
|
||||
@endif
|
||||
@if($convertToPrimary && null !== $transaction['pc_amount'])
|
||||
({!! \FireflyIII\Support\Facades\Steam::formatAmountBySymbol(bcmul($transaction['pc_amount'], '-1'), $primaryCurrency->symbol, $primaryCurrency->decimal_places) !!})
|
||||
@endif
|
||||
@endif
|
||||
|
||||
@if(\FireflyIII\Enums\TransactionTypeEnum::WITHDRAWAL->value === $transaction['transaction_type_type'])
|
||||
{!! \FireflyIII\Support\Facades\Steam::formatAmountBySymbol($transaction['amount'], $transaction['currency_symbol'], $transaction['currency_decimal_places']) !!}
|
||||
@if(null !== $transaction['foreign_amount'])
|
||||
({!! \FireflyIII\Support\Facades\Steam::formatAmountBySymbol($transaction['foreign_amount'], $transaction['foreign_currency_symbol'], $transaction['foreign_currency_decimal_places']) !!})
|
||||
@endif
|
||||
@if($convertToPrimary && null !== $transaction['pc_amount'])
|
||||
({!! \FireflyIII\Support\Facades\Steam::formatAmountBySymbol($transaction['pc_amount'], $primaryCurrency->symbol, $primaryCurrency->decimal_places) !!})
|
||||
@endif
|
||||
@endif
|
||||
|
||||
@if(\FireflyIII\Enums\TransactionTypeEnum::TRANSFER->value === $transaction['transaction_type_type'])
|
||||
<span class="text-info money-transfer">
|
||||
{{-- transfer away --}}
|
||||
@if(isset($account) && $transaction['source_account_id'] === $account->id)
|
||||
{!! \FireflyIII\Support\Facades\Steam::formatAmountBySymbol(bcmul($transaction['amount'],'-1'), $transaction['currency_symbol'], $transaction['currency_decimal_places'], false) !!}
|
||||
@if(null !== $transaction['foreign_amount'])
|
||||
({!! \FireflyIII\Support\Facades\Steam::formatAmountBySymbol(bcmul($transaction['foreign_amount'],'-1'), $transaction['foreign_currency_symbol'], $transaction['foreign_currency_decimal_places'], false) !!})
|
||||
@endif
|
||||
@if($convertToPrimary && null !== $transaction['pc_amount'])
|
||||
({!! \FireflyIII\Support\Facades\Steam::formatAmountBySymbol(bcmul($transaction['pc_amount'], '-1'), $primaryCurrency->symbol, $primaryCurrency->decimal_places, false) !!})
|
||||
@endif
|
||||
@endif
|
||||
|
||||
{{-- transfer in (default) --}}
|
||||
@if(!isset($account) || $transaction['source_account_id'] !== $account->id)
|
||||
{!! \FireflyIII\Support\Facades\Steam::formatAmountBySymbol($transaction['amount'], $transaction['currency_symbol'], $transaction['currency_decimal_places'], false) !!}
|
||||
@if(null !== $transaction['foreign_amount'])
|
||||
({!! \FireflyIII\Support\Facades\Steam::formatAmountBySymbol($transaction['foreign_amount'], $transaction['foreign_currency_symbol'], $transaction['foreign_currency_decimal_places'], false) !!})
|
||||
@endif
|
||||
@if($convertToPrimary && null !== $transaction['pc_amount'])
|
||||
({!! \FireflyIII\Support\Facades\Steam::formatAmountBySymbol($transaction['pc_amount'], $primaryCurrency->symbol, $primaryCurrency->decimal_places, false) !!})
|
||||
@endif
|
||||
@endif
|
||||
</span>
|
||||
@endif
|
||||
|
||||
|
||||
@if(\FireflyIII\Enums\TransactionTypeEnum::OPENING_BALANCE->value === $transaction['transaction_type_type'])
|
||||
{{-- Opening balance is deposited on this account (render as positive amount) --}}
|
||||
@if(\FireflyIII\Enums\AccountTypeEnum::INITIAL_BALANCE->value === $transaction['source_account_type'])
|
||||
{!! \FireflyIII\Support\Facades\Steam::formatAmountBySymbol(bcmul($transaction['amount'],'-1'), $transaction['currency_symbol'], $transaction['currency_decimal_places'], false) !!}
|
||||
@if(null !== $transaction['foreign_amount'])
|
||||
({!! \FireflyIII\Support\Facades\Steam::formatAmountBySymbol(bcmul($transaction['foreign_amount'],'-1'), $transaction['foreign_currency_symbol'], $transaction['foreign_currency_decimal_places'], false) !!})
|
||||
@endif
|
||||
@if($convertToPrimary && null !== $transaction['pc_amount'])
|
||||
({!! \FireflyIII\Support\Facades\Steam::formatAmountBySymbol(bcmul($transaction['pc_amount'], '-1'), $primaryCurrency->symbol, $primaryCurrency->decimal_places, false) !!})
|
||||
@endif
|
||||
@endif
|
||||
|
||||
{{-- Opening balance is removed from this account (render as negative amount) --}}
|
||||
@if(\FireflyIII\Enums\AccountTypeEnum::INITIAL_BALANCE->value === $transaction['destination_account_type'])
|
||||
{!! \FireflyIII\Support\Facades\Steam::formatAmountBySymbol($transaction['amount'], $transaction['currency_symbol'], $transaction['currency_decimal_places'], false) !!}
|
||||
@if(null !== $transaction['foreign_amount'])
|
||||
({!! \FireflyIII\Support\Facades\Steam::formatAmountBySymbol($transaction['foreign_amount'], $transaction['foreign_currency_symbol'], $transaction['foreign_currency_decimal_places'], false) !!})
|
||||
@endif
|
||||
@if($convertToPrimary && null !== $transaction['pc_amount'])
|
||||
({!! \FireflyIII\Support\Facades\Steam::formatAmountBySymbol($transaction['pc_amount'], $primaryCurrency->symbol, $primaryCurrency->decimal_places, false) !!})
|
||||
@endif
|
||||
@endif
|
||||
@endif
|
||||
|
||||
@if(\FireflyIII\Enums\TransactionTypeEnum::RECONCILIATION->value === $transaction['transaction_type_type'])
|
||||
{{-- Reconciliation correction is deposited on this account (render as positive amount) --}}
|
||||
@if(\FireflyIII\Enums\AccountTypeEnum::RECONCILIATION->value === $transaction['source_account_type'])
|
||||
{!! \FireflyIII\Support\Facades\Steam::formatAmountBySymbol(bcmul($transaction['amount'],'-1'), $transaction['currency_symbol'], $transaction['currency_decimal_places'], false) !!}
|
||||
@if(null !== $transaction['foreign_amount'])
|
||||
({!! \FireflyIII\Support\Facades\Steam::formatAmountBySymbol(bcmul($transaction['foreign_amount'],'-1'), $transaction['foreign_currency_symbol'], $transaction['foreign_currency_decimal_places'], false) !!})
|
||||
@endif
|
||||
@if($convertToPrimary && null !== $transaction['pc_amount'])
|
||||
({!! \FireflyIII\Support\Facades\Steam::formatAmountBySymbol(bcmul($transaction['pc_amount'], '-1'), $primaryCurrency->symbol, $primaryCurrency->decimal_places, false) !!})
|
||||
@endif
|
||||
@endif
|
||||
|
||||
{{-- Reconciliation correction is removed from this account (render as negative amount) --}}
|
||||
@if(\FireflyIII\Enums\AccountTypeEnum::RECONCILIATION->value === $transaction['destination_account_type'])
|
||||
{!! \FireflyIII\Support\Facades\Steam::formatAmountBySymbol($transaction['amount'], $transaction['currency_symbol'], $transaction['currency_decimal_places'], false) !!}
|
||||
@if(null !== $transaction['foreign_amount'])
|
||||
({!! \FireflyIII\Support\Facades\Steam::formatAmountBySymbol($transaction['foreign_amount'], $transaction['foreign_currency_symbol'], $transaction['foreign_currency_decimal_places'], false) !!})
|
||||
@endif
|
||||
@if($convertToPrimary && null !== $transaction['pc_amount'])
|
||||
({!! \FireflyIII\Support\Facades\Steam::formatAmountBySymbol($transaction['pc_amount'], $primaryCurrency->symbol, $primaryCurrency->decimal_places, false) !!})
|
||||
@endif
|
||||
@endif
|
||||
@endif
|
||||
|
||||
|
||||
{{--
|
||||
<span class="pull-right small">
|
||||
|
||||
|
||||
{% elseif transaction.transaction_type_type == 'Reconciliation' %}
|
||||
{% else %}
|
||||
{{ formatAmountBySymbol(transaction.amount, transaction.currency_symbol, transaction.currency_decimal_places) }}
|
||||
{% if null != transaction.foreign_amount %}
|
||||
({{ formatAmountBySymbol(transaction.foreign_amount, transaction.foreign_currency_symbol, transaction.foreign_currency_decimal_places) }})
|
||||
{% endif %}
|
||||
{% if convertToPrimary and null != transaction.pc_amount %}
|
||||
({{ formatAmountBySymbol(transaction.pc_amount, primaryCurrency.symbol, foreign_currency_.decimal_places) }})
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
</span>
|
||||
--}}
|
||||
154
resources/views/components/layout/create-menu.blade.php
Normal file
154
resources/views/components/layout/create-menu.blade.php
Normal file
@@ -0,0 +1,154 @@
|
||||
<!-- begin create menu -->
|
||||
<li class="nav-item dropdown">
|
||||
<a class="nav-link" data-bs-toggle="dropdown" href="#" aria-expanded="false">
|
||||
<em class="bi bi-plus-circle"></em>
|
||||
</a>
|
||||
<div class="dropdown-menu dropdown-menu-lg dropdown-menu-end">
|
||||
<a href="{{ route('transactions.create', ['withdrawal']) }}" class="dropdown-item">
|
||||
<div class="d-flex">
|
||||
<div class="grow">
|
||||
<h3 class="dropdown-item-title">
|
||||
<!-- withdrawal, deposit, transfer -->
|
||||
<em class="bi bi-arrow-left me-2"></em>
|
||||
{{ __('firefly.create_new_withdrawal') }}
|
||||
</h3>
|
||||
</div>
|
||||
</div>
|
||||
</a>
|
||||
<div class="dropdown-divider"></div>
|
||||
<a href="{{ route('transactions.create', ['deposit']) }}" class="dropdown-item">
|
||||
<div class="d-flex">
|
||||
<div class="grow">
|
||||
<h3 class="dropdown-item-title">
|
||||
<!-- withdrawal, deposit, transfer -->
|
||||
<em class="bi bi-arrow-right me-2"></em>
|
||||
{{ __('firefly.create_new_deposit') }}
|
||||
</h3>
|
||||
</div>
|
||||
</div>
|
||||
</a>
|
||||
<div class="dropdown-divider"></div>
|
||||
<a href="{{ route('transactions.create', ['transfer']) }}" class="dropdown-item">
|
||||
<div class="d-flex">
|
||||
<div class="grow">
|
||||
<h3 class="dropdown-item-title">
|
||||
<!-- withdrawal, deposit, transfer -->
|
||||
<em class="bi bi-arrow-left-right me-2"></em>
|
||||
{{ __('firefly.create_new_transfer') }}
|
||||
</h3>
|
||||
</div>
|
||||
</div>
|
||||
</a>
|
||||
<div class="dropdown-divider"></div>
|
||||
|
||||
<a href="{{ route('accounts.create', ['asset']) }}" class="dropdown-item">
|
||||
<div class="d-flex">
|
||||
<div class="grow">
|
||||
<h3 class="dropdown-item-title">
|
||||
<!-- withdrawal, deposit, transfer -->
|
||||
<em class="bi bi-cash me-2"></em>
|
||||
{{ __('firefly.create_new_asset') }}
|
||||
</h3>
|
||||
</div>
|
||||
</div>
|
||||
</a>
|
||||
<div class="dropdown-divider"></div>
|
||||
<a href="{{ route('accounts.create', ['liabilities']) }}" class="dropdown-item">
|
||||
<div class="d-flex">
|
||||
<div class="grow">
|
||||
<h3 class="dropdown-item-title">
|
||||
<!-- withdrawal, deposit, transfer -->
|
||||
<em class="bi bi-ticket-detailed me-2"></em>
|
||||
{{ __('firefly.create_new_liabilities') }}
|
||||
</h3>
|
||||
</div>
|
||||
</div>
|
||||
</a>
|
||||
<div class="dropdown-divider"></div>
|
||||
|
||||
<a href="{{ route('budgets.create') }}" class="dropdown-item">
|
||||
<div class="d-flex">
|
||||
<div class="grow">
|
||||
<h3 class="dropdown-item-title">
|
||||
<!-- withdrawal, deposit, transfer -->
|
||||
<em class="bi bi-pie-chart me-2"></em>
|
||||
{{ __('firefly.create_new_budget') }}
|
||||
</h3>
|
||||
</div>
|
||||
</div>
|
||||
</a>
|
||||
<div class="dropdown-divider"></div>
|
||||
<a href="{{ route('categories.create') }}" class="dropdown-item">
|
||||
<div class="d-flex">
|
||||
<div class="grow">
|
||||
<h3 class="dropdown-item-title">
|
||||
<!-- withdrawal, deposit, transfer -->
|
||||
<em class="bi bi-bookmark me-2"></em>
|
||||
{{ __('firefly.create_new_category') }}
|
||||
</h3>
|
||||
</div>
|
||||
</div>
|
||||
</a>
|
||||
<div class="dropdown-divider"></div>
|
||||
<a href="{{ route('piggy-banks.create') }}" class="dropdown-item">
|
||||
<div class="d-flex">
|
||||
<div class="grow">
|
||||
<h3 class="dropdown-item-title">
|
||||
<!-- withdrawal, deposit, transfer -->
|
||||
<em class="bi bi-bullseye me-2"></em>
|
||||
{{ __('firefly.create_new_piggy_bank') }}
|
||||
</h3>
|
||||
</div>
|
||||
</div>
|
||||
</a>
|
||||
<div class="dropdown-divider"></div>
|
||||
<a href="{{ route('subscriptions.create') }}" class="dropdown-item">
|
||||
<div class="d-flex">
|
||||
<div class="grow">
|
||||
<h3 class="dropdown-item-title">
|
||||
<!-- withdrawal, deposit, transfer -->
|
||||
<em class="bi bi-calendar me-2"></em>
|
||||
{{ __('firefly.create_new_subscription') }}
|
||||
</h3>
|
||||
</div>
|
||||
</div>
|
||||
</a>
|
||||
<div class="dropdown-divider"></div>
|
||||
<a href="{{ route('rules.create') }}" class="dropdown-item">
|
||||
<div class="d-flex">
|
||||
<div class="grow">
|
||||
<h3 class="dropdown-item-title">
|
||||
<!-- withdrawal, deposit, transfer -->
|
||||
<em class="bi bi-shuffle me-2"></em>
|
||||
{{ __('firefly.create_new_rule') }}
|
||||
</h3>
|
||||
</div>
|
||||
</div>
|
||||
</a>
|
||||
<div class="dropdown-divider"></div>
|
||||
<a href="{{ route('recurring.create') }}" class="dropdown-item">
|
||||
<div class="d-flex">
|
||||
<div class="grow">
|
||||
<h3 class="dropdown-item-title">
|
||||
<!-- withdrawal, deposit, transfer -->
|
||||
<em class="bi bi-paint-bucket me-2"></em>
|
||||
{{ __('firefly.create_new_recurrence') }}
|
||||
</h3>
|
||||
</div>
|
||||
</div>
|
||||
</a>
|
||||
<div class="dropdown-divider"></div>
|
||||
<a href="{{ route('webhooks.create') }}" class="dropdown-item">
|
||||
<div class="d-flex">
|
||||
<div class="grow">
|
||||
<h3 class="dropdown-item-title">
|
||||
<!-- withdrawal, deposit, transfer -->
|
||||
<em class="bi bi-lightning me-2"></em>
|
||||
{{ __('firefly.create_new_webhook') }}
|
||||
</h3>
|
||||
</div>
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
</li>
|
||||
<!-- end create menu -->
|
||||
11
resources/views/components/layout/fav-icons.blade.php
Normal file
11
resources/views/components/layout/fav-icons.blade.php
Normal file
@@ -0,0 +1,11 @@
|
||||
<link rel="apple-touch-icon" sizes="180x180" href="apple-touch-icon.png">
|
||||
<link rel="icon" type="image/png" sizes="32x32" href="favicon-32x32.png?v=3e8AboOwbd">
|
||||
<link rel="icon" type="image/png" sizes="16x16" href="favicon-16x16.png?v=3e8AboOwbd">
|
||||
<link rel="manifest" href="manifest.webmanifest?v=3e8AboOwbd" crossorigin="use-credentials">
|
||||
<link rel="mask-icon" href="safari-pinned-tab.svg" color="#3c8dbc">
|
||||
<link rel="shortcut icon" href="favicon.ico?v=3e8AboOwbd">
|
||||
<meta name="apple-mobile-web-app-title" content="Firefly III">
|
||||
<meta name="application-name" content="Firefly III">
|
||||
<meta name="msapplication-TileColor" content="#3c8dbc">
|
||||
<meta name="msapplication-TileImage" content="mstile-144x144.png?v=3e8AboOwbd">
|
||||
<meta name="theme-color" content="#3c8dbc">
|
||||
229
resources/views/components/layout/sidebar.blade.php
Normal file
229
resources/views/components/layout/sidebar.blade.php
Normal file
@@ -0,0 +1,229 @@
|
||||
<ul
|
||||
class="nav sidebar-menu flex-column"
|
||||
data-lte-toggle="treeview"
|
||||
role="navigation"
|
||||
aria-label="Main navigation"
|
||||
data-accordion="false"
|
||||
id="navigation"
|
||||
x-data="sidebar"
|
||||
>
|
||||
<!-- <li class="nav-item menu-open"> -->
|
||||
<!-- <a href="route('index')" class="nav-link active"> -->
|
||||
<li class="nav-item">
|
||||
<a href="{{ route('index') }}" class="nav-link @menuItemActive('index')">
|
||||
<em class="nav-icon bi bi-speedometer"></em>
|
||||
<p>{{ __('firefly.dashboard') }}</p>
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-header text-uppercase">{{ __('firefly.financial_control') }}</li>
|
||||
<li class="nav-item">
|
||||
<a href="{{ route('budgets.index') }}" class="nav-link @menuItemActive('budgets')">
|
||||
<em class="nav-icon bi bi-pie-chart"></em>
|
||||
<p>
|
||||
{{ __('firefly.budgets') }}
|
||||
</p>
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a href="{{ route('subscriptions.index') }}" class="nav-link @menuItemActive('subscriptions')">
|
||||
<em class="nav-icon bi bi-calendar"></em>
|
||||
<p>
|
||||
{{ __('firefly.subscriptions') }}
|
||||
</p>
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a href="{{ route('piggy-banks.index') }}" class="nav-link @menuItemActive('piggy-banks')">
|
||||
<em class="nav-icon bi bi-bullseye"></em>
|
||||
<p>
|
||||
{{ __('firefly.piggyBanks') }}
|
||||
</p>
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-header text-uppercase">{{ __('firefly.accounting') }}</li>
|
||||
|
||||
<li class="nav-item">
|
||||
<a href="#" class="nav-link">
|
||||
<em class="nav-icon bi bi-wallet"></em>
|
||||
<p>
|
||||
{{ __('firefly.transactions') }}
|
||||
<em class="nav-arrow bi bi-chevron-right"></em>
|
||||
</p>
|
||||
</a>
|
||||
<ul class="nav nav-treeview">
|
||||
<li class="nav-item">
|
||||
<a href="{{ route('transactions.index', ['withdrawal']) }}" class="nav-link">
|
||||
<em class="nav-icon bi bi-arrow-left"></em>
|
||||
<p>{{ __('firefly.expenses') }}</p>
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a href="{{ route('transactions.index', ['withdrawal']) }}" class="nav-link">
|
||||
<em class="nav-icon bi bi-arrow-right"></em>
|
||||
<p>{{ __('firefly.income') }}</p>
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a href="{{ route('transactions.index', ['transfers']) }}" class="nav-link">
|
||||
<em class="nav-icon bi bi-arrow-left-right"></em>
|
||||
<p>{{ __('firefly.transfers') }}</p>
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a href="{{ route('transactions.index', ['all']) }}" class="nav-link">
|
||||
<em class="nav-icon bi bi-arrow-repeat"></em>
|
||||
<p>{{ __('firefly.all_transactions') }}</p>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a href="#" class="nav-link">
|
||||
<em class="nav-icon bi bi-cpu"></em>
|
||||
<p>
|
||||
{{ __('firefly.automation') }}
|
||||
<em class="nav-arrow bi bi-chevron-right"></em>
|
||||
</p>
|
||||
</a>
|
||||
<ul class="nav nav-treeview">
|
||||
<li class="nav-item">
|
||||
<a href="{{ route('rules.index') }}" class="nav-link">
|
||||
<em class="nav-icon bi bi-shuffle"></em>
|
||||
<p>{{__('firefly.rules')}}</p>
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a href="{{ route('recurring.index') }}" class="nav-link">
|
||||
<em class="nav-icon bi bi-paint-bucket"></em>
|
||||
<p>{{__('firefly.recurrences') }}</p>
|
||||
</a>
|
||||
</li>
|
||||
@if(true === $featuringWebhooks)
|
||||
<li class="nav-item">
|
||||
<a href="{{ route('webhooks.index') }}" class="nav-link">
|
||||
<em class="nav-icon bi bi-lightning"></em>
|
||||
<p>{{ __('firefly.webhooks') }}</p>
|
||||
</a>
|
||||
</li>
|
||||
@endif
|
||||
@if(false === $featuringWebhooks)
|
||||
<li class="nav-item">
|
||||
<a href="#" class="nav-link">
|
||||
<em class="nav-icon bi bi-lightning"></em>
|
||||
<p>{{ __('firefly.webhooks') }} ({{ trans('firefly.webhooks_menu_disabled') }})</p>
|
||||
</a>
|
||||
</li>
|
||||
@endif
|
||||
</ul>
|
||||
</li>
|
||||
<li class="nav-header text-uppercase">{{ __('firefly.organization') }}</li>
|
||||
<li class="nav-item">
|
||||
<a href="#" class="nav-link">
|
||||
<em class="nav-icon bi bi-credit-card"></em>
|
||||
<p>
|
||||
{{__('firefly.accounts')}}
|
||||
<em class="nav-arrow bi bi-chevron-right"></em>
|
||||
</p>
|
||||
</a>
|
||||
<ul class="nav nav-treeview">
|
||||
<li class="nav-item">
|
||||
<a href="{{ route('accounts.index', ['asset']) }}" class="nav-link">
|
||||
<em class="nav-icon bi bi-cash"></em>
|
||||
<p>{{ __('firefly.asset_accounts') }}</p>
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a href="{{ route('accounts.index', ['expense']) }}" class="nav-link">
|
||||
<em class="nav-icon bi bi-cart"></em>
|
||||
<p>{{trans('firefly.expense_accounts')}}</p>
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a href="{{ route('accounts.index', ['revenue']) }}" class="nav-link">
|
||||
<em class="nav-icon bi bi-box-arrow-down"></em>
|
||||
<p>{{ __('firefly.revenue_accounts') }}</p>
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a href="{{ route('accounts.index', ['liabilities']) }}" class="nav-link">
|
||||
<em class="nav-icon bi bi-ticket-detailed"></em>
|
||||
<p>{{ __('firefly.liabilities_accounts') }}</p>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
|
||||
<li class="nav-item">
|
||||
<a href="#" class="nav-link">
|
||||
<em class="nav-icon bi bi-tags"></em>
|
||||
<p>
|
||||
{{trans('firefly.classification')}}
|
||||
<em class="nav-arrow bi bi-chevron-right"></em>
|
||||
</p>
|
||||
</a>
|
||||
<ul class="nav nav-treeview">
|
||||
<li class="nav-item">
|
||||
<a href="{{ route('categories.index') }}" class="nav-link">
|
||||
<em class="nav-icon bi bi-bookmark"></em>
|
||||
<p>{{trans('firefly.categories')}}</p>
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a href="{{ route('tags.index') }}" class="nav-link">
|
||||
<em class="nav-icon bi bi-tag"></em>
|
||||
<p>{{trans('firefly.tags')}}</p>
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a href="{{ route('object-groups.index') }}" class="nav-link">
|
||||
<em class="nav-icon bi bi-envelope"></em>
|
||||
<p>{{trans('firefly.object_groups_menu_bar')}}</p>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
|
||||
|
||||
<li class="nav-header text-uppercase">{{ __('firefly.others') }}</li>
|
||||
<li class="nav-item">
|
||||
<a href="{{ route('currencies.index') }}" class="nav-link">
|
||||
<em class="nav-icon bi bi-currency-euro"></em>
|
||||
<p>{{ __('firefly.currencies') }}</p>
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a href="{{ route('exchange-rates.index') }}" class="nav-link">
|
||||
<em class="nav-icon bi bi-currency-exchange"></em>
|
||||
<p>{{ __('firefly.menu_exchange_rates_index') }}</p>
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a href="{{ route('reports.index') }}" class="nav-link">
|
||||
<em class="nav-icon bi bi-bar-chart"></em>
|
||||
<p>{{ __('firefly.reports') }}</p>
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a href="{{ route('export.index') }}" class="nav-link">
|
||||
<em class="nav-icon bi bi-upload"></em>
|
||||
<p>{{ __('firefly.export_data_menu') }}</p>
|
||||
</a>
|
||||
</li>
|
||||
|
||||
@if('web' === $authGuard)
|
||||
<li class="nav-item">
|
||||
<a href="{{ route('logout') }}" @click="logoutUser" class="nav-link logout-link">
|
||||
<em class="nav-icon bi bi-person text-danger"></em>
|
||||
<p>{{ __('firefly.logout') }}</p>
|
||||
</a>
|
||||
</li>
|
||||
@endif
|
||||
@if('remote_user_guard' === $authGuard && '' !== $logoutUrl)
|
||||
<li class="nav-item">
|
||||
<a href="{{ $logoutUrl }}" class="nav-link logout-link">
|
||||
<em class="nav-icon bi bi-person text-danger"></em>
|
||||
<p>{{ __('firefly.logout') }}</p>
|
||||
</a>
|
||||
</li>
|
||||
@endif
|
||||
</ul>
|
||||
3
resources/views/components/layout/top-boxes.blade.php
Normal file
3
resources/views/components/layout/top-boxes.blade.php
Normal file
@@ -0,0 +1,3 @@
|
||||
<div>
|
||||
<!-- He who is contented is rich. - Laozi -->
|
||||
</div>
|
||||
28
resources/views/components/layout/user-menu.blade.php
Normal file
28
resources/views/components/layout/user-menu.blade.php
Normal file
@@ -0,0 +1,28 @@
|
||||
<li class="nav-item dropdown">
|
||||
<a class="nav-link" data-bs-toggle="dropdown" href="#">
|
||||
<em class="bi bi-person"></em>
|
||||
</a>
|
||||
<div class="dropdown-menu dropdown-menu-lg dropdown-menu-end">
|
||||
<span class="dropdown-item dropdown-header">{{ Auth::user()->email }}</span>
|
||||
<div class="dropdown-divider"></div>
|
||||
<a href="#" class="dropdown-item">
|
||||
<i class="bi bi-envelope me-2"></i> Profile
|
||||
</a>
|
||||
<div class="dropdown-divider"></div>
|
||||
<a href="#" class="dropdown-item">
|
||||
<i class="bi bi-people-fill me-2"></i> Preferences
|
||||
</a>
|
||||
<div class="dropdown-divider"></div>
|
||||
<a href="#" class="dropdown-item">
|
||||
<i class="bi bi-file-earmark-fill me-2"></i> Tokens
|
||||
</a>
|
||||
<div class="dropdown-divider"></div>
|
||||
<a href="#" class="dropdown-item">
|
||||
<i class="bi bi-file-earmark-fill me-2"></i> Financial administrations
|
||||
</a>
|
||||
<div class="dropdown-divider"></div>
|
||||
<a href="#" class="dropdown-item">
|
||||
<i class="bi bi-file-earmark-fill me-2"></i> System settings
|
||||
</a>
|
||||
</div>
|
||||
</li>
|
||||
14
resources/views/components/lists/groups-tiny.blade.php
Normal file
14
resources/views/components/lists/groups-tiny.blade.php
Normal file
@@ -0,0 +1,14 @@
|
||||
<div class="list-group">
|
||||
@foreach($transactions as $transaction)
|
||||
|
||||
<a class="list-group-item list-group-item-action d-flex justify-content-between align-items-center" href="{{ route('transactions.show', [$transaction['transaction_group_id']]) }}">
|
||||
@if('' !== (string) $transaction['transaction_group_title'])
|
||||
{{ $transaction['transaction_group_title'] }}:
|
||||
@endif
|
||||
{{ $transaction['description'] }}
|
||||
<span class="small">
|
||||
<x-generic.amount :transaction="$transaction" />
|
||||
</span>
|
||||
</a>
|
||||
@endforeach
|
||||
</div>
|
||||
250
resources/views/index.blade.php
Normal file
250
resources/views/index.blade.php
Normal file
@@ -0,0 +1,250 @@
|
||||
@extends('layout.v3.session')
|
||||
@section('content')
|
||||
TODO internals modal voor pagina settings
|
||||
TODO wizard modal voor weet ik veel
|
||||
TODO dark mode ook onthouden en dat script in het template
|
||||
TODO date picker
|
||||
TODO intro js
|
||||
|
||||
<x-dashboard.boxes :start="$start" :end="$end" />
|
||||
|
||||
<div class="row" x-data="index">
|
||||
<div class="col-lg-8 col-md-12 col-sm-12">
|
||||
<!--ACCOUNTS -->
|
||||
<div class="card card-primary card-outline mb-4">
|
||||
<div class="card-header with-border">
|
||||
<div class="card-title"><a href="{{ route('accounts.index',['asset']) }}" title="{{ __('firefly.yourAccounts') }}">{{ __('firefly.yourAccounts') }}</a></div>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<canvas id="accounts-chart" class="wide-chart" height="400" width="100%"></canvas>
|
||||
</div>
|
||||
<div class="card-footer">
|
||||
<a href="{{ route('accounts.index',['asset']) }}" class="btn btn-primary btn-sm"><span class="bi bi-cash"></span> {{ __('firefly.go_to_asset_accounts') }}</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!--BUDGETS -->
|
||||
<div class="card card-outline mb-4">
|
||||
<div class="card-header with-border">
|
||||
<div class="card-title"><a href="{{ route('budgets.index') }}"
|
||||
title="{{ __('firefly.budgetsAndSpending') }}">{{ __('firefly.budgetsAndSpending') }}</a></div>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<canvas id="budgets-chart" class="wide-chart" height="400" width="100%"></canvas>
|
||||
</div>
|
||||
<div class="card-footer">
|
||||
<a href="{{ route('budgets.index') }}" class="btn btn-primary btn-sm">
|
||||
<span class="bi bi-pie-chart"></span>
|
||||
<span>{{ __('firefly.go_to_budgets') }}</span>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<!--CATEGORIES -->
|
||||
<div class="card card-outline mb-4">
|
||||
<div class="card-header with-border">
|
||||
<div class="card-title"><a href="{{ route('categories.index') }}"
|
||||
title="{{ __('firefly.categories') }}">{{ __('firefly.categories') }}</a></div>
|
||||
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<canvas id="categories-chart" class="wide-chart" height="400" width="100%"></canvas>
|
||||
</div>
|
||||
<div class="card-footer">
|
||||
<a href="{{ route('categories.index') }}" class="btn btn-primary btn-sm">
|
||||
<span class="bi bi-bookmark"></span>
|
||||
<span>{{ __('firefly.go_to_categories') }}</span>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-lg-4 col-md-6 col-sm-12">
|
||||
|
||||
<!--TRANSACTIONS -->
|
||||
<div id="all_transactions">
|
||||
@foreach($transactions as $data)
|
||||
<div class="card mb-4">
|
||||
<div class="card-header with-border">
|
||||
<div class="card-title"><a href="{{ route('accounts.show', [$data['account']['id']]) }}">{{ $data['account']['name'] }}</a>
|
||||
</div>
|
||||
</div>
|
||||
@if(count($data['transactions']) > 0)
|
||||
<div class="card-body p-0">
|
||||
<x-lists.groups-tiny :transactions="$data['transactions']" />
|
||||
</div>
|
||||
@endif
|
||||
@if(0 === count($data['transactions']))
|
||||
<div class="card-body">
|
||||
<p>
|
||||
<em>
|
||||
{{ __('firefly.no_transactions_account', ['name' => $data['account']['name']]) }}
|
||||
</em>
|
||||
</p>
|
||||
|
||||
</div>
|
||||
@endif
|
||||
|
||||
<div class="card-footer">
|
||||
<!-- Single button -->
|
||||
<div class="btn-group" role="group">
|
||||
<button type="button" class="btn btn-primary btn-sm dropdown-toggle" data-bs-toggle="dropdown" aria-expanded="false">{{ __('firefly.sidebar_frontpage_create') }}</button>
|
||||
<ul class="dropdown-menu">
|
||||
<li>
|
||||
<a class="dropdown-item" href="{{ route('transactions.create', ['withdrawal']) }}?source={{ $data['account']['id'] }}">{{ __('firefly.create_new_withdrawal') }}</a>
|
||||
</li>
|
||||
<li>
|
||||
<a class="dropdown-item" href="{{ route('transactions.create', ['deposit']) }}?destination={{ $data['account']['id'] }}">{{ __('firefly.create_new_deposit') }}</a>
|
||||
</li>
|
||||
<li>
|
||||
<a class="dropdown-item" href="{{ route('transactions.create', ['transfer']) }}?source={{ $data['account']['id'] }}">{{ __('firefly.create_new_transfer') }}</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="btn-group" role="group">
|
||||
<button type="button" class="btn btn-primary btn-sm dropdown-toggle" data-bs-toggle="dropdown" aria-expanded="false">
|
||||
{{ bladeAccountBalance($data['account']) }}
|
||||
</button>
|
||||
<ul class="dropdown-menu">
|
||||
<li>
|
||||
<a class="dropdown-item" href="{{ route('accounts.show', [$data['account']['id']]) }}">{{ __('firefly.show') }}</a>
|
||||
</li>
|
||||
<li>
|
||||
<a class="dropdown-item" href="{{ route('accounts.reconcile', [$data['account']['id']]) }}">{{ __('firefly.reconcile') }}</a>
|
||||
</li>
|
||||
<li>
|
||||
<a class="dropdown-item" href="{{ route('accounts.edit', [$data['account']['id']]) }}">{{ __('firefly.edit') }}</a>
|
||||
</li>
|
||||
<li>
|
||||
<a class="dropdown-item" href="{{ route('accounts.delete', [$data['account']['id']]) }}">{{ __('firefly.delete') }}</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@endforeach
|
||||
</div>
|
||||
|
||||
@if($billCount > 0)
|
||||
<!--BILLS -->
|
||||
<div class="card mb-4">
|
||||
<div class="card-header with-border">
|
||||
<div class="card-title"><a href="{{ route('subscriptions.index') }}" title="{{ __('firefly.bills') }}">{{ __('firefly.bills') }}</a></div>
|
||||
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="center-chart">
|
||||
<canvas id="bills-chart" class="low-chart" height="200"></canvas>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-footer">
|
||||
<a href="{{ route('bills.index') }}" class="btn btn-primary btn-sm"><span
|
||||
class="bi bi-calendar"></span> {{ __('firefly.go_to_bills') }}</a>
|
||||
</div>
|
||||
</div>
|
||||
@endif
|
||||
|
||||
<!--box for piggy bank data (JSON) -->
|
||||
<div id="piggy_bank_overview">
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-lg-12 col-md-12 col-sm-12">
|
||||
<!--EXPENSE ACCOUNTS -->
|
||||
<div class="card mb-4">
|
||||
<div class="card-header with-border">
|
||||
<div class="card-title"><a href="{{ route('accounts.index',['expense']) }}" title="{{ __('firefly.expense_accounts') }}">{{ __('firefly.expense_accounts') }}</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<canvas id="expense-accounts-chart" class="wide-chart" height="400"
|
||||
width="100%"></canvas>
|
||||
</div>
|
||||
<div class="card-footer">
|
||||
<a href="{{ route('accounts.index', ['expense']) }}" class="btn btn-primary btn-sm"><span
|
||||
class="bi bi-cart"></span> {{ __('firefly.go_to_expense_accounts') }}</a>
|
||||
</div>
|
||||
</div>
|
||||
<!--OPTIONAL REVENUE ACCOUNTS -->
|
||||
<div class="card mb-4">
|
||||
<div class="card-header with-border">
|
||||
<div class="card-title"><a href="{{ route('accounts.index',['revenue']) }}"
|
||||
title="{{ __('firefly.revenue_accounts') }}">{{ __('firefly.revenue_accounts') }}</a></div>
|
||||
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<canvas id="revenue-accounts-chart" class="wide-chart" height="400"
|
||||
width="100%"></canvas>
|
||||
</div>
|
||||
<div class="card-footer">
|
||||
<a href="{{ route('accounts.index', ['revenue']) }}" class="btn btn-primary btn-sm"><span
|
||||
class="bi bi-box-arrow-down"></span> {{ __('firefly.go_to_revenue_accounts') }}</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@endsection
|
||||
@section('scripts')
|
||||
@vite(['js/pages/dashboard/dashboard.js'])
|
||||
|
||||
|
||||
<script type="text/javascript" nonce="{{ $JS_NONCE }}">
|
||||
var lineColor = 'red';
|
||||
var lineTextColor = '#000';
|
||||
if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) {
|
||||
lineColor = '#a00';
|
||||
lineTextColor = '#bec5cb';
|
||||
}
|
||||
var billCount = {{ $billCount }};
|
||||
var accountFrontpageUrl = '{{ route('chart.account.frontpage') }}';
|
||||
var accountRevenueUrl = '{{ route('chart.account.revenue') }}';
|
||||
var accountExpenseUrl = '{{ route('chart.account.expense') }}';
|
||||
var piggyInfoUrl = '{{ route('json.fp.piggy-banks') }}';
|
||||
var drawVerticalLine = '';
|
||||
{{-- render vertical line with text "today" --}}
|
||||
@if($start->lte($today) && $end->gte($today))
|
||||
drawVerticalLine = '{{ $today->isoFormat($monthAndDayFormat) }}';
|
||||
@endif
|
||||
</script>
|
||||
|
||||
<script type="text/javascript" src="v1/js/lib/Chart.bundle.min.js?v={{ $FF_BUILD_TIME }}"
|
||||
nonce="{{ $JS_NONCE }}"></script>
|
||||
<script type="text/javascript" src="v1/js/lib/chartjs-plugin-annotation.min.js?v={{ $FF_BUILD_TIME }}"
|
||||
nonce="{{ $JS_NONCE }}"></script>
|
||||
<script type="text/javascript" src="v1/js/ff/charts.defaults.js?v={{ $FF_BUILD_TIME }}"
|
||||
nonce="{{ $JS_NONCE }}"></script>
|
||||
<script type="text/javascript" src="v1/js/ff/charts.js?v={{ $FF_BUILD_TIME }}" nonce="{{ $JS_NONCE }}"></script>
|
||||
<script type="text/javascript" src="v1/js/ff/index.js?v={{ $FF_BUILD_TIME }}" nonce="{{ $JS_NONCE }}"></script>
|
||||
|
||||
@endsection
|
||||
{{--
|
||||
<script type="text/javascript" nonce="{{ $JS_NONCE }}">
|
||||
var lineColor = 'red';
|
||||
var lineTextColor = '#000';
|
||||
if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) {
|
||||
lineColor = '#a00';
|
||||
lineTextColor = '#bec5cb';
|
||||
}
|
||||
var billCount = {{ $billCount }};
|
||||
var accountFrontpageUrl = '{{ route('chart.account.frontpage') }}';
|
||||
var accountRevenueUrl = '{{ route('chart.account.revenue') }}';
|
||||
var accountExpenseUrl = '{{ route('chart.account.expense') }}';
|
||||
var piggyInfoUrl = '{{ route('json.fp.piggy-banks') }}';
|
||||
var drawVerticalLine = '';
|
||||
<!--render vertical line with text "today" -->
|
||||
@if($start->lte($today) and $end->gte($today))
|
||||
drawVerticalLine = '{{ $today->isoFormat($monthAndDayFormat) }}';
|
||||
@endif
|
||||
</script>
|
||||
|
||||
<script type="text/javascript" src="v1/js/lib/Chart.bundle.min.js?v={{ $FF_BUILD_TIME }}"
|
||||
nonce="{{ $JS_NONCE }}"></script>
|
||||
<script type="text/javascript" src="v1/js/lib/chartjs-plugin-annotation.min.js?v={{ $FF_BUILD_TIME }}"
|
||||
nonce="{{ $JS_NONCE }}"></script>
|
||||
<script type="text/javascript" src="v1/js/ff/charts.defaults.js?v={{ $FF_BUILD_TIME }}"
|
||||
nonce="{{ $JS_NONCE }}"></script>
|
||||
<script type="text/javascript" src="v1/js/ff/charts.js?v={{ $FF_BUILD_TIME }}" nonce="{{ $JS_NONCE }}"></script>
|
||||
<script type="text/javascript" src="v1/js/ff/index.js?v={{ $FF_BUILD_TIME }}" nonce="{{ $JS_NONCE }}"></script>
|
||||
--}}
|
||||
37
resources/views/json/piggy-banks.blade.php
Normal file
37
resources/views/json/piggy-banks.blade.php
Normal file
@@ -0,0 +1,37 @@
|
||||
<div class="card mb-4">
|
||||
<div class="card-header">
|
||||
<div class="card-title"><a href="{{ route('piggy-banks.index') }}" title="{{ __('firefly.piggyBanks') }}">{{ __('firefly.piggyBanks') }}</a></div>
|
||||
|
||||
</div>
|
||||
<div class="card-body">
|
||||
@foreach($info as $entry)
|
||||
<strong>{{ $entry['name'] }}</strong><br/>
|
||||
<div class="progress">
|
||||
<div class="progress-bar progress-bar-striped w-{{ round($entry['percentage']) }}" role="progressbar" aria-valuenow="{{ $entry['percentage'] }}" aria-valuemin="0" aria-valuemax="100">
|
||||
@if($entry['percentage'] > 20)
|
||||
@if($convertToPrimary && 0 !== $avg['pc_amount'])
|
||||
{{ \FireflyIII\Support\Facades\Steam::formatAmountBySymbol($entry['pc_amount'], $entry['primary_currency_symbol'], $entry['primary_currency_decimal_places'], false) }}
|
||||
({{ \FireflyIII\Support\Facades\Steam::formatAmountBySymbol($entry['amount'], $entry['currency_symbol'], $entry['currency_decimal_places'], false) }})
|
||||
@endif
|
||||
@if(!$convertToPrimary)
|
||||
{{ \FireflyIII\Support\Facades\Steam::formatAmountBySymbol($entry['amount'], $entry['currency_symbol'], $entry['currency_decimal_places'], false) }}
|
||||
@endif
|
||||
@endif
|
||||
</div>
|
||||
@if($entry['percentage'] <= 20)
|
||||
|
||||
@if($convertToPrimary && 0 !== $avg['pc_amount'])
|
||||
{{ \FireflyIII\Support\Facades\Steam::formatAmountBySymbol($entry['pc_amount'], $entry['primary_currency_symbol'], $entry['primary_currency_decimal_places'], false) }}
|
||||
({{ \FireflyIII\Support\Facades\Steam::formatAmountBySymbol($entry['amount'], $entry['currency_symbol'], $entry['currency_decimal_places'], false) }})
|
||||
@endif
|
||||
@if(!$convertToPrimary)
|
||||
{{ \FireflyIII\Support\Facades\Steam::formatAmountBySymbol($entry['amount'], $entry['currency_symbol'], $entry['currency_decimal_places'], false) }}
|
||||
@endif
|
||||
@endif
|
||||
</div>
|
||||
@endforeach
|
||||
</div>
|
||||
<div class="card-footer">
|
||||
<a href="{{ route('piggy-banks.index') }}" class="btn btn-primary btn-sm"><span class="bi bi-bullseye"></span> {{ __('firefly.go_to_piggies') }}</a>
|
||||
</div>
|
||||
</div>
|
||||
@@ -62,7 +62,7 @@
|
||||
})()
|
||||
</script>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
@vite(['src/sass/app.scss'])
|
||||
{{-- @vite(['css/app.css', 'js/app.js']) --}}
|
||||
<style nonce="{{ $JS_NONCE ?? '' }}">
|
||||
.monospace {font-family: monospace;font-size:11px;}
|
||||
</style>
|
||||
|
||||
@@ -62,7 +62,7 @@
|
||||
})()
|
||||
</script>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
@vite(['src/sass/app.scss'])
|
||||
@vite(['sass/app.scss'])
|
||||
</head>
|
||||
|
||||
<body class="login-page bg-body-secondary">
|
||||
|
||||
376
resources/views/layout/v3/session.blade.php
Normal file
376
resources/views/layout/v3/session.blade.php
Normal file
@@ -0,0 +1,376 @@
|
||||
<!doctype html>
|
||||
<html lang="{{ __('config.html_language') }}">
|
||||
<!--begin::Head-->
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||
<meta charset="UTF-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="csrf-token" content="{{ csrf_token() }}">
|
||||
<meta name="robots" content="noindex, nofollow, noarchive, noodp, NoImageIndex, noydir">
|
||||
<meta name="apple-mobile-web-app-capable" content="yes">
|
||||
<!--
|
||||
If the base href URL begins with "http://" but you are sure it should start with "https://",
|
||||
please visit the following page: https://bit.ly/FF3-broken-base-href
|
||||
-->
|
||||
<base href="{{ route('index', null, true) }}/">
|
||||
<title>
|
||||
@if('' !== (string)$pageTitle)
|
||||
{{ $pageTitle }} »
|
||||
@endif
|
||||
@if('' !== (string)$subTitle && '' === (string) $pageTitle)
|
||||
{{ $subTitle }} »
|
||||
@endif
|
||||
@if('Firefly III' !== $title)
|
||||
{{ $title }} »
|
||||
@endif
|
||||
Firefly III
|
||||
</title>
|
||||
|
||||
<!--begin::Accessibility Meta Tags-->
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
|
||||
<meta name="color-scheme" content="light dark" />
|
||||
<meta name="theme-color" content="#007bff" media="(prefers-color-scheme: light)" />
|
||||
<meta name="theme-color" content="#1a1a1a" media="(prefers-color-scheme: dark)" />
|
||||
<!--end::Accessibility Meta Tags-->
|
||||
|
||||
<!--begin::Accessibility Features-->
|
||||
<!-- Skip links will be dynamically added by accessibility.js -->
|
||||
@if('browser' === $darkMode)
|
||||
<meta name="color-scheme" content="light dark">
|
||||
@endif
|
||||
@if('dark' === $darkMode)
|
||||
<meta name="color-scheme" content="dark">
|
||||
@endif
|
||||
@if('light' === $darkMode)
|
||||
<meta name="color-scheme" content="light">
|
||||
@endif
|
||||
|
||||
@vite(['sass/app.scss'])
|
||||
|
||||
<x-layout.fav-icons />
|
||||
<!--end::Accessibility Features-->
|
||||
|
||||
</head>
|
||||
<!--end::Head-->
|
||||
<!--begin::Body-->
|
||||
<body class="layout-fixed sidebar-mini sidebar-expand-lg bg-body-tertiary">
|
||||
<!--begin::App Wrapper-->
|
||||
<div class="app-wrapper">
|
||||
<!--begin::Header-->
|
||||
<nav class="app-header navbar navbar-expand bg-body">
|
||||
<!--begin::Container-->
|
||||
<div class="container-fluid">
|
||||
<!--begin::Start Navbar Links-->
|
||||
<ul class="navbar-nav">
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" data-lte-toggle="sidebar" href="#" role="button">
|
||||
<i class="bi bi-list"></i>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
<!--begin::End Navbar Links-->
|
||||
<ul class="navbar-nav ms-auto">
|
||||
<!--begin::Navbar Search-->
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" data-widget="navbar-search" href="{{route('search.index')}}" role="button">
|
||||
<em class="bi bi-search"></em>
|
||||
</a>
|
||||
</li>
|
||||
<!--end::Navbar Search-->
|
||||
|
||||
<!--begin::Fullscreen Toggle-->
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="#" data-lte-toggle="fullscreen">
|
||||
<i data-lte-icon="maximize" class="bi bi-arrows-fullscreen"></i>
|
||||
<i data-lte-icon="minimize" class="bi bi-fullscreen-exit d-none"></i>
|
||||
</a>
|
||||
</li>
|
||||
<!--end::Fullscreen Toggle-->
|
||||
|
||||
<!--begin::Color Mode Toggle (#6010)-->
|
||||
<li class="nav-item dropdown">
|
||||
<a
|
||||
class="nav-link"
|
||||
href="#"
|
||||
id="bd-theme"
|
||||
aria-label="Toggle color scheme"
|
||||
data-bs-toggle="dropdown"
|
||||
aria-expanded="false"
|
||||
>
|
||||
<i class="bi bi-sun-fill" data-lte-theme-icon="light"></i>
|
||||
<i class="bi bi-moon-fill d-none" data-lte-theme-icon="dark"></i>
|
||||
<i class="bi bi-circle-half d-none" data-lte-theme-icon="auto"></i>
|
||||
</a>
|
||||
<ul
|
||||
class="dropdown-menu dropdown-menu-end"
|
||||
aria-labelledby="bd-theme"
|
||||
style="--bs-dropdown-min-width: 8rem"
|
||||
>
|
||||
<li>
|
||||
<button
|
||||
type="button"
|
||||
class="dropdown-item d-flex align-items-center"
|
||||
data-bs-theme-value="light"
|
||||
aria-pressed="false"
|
||||
>
|
||||
<i class="bi bi-sun-fill me-2"></i>
|
||||
Light
|
||||
<i class="bi bi-check-lg ms-auto d-none"></i>
|
||||
</button>
|
||||
</li>
|
||||
<li>
|
||||
<button
|
||||
type="button"
|
||||
class="dropdown-item d-flex align-items-center"
|
||||
data-bs-theme-value="dark"
|
||||
aria-pressed="false"
|
||||
>
|
||||
<i class="bi bi-moon-fill me-2"></i>
|
||||
Dark
|
||||
<i class="bi bi-check-lg ms-auto d-none"></i>
|
||||
</button>
|
||||
</li>
|
||||
<li>
|
||||
<button
|
||||
type="button"
|
||||
class="dropdown-item d-flex align-items-center active"
|
||||
data-bs-theme-value="auto"
|
||||
aria-pressed="true"
|
||||
>
|
||||
<i class="bi bi-circle-half me-2"></i>
|
||||
Auto
|
||||
<i class="bi bi-check-lg ms-auto d-none"></i>
|
||||
</button>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
<!--end::Color Mode Toggle-->
|
||||
<x-layout.create-menu />
|
||||
<x-layout.user-menu />
|
||||
|
||||
<!--end::User Menu Dropdown-->
|
||||
</ul>
|
||||
<!--end::End Navbar Links-->
|
||||
</div>
|
||||
<!--end::Container-->
|
||||
</nav>
|
||||
<!--end::Header-->
|
||||
<!--begin::Sidebar-->
|
||||
<aside class="app-sidebar bg-body-secondary shadow" data-bs-theme="dark">
|
||||
<!--begin::Sidebar Brand-->
|
||||
<div class="sidebar-brand">
|
||||
<!--begin::Brand Link-->
|
||||
<a href="{{ route('index') }}" class="brand-link">
|
||||
<!--begin::Brand Image-->
|
||||
<img
|
||||
src="./images/logo-session.png"
|
||||
alt="Firefly III"
|
||||
class="brand-image opacity-75 shadow"
|
||||
/>
|
||||
<!--end::Brand Image-->
|
||||
<!--begin::Brand Text-->
|
||||
<span class="brand-text fw-light">Firefly III</span>
|
||||
<!--end::Brand Text-->
|
||||
</a>
|
||||
<!--end::Brand Link-->
|
||||
</div>
|
||||
<!--end::Sidebar Brand-->
|
||||
<!--begin::Sidebar Wrapper-->
|
||||
<div class="sidebar-wrapper">
|
||||
<nav class="mt-2">
|
||||
<!--begin::Sidebar Menu-->
|
||||
<x-layout.sidebar />
|
||||
<!--end::Sidebar Menu-->
|
||||
|
||||
<!-- Docs CTA (bottom of sidebar) -->
|
||||
{{--
|
||||
<div class="p-3 mt-3 border-top border-secondary border-opacity-25">
|
||||
<a
|
||||
href="https://docs.firefly-iii.org/"
|
||||
class="btn btn-sm btn-outline-light w-100 d-flex align-items-center justify-content-center gap-2"
|
||||
>
|
||||
<i class="bi bi-book" aria-hidden="true"></i>
|
||||
{{ trans('firefly.view_documentation') }}
|
||||
</a>
|
||||
</div>
|
||||
--}}
|
||||
</nav>
|
||||
</div>
|
||||
<!--end::Sidebar Wrapper-->
|
||||
</aside>
|
||||
<!--end::Sidebar-->
|
||||
<!--begin::App Main-->
|
||||
<main class="app-main">
|
||||
<!--begin::App Content Header-->
|
||||
<div class="app-content-header">
|
||||
<!--begin::Container-->
|
||||
<div class="container-fluid">
|
||||
<!--begin::Row-->
|
||||
<div class="row">
|
||||
<div class="col-sm-6">
|
||||
<h3 class="mb-0">
|
||||
<em class="bi {{ $mainTitleIcon }}"></em>
|
||||
{{ $pageTitle }}
|
||||
|
||||
<small class="text-xs text-muted">@if(isset($subTitleIcon))<em class="bi {{ $subTitleIcon }}"></em>X @endif{{$subTitle}}</small>
|
||||
</h3>
|
||||
</div>
|
||||
|
||||
<div class="col-sm-6">
|
||||
{{ Breadcrumbs::render() }}
|
||||
</div>
|
||||
</div>
|
||||
<!--end::Row-->
|
||||
</div>
|
||||
<!--end::Container-->
|
||||
</div>
|
||||
<!--end::App Content Header-->
|
||||
<!--begin::App Content-->
|
||||
<div class="app-content">
|
||||
<!--begin::Container-->
|
||||
<div class="container-fluid">
|
||||
@yield('content')
|
||||
|
||||
<!--begin::Row-->
|
||||
<!--end::Row-->
|
||||
<!--begin::Row-->
|
||||
<!-- /.row (main row) -->
|
||||
</div>
|
||||
<!--end::Container-->
|
||||
</div>
|
||||
<!--end::App Content-->
|
||||
</main>
|
||||
<!--end::App Main-->
|
||||
<!--begin::Footer-->
|
||||
<footer class="app-footer">
|
||||
<!--begin::To the end-->
|
||||
<div class="float-end d-none d-sm-inline">
|
||||
<a href="{{route('debug')}}">v{{ $FF_VERSION }}</a>
|
||||
</div>
|
||||
<!--end::To the end-->
|
||||
<!--begin::Copyright-->
|
||||
<span>
|
||||
<a href="https://www.firefly-iii.org/" target="_blank" title="Firefly III">Firefly III</a> © James Cole, <a href="https://www.gnu.org/licenses/agpl-3.0.html" title="AGPL-3.0-or-later.">AGPL-3.0-or-later</a>.
|
||||
</span>
|
||||
<!--end::Copyright-->
|
||||
</footer>
|
||||
<!--end::Footer-->
|
||||
</div>
|
||||
<!--end::App Wrapper-->
|
||||
<!--begin::Script-->
|
||||
<!--begin::Third Party Plugin(OverlayScrollbars)-->
|
||||
<!--end::Third Party Plugin(OverlayScrollbars)--><!--begin::Required Plugin(popperjs for Bootstrap 5)-->
|
||||
<!--end::Required Plugin(popperjs for Bootstrap 5)--><!--begin::Required Plugin(Bootstrap 5)-->
|
||||
<!--end::Required Plugin(Bootstrap 5)--><!--begin::Required Plugin(AdminLTE)-->
|
||||
<!--end::Required Plugin(AdminLTE)-->
|
||||
<!--begin::OverlayScrollbars Configure-->
|
||||
|
||||
<!--end::OverlayScrollbars Configure-->
|
||||
|
||||
{{-- Moment JS --}}
|
||||
<script src="v1/js/lib/moment.min.js?v={{ $FF_BUILD_TIME }}" type="text/javascript" nonce="{{ $JS_NONCE }}"></script>
|
||||
<script src="v1/js/lib/moment/{{ str_replace($language,'-','_') }}.js?v={{ $FF_BUILD_TIME }}" type="text/javascript" nonce="{{ $JS_NONCE }}"></script>
|
||||
|
||||
{{-- All kinds of variables. --}}
|
||||
<script src="{{ route('javascript.variables') }}?ext=.js&v={{ $FF_VERSION }}@if(isset($account))&account={{ $account->id }}@endif" type="text/javascript" nonce="{{ $JS_NONCE }}"></script>
|
||||
|
||||
{{-- Base script: jquery and bootstrap --}}
|
||||
<script src="v1/js/app.js?v={{ $FF_BUILD_TIME }}" type="text/javascript" nonce="{{ $JS_NONCE }}"></script>
|
||||
|
||||
|
||||
{{-- date range picker, current template, etc. --}}
|
||||
<script src="v1/js/lib/daterangepicker.js?v={{ $FF_BUILD_TIME }}" type="text/javascript" nonce="{{ $JS_NONCE }}"></script>
|
||||
<script src="v1/lib/adminlte/js/adminlte.min.js?v={{ $FF_BUILD_TIME }}" type="text/javascript" nonce="{{ $JS_NONCE }}"></script>
|
||||
<script type="text/javascript" src="v1/js/lib/accounting.min.js?v={{ $FF_BUILD_TIME }}" nonce="{{ $JS_NONCE }}"></script>
|
||||
|
||||
{{-- Firefly III code --}}
|
||||
<script type="text/javascript" src="v1/js/ff/firefly.js?v={{ $FF_BUILD_TIME }}" nonce="{{ $JS_NONCE }}"></script>
|
||||
<script type="text/javascript" src="v1/js/ff/help.js?v={{ $FF_BUILD_TIME }}" nonce="{{ $JS_NONCE }}"></script>
|
||||
|
||||
@yield('scripts')
|
||||
|
||||
<!--begin::Color Mode Toggle (#6010)-->
|
||||
<script>
|
||||
(() => {
|
||||
'use strict';
|
||||
|
||||
const STORAGE_KEY = 'lte-theme';
|
||||
|
||||
const getStoredTheme = () => localStorage.getItem(STORAGE_KEY);
|
||||
const setStoredTheme = (theme) => localStorage.setItem(STORAGE_KEY, theme);
|
||||
|
||||
const prefersDark = () => globalThis.matchMedia('(prefers-color-scheme: dark)').matches;
|
||||
|
||||
const getPreferredTheme = () => {
|
||||
const stored = getStoredTheme();
|
||||
if (stored) return stored;
|
||||
return prefersDark() ? 'dark' : 'light';
|
||||
};
|
||||
|
||||
const setTheme = (theme) => {
|
||||
const resolved = theme === 'auto' ? (prefersDark() ? 'dark' : 'light') : theme;
|
||||
document.documentElement.setAttribute('data-bs-theme', resolved);
|
||||
};
|
||||
|
||||
setTheme(getPreferredTheme());
|
||||
|
||||
const showActiveTheme = (theme) => {
|
||||
// Highlight the active dropdown option
|
||||
document.querySelectorAll('[data-bs-theme-value]').forEach((el) => {
|
||||
el.classList.remove('active');
|
||||
el.setAttribute('aria-pressed', 'false');
|
||||
const check = el.querySelector('.bi-check-lg');
|
||||
if (check) check.classList.add('d-none');
|
||||
});
|
||||
const active = document.querySelector(`[data-bs-theme-value="${theme}"]`);
|
||||
if (active) {
|
||||
active.classList.add('active');
|
||||
active.setAttribute('aria-pressed', 'true');
|
||||
const check = active.querySelector('.bi-check-lg');
|
||||
if (check) check.classList.remove('d-none');
|
||||
}
|
||||
// Sync the topbar trigger icon
|
||||
document.querySelectorAll('[data-lte-theme-icon]').forEach((icon) => {
|
||||
icon.classList.toggle('d-none', icon.dataset.lteThemeIcon !== theme);
|
||||
});
|
||||
};
|
||||
|
||||
globalThis.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', () => {
|
||||
const stored = getStoredTheme();
|
||||
if (!stored || stored === 'auto') setTheme(getPreferredTheme());
|
||||
});
|
||||
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
showActiveTheme(getPreferredTheme());
|
||||
document.querySelectorAll('[data-bs-theme-value]').forEach((toggle) => {
|
||||
toggle.addEventListener('click', () => {
|
||||
const theme = toggle.getAttribute('data-bs-theme-value');
|
||||
setStoredTheme(theme);
|
||||
setTheme(theme);
|
||||
showActiveTheme(theme);
|
||||
});
|
||||
});
|
||||
});
|
||||
})();
|
||||
</script>
|
||||
<!--end::Color Mode Toggle-->
|
||||
|
||||
<!-- OPTIONAL SCRIPTS -->
|
||||
|
||||
<!-- sortablejs -->
|
||||
|
||||
<!-- sortablejs -->
|
||||
|
||||
<!-- apexcharts -->
|
||||
|
||||
<!-- ChartJS -->
|
||||
|
||||
<!-- jsvectormap -->
|
||||
<!-- jsvectormap -->
|
||||
<!--end::Script-->
|
||||
<form id="logout-form" action="{{ route('logout') }}" method="POST" class="hidden">
|
||||
<input type="hidden" name="_token" value="{{ csrf_token() }}"/>
|
||||
</form>
|
||||
</body>
|
||||
<!--end::Body-->
|
||||
</html>
|
||||
@@ -1,30 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<base href="{{ route('index') }}/" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>{{ 'login_page_title'|_ }}</title>
|
||||
|
||||
<!-- fonts and styles -->
|
||||
<link rel="stylesheet" href="v3-local/css/fonts.css?v={{ FF_BUILD_TIME }}">
|
||||
<link rel="stylesheet" href="v3-local/lib/fontawesome-free/css/all.min.css?v={{ FF_BUILD_TIME }}">
|
||||
<link rel="stylesheet" href="v3-local/lib/icheck-bootstrap/icheck-bootstrap.min.css?v={{ FF_BUILD_TIME }}">
|
||||
<link rel="stylesheet" href="v3-local/dist/css/adminlte.min.css?v={{ FF_BUILD_TIME }}">
|
||||
|
||||
{# favicons #}
|
||||
{% include 'partials.favicons' %}
|
||||
</head>
|
||||
<body class="hold-transition login-page dark-mode">
|
||||
{% block content %}{% endblock %}
|
||||
|
||||
<!-- jQuery -->
|
||||
<script src="v3-local/lib/jquery/jquery.min.js?v={{ FF_BUILD_TIME }}" nonce="{{ JS_NONCE }}"></script>
|
||||
<!-- Bootstrap 4 -->
|
||||
<script src="v3-local/lib/bootstrap/js/bootstrap.bundle.min.js?v={{ FF_BUILD_TIME }}" nonce="{{ JS_NONCE }}"></script>
|
||||
<!-- AdminLTE App -->
|
||||
<script src="v3-local/dist/js/adminlte.min.js?v={{ FF_BUILD_TIME }}" nonce="{{ JS_NONCE }}"></script>
|
||||
{% block scripts %}
|
||||
{% endblock %}
|
||||
</body>
|
||||
</html>
|
||||
13
resources/views/partials/layout/breadcrumbs-v3.blade.php
Normal file
13
resources/views/partials/layout/breadcrumbs-v3.blade.php
Normal file
@@ -0,0 +1,13 @@
|
||||
@if(count($breadcrumbs) > 0)
|
||||
<ol class="breadcrumb float-sm-end">
|
||||
@foreach($breadcrumbs as $breadcrumb)
|
||||
@if($breadcrumb->url && !$loop->last)
|
||||
<li class="breadcrumb-item"><a href="{{ $breadcrumb->url }}">{{ $breadcrumb->title }}</a></li>
|
||||
@endif
|
||||
@if(!$breadcrumb->url || $loop->last)
|
||||
<li class="breadcrumb-item active" aria-current="page">{{ $breadcrumb->title }}</li>
|
||||
@endif
|
||||
@endforeach
|
||||
|
||||
</ol>
|
||||
@endif
|
||||
@@ -57,11 +57,7 @@
|
||||
<i class="fa-solid fa-plus-circle"></i>
|
||||
</a>
|
||||
<div class="dropdown-menu dropdown-menu-lg dropdown-menu-end">
|
||||
<!-- withdrawal, deposit, transfer -->
|
||||
<a href="{{ route('transactions.create', ['withdrawal']) }}" class="dropdown-item">
|
||||
<em class="fa-solid fa-arrow-left fa-fw me-2"></em>
|
||||
{{ __('firefly.create_new_withdrawal') }}
|
||||
</a>
|
||||
|
||||
<a href="{{ route('transactions.create', ['deposit']) }}" class="dropdown-item">
|
||||
<em class="fa-solid fa-arrow-right fa-fw me-2"></em>
|
||||
{{ __('firefly.create_new_deposit') }}
|
||||
|
||||
Reference in New Issue
Block a user