Compare commits

...

58 Commits

Author SHA1 Message Date
github-actions[bot]
d0e55804f8 Merge pull request #11110 from firefly-iii/release-1761467960
🤖 Automatically merge the PR into the develop branch.
2025-10-26 09:39:29 +01:00
JC5
0a9715b8c1 🤖 Auto commit for release 'develop' on 2025-10-26 2025-10-26 09:39:20 +01:00
James Cole
61390e67f6 Add debug info. 2025-10-26 09:34:40 +01:00
James Cole
536d25980f Fix issues related to #11109 2025-10-26 09:31:07 +01:00
github-actions[bot]
3253b2e569 Merge pull request #11107 from firefly-iii/release-1761395685
🤖 Automatically merge the PR into the develop branch.
2025-10-25 14:34:54 +02:00
JC5
11ac955303 🤖 Auto commit for release 'develop' on 2025-10-25 2025-10-25 14:34:46 +02:00
James Cole
caf9a31bc4 Replace version with build time. 2025-10-25 14:30:22 +02:00
github-actions[bot]
8c84ab5855 Merge pull request #11106 from firefly-iii/release-1761394994
🤖 Automatically merge the PR into the develop branch.
2025-10-25 14:23:23 +02:00
JC5
91a56a7396 🤖 Auto commit for release 'develop' on 2025-10-25 2025-10-25 14:23:14 +02:00
James Cole
f5806ea6de Fix #11102 2025-10-25 14:09:44 +02:00
James Cole
60b3692ac9 Merge branch 'develop' of github.com:firefly-iii/firefly-iii into develop 2025-10-25 11:50:43 +02:00
James Cole
0bdb4f2e69 Fix https://github.com/orgs/firefly-iii/discussions/11104 2025-10-25 11:50:34 +02:00
github-actions[bot]
f89f50c2db Merge pull request #11101 from firefly-iii/release-1761383546
🤖 Automatically merge the PR into the develop branch.
2025-10-25 11:12:35 +02:00
JC5
394df46961 🤖 Auto commit for release 'develop' on 2025-10-25 2025-10-25 11:12:26 +02:00
James Cole
535e5e4f50 Catch null pointer. 2025-10-25 11:08:07 +02:00
James Cole
00ba2a46d2 Fix #11063 2025-10-25 09:20:21 +02:00
James Cole
a3ff26e3e4 Fix https://github.com/firefly-iii/firefly-iii/issues/11096 2025-10-23 16:54:13 +02:00
github-actions[bot]
54aeb4b4ef Merge pull request #11084 from firefly-iii/release-1760930902
🤖 Automatically merge the PR into the develop branch.
2025-10-20 05:28:30 +02:00
JC5
9eb3ad62dd 🤖 Auto commit for release 'develop' on 2025-10-20 2025-10-20 05:28:22 +02:00
github-actions[bot]
4f0e978687 Merge pull request #11060 from firefly-iii/release-1760325917
🤖 Automatically merge the PR into the develop branch.
2025-10-13 05:25:26 +02:00
JC5
e1cf9f7a79 🤖 Auto commit for release 'develop' on 2025-10-13 2025-10-13 05:25:17 +02:00
James Cole
7ce055a22c Merge pull request #11056 from ctrl-f5/feat/account-attachment-list-request
account/attachments endpoint use request object for pagination, add test
2025-10-12 20:15:00 +02:00
Nicky De Maeyer
7bd915930c account/attachments endpoint use request object for pagination, add test 2025-10-12 19:54:47 +02:00
github-actions[bot]
75aa2d99fd Merge pull request #11055 from firefly-iii/release-1760278017
🤖 Automatically merge the PR into the develop branch.
2025-10-12 16:07:07 +02:00
JC5
f52bc0e242 🤖 Auto commit for release 'develop' on 2025-10-12 2025-10-12 16:06:57 +02:00
James Cole
55cf924794 Another fix for #11054 2025-10-12 16:02:14 +02:00
James Cole
df3e4a6554 Fix #11054 2025-10-12 12:25:21 +02:00
James Cole
7c4ada458e Merge pull request #11052 from ctrl-f5/fix/incorrect-validator-function
correct validator function to check for errors + `Account\ShowControllerTest`
2025-10-12 06:47:19 +02:00
Nicky De Maeyer
2a4a98dd10 use the correct validator function to check for errors, add a test for ShowController 2025-10-11 23:02:54 +02:00
github-actions[bot]
a3bf845851 Merge pull request #11051 from firefly-iii/release-1760189013
🤖 Automatically merge the PR into the develop branch.
2025-10-11 15:23:39 +02:00
JC5
78e832cdba 🤖 Auto commit for release 'develop' on 2025-10-11 2025-10-11 15:23:33 +02:00
James Cole
d47e4c4f24 Fix #11050 2025-10-11 15:17:51 +02:00
github-actions[bot]
056329291f Merge pull request #11049 from firefly-iii/release-1760159506
🤖 Automatically merge the PR into the develop branch.
2025-10-11 07:11:57 +02:00
JC5
977946064d 🤖 Auto commit for release 'develop' on 2025-10-11 2025-10-11 07:11:46 +02:00
James Cole
1870345ddf Add new request in style of aggregated requests, fix issue with missing field. 2025-10-11 07:05:32 +02:00
James Cole
6980717075 Set version in more places. 2025-10-11 06:47:55 +02:00
James Cole
1fe0aebacb Validate version using build_time. 2025-10-11 06:45:16 +02:00
github-actions[bot]
cbf7aef0c1 Merge pull request #11048 from firefly-iii/release-1760157167
🤖 Automatically merge the PR into the develop branch.
2025-10-11 06:33:00 +02:00
JC5
8c3e6c0189 🤖 Auto commit for release 'develop' on 2025-10-11 2025-10-11 06:32:47 +02:00
James Cole
cf7ee79c1c Fix two bugs in requests. 2025-10-11 06:27:55 +02:00
github-actions[bot]
7e344e4332 Merge pull request #11047 from firefly-iii/release-1760124177
🤖 Automatically merge the PR into the develop branch.
2025-10-10 21:23:04 +02:00
JC5
0a55e9fb4e 🤖 Auto commit for release 'develop' on 2025-10-10 2025-10-10 21:22:57 +02:00
James Cole
ed2e0e86dc Don't validate on empty string. 2025-10-10 20:54:51 +02:00
James Cole
9d1fb2cd6a Make sure that null|string passed is always a string 2025-10-10 20:54:31 +02:00
github-actions[bot]
57617b750f Merge pull request #11045 from firefly-iii/release-1760116335
🤖 Automatically merge the PR into the develop branch.
2025-10-10 19:12:23 +02:00
JC5
f6411fdc5a 🤖 Auto commit for release 'develop' on 2025-10-10 2025-10-10 19:12:15 +02:00
James Cole
02e24fc919 Whoops. 2025-10-10 19:07:28 +02:00
github-actions[bot]
dbc0210304 Merge pull request #11044 from firefly-iii/release-1760115302
🤖 Automatically merge the PR into the develop branch.
2025-10-10 18:55:11 +02:00
JC5
a709e224d4 🤖 Auto commit for release 'develop' on 2025-10-10 2025-10-10 18:55:02 +02:00
James Cole
83f3eddf44 Small code changes for @ctrl-f5's PR.
- Dropped some "setParameters" calls if unused in transformer.
- Add correct copyright
- Sprintf instead of string concat
- Small ident changes courtesy of phpstorm.
2025-10-10 18:50:39 +02:00
James Cole
7cfc4c2671 Merge pull request #11039 from ctrl-f5/feat/improve-request-objects
proposal for improved request handling
2025-10-10 18:38:02 +02:00
mergify[bot]
1c6055cb2d Merge branch 'develop' into feat/improve-request-objects 2025-10-10 14:42:25 +00:00
James Cole
4f4576e458 Add option to select date, fix #11042 2025-10-10 16:41:46 +02:00
mergify[bot]
84d3bcbb37 Merge branch 'develop' into feat/improve-request-objects 2025-10-10 11:33:40 +00:00
mergify[bot]
ad67bb80f3 Merge branch 'develop' into feat/improve-request-objects 2025-10-10 11:29:39 +00:00
mergify[bot]
569f553d26 Merge branch 'develop' into feat/improve-request-objects 2025-10-10 06:58:56 +00:00
mergify[bot]
58c76bee94 Merge branch 'develop' into feat/improve-request-objects 2025-10-10 06:46:55 +00:00
Nicky De Maeyer
52f3ec7d3d improved request handling 2025-10-09 15:05:52 +02:00
124 changed files with 1882 additions and 1116 deletions

View File

@@ -402,16 +402,16 @@
},
{
"name": "friendsofphp/php-cs-fixer",
"version": "v3.88.2",
"version": "v3.89.1",
"source": {
"type": "git",
"url": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer.git",
"reference": "a8d15584bafb0f0d9d938827840060fd4a3ebc99"
"reference": "f34967da2866ace090a2b447de1f357356474573"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/PHP-CS-Fixer/PHP-CS-Fixer/zipball/a8d15584bafb0f0d9d938827840060fd4a3ebc99",
"reference": "a8d15584bafb0f0d9d938827840060fd4a3ebc99",
"url": "https://api.github.com/repos/PHP-CS-Fixer/PHP-CS-Fixer/zipball/f34967da2866ace090a2b447de1f357356474573",
"reference": "f34967da2866ace090a2b447de1f357356474573",
"shasum": ""
},
"require": {
@@ -426,7 +426,6 @@
"php": "^7.4 || ^8.0",
"react/child-process": "^0.6.6",
"react/event-loop": "^1.5",
"react/promise": "^3.3",
"react/socket": "^1.16",
"react/stream": "^1.4",
"sebastian/diff": "^4.0.6 || ^5.1.1 || ^6.0.2 || ^7.0",
@@ -494,7 +493,7 @@
],
"support": {
"issues": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/issues",
"source": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/tree/v3.88.2"
"source": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/tree/v3.89.1"
},
"funding": [
{
@@ -502,7 +501,7 @@
"type": "github"
}
],
"time": "2025-09-27T00:24:15+00:00"
"time": "2025-10-24T12:05:10+00:00"
},
{
"name": "psr/container",

View File

@@ -67,6 +67,8 @@ abstract class Controller extends BaseController
protected bool $convertToPrimary = false;
protected TransactionCurrency $primaryCurrency;
/** @deprecated use Request classes */
protected ParameterBag $parameters;
/**
@@ -98,7 +100,8 @@ abstract class Controller extends BaseController
}
/**
* Method to grab all parameters from the URL.
* @deprecated use Request classes
* Method to grab all parameters from the URL
*/
private function getParameters(): ParameterBag
{

View File

@@ -25,6 +25,7 @@ declare(strict_types=1);
namespace FireflyIII\Api\V1\Controllers\Models\Account;
use FireflyIII\Api\V1\Controllers\Controller;
use FireflyIII\Api\V1\Requests\PaginationRequest;
use FireflyIII\Helpers\Collector\GroupCollectorInterface;
use FireflyIII\Models\Account;
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
@@ -69,22 +70,25 @@ class ListController extends Controller
);
}
public function attachments(Account $account): JsonResponse
public function attachments(Account $account, PaginationRequest $request): JsonResponse
{
$manager = $this->getManager();
$pageSize = $this->parameters->get('limit');
[
'limit' => $limit,
'offset' => $offset,
'page' => $page,
] = $request->attributes->all();
$collection = $this->repository->getAttachments($account);
$count = $collection->count();
$attachments = $collection->slice(($this->parameters->get('page') - 1) * $pageSize, $pageSize);
$attachments = $collection->slice($offset, $limit);
// make paginator:
$paginator = new LengthAwarePaginator($attachments, $count, $pageSize, $this->parameters->get('page'));
$paginator = new LengthAwarePaginator($attachments, $count, $limit, $page);
$paginator->setPath(route('api.v1.accounts.attachments', [$account->id]).$this->buildParams());
/** @var AttachmentTransformer $transformer */
$transformer = app(AttachmentTransformer::class);
$transformer->setParameters($this->parameters);
$resource = new FractalCollection($attachments, $transformer, 'attachments');
$resource->setPaginator(new IlluminatePaginatorAdapter($paginator));

View File

@@ -71,45 +71,45 @@ class ShowController extends Controller
public function index(ShowRequest $request): JsonResponse
{
$manager = $this->getManager();
$params = $request->getParameters();
$this->parameters->set('type', $params['type']);
// types to get, page size:
$types = $this->mapAccountTypes($params['type']);
[
'types' => $types,
'page' => $page,
'limit' => $limit,
'offset' => $offset,
'sort' => $sort,
'start' => $start,
'end' => $end,
'date' => $date,
]
= $request->attributes->all();
// get list of accounts. Count it and split it.
$this->repository->resetAccountOrder();
$collection = $this->repository->getAccountsByType($types, $params['sort']);
$collection = $this->repository->getAccountsByType($types, $sort);
$count = $collection->count();
// continue sort:
// TODO if the user sorts on DB dependent field there must be no slice before enrichment, only after.
// TODO still need to figure out how to do this easily.
$accounts = $collection->slice(($this->parameters->get('page') - 1) * $params['limit'], $params['limit']);
// #11007 go to the end of the previous day.
$this->parameters->set('start', $this->parameters->get('start')?->subSecond());
// #11018 also end of the day.
$this->parameters->set('end', $this->parameters->get('end')?->endOfDay());
$accounts = $collection->slice($offset, $limit);
// enrich
/** @var User $admin */
$admin = auth()->user();
$enrichment = new AccountEnrichment();
$enrichment->setSort($params['sort']);
$enrichment->setDate($this->parameters->get('date'));
$enrichment->setStart($this->parameters->get('start'));
$enrichment->setEnd($this->parameters->get('end'));
$enrichment->setSort($sort);
$enrichment->setDate($date);
$enrichment->setStart($start);
$enrichment->setEnd($end);
$enrichment->setUser($admin);
$accounts = $enrichment->enrich($accounts);
// make paginator:
$paginator = new LengthAwarePaginator($accounts, $count, $params['limit'], $this->parameters->get('page'));
$paginator = new LengthAwarePaginator($accounts, $count, $limit, $page);
$paginator->setPath(route('api.v1.accounts.index').$this->buildParams());
/** @var AccountTransformer $transformer */
$transformer = app(AccountTransformer::class);
$transformer->setParameters($this->parameters);
$resource = new FractalCollection($accounts, $transformer, self::RESOURCE_KEY);
$resource->setPaginator(new IlluminatePaginatorAdapter($paginator));
@@ -128,28 +128,25 @@ class ShowController extends Controller
// get list of accounts. Count it and split it.
$this->repository->resetAccountOrder();
$account->refresh();
$manager = $this->getManager();
// #11007 go to the end of the previous day.
$this->parameters->set('start', $this->parameters->get('start')?->subSecond());
// #11018 also end of the day.
$this->parameters->set('end', $this->parameters->get('end')?->endOfDay());
$manager = $this->getManager();
['start' => $start,
'end' => $end,
'date' => $date,] = $request->attributes->all();
// enrich
/** @var User $admin */
$admin = auth()->user();
$enrichment = new AccountEnrichment();
$enrichment->setDate($this->parameters->get('date'));
$enrichment->setStart($this->parameters->get('start'));
$enrichment->setEnd($this->parameters->get('end'));
$admin = auth()->user();
$enrichment = new AccountEnrichment();
$enrichment->setDate($date);
$enrichment->setStart($start);
$enrichment->setEnd($end);
$enrichment->setUser($admin);
$account = $enrichment->enrichSingle($account);
$account = $enrichment->enrichSingle($account);
/** @var AccountTransformer $transformer */
$transformer = app(AccountTransformer::class);
$transformer->setParameters($this->parameters);
$resource = new Item($account, $transformer, self::RESOURCE_KEY);
$transformer = app(AccountTransformer::class);
$resource = new Item($account, $transformer, self::RESOURCE_KEY);
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE);
}

View File

@@ -172,7 +172,6 @@ class ShowController extends Controller
/** @var BudgetLimitTransformer $transformer */
$transformer = app(BudgetLimitTransformer::class);
$transformer->setParameters($this->parameters);
$resource = new Item($budgetLimit, $transformer, 'budget_limits');

View File

@@ -28,6 +28,7 @@ use Carbon\Carbon;
use FireflyIII\Api\V1\Controllers\Controller;
use FireflyIII\Api\V1\Requests\Models\CurrencyExchangeRate\DestroyRequest;
use FireflyIII\Enums\UserRoleEnum;
use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Models\CurrencyExchangeRate;
use FireflyIII\Models\TransactionCurrency;
use FireflyIII\Repositories\ExchangeRate\ExchangeRateRepositoryInterface;
@@ -75,6 +76,9 @@ class DestroyController extends Controller
if ($exchangeRate instanceof CurrencyExchangeRate) {
$this->repository->deleteRate($exchangeRate);
}
if (!$exchangeRate instanceof CurrencyExchangeRate) {
throw new FireflyException('Bla');
}
return response()->json([], 204);
}

View File

@@ -82,7 +82,6 @@ class UpdateController extends Controller
$exchangeRate = $this->repository->updateExchangeRate($exchangeRate, $rate, $date);
$transformer = new ExchangeRateTransformer();
$transformer->setParameters($this->parameters);
return response()
->api($this->jsonApiObject(self::RESOURCE_KEY, $exchangeRate, $transformer))

View File

@@ -25,7 +25,7 @@ declare(strict_types=1);
namespace FireflyIII\Api\V1\Controllers\Models\UserGroup;
use FireflyIII\Api\V1\Controllers\Controller;
use FireflyIII\Api\V1\Requests\Data\DateRequest;
use FireflyIII\Api\V1\Requests\PaginationRequest;
use FireflyIII\Repositories\UserGroup\UserGroupRepositoryInterface;
use FireflyIII\Transformers\UserGroupTransformer;
use Illuminate\Http\JsonResponse;
@@ -52,17 +52,19 @@ class IndexController extends Controller
);
}
public function index(DateRequest $request): JsonResponse
public function index(PaginationRequest $request): JsonResponse
{
$administrations = $this->repository->get();
$pageSize = $this->parameters->get('limit');
[
'page' => $page,
'limit' => $limit,
'offset' => $offset,
] = $request->attributes->all();
$count = $administrations->count();
$administrations = $administrations->slice(($this->parameters->get('page') - 1) * $pageSize, $pageSize);
$paginator = new LengthAwarePaginator($administrations, $count, $pageSize, $this->parameters->get('page'));
$administrations = $administrations->slice($offset, $limit);
$paginator = new LengthAwarePaginator($administrations, $count, $limit, $page);
$transformer = new UserGroupTransformer();
$transformer->setParameters($this->parameters); // give params to transformer
return response()
->json($this->jsonApiList(self::RESOURCE_KEY, $paginator, $transformer))
->header('Content-Type', self::CONTENT_TYPE)

View File

@@ -27,7 +27,7 @@ namespace FireflyIII\Api\V1\Controllers\Summary;
use Carbon\Carbon;
use Exception;
use FireflyIII\Api\V1\Controllers\Controller;
use FireflyIII\Api\V1\Requests\Data\DateRequest;
use FireflyIII\Api\V1\Requests\Summary\BasicRequest;
use FireflyIII\Enums\AccountTypeEnum;
use FireflyIII\Enums\TransactionTypeEnum;
use FireflyIII\Helpers\Collector\GroupCollectorInterface;
@@ -88,34 +88,25 @@ class BasicController extends Controller
);
}
/**
* This endpoint is documented at:
* https://api-docs.firefly-iii.org/?urls.primaryName=2.0.0%20(v1)#/summary/getBasicSummary
*
* @throws Exception
*/
public function basic(DateRequest $request): JsonResponse
public function basic(BasicRequest $request): JsonResponse
{
// parameters for boxes:
$dates = $request->getAll();
$start = $dates['start'];
$end = $dates['end'];
$code = $request->get('currency_code');
['start' => $start, 'end' => $end, 'code' => $code] = $request->attributes->all();
// balance information:
$balanceData = $this->getBalanceInformation($start, $end);
$billData = $this->getSubscriptionInformation($start, $end);
$spentData = $this->getLeftToSpendInfo($start, $end);
$netWorthData = $this->getNetWorthInfo($end);
$balanceData = $this->getBalanceInformation($start, $end);
$billData = $this->getSubscriptionInformation($start, $end);
$spentData = $this->getLeftToSpendInfo($start, $end);
$netWorthData = $this->getNetWorthInfo($end);
// $balanceData = [];
// $billData = [];
// $spentData = [];
// $netWorthData = [];
$total = array_merge($balanceData, $billData, $spentData, $netWorthData);
$total = array_merge($balanceData, $billData, $spentData, $netWorthData);
// give new keys
$return = [];
$return = [];
foreach ($total as $entry) {
if (null === $code || ($code === $entry['currency_code'])) {
if ('' === $code || ($code === $entry['currency_code'])) {
$return[$entry['key']] = $entry;
}
}

View File

@@ -0,0 +1,97 @@
<?php
/*
* Copyright (c) 2025 https://github.com/ctrl-f5
*
* 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/>.
*/
declare(strict_types=1);
namespace FireflyIII\Api\V1\Requests;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Log;
use Illuminate\Validation\Validator;
use RuntimeException;
abstract class AggregateFormRequest extends ApiRequest
{
/**
* @var ApiRequest[]
*/
protected array $requests = [];
/** @return class-string[] */
abstract protected function getRequests(): array;
public function initialize(array $query = [], array $request = [], array $attributes = [], array $cookies = [], array $files = [], array $server = [], $content = null): void
{
parent::initialize($query, $request, $attributes, $cookies, $files, $server, $content);
// instantiate all subrequests and share current requests' bags with them
Log::debug('Initializing AggregateFormRequest.');
foreach ($this->getRequests() as $config) {
$requestClass = is_array($config) ? array_shift($config) : $config;
if (!is_a($requestClass, Request::class, true)) {
throw new RuntimeException('getRequests() must return class-strings of subclasses of Request');
}
Log::debug(sprintf('Initializing subrequest %s', $requestClass));
$instance = $this->requests[] = new $requestClass();
$instance->request = $this->request;
$instance->query = $this->query;
$instance->attributes = $this->attributes;
$instance->cookies = $this->cookies;
$instance->files = $this->files;
$instance->server = $this->server;
$instance->headers = $this->headers;
if ($instance instanceof ApiRequest) {
$instance->handleConfig(is_array($config) ? $config : []);
}
}
Log::debug('Done initializing AggregateFormRequest.');
}
public function rules(): array
{
// check all subrequests for rules and combine them
return array_reduce(
$this->requests,
static fn (array $rules, FormRequest $request) => $rules
+ (
method_exists($request, 'rules')
? $request->rules()
: []
),
[],
);
}
public function withValidator(Validator $validator): void
{
// register all subrequests' validators
foreach ($this->requests as $request) {
if (method_exists($request, 'withValidator')) {
Log::debug(sprintf('Process withValidator from class %s', get_class($request)));
$request->withValidator($validator);
}
}
}
}

View File

@@ -0,0 +1,43 @@
<?php
/*
* Copyright (c) 2025 https://github.com/ctrl-f5
*
* 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/>.
*/
declare(strict_types=1);
namespace FireflyIII\Api\V1\Requests;
use FireflyIII\Support\Request\ChecksLogin;
use FireflyIII\Support\Request\ConvertsDataTypes;
use Illuminate\Foundation\Http\FormRequest;
class ApiRequest extends FormRequest
{
use ChecksLogin;
use ConvertsDataTypes;
protected string $required = '';
public function handleConfig(array $config): void
{
if (in_array('required', $config, true)) {
$this->required = 'required';
}
}
}

View File

@@ -1,82 +0,0 @@
<?php
/*
* DateRequest.php
* 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/>.
*/
declare(strict_types=1);
namespace FireflyIII\Api\V1\Requests\Data;
use FireflyIII\Exceptions\ValidationException;
use FireflyIII\Support\Request\ChecksLogin;
use FireflyIII\Support\Request\ConvertsDataTypes;
use Illuminate\Foundation\Http\FormRequest;
/**
* Request class for end points that require date parameters.
*
* Class DateRequest
*/
class DateRequest extends FormRequest
{
use ChecksLogin;
use ConvertsDataTypes;
/**
* Get all data from the request.
*/
public function getAll(): array
{
$start = $this->getCarbonDate('start');
$end = $this->getCarbonDate('end');
if (null === $start) {
$start = now()->startOfMonth();
}
if (null === $end) {
$end = now()->endOfMonth();
}
// sanity check on dates:
[$start, $end] = $end < $start ? [$end, $start] : [$start, $end];
$start->startOfDay();
$end->endOfDay();
if ($start->diffInYears($end, true) > 5) {
throw new ValidationException('Date range out of range.');
}
return [
'start' => $start,
'end' => $end,
'date' => $this->getCarbonDate('date'),
];
}
/**
* The rules that the incoming request must be matched against.
*/
public function rules(): array
{
return [
'date' => 'date|after:1970-01-02|before:2038-01-17',
'start' => 'date|after:1970-01-02|before:2038-01-17|before:end|required_with:end',
'end' => 'date|after:1970-01-02|before:2038-01-17|after:start|required_with:start',
];
}
}

View File

@@ -0,0 +1,57 @@
<?php
/*
* Copyright (c) 2025 https://github.com/ctrl-f5
*
* 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/>.
*/
declare(strict_types=1);
namespace FireflyIII\Api\V1\Requests;
use Illuminate\Validation\Validator;
class DateRangeRequest extends ApiRequest
{
public function rules(): array
{
return [
'start' => sprintf('date|after:1970-01-02|before:2038-01-17|before:end|required_with:end|%s', $this->required),
'end' => sprintf('date|after:1970-01-02|before:2038-01-17|after:start|required_with:start|%s', $this->required),
];
}
public function withValidator(Validator $validator): void
{
$validator->after(
function (Validator $validator): void {
if ($validator->failed()) {
// set null values
$this->attributes->set('start', null);
$this->attributes->set('end', null);
return;
}
$start = $this->getCarbonDate('start')?->startOfDay();
$end = $this->getCarbonDate('end')?->endOfDay();
$this->attributes->set('start', $start);
$this->attributes->set('end', $end);
}
);
}
}

View File

@@ -0,0 +1,58 @@
<?php
/*
* Copyright (c) 2025 https://github.com/ctrl-f5
*
* 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/>.
*/
declare(strict_types=1);
namespace FireflyIII\Api\V1\Requests;
use Carbon\Carbon;
use Illuminate\Validation\Validator;
class DateRequest extends ApiRequest
{
public function rules(): array
{
return [
'date' => 'date|after:1970-01-02|before:2038-01-17|'.$this->required,
];
}
public function withValidator(Validator $validator): void
{
$validator->after(
function (Validator $validator): void {
if ($validator->failed()) {
return;
}
$date = $this->getCarbonDate('date')?->endOfDay();
// if we also have a range, date must be in that range
$start = $this->attributes->get('start');
$end = $this->attributes->get('end');
if ($date instanceof Carbon && $start instanceof Carbon && $end instanceof Carbon && !$date->between($start, $end)) {
$validator->errors()->add('date', (string)trans('validation.between_date'));
}
$this->attributes->set('date', $date);
}
);
}
}

View File

@@ -0,0 +1,57 @@
<?php
declare(strict_types=1);
/*
* AccountTypeApiRequest.php
* Copyright (c) 2025 https://github.com/ctrl-f5
*
* 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/>.
*/
namespace FireflyIII\Api\V1\Requests\Models\Account;
use FireflyIII\Api\V1\Requests\ApiRequest;
use FireflyIII\Support\Http\Api\AccountFilter;
use Illuminate\Validation\Validator;
class AccountTypeApiRequest extends ApiRequest
{
use AccountFilter;
public function rules(): array
{
return [
'type' => sprintf('in:%s', implode(',', array_keys($this->types))),
];
}
public function withValidator(Validator $validator): void
{
$validator->after(
function (Validator $validator): void {
if ($validator->failed()) {
return;
}
$type = $this->convertString('type', 'all');
$this->attributes->add([
'type' => $type,
'types' => $this->mapAccountTypes($type),
]);
}
);
}
}

View File

@@ -23,77 +23,21 @@ declare(strict_types=1);
namespace FireflyIII\Api\V1\Requests\Models\Account;
use Carbon\Carbon;
use FireflyIII\Api\V1\Requests\AggregateFormRequest;
use FireflyIII\Api\V1\Requests\DateRangeRequest;
use FireflyIII\Api\V1\Requests\DateRequest;
use FireflyIII\Api\V1\Requests\PaginationRequest;
use FireflyIII\Models\Account;
use FireflyIII\Rules\IsValidSortInstruction;
use FireflyIII\Support\Facades\Preferences;
use FireflyIII\Support\Http\Api\AccountFilter;
use FireflyIII\Support\Request\ConvertsDataTypes;
use FireflyIII\User;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Validation\Validator;
class ShowRequest extends FormRequest
class ShowRequest extends AggregateFormRequest
{
use AccountFilter;
use ConvertsDataTypes;
public function getParameters(): array
protected function getRequests(): array
{
$limit = $this->convertInteger('limit');
if (0 === $limit) {
// get default for user:
/** @var User $user */
$user = auth()->user();
$limit = (int)Preferences::getForUser($user, 'listPageSize', 50)->data;
}
$page = $this->convertInteger('page');
$page = min(max(1, $page), 2 ** 16);
return [
'type' => $this->convertString('type', 'all'),
'limit' => $limit,
'sort' => $this->convertSortParameters('sort', Account::class),
'page' => $page,
[PaginationRequest::class, 'sort_class' => Account::class],
DateRangeRequest::class,
DateRequest::class,
AccountTypeApiRequest::class,
];
}
public function rules(): array
{
$keys = implode(',', array_keys($this->types));
return [
'date' => 'date',
'start' => 'date|present_with:end|before_or_equal:end|before:2038-01-17|after:1970-01-02',
'end' => 'date|present_with:start|after_or_equal:start|before:2038-01-17|after:1970-01-02',
'sort' => ['nullable', new IsValidSortInstruction(Account::class)],
'type' => sprintf('in:%s', $keys),
'limit' => 'numeric|min:1|max:131337',
'page' => 'numeric|min:1|max:131337',
];
}
public function withValidator(Validator $validator): void
{
$validator->after(
function (Validator $validator): void {
if (count($validator->failed()) > 0) {
return;
}
$data = $validator->getData();
if (array_key_exists('date', $data) && array_key_exists('start', $data) && array_key_exists('end', $data)) {
// assume valid dates, before we got here.
$start = Carbon::parse($data['start'], config('app.timezone'))->startOfDay();
$end = Carbon::parse($data['end'], config('app.timezone'))->endOfDay();
$date = Carbon::parse($data['date'], config('app.timezone'));
if (!$date->between($start, $end)) {
$validator->errors()->add('date', (string)trans('validation.between_date'));
}
}
}
);
}
}

View File

@@ -0,0 +1,50 @@
<?php
declare(strict_types=1);
/*
* CurrencyCodeRequest.php
* Copyright (c) 2025 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/>.
*/
namespace FireflyIII\Api\V1\Requests\Models\TransactionCurrency;
use FireflyIII\Api\V1\Requests\ApiRequest;
use Illuminate\Validation\Validator;
class CurrencyCodeRequest extends ApiRequest
{
public function rules(): array
{
return [
'code' => sprintf('exists:transaction_currencies,code|%s', $this->required),
];
}
public function withValidator(Validator $validator): void
{
$validator->after(
function (Validator $validator): void {
if (!$validator->valid()) {
return;
}
$code = $this->convertString('code', '');
$this->attributes->set('code', $code);
}
);
}
}

View File

@@ -0,0 +1,84 @@
<?php
/*
* Copyright (c) 2025 https://github.com/ctrl-f5
*
* 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/>.
*/
declare(strict_types=1);
namespace FireflyIII\Api\V1\Requests;
use FireflyIII\Rules\IsValidSortInstruction;
use FireflyIII\Support\Facades\Preferences;
use FireflyIII\User;
use Illuminate\Validation\Validator;
use RuntimeException;
class PaginationRequest extends ApiRequest
{
private ?string $sortClass = null;
public function handleConfig(array $config): void
{
parent::handleConfig($config);
$this->sortClass = $config['sort_class'] ?? null;
if (!$this->sortClass) {
throw new RuntimeException('PaginationRequest requires a sort_class config');
}
}
public function rules(): array
{
return [
'sort' => ['nullable', new IsValidSortInstruction((string)$this->sortClass)],
'limit' => 'numeric|min:1|max:131337',
'page' => 'numeric|min:1|max:131337',
];
}
public function withValidator(Validator $validator): void
{
$validator->after(
function (Validator $validator): void {
if ($validator->failed()) {
return;
}
$limit = $this->convertInteger('limit');
if (0 === $limit) {
// get default for user:
/** @var User $user */
$user = auth()->user();
$limit = (int)Preferences::getForUser($user, 'listPageSize', 50)->data;
}
$page = $this->convertInteger('page');
$page = min(max(1, $page), 2 ** 16);
$offset = ($page - 1) * $limit;
$sort = $this->sortClass ? $this->convertSortParameters('sort', $this->sortClass) : $this->get('sort');
$this->attributes->set('limit', $limit);
$this->attributes->set('sort', $sort);
$this->attributes->set('page', $page);
$this->attributes->set('offset', $offset);
}
);
}
}

View File

@@ -0,0 +1,39 @@
<?php
declare(strict_types=1);
/*
* BasicRequest.php
* Copyright (c) 2025 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/>.
*/
namespace FireflyIII\Api\V1\Requests\Summary;
use FireflyIII\Api\V1\Requests\AggregateFormRequest;
use FireflyIII\Api\V1\Requests\DateRangeRequest;
use FireflyIII\Api\V1\Requests\Models\TransactionCurrency\CurrencyCodeRequest;
class BasicRequest extends AggregateFormRequest
{
protected function getRequests(): array
{
return [
[DateRangeRequest::class, 'required'],
CurrencyCodeRequest::class,
];
}
}

View File

@@ -46,7 +46,7 @@ class SetsLatestVersion extends Command
return 0;
}
FireflyConfig::set('ff3_version', config('firefly.version'));
FireflyConfig::set('ff3_build_time', (int) config('firefly.build_time'));
$this->friendlyInfo('Updated version.');
return 0;

View File

@@ -87,7 +87,7 @@ class UpgradesDatabase extends Command
$this->call($command, $args);
}
// index will set FF3 version.
FireflyConfig::set('ff3_version', (string) config('firefly.version'));
FireflyConfig::set('ff3_build_time', (int) config('firefly.build_time'));
return 0;
}

View File

@@ -84,8 +84,10 @@ class AttachmentFactory
return $attachment;
}
public function setUser(User $user): void
public function setUser(User $user): static
{
$this->user = $user;
return $this;
}
}

View File

@@ -221,10 +221,26 @@ class TransactionJournalFactory
];
Log::debug('Source info:', $sourceInfo);
Log::debug('Destination info:', $destInfo);
$sourceAccount = $this->getAccount($type->type, 'source', $sourceInfo);
$destinationAccount = $this->getAccount($type->type, 'destination', $destInfo, $sourceAccount);
$destinationAccount = null;
$sourceAccount = null;
if (TransactionTypeEnum::DEPOSIT->value === $type->type) {
Log::debug('Transaction type is deposit, start with destination first.');
$destinationAccount = $this->getAccount($type->type, 'destination', $destInfo);
$sourceAccount = $this->getAccount($type->type, 'source', $sourceInfo, $destinationAccount);
}
if (TransactionTypeEnum::DEPOSIT->value !== $type->type) {
Log::debug('Transaction type is not deposit, start with source first.');
$sourceAccount = $this->getAccount($type->type, 'source', $sourceInfo);
$destinationAccount = $this->getAccount($type->type, 'destination', $destInfo, $sourceAccount);
}
Log::debug('Done with getAccount(2x)');
// there is a safety catch here. If either account is NULL, they will be replaced with the cash account.
if (null === $destinationAccount) {
Log::warning('Destination account is NULL, will replace with cash account.');
$destinationAccount = $this->accountRepository->getCashAccount();
}
// this is the moment for a reconciliation sanity check (again).
if (TransactionTypeEnum::RECONCILIATION->value === $type->type) {

View File

@@ -27,6 +27,7 @@ use FireflyIII\Enums\WebhookTrigger;
use FireflyIII\Events\RequestedSendWebhookMessages;
use FireflyIII\Events\StoredTransactionGroup;
use FireflyIII\Generator\Webhook\MessageGeneratorInterface;
use FireflyIII\Models\Transaction;
use FireflyIII\Models\TransactionJournal;
use FireflyIII\Repositories\PeriodStatistic\PeriodStatisticRepositoryInterface;
use FireflyIII\Repositories\RuleGroup\RuleGroupRepositoryInterface;
@@ -105,10 +106,18 @@ class StoredGroupEventHandler
/** @var TransactionJournal $journal */
foreach ($event->transactionGroup->transactionJournals as $journal) {
/** @var null|Transaction $source */
$source = $journal->transactions()->where('amount', '<', '0')->first();
/** @var null|Transaction $dest */
$dest = $journal->transactions()->where('amount', '>', '0')->first();
$repository->deleteStatisticsForModel($source->account, $journal->date);
$repository->deleteStatisticsForModel($dest->account, $journal->date);
if (null !== $source) {
$repository->deleteStatisticsForModel($source->account, $journal->date);
}
if (null !== $dest) {
$repository->deleteStatisticsForModel($dest->account, $journal->date);
}
$categories = $journal->categories;
$tags = $journal->tags;
$budgets = $journal->budgets;

View File

@@ -77,6 +77,7 @@ abstract class Controller extends BaseController
View::share('DEMO_USERNAME', config('firefly.demo_username'));
View::share('DEMO_PASSWORD', config('firefly.demo_password'));
View::share('FF_VERSION', config('firefly.version'));
View::share('FF_BUILD_TIME', config('firefly.build_time'));
// is webhooks enabled?
View::share('featuringWebhooks', true === config('firefly.feature_flags.webhooks') && true === config('firefly.allow_webhooks'));
@@ -131,6 +132,7 @@ abstract class Controller extends BaseController
$this->primaryCurrency = null;
// get shown-intro-preference:
if (auth()->check()) {
View::share('anonymous', Steam::anonymous());
$this->primaryCurrency = Amount::getPrimaryCurrency();
$language = Steam::getLanguage();
$locale = Steam::getLocale();

View File

@@ -81,11 +81,11 @@ class DebugController extends Controller
*/
public function displayError(): void
{
app('log')->debug('This is a test message at the DEBUG level.');
app('log')->info('This is a test message at the INFO level.');
Log::debug('This is a test message at the DEBUG level.');
Log::info('This is a test message at the INFO level.');
Log::notice('This is a test message at the NOTICE level.');
app('log')->warning('This is a test message at the WARNING level.');
app('log')->error('This is a test message at the ERROR level.');
Log::warning('This is a test message at the WARNING level.');
Log::error('This is a test message at the ERROR level.');
Log::critical('This is a test message at the CRITICAL level.');
Log::alert('This is a test message at the ALERT level.');
Log::emergency('This is a test message at the EMERGENCY level.');
@@ -187,6 +187,8 @@ class DebugController extends Controller
return [
'php_version' => PHP_VERSION,
'php_os' => PHP_OS,
'build_time' => config('firefly.build_time'),
'build_time_nice' => Carbon::parse(config('firefly.build_time'), 'Europe/Amsterdam')->setTimezone('Europe/Amsterdam')->format('Y-m-d H:i:s e'),
'uname' => php_uname('m'),
'interface' => PHP_SAPI,
'bits' => PHP_INT_SIZE * 8,
@@ -212,11 +214,11 @@ class DebugController extends Controller
try {
if (file_exists('/var/www/counter-main.txt')) {
$return['build'] = trim(file_get_contents('/var/www/counter-main.txt'));
app('log')->debug(sprintf('build is now "%s"', $return['build']));
Log::debug(sprintf('build is now "%s"', $return['build']));
}
} catch (Exception $e) {
app('log')->debug('Could not check build counter, but thats ok.');
app('log')->warning($e->getMessage());
Log::debug('Could not check build counter, but thats ok.');
Log::warning($e->getMessage());
}
try {
@@ -224,8 +226,8 @@ class DebugController extends Controller
$return['build_date'] = trim(file_get_contents('/var/www/build-date-main.txt'));
}
} catch (Exception $e) {
app('log')->debug('Could not check build date, but thats ok.');
app('log')->warning($e->getMessage());
Log::debug('Could not check build date, but thats ok.');
Log::warning($e->getMessage());
}
if ('' !== (string) env('BASE_IMAGE_BUILD')) { // @phpstan-ignore-line
$return['base_build'] = env('BASE_IMAGE_BUILD'); // @phpstan-ignore-line
@@ -282,7 +284,7 @@ class DebugController extends Controller
$parts = Steam::getLocaleArray(Steam::getLocale());
foreach ($parts as $code) {
$code = trim($code);
app('log')->debug(sprintf('Trying to set %s', $code));
Log::debug(sprintf('Trying to set %s', $code));
$result = setlocale(LC_ALL, $code);
$localeAttempts[$code] = $result === $code;
}

View File

@@ -30,6 +30,7 @@ use FireflyIII\Models\Account;
use FireflyIII\Models\TransactionCurrency;
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface;
use FireflyIII\Support\Facades\Steam;
use FireflyIII\Support\Http\Controllers\GetConfigurationData;
use Illuminate\Http\Request;
use Illuminate\Http\Response;
@@ -114,6 +115,7 @@ class JavascriptController extends Controller
'currencyCode' => $currency->code,
'currencySymbol' => $currency->symbol,
'accountingLocaleInfo' => $accounting,
'anonymous' => var_export(Steam::anonymous(), true),
'language' => $lang,
'dateRangeTitle' => $dateRange['title'],
'locale' => $locale,

View File

@@ -24,6 +24,7 @@ declare(strict_types=1);
namespace FireflyIII\Http\Controllers\Rule;
use Carbon\Carbon;
use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Http\Controllers\Controller;
use FireflyIII\Http\Requests\SelectTransactionsRequest;
@@ -56,7 +57,7 @@ class SelectController extends Controller
$this->middleware(
static function ($request, $next) {
app('view')->share('title', (string) trans('firefly.rules'));
app('view')->share('title', (string)trans('firefly.rules'));
app('view')->share('mainTitleIcon', 'fa-random');
return $next($request);
@@ -73,11 +74,20 @@ class SelectController extends Controller
/** @var User $user */
$user = auth()->user();
$accounts = implode(',', $request->get('accounts'));
// create new rule engine:
$newRuleEngine = app(RuleEngineInterface::class);
$newRuleEngine->setUser($user);
// add date operators.
if (null !== $request->get('start')) {
$startDate = new Carbon($request->get('start'));
$newRuleEngine->addOperator(['type' => 'date_after', 'value' => $startDate->format('Y-m-d')]);
}
if (null !== $request->get('end')) {
$endDate = new Carbon($request->get('end'));
$newRuleEngine->addOperator(['type' => 'date_before', 'value' => $endDate->format('Y-m-d')]);
}
// add extra operators:
$newRuleEngine->addOperator(['type' => 'account_id', 'value' => $accounts]);
@@ -102,7 +112,7 @@ class SelectController extends Controller
return redirect(route('rules.index'));
}
// does the user have shared accounts?
$subTitle = (string) trans('firefly.apply_rule_selection', ['title' => $rule->title]);
$subTitle = (string)trans('firefly.apply_rule_selection', ['title' => $rule->title]);
return view('rules.rule.select-transactions', compact('rule', 'subTitle'));
}
@@ -127,7 +137,7 @@ class SelectController extends Controller
// warn if nothing.
if (0 === count($textTriggers)) {
return response()->json(['html' => '', 'warning' => (string) trans('firefly.warning_no_valid_triggers')]);
return response()->json(['html' => '', 'warning' => (string)trans('firefly.warning_no_valid_triggers')]);
}
foreach ($textTriggers as $textTrigger) {
@@ -160,7 +170,7 @@ class SelectController extends Controller
// Warn the user if only a subset of transactions is returned
$warning = '';
if (0 === count($collection)) {
$warning = (string) trans('firefly.warning_no_matching_transactions');
$warning = (string)trans('firefly.warning_no_matching_transactions');
}
// Return json response
@@ -190,7 +200,7 @@ class SelectController extends Controller
$triggers = $rule->ruleTriggers;
if (0 === count($triggers)) {
return response()->json(['html' => '', 'warning' => (string) trans('firefly.warning_no_valid_triggers')]);
return response()->json(['html' => '', 'warning' => (string)trans('firefly.warning_no_valid_triggers')]);
}
// create new rule engine:
$newRuleEngine = app(RuleEngineInterface::class);
@@ -202,7 +212,7 @@ class SelectController extends Controller
$warning = '';
if (0 === count($collection)) {
$warning = (string) trans('firefly.warning_no_matching_transactions');
$warning = (string)trans('firefly.warning_no_matching_transactions');
}
// Return json response

View File

@@ -24,6 +24,7 @@ declare(strict_types=1);
namespace FireflyIII\Http\Controllers\RuleGroup;
use Carbon\Carbon;
use Exception;
use FireflyIII\Http\Controllers\Controller;
use FireflyIII\Http\Requests\SelectTransactionsRequest;
@@ -73,6 +74,16 @@ class ExecutionController extends Controller
$newRuleEngine = app(RuleEngineInterface::class);
$newRuleEngine->setUser($user);
// add date operators.
if (null !== $request->get('start')) {
$startDate = new Carbon($request->get('start'));
$newRuleEngine->addOperator(['type' => 'date_after', 'value' => $startDate->format('Y-m-d')]);
}
if (null !== $request->get('end')) {
$endDate = new Carbon($request->get('end'));
$newRuleEngine->addOperator(['type' => 'date_before', 'value' => $endDate->format('Y-m-d')]);
}
// add extra operators:
$newRuleEngine->addOperator(['type' => 'account_id', 'value' => $accounts]);

View File

@@ -34,6 +34,7 @@ use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Artisan;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\Log;
use Illuminate\View\View;
use Laravel\Passport\Passport;
use phpseclib3\Crypt\RSA;
@@ -81,8 +82,10 @@ class InstallController extends Controller
public function index()
{
app('view')->share('FF_VERSION', config('firefly.version'));
// index will set FF3 version.
FireflyConfig::set('ff3_version', (string) config('firefly.version'));
FireflyConfig::set('ff3_build_time', (int) config('firefly.build_time'));
return view('install.index');
}
@@ -98,18 +101,18 @@ class InstallController extends Controller
'errorMessage' => null,
];
app('log')->debug(sprintf('Will now run commands. Request index is %d', $requestIndex));
Log::debug(sprintf('Will now run commands. Request index is %d', $requestIndex));
$indexes = array_keys($this->upgradeCommands);
if (array_key_exists($requestIndex, $indexes)) {
$command = $indexes[$requestIndex];
$parameters = $this->upgradeCommands[$command];
app('log')->debug(sprintf('Will now execute command "%s" with parameters', $command), $parameters);
Log::debug(sprintf('Will now execute command "%s" with parameters', $command), $parameters);
try {
$result = $this->executeCommand($command, $parameters);
} catch (FireflyException $e) {
app('log')->error($e->getMessage());
app('log')->error($e->getTraceAsString());
Log::error($e->getMessage());
Log::error($e->getTraceAsString());
if (str_contains($e->getMessage(), 'open_basedir restriction in effect')) {
$this->lastError = self::BASEDIR_ERROR;
}
@@ -134,7 +137,7 @@ class InstallController extends Controller
*/
private function executeCommand(string $command, array $args): bool
{
app('log')->debug(sprintf('Will now call command %s with args.', $command), $args);
Log::debug(sprintf('Will now call command %s with args.', $command), $args);
try {
if ('generate-keys' === $command) {
@@ -142,7 +145,7 @@ class InstallController extends Controller
}
if ('generate-keys' !== $command) {
Artisan::call($command, $args);
app('log')->debug(Artisan::output());
Log::debug(Artisan::output());
}
} catch (Exception $e) { // intentional generic exception
throw new FireflyException($e->getMessage(), 0, $e);

View File

@@ -38,6 +38,11 @@ class IsValidSortInstruction implements ValidationRule
return;
}
if ('' === $value) {
// don't validate.
return;
}
$validParameters = config(sprintf('firefly.allowed_sort_parameters.%s', $shortClass));
if (!is_array($validParameters)) {
$fail('validation.no_sort_instructions')->translate(['object' => $shortClass]);

View File

@@ -88,6 +88,7 @@ trait JournalServiceTrait
// the account that Firefly III creates must be "creatable", aka select the one we can create from the list just in case
$creatableType = $this->getCreatableType($expectedTypes[$transactionType]);
Log::debug(sprintf('Creatable type is "%s"', $creatableType), $expectedTypes[$transactionType]);
// if the result is NULL but the ID is set, an account could exist of the wrong type.
// that data can be used to create a new account of the right type.
@@ -227,9 +228,11 @@ trait JournalServiceTrait
}
// find by preferred type.
Log::debug('Find by preferred type.');
$result = $this->accountRepository->findByName($data['name'], [$types[0]]);
// or any expected type.
Log::debug('Find by any expected type.');
$result ??= $this->accountRepository->findByName($data['name'], $types);
if (null !== $result) {

View File

@@ -163,6 +163,7 @@ class Amount
*/
public function formatFlat(string $symbol, int $decimalPlaces, string $amount, ?bool $coloured = null): string
{
$amount = Steam::anonymous() ? '0' : $amount;
$locale = Steam::getLocale();
$rounded = Steam::bcround($amount, $decimalPlaces);
$coloured ??= true;

View File

@@ -634,10 +634,10 @@ trait PeriodOverview
$currencySymbol = $journal['currency_symbol'];
$currencyDecimalPlaces = $journal['currency_decimal_places'];
$foreignCurrencyId = $journal['foreign_currency_id'];
$amount = $journal['amount'] ?? '0';
$amount = (string) ($journal['amount'] ?? '0');
if ($this->convertToPrimary && $currencyId !== $this->primaryCurrency->id && $foreignCurrencyId !== $this->primaryCurrency->id) {
$amount = $journal['pc_amount'] ?? '0';
$amount = (string) ($journal['pc_amount'] ?? '0');
$currencyId = $this->primaryCurrency->id;
$currencyCode = $this->primaryCurrency->code;
$currencyName = $this->primaryCurrency->name;
@@ -650,7 +650,7 @@ trait PeriodOverview
$currencyName = $journal['foreign_currency_name'];
$currencySymbol = $journal['foreign_currency_symbol'];
$currencyDecimalPlaces = $journal['foreign_currency_decimal_places'];
$amount = $journal['foreign_amount'] ?? '0';
$amount = (string) ($journal['foreign_amount'] ?? '0');
}
$return[$currencyId] ??= [
'amount' => '0',

View File

@@ -154,6 +154,9 @@ class BudgetLimitEnrichment implements EnrichmentInterface
$this->start = $this->collection->min('start_date') ?? Carbon::now()->startOfMonth();
$this->end = $this->collection->max('end_date') ?? Carbon::now()->endOfMonth();
// #11096 make sure that the max end date is also at the end of the day,
$this->end->endOfDay();
/** @var BudgetLimit $limit */
foreach ($this->collection as $limit) {
$id = (int)$limit->id;

View File

@@ -627,6 +627,19 @@ class Steam
return $locale;
}
public function anonymous(): bool // get preference
{
$singleton = PreferencesSingleton::getInstance();
$cached = $singleton->getPreference('anonymous');
if (null !== $cached) {
return $cached;
}
$anonymous = app('preferences')->get('anonymous', config('firefly.default_preferences.anonymous', false))->data;
$singleton->setPreference('anonymous', $anonymous);
return $anonymous;
}
public function getLocaleArray(string $locale): array
{
return [

View File

@@ -67,32 +67,16 @@ trait IsOldVersion
protected function isOldVersionInstalled(): bool
{
// version compare thing.
$configVersion = (string)config('firefly.version');
$dbVersion = (string)FireflyConfig::getFresh('ff3_version', '1.0')->data;
$compare = 0;
// compare develop to develop
if (str_starts_with($configVersion, 'develop') && str_starts_with($dbVersion, 'develop')) {
$compare = $this->compareDevelopVersions($configVersion, $dbVersion);
}
// user has develop installed, goes to normal version.
if (!str_starts_with($configVersion, 'develop') && str_starts_with($dbVersion, 'develop')) {
return true;
}
// user has normal, goes to develop version.
if (str_starts_with($configVersion, 'develop') && !str_starts_with($dbVersion, 'develop')) {
return true;
}
// compare normal with normal.
if (!str_starts_with($configVersion, 'develop') && !str_starts_with($dbVersion, 'develop')) {
$compare = version_compare($configVersion, $dbVersion);
}
if (-1 === $compare) {
Log::warning(sprintf('The current configured Firefly III version (%s) is older than the required version (%s). Redirect to migrate routine.', $dbVersion, $configVersion));
$configBuildTime = (int)config('firefly.build_time');
$dbBuildTime = (int)FireflyConfig::getFresh('ff3_build_time', 123)->data;
$configTime = Carbon::createFromTimestamp($configBuildTime, config('app.timezone'));
$dbTime = Carbon::createFromTimestamp($dbBuildTime, config('app.timezone'));
if ($dbBuildTime < $configBuildTime) {
Log::warning(sprintf('Your database was last managed by an older version of Firefly III (I see %s, I expect %s). Redirect to migrate routine.', $dbTime->format('Y-m-d H:i:s'), $configTime->format('Y-m-d H:i:s')));
return true;
}
Log::debug(sprintf('Your database is up to date (I see %s, I expect %s).', $dbTime->format('Y-m-d H:i:s'), $configTime->format('Y-m-d H:i:s')));
return false;
}

View File

@@ -34,11 +34,17 @@ abstract class AbstractTransformer extends TransformerAbstract
{
protected ParameterBag $parameters;
/**
* @deprecated
*/
final public function getParameters(): ParameterBag
{
return $this->parameters;
}
/**
* @deprecated
*/
final public function setParameters(ParameterBag $parameters): void
{
$this->parameters = $parameters;

View File

@@ -30,7 +30,6 @@ use FireflyIII\Models\Account;
use FireflyIII\Models\TransactionCurrency;
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
use FireflyIII\Support\Facades\Amount;
use Symfony\Component\HttpFoundation\ParameterBag;
/**
* Class AccountTransformer
@@ -46,7 +45,6 @@ class AccountTransformer extends AbstractTransformer
*/
public function __construct()
{
$this->parameters = new ParameterBag();
$this->repository = app(AccountRepositoryInterface::class);
$this->convertToPrimary = Amount::convertToPrimary();
$this->primary = Amount::getPrimaryCurrency();

150
composer.lock generated
View File

@@ -1878,16 +1878,16 @@
},
{
"name": "laravel/framework",
"version": "v12.33.0",
"version": "v12.35.1",
"source": {
"type": "git",
"url": "https://github.com/laravel/framework.git",
"reference": "124efc5f09d4668a4dc13f94a1018c524a58bcb1"
"reference": "d6d6e3cb68238e2fb25b440f222442adef5a8a15"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/laravel/framework/zipball/124efc5f09d4668a4dc13f94a1018c524a58bcb1",
"reference": "124efc5f09d4668a4dc13f94a1018c524a58bcb1",
"url": "https://api.github.com/repos/laravel/framework/zipball/d6d6e3cb68238e2fb25b440f222442adef5a8a15",
"reference": "d6d6e3cb68238e2fb25b440f222442adef5a8a15",
"shasum": ""
},
"require": {
@@ -1999,7 +1999,7 @@
"league/flysystem-sftp-v3": "^3.25.1",
"mockery/mockery": "^1.6.10",
"opis/json-schema": "^2.4.1",
"orchestra/testbench-core": "^10.6.5",
"orchestra/testbench-core": "^10.7.0",
"pda/pheanstalk": "^5.0.6|^7.0.0",
"php-http/discovery": "^1.15",
"phpstan/phpstan": "^2.0",
@@ -2093,7 +2093,7 @@
"issues": "https://github.com/laravel/framework/issues",
"source": "https://github.com/laravel/framework"
},
"time": "2025-10-07T14:30:39+00:00"
"time": "2025-10-23T15:25:03+00:00"
},
{
"name": "laravel/passport",
@@ -2296,16 +2296,16 @@
},
{
"name": "laravel/serializable-closure",
"version": "v2.0.5",
"version": "v2.0.6",
"source": {
"type": "git",
"url": "https://github.com/laravel/serializable-closure.git",
"reference": "3832547db6e0e2f8bb03d4093857b378c66eceed"
"reference": "038ce42edee619599a1debb7e81d7b3759492819"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/laravel/serializable-closure/zipball/3832547db6e0e2f8bb03d4093857b378c66eceed",
"reference": "3832547db6e0e2f8bb03d4093857b378c66eceed",
"url": "https://api.github.com/repos/laravel/serializable-closure/zipball/038ce42edee619599a1debb7e81d7b3759492819",
"reference": "038ce42edee619599a1debb7e81d7b3759492819",
"shasum": ""
},
"require": {
@@ -2353,7 +2353,7 @@
"issues": "https://github.com/laravel/serializable-closure/issues",
"source": "https://github.com/laravel/serializable-closure"
},
"time": "2025-09-22T17:29:40+00:00"
"time": "2025-10-09T13:42:30+00:00"
},
{
"name": "laravel/slack-notification-channel",
@@ -2549,22 +2549,22 @@
},
{
"name": "lcobucci/jwt",
"version": "5.5.0",
"version": "5.6.0",
"source": {
"type": "git",
"url": "https://github.com/lcobucci/jwt.git",
"reference": "a835af59b030d3f2967725697cf88300f579088e"
"reference": "bb3e9f21e4196e8afc41def81ef649c164bca25e"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/lcobucci/jwt/zipball/a835af59b030d3f2967725697cf88300f579088e",
"reference": "a835af59b030d3f2967725697cf88300f579088e",
"url": "https://api.github.com/repos/lcobucci/jwt/zipball/bb3e9f21e4196e8afc41def81ef649c164bca25e",
"reference": "bb3e9f21e4196e8afc41def81ef649c164bca25e",
"shasum": ""
},
"require": {
"ext-openssl": "*",
"ext-sodium": "*",
"php": "~8.2.0 || ~8.3.0 || ~8.4.0",
"php": "~8.2.0 || ~8.3.0 || ~8.4.0 || ~8.5.0",
"psr/clock": "^1.0"
},
"require-dev": {
@@ -2606,7 +2606,7 @@
],
"support": {
"issues": "https://github.com/lcobucci/jwt/issues",
"source": "https://github.com/lcobucci/jwt/tree/5.5.0"
"source": "https://github.com/lcobucci/jwt/tree/5.6.0"
},
"funding": [
{
@@ -2618,7 +2618,7 @@
"type": "patreon"
}
],
"time": "2025-01-26T21:29:45+00:00"
"time": "2025-10-17T11:30:53+00:00"
},
{
"name": "league/commonmark",
@@ -2811,16 +2811,16 @@
},
{
"name": "league/csv",
"version": "9.26.0",
"version": "9.27.1",
"source": {
"type": "git",
"url": "https://github.com/thephpleague/csv.git",
"reference": "7fce732754d043f3938899e5183e2d0f3d31b571"
"reference": "26de738b8fccf785397d05ee2fc07b6cd8749797"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/thephpleague/csv/zipball/7fce732754d043f3938899e5183e2d0f3d31b571",
"reference": "7fce732754d043f3938899e5183e2d0f3d31b571",
"url": "https://api.github.com/repos/thephpleague/csv/zipball/26de738b8fccf785397d05ee2fc07b6cd8749797",
"reference": "26de738b8fccf785397d05ee2fc07b6cd8749797",
"shasum": ""
},
"require": {
@@ -2898,7 +2898,7 @@
"type": "github"
}
],
"time": "2025-10-01T11:24:54+00:00"
"time": "2025-10-25T08:35:20+00:00"
},
{
"name": "league/event",
@@ -2956,16 +2956,16 @@
},
{
"name": "league/flysystem",
"version": "3.30.0",
"version": "3.30.1",
"source": {
"type": "git",
"url": "https://github.com/thephpleague/flysystem.git",
"reference": "2203e3151755d874bb2943649dae1eb8533ac93e"
"reference": "c139fd65c1f796b926f4aec0df37f6caa959a8da"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/thephpleague/flysystem/zipball/2203e3151755d874bb2943649dae1eb8533ac93e",
"reference": "2203e3151755d874bb2943649dae1eb8533ac93e",
"url": "https://api.github.com/repos/thephpleague/flysystem/zipball/c139fd65c1f796b926f4aec0df37f6caa959a8da",
"reference": "c139fd65c1f796b926f4aec0df37f6caa959a8da",
"shasum": ""
},
"require": {
@@ -3033,9 +3033,9 @@
],
"support": {
"issues": "https://github.com/thephpleague/flysystem/issues",
"source": "https://github.com/thephpleague/flysystem/tree/3.30.0"
"source": "https://github.com/thephpleague/flysystem/tree/3.30.1"
},
"time": "2025-06-25T13:29:59+00:00"
"time": "2025-10-20T15:35:26+00:00"
},
{
"name": "league/flysystem-local",
@@ -4069,31 +4069,31 @@
},
{
"name": "nunomaduro/termwind",
"version": "v2.3.1",
"version": "v2.3.2",
"source": {
"type": "git",
"url": "https://github.com/nunomaduro/termwind.git",
"reference": "dfa08f390e509967a15c22493dc0bac5733d9123"
"reference": "eb61920a53057a7debd718a5b89c2178032b52c0"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/nunomaduro/termwind/zipball/dfa08f390e509967a15c22493dc0bac5733d9123",
"reference": "dfa08f390e509967a15c22493dc0bac5733d9123",
"url": "https://api.github.com/repos/nunomaduro/termwind/zipball/eb61920a53057a7debd718a5b89c2178032b52c0",
"reference": "eb61920a53057a7debd718a5b89c2178032b52c0",
"shasum": ""
},
"require": {
"ext-mbstring": "*",
"php": "^8.2",
"symfony/console": "^7.2.6"
"symfony/console": "^7.3.4"
},
"require-dev": {
"illuminate/console": "^11.44.7",
"laravel/pint": "^1.22.0",
"illuminate/console": "^11.46.1",
"laravel/pint": "^1.25.1",
"mockery/mockery": "^1.6.12",
"pestphp/pest": "^2.36.0 || ^3.8.2",
"phpstan/phpstan": "^1.12.25",
"pestphp/pest": "^2.36.0 || ^3.8.4",
"phpstan/phpstan": "^1.12.32",
"phpstan/phpstan-strict-rules": "^1.6.2",
"symfony/var-dumper": "^7.2.6",
"symfony/var-dumper": "^7.3.4",
"thecodingmachine/phpstan-strict-rules": "^1.0.0"
},
"type": "library",
@@ -4136,7 +4136,7 @@
],
"support": {
"issues": "https://github.com/nunomaduro/termwind/issues",
"source": "https://github.com/nunomaduro/termwind/tree/v2.3.1"
"source": "https://github.com/nunomaduro/termwind/tree/v2.3.2"
},
"funding": [
{
@@ -4152,7 +4152,7 @@
"type": "github"
}
],
"time": "2025-05-08T08:14:37+00:00"
"time": "2025-10-18T11:10:27+00:00"
},
{
"name": "nyholm/psr7",
@@ -10052,28 +10052,28 @@
},
{
"name": "webmozart/assert",
"version": "1.11.0",
"version": "1.12.0",
"source": {
"type": "git",
"url": "https://github.com/webmozarts/assert.git",
"reference": "11cb2199493b2f8a3b53e7f19068fc6aac760991"
"reference": "541057574806f942c94662b817a50f63f7345360"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/webmozarts/assert/zipball/11cb2199493b2f8a3b53e7f19068fc6aac760991",
"reference": "11cb2199493b2f8a3b53e7f19068fc6aac760991",
"url": "https://api.github.com/repos/webmozarts/assert/zipball/541057574806f942c94662b817a50f63f7345360",
"reference": "541057574806f942c94662b817a50f63f7345360",
"shasum": ""
},
"require": {
"ext-ctype": "*",
"ext-date": "*",
"ext-filter": "*",
"php": "^7.2 || ^8.0"
},
"conflict": {
"phpstan/phpstan": "<0.12.20",
"vimeo/psalm": "<4.6.1 || 4.6.2"
},
"require-dev": {
"phpunit/phpunit": "^8.5.13"
"suggest": {
"ext-intl": "",
"ext-simplexml": "",
"ext-spl": ""
},
"type": "library",
"extra": {
@@ -10104,9 +10104,9 @@
],
"support": {
"issues": "https://github.com/webmozarts/assert/issues",
"source": "https://github.com/webmozarts/assert/tree/1.11.0"
"source": "https://github.com/webmozarts/assert/tree/1.12.0"
},
"time": "2022-06-03T18:03:27+00:00"
"time": "2025-10-20T12:43:39+00:00"
}
],
"packages-dev": [
@@ -10549,16 +10549,16 @@
},
{
"name": "driftingly/rector-laravel",
"version": "2.0.7",
"version": "2.1.1",
"source": {
"type": "git",
"url": "https://github.com/driftingly/rector-laravel.git",
"reference": "625dc02cee08d47ecf0ac86de2f02a55026cf34e"
"reference": "abc336cbf06f53d90ab74cecfd319379fc55d408"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/driftingly/rector-laravel/zipball/625dc02cee08d47ecf0ac86de2f02a55026cf34e",
"reference": "625dc02cee08d47ecf0ac86de2f02a55026cf34e",
"url": "https://api.github.com/repos/driftingly/rector-laravel/zipball/abc336cbf06f53d90ab74cecfd319379fc55d408",
"reference": "abc336cbf06f53d90ab74cecfd319379fc55d408",
"shasum": ""
},
"require": {
@@ -10578,9 +10578,9 @@
"description": "Rector upgrades rules for Laravel Framework",
"support": {
"issues": "https://github.com/driftingly/rector-laravel/issues",
"source": "https://github.com/driftingly/rector-laravel/tree/2.0.7"
"source": "https://github.com/driftingly/rector-laravel/tree/2.1.1"
},
"time": "2025-08-19T20:49:47+00:00"
"time": "2025-10-23T13:53:44+00:00"
},
{
"name": "fakerphp/faker",
@@ -11036,16 +11036,16 @@
},
{
"name": "nikic/php-parser",
"version": "v5.6.1",
"version": "v5.6.2",
"source": {
"type": "git",
"url": "https://github.com/nikic/PHP-Parser.git",
"reference": "f103601b29efebd7ff4a1ca7b3eeea9e3336a2a2"
"reference": "3a454ca033b9e06b63282ce19562e892747449bb"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/f103601b29efebd7ff4a1ca7b3eeea9e3336a2a2",
"reference": "f103601b29efebd7ff4a1ca7b3eeea9e3336a2a2",
"url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/3a454ca033b9e06b63282ce19562e892747449bb",
"reference": "3a454ca033b9e06b63282ce19562e892747449bb",
"shasum": ""
},
"require": {
@@ -11088,9 +11088,9 @@
],
"support": {
"issues": "https://github.com/nikic/PHP-Parser/issues",
"source": "https://github.com/nikic/PHP-Parser/tree/v5.6.1"
"source": "https://github.com/nikic/PHP-Parser/tree/v5.6.2"
},
"time": "2025-08-13T20:13:15+00:00"
"time": "2025-10-21T19:32:17+00:00"
},
{
"name": "phar-io/manifest",
@@ -11333,11 +11333,11 @@
},
{
"name": "phpstan/phpstan",
"version": "2.1.30",
"version": "2.1.31",
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/phpstan/phpstan/zipball/a4a7f159927983dd4f7c8020ed227d80b7f39d7d",
"reference": "a4a7f159927983dd4f7c8020ed227d80b7f39d7d",
"url": "https://api.github.com/repos/phpstan/phpstan/zipball/ead89849d879fe203ce9292c6ef5e7e76f867b96",
"reference": "ead89849d879fe203ce9292c6ef5e7e76f867b96",
"shasum": ""
},
"require": {
@@ -11382,7 +11382,7 @@
"type": "github"
}
],
"time": "2025-10-02T16:07:52+00:00"
"time": "2025-10-10T14:14:11+00:00"
},
{
"name": "phpstan/phpstan-deprecation-rules",
@@ -11920,16 +11920,16 @@
},
{
"name": "rector/rector",
"version": "2.2.2",
"version": "2.2.5",
"source": {
"type": "git",
"url": "https://github.com/rectorphp/rector.git",
"reference": "5b353f7457b9a0c63fc91ef340f5d119a40991ed"
"reference": "fb9418af7777dfb1c87a536dc58398b5b07c74b9"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/rectorphp/rector/zipball/5b353f7457b9a0c63fc91ef340f5d119a40991ed",
"reference": "5b353f7457b9a0c63fc91ef340f5d119a40991ed",
"url": "https://api.github.com/repos/rectorphp/rector/zipball/fb9418af7777dfb1c87a536dc58398b5b07c74b9",
"reference": "fb9418af7777dfb1c87a536dc58398b5b07c74b9",
"shasum": ""
},
"require": {
@@ -11968,7 +11968,7 @@
],
"support": {
"issues": "https://github.com/rectorphp/rector/issues",
"source": "https://github.com/rectorphp/rector/tree/2.2.2"
"source": "https://github.com/rectorphp/rector/tree/2.2.5"
},
"funding": [
{
@@ -11976,7 +11976,7 @@
"type": "github"
}
],
"time": "2025-10-09T19:50:20+00:00"
"time": "2025-10-23T11:22:37+00:00"
},
{
"name": "sebastian/cli-parser",

View File

@@ -78,8 +78,8 @@ return [
'running_balance_column' => env('USE_RUNNING_BALANCE', false),
// see cer.php for exchange rates feature flag.
],
'version' => 'develop/2025-10-10',
'build_time' => 1760095871,
'version' => 'develop/2025-10-26',
'build_time' => 1761467848,
'api_version' => '2.1.0', // field is no longer used.
'db_version' => 28, // field is no longer used.
@@ -182,6 +182,7 @@ return [
'darkMode' => 'browser',
'list_length' => 10, // to be removed if v1 is cancelled.
'default_preferences' => [
'anonymous' => false,
'frontpageAccounts' => [],
'listPageSize' => 50,
'currencyPreference' => 'EUR',

View File

@@ -0,0 +1,24 @@
<?php
declare(strict_types=1);
namespace Database\Factories;
use FireflyIII\Enums\AccountTypeEnum;
use FireflyIII\Models\AccountType;
use Illuminate\Database\Eloquent\Factories\Factory;
class AccountFactory extends Factory
{
public function definition(): array
{
return [
'name' => $this->faker->name(),
'active' => true,
];
}
public function withType(AccountTypeEnum $type): static
{
return $this->for(AccountType::where('type', $type->value)->first());
}
}

View File

@@ -11,34 +11,36 @@ return new class extends Migration
*/
public function up(): void
{
Schema::create('period_statistics', function (Blueprint $table) {
$table->id();
$table->timestamps();
if (!Schema::hasTable('period_statistics')) {
Schema::create('period_statistics', function (Blueprint $table) {
$table->id();
$table->timestamps();
// reference to user group id.
$table->bigInteger('user_group_id', false, true);
// reference to user group id.
$table->bigInteger('user_group_id', false, true);
$table->integer('primary_statable_id', false, true)->nullable();
$table->string('primary_statable_type', 255)->nullable();
$table->integer('primary_statable_id', false, true)->nullable();
$table->string('primary_statable_type', 255)->nullable();
$table->integer('secondary_statable_id', false, true)->nullable();
$table->string('secondary_statable_type', 255)->nullable();
$table->integer('secondary_statable_id', false, true)->nullable();
$table->string('secondary_statable_type', 255)->nullable();
$table->integer('tertiary_statable_id', false, true)->nullable();
$table->string('tertiary_statable_type', 255)->nullable();
$table->integer('tertiary_statable_id', false, true)->nullable();
$table->string('tertiary_statable_type', 255)->nullable();
$table->integer('transaction_currency_id', false, true);
$table->foreign('transaction_currency_id')->references('id')->on('transaction_currencies')->onDelete('cascade');
$table->integer('transaction_currency_id', false, true);
$table->foreign('transaction_currency_id')->references('id')->on('transaction_currencies')->onDelete('cascade');
$table->dateTime('start')->nullable();
$table->string('start_tz', 50)->nullable();
$table->dateTime('end')->nullable();
$table->string('end_tz', 50)->nullable();
$table->string('type',255);
$table->integer('count', false, true)->default(0);
$table->decimal('amount', 32, 12);
$table->foreign('user_group_id')->references('id')->on('user_groups')->onDelete('cascade');
});
$table->dateTime('start')->nullable();
$table->string('start_tz', 50)->nullable();
$table->dateTime('end')->nullable();
$table->string('end_tz', 50)->nullable();
$table->string('type', 255);
$table->integer('count', false, true)->default(0);
$table->decimal('amount', 32, 12);
$table->foreign('user_group_id')->references('id')->on('user_groups')->onDelete('cascade');
});
}
}
/**

716
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -42,13 +42,11 @@ function formatLabel(str, maxwidth) {
if (concat.length > maxwidth) {
sections.push(temp);
temp = "";
}
else {
} else {
if (index === (words.length - 1)) {
sections.push(concat);
return;
}
else {
} else {
temp = concat;
return;
}
@@ -62,8 +60,7 @@ function formatLabel(str, maxwidth) {
if (item.length < maxwidth) {
temp = item;
}
else {
} else {
sections.push(item);
}
@@ -98,9 +95,11 @@ var defaultChartOptions = {
ticks: {
callback: function (tickValue) {
"use strict";
if (anonymous) {
return accounting.formatMoney(0);
}
// use first symbol or null:
return accounting.formatMoney(tickValue);
},
beginAtZero: true
}
@@ -112,8 +111,11 @@ var defaultChartOptions = {
callbacks: {
label: function (tooltipItem, data) {
"use strict";
return data.datasets[tooltipItem.datasetIndex].label + ': ' +
accounting.formatMoney(tooltipItem.yLabel, data.datasets[tooltipItem.datasetIndex].currency_symbol);
var string = accounting.formatMoney(tooltipItem.yLabel, data.datasets[tooltipItem.datasetIndex].currency_symbol);
if (anonymous) {
string = accounting.formatMoney(0);
}
return data.datasets[tooltipItem.datasetIndex].label + ': ' + string;
}
}
}
@@ -125,7 +127,11 @@ var pieOptionsWithCurrency = {
label: function (tooltipItem, data) {
"use strict";
var value = data.datasets[0].data[tooltipItem.index];
return data.labels[tooltipItem.index] + ': ' + accounting.formatMoney(value, data.datasets[tooltipItem.datasetIndex].currency_symbol[tooltipItem.index]);
var string = accounting.formatMoney(value, data.datasets[tooltipItem.datasetIndex].currency_symbol[tooltipItem.index]);
if (anonymous) {
string = accounting.formatMoney(0);
}
return data.labels[tooltipItem.index] + ': ' + string;
}
}
},
@@ -139,7 +145,11 @@ var defaultPieOptions = {
label: function (tooltipItem, data) {
"use strict";
var value = data.datasets[0].data[tooltipItem.index];
return data.labels[tooltipItem.index] + ': ' + accounting.formatMoney(value);
var string = accounting.formatMoney(value);
if (anonymous) {
string = accounting.formatMoney(0);
}
return data.labels[tooltipItem.index] + ': ' + string;
}
}
},
@@ -153,7 +163,11 @@ var neutralDefaultPieOptions = {
label: function (tooltipItem, data) {
"use strict";
var value = data.datasets[0].data[tooltipItem.index];
return data.labels[tooltipItem.index] + ': ' + accounting.formatMoney(value, '¤');
var string = accounting.formatMoney(value, '¤');
if(anonymous) {
string = accounting.formatMoney(0);
}
return data.labels[tooltipItem.index] + ': ' + string;
}
}
},

View File

@@ -47,7 +47,6 @@ function parseToLocalDates() {
$(function () {
"use strict";
configAccounting(currencySymbol);
// on submit of logout button:

View File

@@ -17,13 +17,42 @@
* 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/>.
*/
/** global: token, helpPageTitle */
/** global: token, helpPageTitle, anonymous */
$(function () {
"use strict";
$('#help').click(showHelp);
$('#anonymous').click(changeAnonymity)
});
function submitAnonymity(value) {
$.ajax({
url: 'api/v1/preferences/anonymous',
data: JSON.stringify({data: value}),
type: 'PUT',
headers: {
'Content-Type': 'application/json',
'X-CSRF-Token': $('meta[name="csrf-token"]').attr('content'),
},
});
}
function changeAnonymity(e) {
if (anonymous) {
console.log('Will DISABLE.');
submitAnonymity(false);
alert(anonymous_warning_off_txt);
window.location.reload(true);
}
if (!anonymous) {
console.log('Will ENABLE.');
submitAnonymity(true);
alert(anonymous_warning_on_txt);
window.location.reload(true);
}
return false;
}
function showHelp(e) {
"use strict";
var target = $(e.target);

View File

@@ -44,20 +44,29 @@
<div class="box-body no-padding">
<nav v-if="totalPages > 1">
<ul class="pagination">
<li v-if="1 === this.page" class="page-item disabled" aria-disabled="true" :aria-label="$t('pagination.previous')">
<li v-if="1 === this.page" class="page-item disabled" aria-disabled="true"
:aria-label="$t('pagination.previous')">
<span class="page-link" aria-hidden="true">&lsaquo;</span>
</li>
<li class="page-item" v-if="1 !== this.page">
<a class="page-link" :href="'/exchange-rates/'+from_code+'/'+to_code+'?page=' + (this.page-1)" rel="prev" :aria-label="$t('pagination.next')">&lsaquo;</a>
<a class="page-link"
:href="'/exchange-rates/'+from_code+'/'+to_code+'?page=' + (this.page-1)"
rel="prev" :aria-label="$t('pagination.next')">&lsaquo;</a>
</li>
<li v-for="item in this.totalPages" :class="item === page ? 'page-item active' : 'page-item'" aria-current="page">
<li v-for="item in this.totalPages"
:class="item === page ? 'page-item active' : 'page-item'" aria-current="page">
<span v-if="item === page" class="page-link" v-text="item"></span>
<a v-if="item !== page" class="page-link" :href="'/exchange-rates/'+from_code+'/'+to_code+'?page=' + item" v-text="item"></a>
<a v-if="item !== page" class="page-link"
:href="'/exchange-rates/'+from_code+'/'+to_code+'?page=' + item"
v-text="item"></a>
</li>
<li v-if="totalPages !== page" class="page-item">
<a class="page-link" :href="'/exchange-rates/'+from_code+'/'+to_code+'?page=' + (this.page+1)" rel="next" :aria-label="$t('pagination.next')">&rsaquo;</a>
<a class="page-link"
:href="'/exchange-rates/'+from_code+'/'+to_code+'?page=' + (this.page+1)"
rel="next" :aria-label="$t('pagination.next')">&rsaquo;</a>
</li>
<li v-if="totalPages === page" class="page-item disabled" aria-disabled="true" :aria-label="$t('pagination.next')">
<li v-if="totalPages === page" class="page-item disabled" aria-disabled="true"
:aria-label="$t('pagination.next')">
<span class="page-link" aria-hidden="true">&rsaquo;</span>
</li>
</ul>
@@ -97,9 +106,11 @@
>
</td>
<td>
<!-- (<span v-text="rate.rate_id"></span>) -->
<input type="number" class="form-control" min="0" step="any" v-model="rate.rate">
</td>
<td>
<!-- (<span v-text="rate.inverse_id"></span>) -->
<input type="number" class="form-control" min="0" step="any" v-model="rate.inverse">
</td>
<td>
@@ -122,20 +133,29 @@
<nav v-if="totalPages > 1">
<ul class="pagination">
<li v-if="1 === this.page" class="page-item disabled" aria-disabled="true" :aria-label="$t('pagination.previous')">
<li v-if="1 === this.page" class="page-item disabled" aria-disabled="true"
:aria-label="$t('pagination.previous')">
<span class="page-link" aria-hidden="true">&lsaquo;</span>
</li>
<li class="page-item" v-if="1 !== this.page">
<a class="page-link" :href="'/exchange-rates/'+from_code+'/'+to_code+'?page=' + (this.page-1)" rel="prev" :aria-label="$t('pagination.next')">&lsaquo;</a>
<a class="page-link"
:href="'/exchange-rates/'+from_code+'/'+to_code+'?page=' + (this.page-1)"
rel="prev" :aria-label="$t('pagination.next')">&lsaquo;</a>
</li>
<li v-for="item in this.totalPages" :class="item === page ? 'page-item active' : 'page-item'" aria-current="page">
<li v-for="item in this.totalPages"
:class="item === page ? 'page-item active' : 'page-item'" aria-current="page">
<span v-if="item === page" class="page-link" v-text="item"></span>
<a v-if="item !== page" class="page-link" :href="'/exchange-rates/'+from_code+'/'+to_code+'?page=' + item" v-text="item"></a>
<a v-if="item !== page" class="page-link"
:href="'/exchange-rates/'+from_code+'/'+to_code+'?page=' + item"
v-text="item"></a>
</li>
<li v-if="totalPages !== page" class="page-item">
<a class="page-link" :href="'/exchange-rates/'+from_code+'/'+to_code+'?page=' + (this.page+1)" rel="next" :aria-label="$t('pagination.next')">&rsaquo;</a>
<a class="page-link"
:href="'/exchange-rates/'+from_code+'/'+to_code+'?page=' + (this.page+1)"
rel="next" :aria-label="$t('pagination.next')">&rsaquo;</a>
</li>
<li v-if="totalPages === page" class="page-item disabled" aria-disabled="true" :aria-label="$t('pagination.next')">
<li v-if="totalPages === page" class="page-item disabled" aria-disabled="true"
:aria-label="$t('pagination.next')">
<span class="page-link" aria-hidden="true">&rsaquo;</span>
</li>
</ul>
@@ -160,7 +180,8 @@
<label for="ffInput_date" class="col-sm-4 control-label"
v-text="$t('form.date')"></label>
<div class="col-sm-8">
<input class="form-control" type="date" name="date" id="ffInput_date" :disabled="posting"
<input class="form-control" type="date" name="date" id="ffInput_date"
:disabled="posting"
autocomplete="off" spellcheck="false" v-model="newDate">
</div>
</div>
@@ -168,16 +189,19 @@
<label for="ffInput_rate" class="col-sm-4 control-label"
v-text="$t('form.rate')"></label>
<div class="col-sm-8">
<input class="form-control" type="number" name="rate" id="ffInput_rate" :disabled="posting"
<input class="form-control" type="number" name="rate" id="ffInput_rate"
:disabled="posting"
autocomplete="off" spellcheck="false" v-model="newRate" step="any">
<p class="help-block" v-text="$t('firefly.help_rate_form', {from: from_code, to: to_code})">
<p class="help-block"
v-text="$t('firefly.help_rate_form', {from: from_code, to: to_code})">
</p>
</div>
</div>
</div>
<div class="box-footer">
<button type="submit" class="nodisablebutton btn pull-right btn-success" v-text="$t('firefly.save_new_rate')"></button>
<button type="submit" class="nodisablebutton btn pull-right btn-success"
v-text="$t('firefly.save_new_rate')"></button>
</div>
</div>
@@ -217,9 +241,9 @@ export default {
mounted() {
// get from and to code from URL
this.newDate = format(new Date, 'yyyy-MM-dd');
let parts = window.location.href.split('/');
this.from_code = parts[parts.length - 2];
this.to_code = parts[parts.length - 1];
let parts = window.location.pathname.split('/');
this.from_code = parts[parts.length - 2].toUpperCase();
this.to_code = parts[parts.length - 1].toUpperCase();
const params = new Proxy(new URLSearchParams(window.location.search), {
get: (searchParams, prop) => searchParams.get(prop),
@@ -232,8 +256,8 @@ export default {
this.downloadRates(this.page);
},
methods: {
submitRate: function(e) {
if(e) e.preventDefault();
submitRate: function (e) {
if (e) e.preventDefault();
this.posting = true;
axios.post("./api/v1/exchange-rates", {
@@ -260,33 +284,74 @@ export default {
if (0 === parts.length) {
return;
}
console.log('These are the parts', parts);
if ('' !== this.rates[index].rate) {
//console.log('[a] Rate info is', this.rates[index]);
this.updating = true;
axios.put("./api/v1/exchange-rates/" + this.rates[index].rate_id, {rate: this.rates[index].rate})
.then(() => {
this.updating = false;
});
if (0 === parseInt(this.rates[index].rate_id)) {
console.log('[a] POST, not PUT.');
axios.post('./api/v1/exchange-rates',
{
from: this.from_code,
to: this.to_code,
rate: this.rates[index].rate,
date: this.rates[index].date_field
})
.then(() => {
this.updating = false;
});
}
if (0 !== parseInt(this.rates[index].rate_id)) {
console.log('[a] PUT, not POST.');
axios.put('./api/v1/exchange-rates/' + this.rates[index].rate_id, {rate: this.rates[index].rate})
.then(() => {
this.updating = false;
});
}
}
if ('' !== this.rates[index].inverse) {
//console.log('[b] Rate info is', this.rates[index]);
this.updating = true;
axios.put("./api/v1/exchange-rates/" + this.rates[index].inverse_id, {rate: this.rates[index].inverse})
.then(() => {
this.updating = false;
});
if (0 === parseInt(this.rates[index].inverse_id)) {
console.log('[b] POST, not PUT.');
// post, not put
axios.post('./api/v1/exchange-rates',
{
// remember, this is in reverse.
from: this.to_code,
to: this.from_code,
rate: this.rates[index].inverse,
date: this.rates[index].date_field
})
.then(() => {
this.updating = false;
});
}
if (0 !== parseInt(this.rates[index].inverse_id)) {
console.log('[b] PUT, not POST.');
axios.put('./api/v1/exchange-rates/' + this.rates[index].inverse_id, {rate: this.rates[index].inverse})
.then(() => {
this.updating = false;
});
}
}
},
deleteRate: function (index) {
// console.log(this.rates[index].key);
let parts = this.spliceKey(this.rates[index].key);
if (0 === parts.length) {
return;
}
// console.log(parts);
let rateId = parseInt(this.rates[index].rate_id);
let inverseId = parseInt(this.rates[index].inverse_id);
// delete A to B
axios.delete("./api/v1/exchange-rates/" + parts.from + '/' + parts.to + '/' + format(parts.date, 'yyyy-MM-dd'));
// delete B to A.
axios.delete("./api/v1/exchange-rates/" + parts.to + '/' + parts.from + '/' + format(parts.date, 'yyyy-MM-dd'));
if (rateId > 0) {
axios.delete('./api/v1/exchange-rates/' + rateId);
}
if (inverseId > 0) {
axios.delete('./api/v1/exchange-rates/' + inverseId);
}
this.rates.splice(index, 1);
},
@@ -307,6 +372,7 @@ export default {
};
},
downloadCurrencies: function () {
console.log('Now downloading currencies.');
this.loading = true;
axios.get("./api/v1/currencies/" + this.from_code).then((response) => {
this.from = {
@@ -327,31 +393,36 @@ export default {
downloadRates: function (page) {
this.tempRates = {};
this.loading = true;
axios.get("./api/v1/exchange-rates/" + this.from_code + '/' + this.to_code + '?page=' + page).then((response) => {
console.log('Now downloading rates.', page);
axios.get('./api/v1/exchange-rates/' + this.from_code + '/' + this.to_code + '?page=' + page).then((response) => {
for (let i in response.data.data) {
if (response.data.data.hasOwnProperty(i)) {
console.log('Downloaded entry #' + i);
let current = response.data.data[i];
let date = new Date(current.attributes.date);
let from_code = current.attributes.from_currency_code;
let to_code = current.attributes.to_currency_code;
let from_code = current.attributes.from_currency_code.toUpperCase();
let to_code = current.attributes.to_currency_code.toUpperCase();
let rate = current.attributes.rate;
let inverse = '';
let rate_id = current.id;
let inverse_id = '0';
let key = from_code + '_' + to_code + '_' + format(date, 'yyyy-MM-dd');
// console.log('Key is now "' + key + '"');
console.log('Key is now "' + key + '"');
// perhaps the returned rate is actually the inverse rate.
if (from_code === this.to_code && to_code === this.from_code) {
// console.log('Inverse rate found!');
key = to_code + '_' + from_code + '_' + format(date, 'yyyy-MM-dd');
rate = '';
// new: set rate id to zero.
rate_id = '0';
inverse = current.attributes.rate;
inverse_id = current.id;
// console.log('Key updated to "' + key + '"');
console.log('Key updated to "' + key + '"');
}
if (!this.tempRates.hasOwnProperty(key)) {
console.log('New entry stored');
this.tempRates[key] = {
key: key,
date: date,
@@ -374,6 +445,7 @@ export default {
this.tempRates[key].rate = rate;
this.tempRates[key].rate_id = rate_id;
}
console.log('Found exchange rate #' + this.tempRates[key].rate_id + ' with inverse #' + this.tempRates[key].inverse_id);
}

View File

@@ -235,6 +235,8 @@ return [
'advanced_options_explain' => 'Some pages in Firefly III have advanced options hidden behind this button. This page doesn\'t have anything fancy here, but do check out the others!',
'here_be_dragons' => 'Hic sunt dracones',
'bad_date_transaction' => 'Firefly III has detected you have transactions from before the year 1970. Please correct these transactions at your earliest convenience.',
'anonymous_warning_on' => 'For your privacy, all amounts are now displayed as "zero". Warning: text input boxes may still show the original amounts!',
'anonymous_warning_off' => 'Amounts will be visible again. Please be mindful of your surroundings.',
// Webhooks
'webhooks' => 'Webhooks',

View File

@@ -32,6 +32,7 @@ return [
'webhook_account_info' => 'Cannot deliver account information for budget related webhooks.',
'webhook_transaction_info' => 'Cannot deliver transaction information for budget related webhooks.',
'invalid_account_type' => 'A piggy bank can only be linked to asset accounts and liabilities',
'unique_currency_code' => 'This currency code is already in use',
'invalid_account_currency' => 'This account does not use the currency you have selected',
'current_amount_too_much' => 'The combined amount in "current_amount" cannot exceed the "target_amount".',
'filter_must_be_in' => 'Filter ":filter" must be one of: :values',

View File

@@ -90,15 +90,15 @@
var iAmOwed = '{{ 'i_am_owed_amount'|_|escape('js') }}';
var iOwe = '{{ 'i_owe_amount'|_|escape('js') }}';
</script>
<script type="text/javascript" src="v1/js/lib/modernizr-custom.js?v={{ FF_VERSION }}"
<script type="text/javascript" src="v1/js/lib/modernizr-custom.js?v={{ FF_BUILD_TIME }}"
nonce="{{ JS_NONCE }}"></script>
<script type="text/javascript" src="v1/js/lib/jquery-ui.min.js?v={{ FF_VERSION }}" nonce="{{ JS_NONCE }}"></script>
<script type="text/javascript" src="v1/js/ff/accounts/create.js?v={{ FF_VERSION }}" nonce="{{ JS_NONCE }}"></script>
<script type="text/javascript" src="v1/js/lib/jquery-ui.min.js?v={{ FF_BUILD_TIME }}" nonce="{{ JS_NONCE }}"></script>
<script type="text/javascript" src="v1/js/ff/accounts/create.js?v={{ FF_BUILD_TIME }}" nonce="{{ JS_NONCE }}"></script>
{% endblock %}
{% block styles %}
<link href="v1/css/jquery-ui/jquery-ui.structure.min.css?v={{ FF_VERSION }}" type="text/css" rel="stylesheet"
<link href="v1/css/jquery-ui/jquery-ui.structure.min.css?v={{ FF_BUILD_TIME }}" type="text/css" rel="stylesheet"
media="all" nonce="{{ JS_NONCE }}">
<link href="v1/css/jquery-ui/jquery-ui.theme.min.css?v={{ FF_VERSION }}" type="text/css" rel="stylesheet"
<link href="v1/css/jquery-ui/jquery-ui.theme.min.css?v={{ FF_BUILD_TIME }}" type="text/css" rel="stylesheet"
media="all" nonce="{{ JS_NONCE }}">
{% endblock %}

View File

@@ -122,15 +122,15 @@
var iAmOwed = '{{ 'i_am_owed_amount'|_|escape('js') }}';
var iOwe = '{{ 'i_owe_amount'|_|escape('js') }}';
</script>
<script type="text/javascript" src="v1/js/lib/modernizr-custom.js?v={{ FF_VERSION }}"
<script type="text/javascript" src="v1/js/lib/modernizr-custom.js?v={{ FF_BUILD_TIME }}"
nonce="{{ JS_NONCE }}"></script>
<script type="text/javascript" src="v1/js/lib/jquery-ui.min.js?v={{ FF_VERSION }}" nonce="{{ JS_NONCE }}"></script>
<script type="text/javascript" src="v1/js/ff/accounts/edit.js?v={{ FF_VERSION }}" nonce="{{ JS_NONCE }}"></script>
<script type="text/javascript" src="v1/js/lib/jquery-ui.min.js?v={{ FF_BUILD_TIME }}" nonce="{{ JS_NONCE }}"></script>
<script type="text/javascript" src="v1/js/ff/accounts/edit.js?v={{ FF_BUILD_TIME }}" nonce="{{ JS_NONCE }}"></script>
{% endblock %}
{% block styles %}
<link href="v1/css/jquery-ui/jquery-ui.structure.min.css?v={{ FF_VERSION }}" type="text/css" rel="stylesheet"
<link href="v1/css/jquery-ui/jquery-ui.structure.min.css?v={{ FF_BUILD_TIME }}" type="text/css" rel="stylesheet"
media="all" nonce="{{ JS_NONCE }}">
<link href="v1/css/jquery-ui/jquery-ui.theme.min.css?v={{ FF_VERSION }}" type="text/css" rel="stylesheet"
<link href="v1/css/jquery-ui/jquery-ui.theme.min.css?v={{ FF_BUILD_TIME }}" type="text/css" rel="stylesheet"
media="all" nonce="{{ JS_NONCE }}">
{% endblock %}

View File

@@ -90,6 +90,6 @@
<script type="text/javascript" nonce="{{ JS_NONCE }}">
var objectType = '{{ objectType|escape }}';
</script>
<script src="v1/js/lib/jquery-ui.min.js?v={{ FF_VERSION }}" type="text/javascript" nonce="{{ JS_NONCE }}"></script>
<script type="text/javascript" nonce="{{ JS_NONCE }}" src="v1/js/ff/accounts/index.js?v={{ FF_VERSION }}"></script>
<script src="v1/js/lib/jquery-ui.min.js?v={{ FF_BUILD_TIME }}" type="text/javascript" nonce="{{ JS_NONCE }}"></script>
<script type="text/javascript" nonce="{{ JS_NONCE }}" src="v1/js/ff/accounts/index.js?v={{ FF_BUILD_TIME }}"></script>
{% endblock %}

View File

@@ -133,5 +133,5 @@
var indexUrl = '{{ indexUrl }}';
var selectRangeAndBalance = '{{ 'select_range_and_balance'|_|escape('js') }}';
</script>
<script src="v1/js/ff/accounts/reconcile.js?v={{ FF_VERSION }}" type="text/javascript" nonce="{{ JS_NONCE }}"></script>
<script src="v1/js/ff/accounts/reconcile.js?v={{ FF_BUILD_TIME }}" type="text/javascript" nonce="{{ JS_NONCE }}"></script>
{% endblock %}

View File

@@ -219,25 +219,25 @@
</script>
{% if location %}
<script src="v1/lib/leaflet/leaflet.js?v={{ FF_VERSION }}" nonce="{{ JS_NONCE }}"></script>
<script src="v1/lib/leaflet/leaflet.js?v={{ FF_BUILD_TIME }}" nonce="{{ JS_NONCE }}"></script>
{% endif %}
<script type="text/javascript" src="v1/js/lib/Chart.bundle.min.js?v={{ FF_VERSION }}"
<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_VERSION }}"
<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_VERSION }}" nonce="{{ JS_NONCE }}"></script>
<script type="text/javascript" src="v1/js/ff/charts.js?v={{ FF_VERSION }}" 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 src="v1/js/lib/jquery-ui.min.js?v={{ FF_VERSION }}" type="text/javascript" nonce="{{ JS_NONCE }}"></script>
<script src="v1/js/lib/jquery.color-2.1.2.min.js?v={{ FF_VERSION }}" type="text/javascript"
<script src="v1/js/lib/jquery-ui.min.js?v={{ FF_BUILD_TIME }}" type="text/javascript" nonce="{{ JS_NONCE }}"></script>
<script src="v1/js/lib/jquery.color-2.1.2.min.js?v={{ FF_BUILD_TIME }}" type="text/javascript"
nonce="{{ JS_NONCE }}"></script>
<script src="v1/js/ff/accounts/show.js?v={{ FF_VERSION }}" type="text/javascript" nonce="{{ JS_NONCE }}"></script>
<script src="v1/js/ff/accounts/show.js?v={{ FF_BUILD_TIME }}" type="text/javascript" nonce="{{ JS_NONCE }}"></script>
{# required for groups.twig #}
<script type="text/javascript" src="v1/js/ff/list/groups.js?v={{ FF_VERSION }}" nonce="{{ JS_NONCE }}"></script>
<script type="text/javascript" src="v1/js/ff/list/groups.js?v={{ FF_BUILD_TIME }}" nonce="{{ JS_NONCE }}"></script>
{% endblock %}
{% block styles %}
{% if location %}
<link rel="stylesheet" href="v1/lib/leaflet/leaflet.css?v={{ FF_VERSION }}" nonce="{{ JS_NONCE }}">
<link rel="stylesheet" href="v1/lib/leaflet/leaflet.css?v={{ FF_BUILD_TIME }}" nonce="{{ JS_NONCE }}">
{% endif %}
{% endblock %}

View File

@@ -68,10 +68,10 @@
</div>
{% endblock %}
{% block scripts %}
<script type="text/javascript" src="v1/js/lib/bootstrap-sortable.js?v={{ FF_VERSION }}" nonce="{{ JS_NONCE }}"></script>
<script type="text/javascript" src="v1/js/lib/bootstrap-sortable.js?v={{ FF_BUILD_TIME }}" nonce="{{ JS_NONCE }}"></script>
{% endblock %}
{% block styles %}
<link rel="stylesheet" href="v1/css/bootstrap-sortable.css?v={{ FF_VERSION }}" type="text/css" media="all" nonce="{{ JS_NONCE }}">
<link rel="stylesheet" href="v1/css/bootstrap-sortable.css?v={{ FF_BUILD_TIME }}" type="text/css" media="all" nonce="{{ JS_NONCE }}">
{% endblock %}

View File

@@ -68,17 +68,17 @@
{% endblock %}
{% block styles %}
<link href="v1/css/bootstrap-tagsinput.css?v={{ FF_VERSION }}" type="text/css" rel="stylesheet" media="all" nonce="{{ JS_NONCE }}">
<link href="v1/css/jquery-ui/jquery-ui.structure.min.css?v={{ FF_VERSION }}" type="text/css" rel="stylesheet" media="all" nonce="{{ JS_NONCE }}">
<link href="v1/css/jquery-ui/jquery-ui.theme.min.css?v={{ FF_VERSION }}" type="text/css" rel="stylesheet" media="all" nonce="{{ JS_NONCE }}">
<link href="v1/css/bootstrap-tagsinput.css?v={{ FF_BUILD_TIME }}" type="text/css" rel="stylesheet" media="all" nonce="{{ JS_NONCE }}">
<link href="v1/css/jquery-ui/jquery-ui.structure.min.css?v={{ FF_BUILD_TIME }}" type="text/css" rel="stylesheet" media="all" nonce="{{ JS_NONCE }}">
<link href="v1/css/jquery-ui/jquery-ui.theme.min.css?v={{ FF_BUILD_TIME }}" type="text/css" rel="stylesheet" media="all" nonce="{{ JS_NONCE }}">
{% endblock %}
{% block scripts %}
<script type="text/javascript" src="v1/js/lib/bootstrap-tagsinput.min.js?v={{ FF_VERSION }}" nonce="{{ JS_NONCE }}"></script>
<script type="text/javascript" src="v1/js/lib/modernizr-custom.js?v={{ FF_VERSION }}" nonce="{{ JS_NONCE }}"></script>
<script type="text/javascript" src="v1/js/lib/jquery-ui.min.js?v={{ FF_VERSION }}" nonce="{{ JS_NONCE }}"></script>
<script type="text/javascript" src="v1/js/ff/bills/create.js?v={{ FF_VERSION }}" nonce="{{ JS_NONCE }}"></script>
<script type="text/javascript" src="v1/js/lib/bootstrap-tagsinput.min.js?v={{ FF_BUILD_TIME }}" nonce="{{ JS_NONCE }}"></script>
<script type="text/javascript" src="v1/js/lib/modernizr-custom.js?v={{ FF_BUILD_TIME }}" nonce="{{ JS_NONCE }}"></script>
<script type="text/javascript" src="v1/js/lib/jquery-ui.min.js?v={{ FF_BUILD_TIME }}" nonce="{{ JS_NONCE }}"></script>
<script type="text/javascript" src="v1/js/ff/bills/create.js?v={{ FF_BUILD_TIME }}" nonce="{{ JS_NONCE }}"></script>
{# auto complete for object groups #}
<script type="text/javascript" src="v1/js/lib/typeahead/typeahead.bundle.min.js?v={{ FF_VERSION }}" nonce="{{ JS_NONCE }}"></script>
<script type="text/javascript" src="v1/js/ff/object-groups/create-edit.js?v={{ FF_VERSION }}" nonce="{{ JS_NONCE }}"></script>
<script type="text/javascript" src="v1/js/lib/typeahead/typeahead.bundle.min.js?v={{ FF_BUILD_TIME }}" nonce="{{ JS_NONCE }}"></script>
<script type="text/javascript" src="v1/js/ff/object-groups/create-edit.js?v={{ FF_BUILD_TIME }}" nonce="{{ JS_NONCE }}"></script>
{% endblock %}

View File

@@ -74,24 +74,24 @@
{% endblock %}
{% block styles %}
<link href="v1/css/bootstrap-tagsinput.css?v={{ FF_VERSION }}" type="text/css" rel="stylesheet" media="all"
<link href="v1/css/bootstrap-tagsinput.css?v={{ FF_BUILD_TIME }}" type="text/css" rel="stylesheet" media="all"
nonce="{{ JS_NONCE }}">
<link href="v1/css/jquery-ui/jquery-ui.structure.min.css?v={{ FF_VERSION }}" type="text/css" rel="stylesheet"
<link href="v1/css/jquery-ui/jquery-ui.structure.min.css?v={{ FF_BUILD_TIME }}" type="text/css" rel="stylesheet"
media="all" nonce="{{ JS_NONCE }}">
<link href="v1/css/jquery-ui/jquery-ui.theme.min.css?v={{ FF_VERSION }}" type="text/css" rel="stylesheet"
<link href="v1/css/jquery-ui/jquery-ui.theme.min.css?v={{ FF_BUILD_TIME }}" type="text/css" rel="stylesheet"
media="all" nonce="{{ JS_NONCE }}">
{% endblock %}
{% block scripts %}
<script type="text/javascript" src="v1/js/lib/bootstrap-tagsinput.min.js?v={{ FF_VERSION }}"
<script type="text/javascript" src="v1/js/lib/bootstrap-tagsinput.min.js?v={{ FF_BUILD_TIME }}"
nonce="{{ JS_NONCE }}"></script>
<script type="text/javascript" src="v1/js/lib/modernizr-custom.js?v={{ FF_VERSION }}"
<script type="text/javascript" src="v1/js/lib/modernizr-custom.js?v={{ FF_BUILD_TIME }}"
nonce="{{ JS_NONCE }}"></script>
<script type="text/javascript" src="v1/js/lib/jquery-ui.min.js?v={{ FF_VERSION }}" nonce="{{ JS_NONCE }}"></script>
<script type="text/javascript" src="v1/js/ff/accounts/edit.js?v={{ FF_VERSION }}" nonce="{{ JS_NONCE }}"></script>
<script type="text/javascript" src="v1/js/lib/jquery-ui.min.js?v={{ FF_BUILD_TIME }}" nonce="{{ JS_NONCE }}"></script>
<script type="text/javascript" src="v1/js/ff/accounts/edit.js?v={{ FF_BUILD_TIME }}" nonce="{{ JS_NONCE }}"></script>
{# auto complete for object groups #}
<script type="text/javascript" src="v1/js/lib/typeahead/typeahead.bundle.min.js?v={{ FF_VERSION }}"
<script type="text/javascript" src="v1/js/lib/typeahead/typeahead.bundle.min.js?v={{ FF_BUILD_TIME }}"
nonce="{{ JS_NONCE }}"></script>
<script type="text/javascript" src="v1/js/ff/object-groups/create-edit.js?v={{ FF_VERSION }}"
<script type="text/javascript" src="v1/js/ff/object-groups/create-edit.js?v={{ FF_BUILD_TIME }}"
nonce="{{ JS_NONCE }}"></script>
{% endblock %}

View File

@@ -41,6 +41,6 @@
{% endblock %}
{% block scripts %}
<script src="v1/js/lib/jquery-ui.min.js?v={{ FF_VERSION }}" type="text/javascript" nonce="{{ JS_NONCE }}"></script>
<script type="text/javascript" src="v1/js/ff/bills/index.js?v={{ FF_VERSION }}" nonce="{{ JS_NONCE }}"></script>
<script src="v1/js/lib/jquery-ui.min.js?v={{ FF_BUILD_TIME }}" type="text/javascript" nonce="{{ JS_NONCE }}"></script>
<script type="text/javascript" src="v1/js/ff/bills/index.js?v={{ FF_BUILD_TIME }}" nonce="{{ JS_NONCE }}"></script>
{% endblock %}

View File

@@ -188,10 +188,10 @@
var billCurrencySymbol = "{{ convertToPrimary ? primaryCurrency.symbol : object.data.currency.symbol }}";
var billUrl = '{{ route('chart.bill.single', [object.data.id]) }}';
</script>
<script type="text/javascript" src="v1/js/lib/Chart.bundle.min.js?v={{ FF_VERSION }}" nonce="{{ JS_NONCE }}"></script>
<script type="text/javascript" src="v1/js/ff/charts.defaults.js?v={{ FF_VERSION }}" nonce="{{ JS_NONCE }}"></script>
<script type="text/javascript" src="v1/js/ff/charts.js?v={{ FF_VERSION }}" nonce="{{ JS_NONCE }}"></script>
<script type="text/javascript" src="v1/js/ff/bills/show.js?v={{ FF_VERSION }}" nonce="{{ JS_NONCE }}"></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/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/bills/show.js?v={{ FF_BUILD_TIME }}" nonce="{{ JS_NONCE }}"></script>
{# required for groups.twig #}
<script type="text/javascript" src="v1/js/ff/list/groups.js?v={{ FF_VERSION }}" nonce="{{ JS_NONCE }}"></script>
<script type="text/javascript" src="v1/js/ff/list/groups.js?v={{ FF_BUILD_TIME }}" nonce="{{ JS_NONCE }}"></script>
{% endblock %}

View File

@@ -60,5 +60,5 @@
{% endblock %}
{% block scripts %}
<script type="text/javascript" src="v1/js/ff/budgets/create.js?v={{ FF_VERSION }}" nonce="{{ JS_NONCE }}"></script>
<script type="text/javascript" src="v1/js/ff/budgets/create.js?v={{ FF_BUILD_TIME }}" nonce="{{ JS_NONCE }}"></script>
{% endblock %}

View File

@@ -61,5 +61,5 @@
{% endblock %}
{% block scripts %}
<script type="text/javascript" src="v1/js/ff/budgets/edit.js?v={{ FF_VERSION }}" nonce="{{ JS_NONCE }}"></script>
<script type="text/javascript" src="v1/js/ff/budgets/edit.js?v={{ FF_BUILD_TIME }}" nonce="{{ JS_NONCE }}"></script>
{% endblock %}

View File

@@ -267,9 +267,14 @@
<div class="input-group">
<div class="input-group-addon">{{ primaryCurrency.symbol }}</div>
<input type="hidden" name="balance_currency_id" value="{{ primaryCurrency.id }}"/>
{% if not anonymous %}
<input class="form-control budget_amount" data-original="0" data-id="{{ budget.id }}"
data-currency="{{ primaryCurrency.id }}" data-limit="0" value="0" autocomplete="off" min="0" name="amount"
type="number">
{% endif %}
{% if anonymous %}
---
{% endif %}
</div>
<span class="text-danger budget_warning" data-id="{{ budget.id }}" data-budgetLimit="{{ budgetLimit.id }}"
style="display:none;"></span>
@@ -283,10 +288,15 @@
{% endif %}
<div class="input-group bl_entry" data-budget-limit-id="{{ budgetLimit.id }}">
<div class="input-group-addon">{{ budgetLimit.currency_symbol }}</div>
{% if not anonymous %}
<input class="form-control budget_amount" data-original="{{ budgetLimit.amount }}"
data-id="{{ budget.id }}" data-limit="{{ budgetLimit.id }}" value="{{ budgetLimit.amount }}"
autocomplete="off"
min="0" name="amount" type="number">
{% endif %}
{% if anonymous %}
---
{% endif %}
<div class="input-group-btn">
<button type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown" aria-haspopup="true"
aria-expanded="false"><span class="caret"></span></button>
@@ -455,11 +465,11 @@
{% endblock %}
{% block styles %}
<link href="v1/css/bootstrap-sortable.css?v={{ FF_VERSION }}" type="text/css" rel="stylesheet" media="all" nonce="{{ JS_NONCE }}">
<link href="v1/css/bootstrap-sortable.css?v={{ FF_BUILD_TIME }}" type="text/css" rel="stylesheet" media="all" nonce="{{ JS_NONCE }}">
{% endblock %}
{% block scripts %}
<script src="v1/js/lib/jquery-ui.min.js?v={{ FF_VERSION }}" type="text/javascript" nonce="{{ JS_NONCE }}"></script>
<script src="v1/js/lib/jquery-ui.min.js?v={{ FF_BUILD_TIME }}" type="text/javascript" nonce="{{ JS_NONCE }}"></script>
<script type="text/javascript" nonce="{{ JS_NONCE }}">
// index route.
@@ -478,6 +488,6 @@
var periodStart = "{{ start.format('Y-m-d') }}";
var periodEnd = "{{ end.format('Y-m-d') }}";
</script>
<script type="text/javascript" src="v1/js/lib/bootstrap-sortable.js?v={{ FF_VERSION }}" nonce="{{ JS_NONCE }}"></script>
<script type="text/javascript" src="v1/js/ff/budgets/index.js?v={{ FF_VERSION }}" nonce="{{ JS_NONCE }}"></script>
<script type="text/javascript" src="v1/js/lib/bootstrap-sortable.js?v={{ FF_BUILD_TIME }}" nonce="{{ JS_NONCE }}"></script>
<script type="text/javascript" src="v1/js/ff/budgets/index.js?v={{ FF_BUILD_TIME }}" nonce="{{ JS_NONCE }}"></script>
{% endblock %}

View File

@@ -60,5 +60,5 @@
{% endblock %}
{% block scripts %}
{# required for groups.twig #}
<script type="text/javascript" src="v1/js/ff/list/groups.js?v={{ FF_VERSION }}" nonce="{{ JS_NONCE }}"></script>
<script type="text/javascript" src="v1/js/ff/list/groups.js?v={{ FF_BUILD_TIME }}" nonce="{{ JS_NONCE }}"></script>
{% endblock %}

View File

@@ -230,10 +230,10 @@
{% endif %}
</script>
<script type="text/javascript" src="v1/js/lib/Chart.bundle.min.js?v={{ FF_VERSION }}" nonce="{{ JS_NONCE }}"></script>
<script type="text/javascript" src="v1/js/ff/charts.defaults.js?v={{ FF_VERSION }}" nonce="{{ JS_NONCE }}"></script>
<script type="text/javascript" src="v1/js/ff/charts.js?v={{ FF_VERSION }}" nonce="{{ JS_NONCE }}"></script>
<script type="text/javascript" src="v1/js/ff/budgets/show.js?v={{ FF_VERSION }}" nonce="{{ JS_NONCE }}"></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/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/budgets/show.js?v={{ FF_BUILD_TIME }}" nonce="{{ JS_NONCE }}"></script>
{# required for groups.twig #}
<script type="text/javascript" src="v1/js/ff/list/groups.js?v={{ FF_VERSION }}" nonce="{{ JS_NONCE }}"></script>
<script type="text/javascript" src="v1/js/ff/list/groups.js?v={{ FF_BUILD_TIME }}" nonce="{{ JS_NONCE }}"></script>
{% endblock %}

View File

@@ -53,5 +53,5 @@
</form>
{% endblock %}
{% block scripts %}
<script type="text/javascript" src="v1/js/ff/budgets/create.js?v={{ FF_VERSION }}" nonce="{{ JS_NONCE }}"></script>
<script type="text/javascript" src="v1/js/ff/budgets/create.js?v={{ FF_BUILD_TIME }}" nonce="{{ JS_NONCE }}"></script>
{% endblock %}

View File

@@ -59,5 +59,5 @@
</form>
{% endblock %}
{% block scripts %}
<script type="text/javascript" src="v1/js/ff/categories/edit.js?v={{ FF_VERSION }}" nonce="{{ JS_NONCE }}"></script>
<script type="text/javascript" src="v1/js/ff/categories/edit.js?v={{ FF_BUILD_TIME }}" nonce="{{ JS_NONCE }}"></script>
{% endblock %}

View File

@@ -40,10 +40,10 @@
{% endblock %}
{% block styles %}
<link href="v1/css/bootstrap-sortable.css?v={{ FF_VERSION }}" type="text/css" rel="stylesheet" media="all" nonce="{{ JS_NONCE }}">
<link href="v1/css/bootstrap-sortable.css?v={{ FF_BUILD_TIME }}" type="text/css" rel="stylesheet" media="all" nonce="{{ JS_NONCE }}">
{% endblock %}
{% block scripts %}
<script type="text/javascript" src="v1/js/lib/bootstrap-sortable.js?v={{ FF_VERSION }}" nonce="{{ JS_NONCE }}"></script>
<script type="text/javascript" src="v1/js/ff/categories/index.js?v={{ FF_VERSION }}" nonce="{{ JS_NONCE }}"></script>
<script type="text/javascript" src="v1/js/lib/bootstrap-sortable.js?v={{ FF_BUILD_TIME }}" nonce="{{ JS_NONCE }}"></script>
<script type="text/javascript" src="v1/js/ff/categories/index.js?v={{ FF_BUILD_TIME }}" nonce="{{ JS_NONCE }}"></script>
{% endblock %}

View File

@@ -60,5 +60,5 @@
{% endblock %}
{% block scripts %}
{# required for groups.twig #}
<script type="text/javascript" src="v1/js/ff/list/groups.js?v={{ FF_VERSION }}" nonce="{{ JS_NONCE }}"></script>
<script type="text/javascript" src="v1/js/ff/list/groups.js?v={{ FF_BUILD_TIME }}" nonce="{{ JS_NONCE }}"></script>
{% endblock %}

View File

@@ -113,10 +113,10 @@
var everything = '{{ route('chart.category.all', [category.id]) }}';
var specific = '{{ route('chart.category.specific', [category.id, start.format('Ymd')]) }}';
</script>
<script type="text/javascript" src="v1/js/lib/Chart.bundle.min.js?v={{ FF_VERSION }}" nonce="{{ JS_NONCE }}"></script>
<script type="text/javascript" src="v1/js/ff/charts.defaults.js?v={{ FF_VERSION }}" nonce="{{ JS_NONCE }}"></script>
<script type="text/javascript" src="v1/js/ff/charts.js?v={{ FF_VERSION }}" nonce="{{ JS_NONCE }}"></script>
<script type="text/javascript" src="v1/js/ff/categories/show.js?v={{ FF_VERSION }}" nonce="{{ JS_NONCE }}"></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/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/categories/show.js?v={{ FF_BUILD_TIME }}" nonce="{{ JS_NONCE }}"></script>
{# required for groups.twig #}
<script type="text/javascript" src="v1/js/ff/list/groups.js?v={{ FF_VERSION }}" nonce="{{ JS_NONCE }}"></script>
<script type="text/javascript" src="v1/js/ff/list/groups.js?v={{ FF_BUILD_TIME }}" nonce="{{ JS_NONCE }}"></script>
{% endblock %}

View File

@@ -98,5 +98,5 @@
var redirectUrl = "{{ route('currencies.index') }}";
var updateCurrencyUrl = "{{ route('api.v1.currencies.update', ['']) }}";
</script>
<script type="text/javascript" src="v1/js/ff/currencies/index.js?v={{ FF_VERSION }}" nonce="{{ JS_NONCE }}"></script>
<script type="text/javascript" src="v1/js/ff/currencies/index.js?v={{ FF_BUILD_TIME }}" nonce="{{ JS_NONCE }}"></script>
{% endblock %}

View File

@@ -211,14 +211,14 @@
{% endif %}
</script>
<script type="text/javascript" src="v1/js/lib/Chart.bundle.min.js?v={{ FF_VERSION }}"
<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_VERSION }}"
<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_VERSION }}"
<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_VERSION }}" nonce="{{ JS_NONCE }}"></script>
<script type="text/javascript" src="v1/js/ff/index.js?v={{ FF_VERSION }}" 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>
{% endblock %}
{% block styles %}
{% endblock %}

View File

@@ -26,6 +26,7 @@ ranges: ranges
};
var uid = "{{ uid }}";
var anonymous = {{ anonymous }};
var language = "{{ language|escape }}";
var locale = "{{ locale|escape }}";
var currencyCode = '{{ currencyCode|escape('js') }}';
@@ -51,6 +52,9 @@ var acc_config_new = {format: accountingConfig};
var helpPageTitle = "{{ trans('firefly.help_for_this_page')|escape('js') }}";
var helpPageBody = "{{ trans('firefly.help_for_this_page_body')|escape('js') }}";
var anonymous_warning_on_txt = "{{ trans('firefly.anonymous_warning_on')|escape('js') }}";
var anonymous_warning_off_txt= "{{ trans('firefly.anonymous_warning_off')|escape('js') }}";
var edit_selected_txt = "{{ trans('firefly.mass_edit')|escape('js') }}";
var edit_bulk_selected_txt = "{{ trans('firefly.bulk_edit')|escape('js') }}";
var delete_selected_txt = "{{ trans('firefly.mass_delete')|escape('js') }}";

View File

@@ -29,14 +29,14 @@
</title>
<meta content='width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no' name='viewport'>
{# CSS things #}
<link href="v1/lib/bs/css/bootstrap.min.css?v={{ FF_VERSION }}" rel="stylesheet" type="text/css"
<link href="v1/lib/bs/css/bootstrap.min.css?v={{ FF_BUILD_TIME }}" rel="stylesheet" type="text/css"
nonce="{{ JS_NONCE }}">
<link href="v1/lib/fa/css/font-awesome.min.css?v={{ FF_VERSION }}" rel="stylesheet" type="text/css"
<link href="v1/lib/fa/css/font-awesome.min.css?v={{ FF_BUILD_TIME }}" rel="stylesheet" type="text/css"
nonce="{{ JS_NONCE }}">
{# the theme #}
<link href="v1/lib/adminlte/css/AdminLTE.min.css?v={{ FF_VERSION }}" rel="stylesheet" type="text/css"
<link href="v1/lib/adminlte/css/AdminLTE.min.css?v={{ FF_BUILD_TIME }}" rel="stylesheet" type="text/css"
nonce="{{ JS_NONCE }}">
{% if 'browser' == darkMode %}
<script nonce="{{ JS_NONCE }}">
@@ -46,43 +46,43 @@
document.documentElement.style.display = 'none';
document.head.insertAdjacentHTML(
'beforeend',
'<link rel="stylesheet" href="v1/lib/adminlte/css/skins/skin-light.min.css?v={{ FF_VERSION }}" nonce="{{ JS_NONCE }}" onload="document.documentElement.style.display = \'\'">',
'<link rel="stylesheet" href="v1/lib/adminlte/css/skins/skin-light.min.css?v={{ FF_BUILD_TIME }}" nonce="{{ JS_NONCE }}" onload="document.documentElement.style.display = \'\'">',
);
}
</script>
<link href="v1/css/daterangepicker-default.css?v={{ FF_VERSION }}" rel="stylesheet" type="text/css"
<link href="v1/css/daterangepicker-default.css?v={{ FF_BUILD_TIME }}" rel="stylesheet" type="text/css"
nonce="{{ JS_NONCE }}">
<link href="v1/lib/adminlte/css/skins/skin-dark.min.css?v={{ FF_VERSION }}" rel="stylesheet" type="text/css"
<link href="v1/lib/adminlte/css/skins/skin-dark.min.css?v={{ FF_BUILD_TIME }}" rel="stylesheet" type="text/css"
nonce="{{ JS_NONCE }}" media="(prefers-color-scheme: dark)">
<link href="v1/lib/adminlte/css/skins/skin-light.min.css?v={{ FF_VERSION }}" rel="stylesheet" type="text/css"
<link href="v1/lib/adminlte/css/skins/skin-light.min.css?v={{ FF_BUILD_TIME }}" rel="stylesheet" type="text/css"
nonce="{{ JS_NONCE }}" media="(prefers-color-scheme: light)">
{% endif %}
{% if 'dark' == darkMode %}
<link href="v1/css/daterangepicker-dark.css?v={{ FF_VERSION }}" rel="stylesheet" type="text/css"
<link href="v1/css/daterangepicker-dark.css?v={{ FF_BUILD_TIME }}" rel="stylesheet" type="text/css"
nonce="{{ JS_NONCE }}">
<link href="v1/lib/adminlte/css/skins/skin-dark.min.css?v={{ FF_VERSION }}" rel="stylesheet" type="text/css"
<link href="v1/lib/adminlte/css/skins/skin-dark.min.css?v={{ FF_BUILD_TIME }}" rel="stylesheet" type="text/css"
nonce="{{ JS_NONCE }}">
{% endif %}
{% if 'light' == darkMode %}
<link href="v1/css/daterangepicker-light.css?v={{ FF_VERSION }}" rel="stylesheet" type="text/css"
<link href="v1/css/daterangepicker-light.css?v={{ FF_BUILD_TIME }}" rel="stylesheet" type="text/css"
nonce="{{ JS_NONCE }}">
<link href="v1/lib/adminlte/css/skins/skin-light.min.css?v={{ FF_VERSION }}" rel="stylesheet" type="text/css"
<link href="v1/lib/adminlte/css/skins/skin-light.min.css?v={{ FF_BUILD_TIME }}" rel="stylesheet" type="text/css"
nonce="{{ JS_NONCE }}">
{% endif %}
{# Firefly III customisations #}
<link href="v1/css/firefly.css?v={{ FF_VERSION }}" rel="stylesheet" type="text/css" nonce="{{ JS_NONCE }}">
<link href="v1/css/firefly.css?v={{ FF_BUILD_TIME }}" rel="stylesheet" type="text/css" nonce="{{ JS_NONCE }}">
{# Extra CSS for the demo: #}
{% if not shownDemo %}
<link href="v1/lib/intro/introjs.min.css?v={{ FF_VERSION }}" rel="stylesheet" type="text/css"
<link href="v1/lib/intro/introjs.min.css?v={{ FF_BUILD_TIME }}" rel="stylesheet" type="text/css"
nonce="{{ JS_NONCE }}">
{% endif %}
{# Any local custom CSS. #}
{% block styles %}{% endblock %}
<!--[if lt IE 9]>
<script src="v1/js/lib/html5shiv.min.js?v={{ FF_VERSION }}" nonce="{{ JS_NONCE }}"></script>
<script src="v1/js/lib/respond.min.js?v={{ FF_VERSION }}" nonce="{{ JS_NONCE }}"></script>
<script src="v1/js/lib/html5shiv.min.js?v={{ FF_BUILD_TIME }}" nonce="{{ JS_NONCE }}"></script>
<script src="v1/js/lib/respond.min.js?v={{ FF_BUILD_TIME }}" nonce="{{ JS_NONCE }}"></script>
<![endif]-->
{# this entry is in the header so it's loaded early #}
@@ -111,7 +111,16 @@
</a>
<div class="navbar-custom-menu">
<ul class="nav navbar-nav">
<li class="hidden-sm hidden-xs">
<a href="#" id="anonymous">
{% if anonymous %}
<span class="text-danger fa fa-eye-slash"></span>
{% endif %}
{% if not anonymous %}
<span class="text-success fa fa-eye"></span>
{% endif %}
</a>
</li>
<li class="hidden-sm hidden-xs">
<a href="#" id="help" data-route="{{ original_route_name }}"
data-extra="{{ objectType|default("") }}">
@@ -219,8 +228,8 @@
{% block definitions %}{% endblock %}
{# Moment JS #}
<script src="v1/js/lib/moment.min.js?v={{ FF_VERSION }}" type="text/javascript" nonce="{{ JS_NONCE }}"></script>
<script src="v1/js/lib/moment/{{ language|replace({'-':'_'}) }}.js?v={{ FF_VERSION }}" type="text/javascript"
<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/{{ language|replace({'-':'_'}) }}.js?v={{ FF_BUILD_TIME }}" type="text/javascript"
nonce="{{ JS_NONCE }}"></script>
{# All kinds of variables. #}
@@ -229,32 +238,32 @@
type="text/javascript" nonce="{{ JS_NONCE }}"></script>
{# Base script: jquery and bootstrap #}
<script src="v1/js/app.js?v={{ FF_VERSION }}" type="text/javascript" nonce="{{ JS_NONCE }}"></script>
<script src="v1/js/app.js?v={{ FF_BUILD_TIME }}" type="text/javascript" nonce="{{ JS_NONCE }}"></script>
{# Vue scripts and components. Only loaded when needed #}
{% if VUE_SCRIPT_NAME %}
<script src="v1/js/app_vue.js?v={{ FF_VERSION }}" type="text/javascript" nonce="{{ JS_NONCE }}"></script>
<script src="v1/js/{{ VUE_SCRIPT_NAME }}.js?v={{ FF_VERSION }}" type="text/javascript"
<script src="v1/js/app_vue.js?v={{ FF_BUILD_TIME }}" type="text/javascript" nonce="{{ JS_NONCE }}"></script>
<script src="v1/js/{{ VUE_SCRIPT_NAME }}.js?v={{ FF_BUILD_TIME }}" type="text/javascript"
nonce="{{ JS_NONCE }}"></script>
{% endif %}
{# date range picker, current template, etc. #}
<script src="v1/js/lib/daterangepicker.js?v={{ FF_VERSION }}" type="text/javascript" nonce="{{ JS_NONCE }}"></script>
<script src="v1/lib/adminlte/js/adminlte.min.js?v={{ FF_VERSION }}" type="text/javascript"
<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_VERSION }}" 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_VERSION }}" nonce="{{ JS_NONCE }}"></script>
<script type="text/javascript" src="v1/js/ff/help.js?v={{ FF_VERSION }}" nonce="{{ JS_NONCE }}"></script>
<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>
{% if not shownDemo %}
<script type="text/javascript" nonce="{{ JS_NONCE }}">
var routeForTour = "{{ current_route_name }}";
var routeStepsUrl = "{{ route('json.intro', [current_route_name, objectType|default("")]) }}";
var routeForFinishedTour = "{{ route('json.intro.finished', [current_route_name, objectType|default("")]) }}";
</script>
<script type="text/javascript" src="v1/lib/intro/intro.min.js?v={{ FF_VERSION }}" nonce="{{ JS_NONCE }}"></script>
<script type="text/javascript" src="v1/js/ff/intro/intro.js?v={{ FF_VERSION }}" nonce="{{ JS_NONCE }}"></script>
<script type="text/javascript" src="v1/lib/intro/intro.min.js?v={{ FF_BUILD_TIME }}" nonce="{{ JS_NONCE }}"></script>
<script type="text/javascript" src="v1/js/ff/intro/intro.js?v={{ FF_BUILD_TIME }}" nonce="{{ JS_NONCE }}"></script>
{% endif %}
{% block scripts %}{% endblock %}

View File

@@ -14,11 +14,11 @@
{# CSS things #}
{# libraries #}
<link href="v1/lib/bs/css/bootstrap.min.css?v={{ FF_VERSION }}" rel="stylesheet" type="text/css" nonce="{{ JS_NONCE }}">
<link href="v1/lib/fa/css/font-awesome.min.css?v={{ FF_VERSION }}" rel="stylesheet" type="text/css" nonce="{{ JS_NONCE }}">
<link href="v1/lib/bs/css/bootstrap.min.css?v={{ FF_BUILD_TIME }}" rel="stylesheet" type="text/css" nonce="{{ JS_NONCE }}">
<link href="v1/lib/fa/css/font-awesome.min.css?v={{ FF_BUILD_TIME }}" rel="stylesheet" type="text/css" nonce="{{ JS_NONCE }}">
{# the theme #}
<link href="v1/lib/adminlte/css/AdminLTE.min.css?v={{ FF_VERSION }}" rel="stylesheet" type="text/css" nonce="{{ JS_NONCE }}">
<link href="v1/lib/adminlte/css/AdminLTE.min.css?v={{ FF_BUILD_TIME }}" rel="stylesheet" type="text/css" nonce="{{ JS_NONCE }}">
{% if 'browser' == darkMode %}
<script nonce="{{ JS_NONCE }}">
// If `prefers-color-scheme` is not supported, fall back to light mode.
@@ -27,26 +27,26 @@
document.documentElement.style.display = 'none';
document.head.insertAdjacentHTML(
'beforeend',
'<link rel="stylesheet" href="v1/lib/adminlte/css/skins/skin-light.min.css?v={{ FF_VERSION }}" nonce="{{ JS_NONCE }}" onload="document.documentElement.style.display = \'\'">',
'<link rel="stylesheet" href="v1/lib/adminlte/css/skins/skin-light.min.css?v={{ FF_BUILD_TIME }}" nonce="{{ JS_NONCE }}" onload="document.documentElement.style.display = \'\'">',
);
}
</script>
<link href="v1/lib/adminlte/css/skins/skin-dark.min.css?v={{ FF_VERSION }}" rel="stylesheet" type="text/css" nonce="{{ JS_NONCE }}" media="(prefers-color-scheme: dark)">
<link href="v1/lib/adminlte/css/skins/skin-light.min.css?v={{ FF_VERSION }}" rel="stylesheet" type="text/css" nonce="{{ JS_NONCE }}" media="(prefers-color-scheme: light)">
<link href="v1/lib/adminlte/css/skins/skin-dark.min.css?v={{ FF_BUILD_TIME }}" rel="stylesheet" type="text/css" nonce="{{ JS_NONCE }}" media="(prefers-color-scheme: dark)">
<link href="v1/lib/adminlte/css/skins/skin-light.min.css?v={{ FF_BUILD_TIME }}" rel="stylesheet" type="text/css" nonce="{{ JS_NONCE }}" media="(prefers-color-scheme: light)">
{% endif %}
{% if 'dark' == darkMode %}
<link href="v1/lib/adminlte/css/skins/skin-dark.min.css?v={{ FF_VERSION }}" rel="stylesheet" type="text/css" nonce="{{ JS_NONCE }}">
<link href="v1/lib/adminlte/css/skins/skin-dark.min.css?v={{ FF_BUILD_TIME }}" rel="stylesheet" type="text/css" nonce="{{ JS_NONCE }}">
{% endif %}
{% if 'light' == darkMode %}
<link href="v1/lib/adminlte/css/skins/skin-light.min.css?v={{ FF_VERSION }}" rel="stylesheet" type="text/css" nonce="{{ JS_NONCE }}">
<link href="v1/lib/adminlte/css/skins/skin-light.min.css?v={{ FF_BUILD_TIME }}" rel="stylesheet" type="text/css" nonce="{{ JS_NONCE }}">
{% endif %}
{# Firefly III customisations #}
<link href="v1/css/firefly.css?v={{ FF_VERSION }}" rel="stylesheet" type="text/css" nonce="{{ JS_NONCE }}">
<link href="v1/css/firefly.css?v={{ FF_BUILD_TIME }}" rel="stylesheet" type="text/css" nonce="{{ JS_NONCE }}">
<!--[if lt IE 9]>
<script src="v1/js/lib/html5shiv.min.js?v={{ FF_VERSION }}" nonce="{{ JS_NONCE }}"></script>
<script src="v1/js/lib/respond.min.js?v={{ FF_VERSION }}" nonce="{{ JS_NONCE }}"></script>
<script src="v1/js/lib/html5shiv.min.js?v={{ FF_BUILD_TIME }}" nonce="{{ JS_NONCE }}"></script>
<script src="v1/js/lib/respond.min.js?v={{ FF_BUILD_TIME }}" nonce="{{ JS_NONCE }}"></script>
<![endif]-->
{# favicons #}
@@ -61,7 +61,7 @@
{% block content %}{% endblock %}
</div>
<script src="v1/js/app.js?v={{ FF_VERSION }}" type="text/javascript" nonce="{{ JS_NONCE }}"></script>
<script src="v1/js/app.js?v={{ FF_BUILD_TIME }}" type="text/javascript" nonce="{{ JS_NONCE }}"></script>
{% if config('firefly.tracker_site_id') != '' and config('firefly.tracker_url') != '' %}
<!-- This tracker tag is only here because this instance of Firefly III was purposefully configured to include it -->

View File

@@ -24,11 +24,11 @@
{# CSS things #}
{# libraries #}
<link href="v1/lib/bs/css/bootstrap.min.css?v={{ FF_VERSION }}" rel="stylesheet" type="text/css" nonce="{{ JS_NONCE }}">
<link href="v1/lib/fa/css/font-awesome.min.css?v={{ FF_VERSION }}" rel="stylesheet" type="text/css" nonce="{{ JS_NONCE }}">
<link href="v1/lib/bs/css/bootstrap.min.css?v={{ FF_BUILD_TIME }}" rel="stylesheet" type="text/css" nonce="{{ JS_NONCE }}">
<link href="v1/lib/fa/css/font-awesome.min.css?v={{ FF_BUILD_TIME }}" rel="stylesheet" type="text/css" nonce="{{ JS_NONCE }}">
{# the theme #}
<link href="v1/lib/adminlte/css/AdminLTE.min.css?v={{ FF_VERSION }}" rel="stylesheet" type="text/css" nonce="{{ JS_NONCE }}">
<link href="v1/lib/adminlte/css/AdminLTE.min.css?v={{ FF_BUILD_TIME }}" rel="stylesheet" type="text/css" nonce="{{ JS_NONCE }}">
{% if 'browser' == darkMode %}
<script nonce="{{ JS_NONCE }}">
// If `prefers-color-scheme` is not supported, fall back to light mode.
@@ -37,26 +37,26 @@
document.documentElement.style.display = 'none';
document.head.insertAdjacentHTML(
'beforeend',
'<link rel="stylesheet" href="v1/lib/adminlte/css/skins/skin-light.min.css?v={{ FF_VERSION }}" nonce="{{ JS_NONCE }}" onload="document.documentElement.style.display = \'\'">',
'<link rel="stylesheet" href="v1/lib/adminlte/css/skins/skin-light.min.css?v={{ FF_BUILD_TIME }}" nonce="{{ JS_NONCE }}" onload="document.documentElement.style.display = \'\'">',
);
}
</script>
<link href="v1/lib/adminlte/css/skins/skin-dark.min.css?v={{ FF_VERSION }}" rel="stylesheet" type="text/css" nonce="{{ JS_NONCE }}" media="(prefers-color-scheme: dark)">
<link href="v1/lib/adminlte/css/skins/skin-light.min.css?v={{ FF_VERSION }}" rel="stylesheet" type="text/css" nonce="{{ JS_NONCE }}" media="(prefers-color-scheme: light)">
<link href="v1/lib/adminlte/css/skins/skin-dark.min.css?v={{ FF_BUILD_TIME }}" rel="stylesheet" type="text/css" nonce="{{ JS_NONCE }}" media="(prefers-color-scheme: dark)">
<link href="v1/lib/adminlte/css/skins/skin-light.min.css?v={{ FF_BUILD_TIME }}" rel="stylesheet" type="text/css" nonce="{{ JS_NONCE }}" media="(prefers-color-scheme: light)">
{% endif %}
{% if 'dark' == darkMode %}
<link href="v1/lib/adminlte/css/skins/skin-dark.min.css?v={{ FF_VERSION }}" rel="stylesheet" type="text/css" nonce="{{ JS_NONCE }}">
<link href="v1/lib/adminlte/css/skins/skin-dark.min.css?v={{ FF_BUILD_TIME }}" rel="stylesheet" type="text/css" nonce="{{ JS_NONCE }}">
{% endif %}
{% if 'light' == darkMode %}
<link href="v1/lib/adminlte/css/skins/skin-light.min.css?v={{ FF_VERSION }}" rel="stylesheet" type="text/css" nonce="{{ JS_NONCE }}">
<link href="v1/lib/adminlte/css/skins/skin-light.min.css?v={{ FF_BUILD_TIME }}" rel="stylesheet" type="text/css" nonce="{{ JS_NONCE }}">
{% endif %}
{# Firefly III customisations #}
<link href="v1/css/firefly.css?v={{ FF_VERSION }}" rel="stylesheet" type="text/css" nonce="{{ JS_NONCE }}">
<link href="v1/css/firefly.css?v={{ FF_BUILD_TIME }}" rel="stylesheet" type="text/css" nonce="{{ JS_NONCE }}">
<!--[if lt IE 9]>
<script src="v1/js/lib/html5shiv.min.js?v={{ FF_VERSION }}" nonce="{{ JS_NONCE }}"></script>
<script src="v1/js/lib/respond.min.js?v={{ FF_VERSION }}" nonce="{{ JS_NONCE }}"></script>
<script src="v1/js/lib/html5shiv.min.js?v={{ FF_BUILD_TIME }}" nonce="{{ JS_NONCE }}"></script>
<script src="v1/js/lib/respond.min.js?v={{ FF_BUILD_TIME }}" nonce="{{ JS_NONCE }}"></script>
<![endif]-->
{# favicons #}
@@ -75,8 +75,8 @@
Developed by James Cole, the source code is licensed under the <a href="https://www.gnu.org/licenses/agpl-3.0.html">AGPL-3.0-or-later</a>.
</small>
</div>
<script src="v1/js/app.js?v={{ FF_VERSION }}" type="text/javascript" nonce="{{ JS_NONCE }}"></script>
<script type="text/javascript" src="v1/js/ff/guest.js?v={{ FF_VERSION }}" nonce="{{ JS_NONCE }}"></script>
<script src="v1/js/app.js?v={{ FF_BUILD_TIME }}" type="text/javascript" nonce="{{ JS_NONCE }}"></script>
<script type="text/javascript" src="v1/js/ff/guest.js?v={{ FF_BUILD_TIME }}" nonce="{{ JS_NONCE }}"></script>
{% if config('firefly.tracker_site_id') != '' and config('firefly.tracker_url') != '' %}
<!-- This tracker tag is only here because this instance of Firefly III was purposefully configured to include it -->

View File

@@ -35,8 +35,8 @@
Developed by James Cole, the source code is licensed under the <a href="https://www.gnu.org/licenses/agpl-3.0.html">AGPL-3.0-or-later</a>.
</small>
</div>
<script src="v1/js/app.js?v={{ FF_VERSION }}" type="text/javascript" nonce="{{ JS_NONCE }}"></script>
<script type="text/javascript" src="v1/js/ff/guest.js?v={{ FF_VERSION }}" nonce="{{ JS_NONCE }}"></script>
<script src="v1/js/app.js?v={{ FF_BUILD_TIME }}" type="text/javascript" nonce="{{ JS_NONCE }}"></script>
<script type="text/javascript" src="v1/js/ff/guest.js?v={{ FF_BUILD_TIME }}" nonce="{{ JS_NONCE }}"></script>
{% block scripts %}{% endblock %}
{% if config('firefly.tracker_site_id') != '' and config('firefly.tracker_url') != '' %}
<!-- This tracker tag is only here because this instance of Firefly III was purposefully configured to include it -->

View File

@@ -7,10 +7,10 @@
<title>{{ 'login_page_title'|_ }}</title>
<!-- fonts and styles -->
<link rel="stylesheet" href="v3-local/css/fonts.css?v={{ FF_VERSION }}">
<link rel="stylesheet" href="v3-local/lib/fontawesome-free/css/all.min.css?v={{ FF_VERSION }}">
<link rel="stylesheet" href="v3-local/lib/icheck-bootstrap/icheck-bootstrap.min.css?v={{ FF_VERSION }}">
<link rel="stylesheet" href="v3-local/dist/css/adminlte.min.css?v={{ FF_VERSION }}">
<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' %}
@@ -19,11 +19,11 @@
{% block content %}{% endblock %}
<!-- jQuery -->
<script src="v3-local/lib/jquery/jquery.min.js?v={{ FF_VERSION }}" nonce="{{ JS_NONCE }}"></script>
<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_VERSION }}" nonce="{{ JS_NONCE }}"></script>
<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_VERSION }}" nonce="{{ JS_NONCE }}"></script>
<script src="v3-local/dist/js/adminlte.min.js?v={{ FF_BUILD_TIME }}" nonce="{{ JS_NONCE }}"></script>
{% block scripts %}
{% endblock %}
</body>

View File

@@ -47,21 +47,21 @@
</form>
{% endblock %}
{% block scripts %}
<script type="text/javascript" src="v1/js/lib/modernizr-custom.js?v={{ FF_VERSION }}"
<script type="text/javascript" src="v1/js/lib/modernizr-custom.js?v={{ FF_BUILD_TIME }}"
nonce="{{ JS_NONCE }}"></script>
<script type="text/javascript" src="v1/js/lib/jquery-ui.min.js?v={{ FF_VERSION }}" nonce="{{ JS_NONCE }}"></script>
<script type="text/javascript" src="v1/js/ff/piggy-banks/create.js?v={{ FF_VERSION }}"
<script type="text/javascript" src="v1/js/lib/jquery-ui.min.js?v={{ FF_BUILD_TIME }}" nonce="{{ JS_NONCE }}"></script>
<script type="text/javascript" src="v1/js/ff/piggy-banks/create.js?v={{ FF_BUILD_TIME }}"
nonce="{{ JS_NONCE }}"></script>
{# auto complete for object groups #}
<script type="text/javascript" src="v1/js/lib/typeahead/typeahead.bundle.min.js?v={{ FF_VERSION }}"
<script type="text/javascript" src="v1/js/lib/typeahead/typeahead.bundle.min.js?v={{ FF_BUILD_TIME }}"
nonce="{{ JS_NONCE }}"></script>
<script type="text/javascript" src="v1/js/ff/object-groups/create-edit.js?v={{ FF_VERSION }}"
<script type="text/javascript" src="v1/js/ff/object-groups/create-edit.js?v={{ FF_BUILD_TIME }}"
nonce="{{ JS_NONCE }}"></script>
{% endblock %}
{% block styles %}
<link href="v1/css/jquery-ui/jquery-ui.structure.min.css?v={{ FF_VERSION }}" type="text/css" rel="stylesheet"
<link href="v1/css/jquery-ui/jquery-ui.structure.min.css?v={{ FF_BUILD_TIME }}" type="text/css" rel="stylesheet"
media="all" nonce="{{ JS_NONCE }}">
<link href="v1/css/jquery-ui/jquery-ui.theme.min.css?v={{ FF_VERSION }}" type="text/css" rel="stylesheet"
<link href="v1/css/jquery-ui/jquery-ui.theme.min.css?v={{ FF_BUILD_TIME }}" type="text/css" rel="stylesheet"
media="all" nonce="{{ JS_NONCE }}">
{% endblock %}

View File

@@ -70,8 +70,8 @@
</div>
{% endblock %}
{% block scripts %}
<script src="v1/js/lib/jquery-ui.min.js?v={{ FF_VERSION }}" type="text/javascript" nonce="{{ JS_NONCE }}"></script>
<script type="text/javascript" src="v1/js/ff/object-groups/index.js?v={{ FF_VERSION }}" nonce="{{ JS_NONCE }}"></script>
<script src="v1/js/lib/jquery-ui.min.js?v={{ FF_BUILD_TIME }}" type="text/javascript" nonce="{{ JS_NONCE }}"></script>
<script type="text/javascript" src="v1/js/ff/object-groups/index.js?v={{ FF_BUILD_TIME }}" nonce="{{ JS_NONCE }}"></script>
{% endblock %}
{% block styles %}
{% endblock %}

View File

@@ -14,6 +14,10 @@
<td>Firefly III</td>
<td>{% if FF_IS_DEVELOP %}<!-- .Z9JBCmw64Zkx1pQw -->{% endif %}{% if not FF_IS_DEVELOP %}v{% endif %}{{ FF_VERSION }}</td>
</tr>
<tr>
<td>Build time</td>
<td>{{ system.build_time_nice }} ({{ system.build_time }})</td>
</tr>
{# PHP version + settings #}
<tr>
<td>PHP version</td>

View File

@@ -59,16 +59,16 @@
</form>
{% endblock %}
{% block scripts %}
<script type="text/javascript" src="v1/js/lib/modernizr-custom.js?v={{ FF_VERSION }}" nonce="{{ JS_NONCE }}"></script>
<script type="text/javascript" src="v1/js/lib/jquery-ui.min.js?v={{ FF_VERSION }}" nonce="{{ JS_NONCE }}"></script>
<script type="text/javascript" src="v1/js/ff/piggy-banks/create.js?v={{ FF_VERSION }}" nonce="{{ JS_NONCE }}"></script>
<script type="text/javascript" src="v1/js/lib/modernizr-custom.js?v={{ FF_BUILD_TIME }}" nonce="{{ JS_NONCE }}"></script>
<script type="text/javascript" src="v1/js/lib/jquery-ui.min.js?v={{ FF_BUILD_TIME }}" nonce="{{ JS_NONCE }}"></script>
<script type="text/javascript" src="v1/js/ff/piggy-banks/create.js?v={{ FF_BUILD_TIME }}" nonce="{{ JS_NONCE }}"></script>
{# auto complete for object groups #}
<script type="text/javascript" src="v1/js/lib/typeahead/typeahead.bundle.min.js?v={{ FF_VERSION }}" nonce="{{ JS_NONCE }}"></script>
<script type="text/javascript" src="v1/js/ff/object-groups/create-edit.js?v={{ FF_VERSION }}" nonce="{{ JS_NONCE }}"></script>
<script type="text/javascript" src="v1/js/lib/typeahead/typeahead.bundle.min.js?v={{ FF_BUILD_TIME }}" nonce="{{ JS_NONCE }}"></script>
<script type="text/javascript" src="v1/js/ff/object-groups/create-edit.js?v={{ FF_BUILD_TIME }}" nonce="{{ JS_NONCE }}"></script>
{% endblock %}
{% block styles %}
<link href="v1/css/jquery-ui/jquery-ui.structure.min.css?v={{ FF_VERSION }}" type="text/css" rel="stylesheet" media="all" nonce="{{ JS_NONCE }}">
<link href="v1/css/jquery-ui/jquery-ui.theme.min.css?v={{ FF_VERSION }}" type="text/css" rel="stylesheet" media="all" nonce="{{ JS_NONCE }}">
<link href="v1/css/jquery-ui/jquery-ui.structure.min.css?v={{ FF_BUILD_TIME }}" type="text/css" rel="stylesheet" media="all" nonce="{{ JS_NONCE }}">
<link href="v1/css/jquery-ui/jquery-ui.theme.min.css?v={{ FF_BUILD_TIME }}" type="text/css" rel="stylesheet" media="all" nonce="{{ JS_NONCE }}">
{% endblock %}

View File

@@ -67,21 +67,21 @@
</form>
{% endblock %}
{% block scripts %}
<script type="text/javascript" src="v1/js/lib/modernizr-custom.js?v={{ FF_VERSION }}"
<script type="text/javascript" src="v1/js/lib/modernizr-custom.js?v={{ FF_BUILD_TIME }}"
nonce="{{ JS_NONCE }}"></script>
<script type="text/javascript" src="v1/js/lib/jquery-ui.min.js?v={{ FF_VERSION }}" nonce="{{ JS_NONCE }}"></script>
<script type="text/javascript" src="v1/js/ff/piggy-banks/create.js?v={{ FF_VERSION }}"
<script type="text/javascript" src="v1/js/lib/jquery-ui.min.js?v={{ FF_BUILD_TIME }}" nonce="{{ JS_NONCE }}"></script>
<script type="text/javascript" src="v1/js/ff/piggy-banks/create.js?v={{ FF_BUILD_TIME }}"
nonce="{{ JS_NONCE }}"></script>
{# auto complete for object groups #}
<script type="text/javascript" src="v1/js/lib/typeahead/typeahead.bundle.min.js?v={{ FF_VERSION }}"
<script type="text/javascript" src="v1/js/lib/typeahead/typeahead.bundle.min.js?v={{ FF_BUILD_TIME }}"
nonce="{{ JS_NONCE }}"></script>
<script type="text/javascript" src="v1/js/ff/object-groups/create-edit.js?v={{ FF_VERSION }}"
<script type="text/javascript" src="v1/js/ff/object-groups/create-edit.js?v={{ FF_BUILD_TIME }}"
nonce="{{ JS_NONCE }}"></script>
{% endblock %}
{% block styles %}
<link href="v1/css/jquery-ui/jquery-ui.structure.min.css?v={{ FF_VERSION }}" type="text/css" rel="stylesheet"
<link href="v1/css/jquery-ui/jquery-ui.structure.min.css?v={{ FF_BUILD_TIME }}" type="text/css" rel="stylesheet"
media="all" nonce="{{ JS_NONCE }}">
<link href="v1/css/jquery-ui/jquery-ui.theme.min.css?v={{ FF_VERSION }}" type="text/css" rel="stylesheet"
<link href="v1/css/jquery-ui/jquery-ui.theme.min.css?v={{ FF_BUILD_TIME }}" type="text/css" rel="stylesheet"
media="all" nonce="{{ JS_NONCE }}">
{% endblock %}

View File

@@ -75,6 +75,6 @@
{% endif %}
{% endblock %}
{% block scripts %}
<script src="v1/js/lib/jquery-ui.min.js?v={{ FF_VERSION }}" type="text/javascript" nonce="{{ JS_NONCE }}"></script>
<script type="text/javascript" src="v1/js/ff/piggy-banks/index.js?v={{ FF_VERSION }}" nonce="{{ JS_NONCE }}"></script>
<script src="v1/js/lib/jquery-ui.min.js?v={{ FF_BUILD_TIME }}" type="text/javascript" nonce="{{ JS_NONCE }}"></script>
<script type="text/javascript" src="v1/js/ff/piggy-banks/index.js?v={{ FF_BUILD_TIME }}" nonce="{{ JS_NONCE }}"></script>
{% endblock %}

View File

@@ -162,8 +162,8 @@
var piggyBankID = {{ piggyBank.id }};
</script>
<script type="text/javascript" src="v1/js/lib/Chart.bundle.min.js?v={{ FF_VERSION }}" nonce="{{ JS_NONCE }}"></script>
<script type="text/javascript" src="v1/js/ff/charts.defaults.js?v={{ FF_VERSION }}" nonce="{{ JS_NONCE }}"></script>
<script type="text/javascript" src="v1/js/ff/charts.js?v={{ FF_VERSION }}" nonce="{{ JS_NONCE }}"></script>
<script type="text/javascript" src="v1/js/ff/piggy-banks/show.js?v={{ FF_VERSION }}" nonce="{{ JS_NONCE }}"></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/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/piggy-banks/show.js?v={{ FF_BUILD_TIME }}" nonce="{{ JS_NONCE }}"></script>
{% endblock %}

View File

@@ -402,16 +402,16 @@
<script type="text/javascript" nonce="{{ JS_NONCE }}">
var postUrl = "{{ route('preferences.test-notification') }}";
</script>
<script type="text/javascript" src="v1/js/lib/modernizr-custom.js?v={{ FF_VERSION }}"
<script type="text/javascript" src="v1/js/lib/modernizr-custom.js?v={{ FF_BUILD_TIME }}"
nonce="{{ JS_NONCE }}"></script>
<script type="text/javascript" src="v1/js/lib/jquery-ui.min.js?v={{ FF_VERSION }}" nonce="{{ JS_NONCE }}"></script>
<script type="text/javascript" src="v1/js/ff/preferences/index.js?v={{ FF_VERSION }}"
<script type="text/javascript" src="v1/js/lib/jquery-ui.min.js?v={{ FF_BUILD_TIME }}" nonce="{{ JS_NONCE }}"></script>
<script type="text/javascript" src="v1/js/ff/preferences/index.js?v={{ FF_BUILD_TIME }}"
nonce="{{ JS_NONCE }}"></script>
{% endblock %}
{% block styles %}
<link href="v1/css/jquery-ui/jquery-ui.structure.min.css?v={{ FF_VERSION }}" type="text/css" rel="stylesheet"
<link href="v1/css/jquery-ui/jquery-ui.structure.min.css?v={{ FF_BUILD_TIME }}" type="text/css" rel="stylesheet"
media="all" nonce="{{ JS_NONCE }}">
<link href="v1/css/jquery-ui/jquery-ui.theme.min.css?v={{ FF_VERSION }}" type="text/css" rel="stylesheet"
<link href="v1/css/jquery-ui/jquery-ui.theme.min.css?v={{ FF_BUILD_TIME }}" type="text/css" rel="stylesheet"
media="all" nonce="{{ JS_NONCE }}">
{% endblock %}

View File

@@ -205,16 +205,16 @@
</div>
{% endblock %}
{% block scripts %}
<script type="text/javascript" src="v1/js/lib/modernizr-custom.js?v={{ FF_VERSION }}"
<script type="text/javascript" src="v1/js/lib/modernizr-custom.js?v={{ FF_BUILD_TIME }}"
nonce="{{ JS_NONCE }}"></script>
<script type="text/javascript" src="v1/js/lib/typeahead/typeahead.bundle.min.js?v={{ FF_VERSION }}"
<script type="text/javascript" src="v1/js/lib/typeahead/typeahead.bundle.min.js?v={{ FF_BUILD_TIME }}"
nonce="{{ JS_NONCE }}"></script>
<script type="text/javascript" src="v1/js/ff/common/autocomplete.js?v={{ FF_VERSION }}"
<script type="text/javascript" src="v1/js/ff/common/autocomplete.js?v={{ FF_BUILD_TIME }}"
nonce="{{ JS_NONCE }}"></script>
<script type="text/javascript" src="v1/js/lib/bootstrap-tagsinput.min.js?v={{ FF_VERSION }}"
<script type="text/javascript" src="v1/js/lib/bootstrap-tagsinput.min.js?v={{ FF_BUILD_TIME }}"
nonce="{{ JS_NONCE }}"></script>
<script type="text/javascript" src="v1/js/lib/jquery-ui.min.js?v={{ FF_VERSION }}" nonce="{{ JS_NONCE }}"></script>
<script type="text/javascript" src="v1/lib/fc/fullcalendar.min.js?v={{ FF_VERSION }}"
<script type="text/javascript" src="v1/js/lib/jquery-ui.min.js?v={{ FF_BUILD_TIME }}" nonce="{{ JS_NONCE }}"></script>
<script type="text/javascript" src="v1/lib/fc/fullcalendar.min.js?v={{ FF_BUILD_TIME }}"
nonce="{{ JS_NONCE }}"></script>
<script type="text/javascript" nonce="{{ JS_NONCE }}">
var transactionType = "{{ preFilled.transaction_type }}";
@@ -222,17 +222,17 @@
var eventsUrl = "{{ route('recurring.events') }}";
var oldRepetitionType = "{{ oldRepetitionType }}";
</script>
<script type="text/javascript" src="v1/js/ff/recurring/create.js?v={{ FF_VERSION }}"
<script type="text/javascript" src="v1/js/ff/recurring/create.js?v={{ FF_BUILD_TIME }}"
nonce="{{ JS_NONCE }}"></script>
{% endblock %}
{% block styles %}
<link href="v1/css/bootstrap-tagsinput.css?v={{ FF_VERSION }}" type="text/css" rel="stylesheet" media="all"
<link href="v1/css/bootstrap-tagsinput.css?v={{ FF_BUILD_TIME }}" type="text/css" rel="stylesheet" media="all"
nonce="{{ JS_NONCE }}">
<link href="v1/css/jquery-ui/jquery-ui.structure.min.css?v={{ FF_VERSION }}" type="text/css" rel="stylesheet"
<link href="v1/css/jquery-ui/jquery-ui.structure.min.css?v={{ FF_BUILD_TIME }}" type="text/css" rel="stylesheet"
media="all" nonce="{{ JS_NONCE }}">
<link href="v1/css/jquery-ui/jquery-ui.theme.min.css?v={{ FF_VERSION }}" type="text/css" rel="stylesheet"
<link href="v1/css/jquery-ui/jquery-ui.theme.min.css?v={{ FF_BUILD_TIME }}" type="text/css" rel="stylesheet"
media="all" nonce="{{ JS_NONCE }}">
<link href="v1/lib/fc/fullcalendar.min.css?v={{ FF_VERSION }}" type="text/css" rel="stylesheet" media="all"
<link href="v1/lib/fc/fullcalendar.min.css?v={{ FF_BUILD_TIME }}" type="text/css" rel="stylesheet" media="all"
nonce="{{ JS_NONCE }}">
{% endblock %}

View File

@@ -204,16 +204,16 @@
</div>
{% endblock %}
{% block scripts %}
<script type="text/javascript" src="v1/js/lib/modernizr-custom.js?v={{ FF_VERSION }}"
<script type="text/javascript" src="v1/js/lib/modernizr-custom.js?v={{ FF_BUILD_TIME }}"
nonce="{{ JS_NONCE }}"></script>
<script type="text/javascript" src="v1/js/lib/typeahead/typeahead.bundle.min.js?v={{ FF_VERSION }}"
<script type="text/javascript" src="v1/js/lib/typeahead/typeahead.bundle.min.js?v={{ FF_BUILD_TIME }}"
nonce="{{ JS_NONCE }}"></script>
<script type="text/javascript" src="v1/js/ff/common/autocomplete.js?v={{ FF_VERSION }}"
<script type="text/javascript" src="v1/js/ff/common/autocomplete.js?v={{ FF_BUILD_TIME }}"
nonce="{{ JS_NONCE }}"></script>
<script type="text/javascript" src="v1/js/lib/bootstrap-tagsinput.min.js?v={{ FF_VERSION }}"
<script type="text/javascript" src="v1/js/lib/bootstrap-tagsinput.min.js?v={{ FF_BUILD_TIME }}"
nonce="{{ JS_NONCE }}"></script>
<script type="text/javascript" src="v1/js/lib/jquery-ui.min.js?v={{ FF_VERSION }}" nonce="{{ JS_NONCE }}"></script>
<script type="text/javascript" src="v1/lib/fc/fullcalendar.min.js?v={{ FF_VERSION }}"
<script type="text/javascript" src="v1/js/lib/jquery-ui.min.js?v={{ FF_BUILD_TIME }}" nonce="{{ JS_NONCE }}"></script>
<script type="text/javascript" src="v1/lib/fc/fullcalendar.min.js?v={{ FF_BUILD_TIME }}"
nonce="{{ JS_NONCE }}"></script>
<script type="text/javascript" nonce="{{ JS_NONCE }}">
var transactionType = "{{ preFilled.transaction_type }}";
@@ -221,16 +221,16 @@
var eventsUrl = "{{ route('recurring.events') }}";
var currentRepType = "{{ currentRepType }}";
</script>
<script type="text/javascript" src="v1/js/ff/recurring/edit.js?v={{ FF_VERSION }}" nonce="{{ JS_NONCE }}"></script>
<script type="text/javascript" src="v1/js/ff/recurring/edit.js?v={{ FF_BUILD_TIME }}" nonce="{{ JS_NONCE }}"></script>
{% endblock %}
{% block styles %}
<link href="v1/css/bootstrap-tagsinput.css?v={{ FF_VERSION }}" type="text/css" rel="stylesheet" media="all"
<link href="v1/css/bootstrap-tagsinput.css?v={{ FF_BUILD_TIME }}" type="text/css" rel="stylesheet" media="all"
nonce="{{ JS_NONCE }}">
<link href="v1/css/jquery-ui/jquery-ui.structure.min.css?v={{ FF_VERSION }}" type="text/css" rel="stylesheet"
<link href="v1/css/jquery-ui/jquery-ui.structure.min.css?v={{ FF_BUILD_TIME }}" type="text/css" rel="stylesheet"
media="all" nonce="{{ JS_NONCE }}">
<link href="v1/css/jquery-ui/jquery-ui.theme.min.css?v={{ FF_VERSION }}" type="text/css" rel="stylesheet"
<link href="v1/css/jquery-ui/jquery-ui.theme.min.css?v={{ FF_BUILD_TIME }}" type="text/css" rel="stylesheet"
media="all" nonce="{{ JS_NONCE }}">
<link href="v1/lib/fc/fullcalendar.min.css?v={{ FF_VERSION }}" type="text/css" rel="stylesheet" media="all"
<link href="v1/lib/fc/fullcalendar.min.css?v={{ FF_BUILD_TIME }}" type="text/css" rel="stylesheet" media="all"
nonce="{{ JS_NONCE }}">
{% endblock %}

View File

@@ -158,9 +158,9 @@
{% endblock %}
{% block styles %}
<link rel="stylesheet" href="v1/css/bootstrap-sortable.css?v={{ FF_VERSION }}" type="text/css" media="all" nonce="{{ JS_NONCE }}">
<link rel="stylesheet" href="v1/css/bootstrap-sortable.css?v={{ FF_BUILD_TIME }}" type="text/css" media="all" nonce="{{ JS_NONCE }}">
{% endblock %}
{% block scripts %}
<script type="text/javascript" src="v1/js/lib/bootstrap-sortable.js?v={{ FF_VERSION }}" nonce="{{ JS_NONCE }}"></script>
<script type="text/javascript" src="v1/js/lib/bootstrap-sortable.js?v={{ FF_BUILD_TIME }}" nonce="{{ JS_NONCE }}"></script>
{% endblock %}

View File

@@ -213,13 +213,13 @@
{% endblock %}
{% block styles %}
<link rel="stylesheet" href="v1/css/bootstrap-sortable.css?v={{ FF_VERSION }}" type="text/css" media="all"
<link rel="stylesheet" href="v1/css/bootstrap-sortable.css?v={{ FF_BUILD_TIME }}" type="text/css" media="all"
nonce="{{ JS_NONCE }}">
{% endblock %}
{% block scripts %}
<script type="text/javascript" src="v1/js/lib/bootstrap-sortable.js?v={{ FF_VERSION }}"
<script type="text/javascript" src="v1/js/lib/bootstrap-sortable.js?v={{ FF_BUILD_TIME }}"
nonce="{{ JS_NONCE }}"></script>
{# required for groups.twig #}
<script type="text/javascript" src="v1/js/ff/list/groups.js?v={{ FF_VERSION }}" nonce="{{ JS_NONCE }}"></script>
<script type="text/javascript" src="v1/js/ff/list/groups.js?v={{ FF_BUILD_TIME }}" nonce="{{ JS_NONCE }}"></script>
{% endblock %}

View File

@@ -87,6 +87,6 @@
<script type="text/javascript" nonce="{{ JS_NONCE }}">
var hideable = {{ hideable|json_encode|raw }};
</script>
<script type="text/javascript" src="v1/js/ff/reports/all.js?v={{ FF_VERSION }}" nonce="{{ JS_NONCE }}"></script>
<script type="text/javascript" src="v1/js/ff/reports/audit/all.js?v={{ FF_VERSION }}" nonce="{{ JS_NONCE }}"></script>
<script type="text/javascript" src="v1/js/ff/reports/all.js?v={{ FF_BUILD_TIME }}" nonce="{{ JS_NONCE }}"></script>
<script type="text/javascript" src="v1/js/ff/reports/audit/all.js?v={{ FF_BUILD_TIME }}" nonce="{{ JS_NONCE }}"></script>
{% endblock %}

View File

@@ -149,10 +149,10 @@
{% endblock %}
{% block scripts %}
<script type="text/javascript" src="v1/js/lib/Chart.bundle.min.js?v={{ FF_VERSION }}" nonce="{{ JS_NONCE }}"></script>
<script type="text/javascript" src="v1/js/ff/charts.defaults.js?v={{ FF_VERSION }}" nonce="{{ JS_NONCE }}"></script>
<script type="text/javascript" src="v1/js/ff/charts.js?v={{ FF_VERSION }}" nonce="{{ JS_NONCE }}"></script>
<script type="text/javascript" src="v1/js/lib/bootstrap-sortable.js?v={{ FF_VERSION }}" nonce="{{ JS_NONCE }}"></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/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/lib/bootstrap-sortable.js?v={{ FF_BUILD_TIME }}" nonce="{{ JS_NONCE }}"></script>
<script type="text/javascript" nonce="{{ JS_NONCE }}">
// to report another URL:
@@ -175,11 +175,11 @@
</script>
<script type="text/javascript" src="v1/js/ff/reports/all.js?v={{ FF_VERSION }}" nonce="{{ JS_NONCE }}"></script>
<script type="text/javascript" src="v1/js/ff/reports/budget/month.js?v={{ FF_VERSION }}" nonce="{{ JS_NONCE }}"></script>
<script type="text/javascript" src="v1/js/ff/reports/all.js?v={{ FF_BUILD_TIME }}" nonce="{{ JS_NONCE }}"></script>
<script type="text/javascript" src="v1/js/ff/reports/budget/month.js?v={{ FF_BUILD_TIME }}" nonce="{{ JS_NONCE }}"></script>
{% endblock %}
{% block styles %}
<link rel="stylesheet" href="v1/css/bootstrap-sortable.css?v={{ FF_VERSION }}" type="text/css" media="all" nonce="{{ JS_NONCE }}">
<link rel="stylesheet" href="v1/css/bootstrap-sortable.css?v={{ FF_BUILD_TIME }}" type="text/css" media="all" nonce="{{ JS_NONCE }}">
{% endblock %}

View File

@@ -214,12 +214,12 @@
{% endblock %}
{% block scripts %}
<script type="text/javascript" src="v1/js/lib/Chart.bundle.min.js?v={{ FF_VERSION }}" nonce="{{ JS_NONCE }}"></script>
<script type="text/javascript" src="v1/js/ff/charts.defaults.js?v={{ FF_VERSION }}" nonce="{{ JS_NONCE }}"></script>
<script type="text/javascript" src="v1/js/ff/charts.js?v={{ FF_VERSION }}" nonce="{{ JS_NONCE }}"></script>
<script type="text/javascript" src="v1/js/lib/bootstrap-sortable.js?v={{ FF_VERSION }}" nonce="{{ JS_NONCE }}"></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/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/lib/bootstrap-sortable.js?v={{ FF_BUILD_TIME }}" nonce="{{ JS_NONCE }}"></script>
<script type="text/javascript" src="v1/js/ff/reports/all.js?v={{ FF_VERSION }}" nonce="{{ JS_NONCE }}"></script>
<script type="text/javascript" src="v1/js/ff/reports/all.js?v={{ FF_BUILD_TIME }}" nonce="{{ JS_NONCE }}"></script>
<script type="text/javascript" nonce="{{ JS_NONCE }}">
// to report another URL:
var startDate = '{{ start.format('Ymd') }}';
@@ -247,10 +247,10 @@
var topIncomeUrl = '{{ route('report-data.category.top-income', [accountIds, categoryIds, start.format('Ymd'), end.format('Ymd')]) }}';
</script>
<script type="text/javascript" src="v1/js/ff/reports/category/month.js?v={{ FF_VERSION }}" nonce="{{ JS_NONCE }}"></script>
<script type="text/javascript" src="v1/js/ff/reports/category/month.js?v={{ FF_BUILD_TIME }}" nonce="{{ JS_NONCE }}"></script>
{% endblock %}
{% block styles %}
<link rel="stylesheet" href="v1/css/bootstrap-sortable.css?v={{ FF_VERSION }}" type="text/css" media="all" nonce="{{ JS_NONCE }}">
<link rel="stylesheet" href="v1/css/bootstrap-sortable.css?v={{ FF_BUILD_TIME }}" type="text/css" media="all" nonce="{{ JS_NONCE }}">
{% endblock %}

View File

@@ -142,14 +142,14 @@
</div>
{% endblock %}
{% block styles %}
<link rel="stylesheet" href="v1/css/bootstrap-sortable.css?v={{ FF_VERSION }}" type="text/css" media="all" nonce="{{ JS_NONCE }}">
<link rel="stylesheet" href="v1/css/bootstrap-sortable.css?v={{ FF_BUILD_TIME }}" type="text/css" media="all" nonce="{{ JS_NONCE }}">
{% endblock %}
{% block scripts %}
<script type="text/javascript" src="v1/js/lib/bootstrap-sortable.js?v={{ FF_VERSION }}" nonce="{{ JS_NONCE }}"></script>
<script type="text/javascript" src="v1/js/lib/Chart.bundle.min.js?v={{ FF_VERSION }}" nonce="{{ JS_NONCE }}"></script>
<script type="text/javascript" src="v1/js/ff/charts.defaults.js?v={{ FF_VERSION }}" nonce="{{ JS_NONCE }}"></script>
<script type="text/javascript" src="v1/js/ff/charts.js?v={{ FF_VERSION }}" nonce="{{ JS_NONCE }}"></script>
<script type="text/javascript" src="v1/js/lib/bootstrap-sortable.js?v={{ FF_BUILD_TIME }}" nonce="{{ JS_NONCE }}"></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/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" nonce="{{ JS_NONCE }}">
var year = {{ start.year }};
var month = {{ start.month }};
@@ -172,7 +172,7 @@
var accountChartUrl = '{{ route('chart.account.report', [accountIds, start.format('Ymd'), end.format('Ymd')]) }}';
</script>
<script type="text/javascript" src="v1/js/ff/reports/all.js?v={{ FF_VERSION }}" nonce="{{ JS_NONCE }}"></script>
<script type="text/javascript" src="v1/js/ff/reports/default/all.js?v={{ FF_VERSION }}" nonce="{{ JS_NONCE }}"></script>
<script type="text/javascript" src="v1/js/ff/reports/default/month.js?v={{ FF_VERSION }}" nonce="{{ JS_NONCE }}"></script>
<script type="text/javascript" src="v1/js/ff/reports/all.js?v={{ FF_BUILD_TIME }}" nonce="{{ JS_NONCE }}"></script>
<script type="text/javascript" src="v1/js/ff/reports/default/all.js?v={{ FF_BUILD_TIME }}" nonce="{{ JS_NONCE }}"></script>
<script type="text/javascript" src="v1/js/ff/reports/default/month.js?v={{ FF_BUILD_TIME }}" nonce="{{ JS_NONCE }}"></script>
{% endblock %}

View File

@@ -185,14 +185,14 @@
{% endblock %}
{% block styles %}
<link rel="stylesheet" href="v1/css/bootstrap-sortable.css?v={{ FF_VERSION }}" type="text/css" media="all" nonce="{{ JS_NONCE }}">
<link rel="stylesheet" href="v1/css/bootstrap-sortable.css?v={{ FF_BUILD_TIME }}" type="text/css" media="all" nonce="{{ JS_NONCE }}">
{% endblock %}
{% block scripts %}
<script type="text/javascript" src="v1/js/lib/bootstrap-sortable.js?v={{ FF_VERSION }}" nonce="{{ JS_NONCE }}"></script>
<script type="text/javascript" src="v1/js/lib/Chart.bundle.min.js?v={{ FF_VERSION }}" nonce="{{ JS_NONCE }}"></script>
<script type="text/javascript" src="v1/js/ff/charts.defaults.js?v={{ FF_VERSION }}" nonce="{{ JS_NONCE }}"></script>
<script type="text/javascript" src="v1/js/ff/charts.js?v={{ FF_VERSION }}" nonce="{{ JS_NONCE }}"></script>
<script type="text/javascript" src="v1/js/lib/bootstrap-sortable.js?v={{ FF_BUILD_TIME }}" nonce="{{ JS_NONCE }}"></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/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" nonce="{{ JS_NONCE }}">
var year = {{ start.year }};
var month = {{ start.month }};
@@ -216,7 +216,7 @@
var billReportUrl = '';
</script>
<script type="text/javascript" src="v1/js/ff/reports/all.js?v={{ FF_VERSION }}" nonce="{{ JS_NONCE }}"></script>
<script type="text/javascript" src="v1/js/ff/reports/default/all.js?v={{ FF_VERSION }}" nonce="{{ JS_NONCE }}"></script>
<script type="text/javascript" src="v1/js/ff/reports/default/multi-year.js?v={{ FF_VERSION }}" nonce="{{ JS_NONCE }}"></script>
<script type="text/javascript" src="v1/js/ff/reports/all.js?v={{ FF_BUILD_TIME }}" nonce="{{ JS_NONCE }}"></script>
<script type="text/javascript" src="v1/js/ff/reports/default/all.js?v={{ FF_BUILD_TIME }}" nonce="{{ JS_NONCE }}"></script>
<script type="text/javascript" src="v1/js/ff/reports/default/multi-year.js?v={{ FF_BUILD_TIME }}" nonce="{{ JS_NONCE }}"></script>
{% endblock %}

View File

@@ -184,10 +184,10 @@
{% endblock %}
{% block scripts %}
<script type="text/javascript" src="v1/js/lib/bootstrap-sortable.js?v={{ FF_VERSION }}" nonce="{{ JS_NONCE }}"></script>
<script type="text/javascript" src="v1/js/lib/Chart.bundle.min.js?v={{ FF_VERSION }}" nonce="{{ JS_NONCE }}"></script>
<script type="text/javascript" src="v1/js/ff/charts.defaults.js?v={{ FF_VERSION }}" nonce="{{ JS_NONCE }}"></script>
<script type="text/javascript" src="v1/js/ff/charts.js?v={{ FF_VERSION }}" nonce="{{ JS_NONCE }}"></script>
<script type="text/javascript" src="v1/js/lib/bootstrap-sortable.js?v={{ FF_BUILD_TIME }}" nonce="{{ JS_NONCE }}"></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/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" nonce="{{ JS_NONCE }}">
var year = '{{ start.year }}';
@@ -210,11 +210,11 @@
var billReportUrl = '';
</script>
<script type="text/javascript" src="v1/js/ff/reports/all.js?v={{ FF_VERSION }}" nonce="{{ JS_NONCE }}"></script>
<script type="text/javascript" src="v1/js/ff/reports/default/all.js?v={{ FF_VERSION }}" nonce="{{ JS_NONCE }}"></script>
<script type="text/javascript" src="v1/js/ff/reports/default/year.js?v={{ FF_VERSION }}" nonce="{{ JS_NONCE }}"></script>
<script type="text/javascript" src="v1/js/ff/reports/all.js?v={{ FF_BUILD_TIME }}" nonce="{{ JS_NONCE }}"></script>
<script type="text/javascript" src="v1/js/ff/reports/default/all.js?v={{ FF_BUILD_TIME }}" nonce="{{ JS_NONCE }}"></script>
<script type="text/javascript" src="v1/js/ff/reports/default/year.js?v={{ FF_BUILD_TIME }}" nonce="{{ JS_NONCE }}"></script>
{% endblock %}
{% block styles %}
<link rel="stylesheet" href="v1/css/bootstrap-sortable.css?v={{ FF_VERSION }}" type="text/css" media="all" nonce="{{ JS_NONCE }}">
<link rel="stylesheet" href="v1/css/bootstrap-sortable.css?v={{ FF_BUILD_TIME }}" type="text/css" media="all" nonce="{{ JS_NONCE }}">
{% endblock %}

View File

@@ -192,10 +192,10 @@
{% endblock %}
{% block scripts %}
<script type="text/javascript" src="v1/js/lib/Chart.bundle.min.js?v={{ FF_VERSION }}" nonce="{{ JS_NONCE }}"></script>
<script type="text/javascript" src="v1/js/ff/charts.defaults.js?v={{ FF_VERSION }}" nonce="{{ JS_NONCE }}"></script>
<script type="text/javascript" src="v1/js/ff/charts.js?v={{ FF_VERSION }}" nonce="{{ JS_NONCE }}"></script>
<script type="text/javascript" src="v1/js/lib/bootstrap-sortable.js?v={{ FF_VERSION }}" nonce="{{ JS_NONCE }}"></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/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/lib/bootstrap-sortable.js?v={{ FF_BUILD_TIME }}" nonce="{{ JS_NONCE }}"></script>
<script type="text/javascript" nonce="{{ JS_NONCE }}">
// to report another URL:
@@ -222,11 +222,11 @@
var topIncomeUrl = '{{ route('report-data.double.top-income', [accountIds, doubleIds, start.format('Ymd'), end.format('Ymd')]) }}';
</script>
<script type="text/javascript" src="v1/js/ff/reports/all.js?v={{ FF_VERSION }}" nonce="{{ JS_NONCE }}"></script>
<script type="text/javascript" src="v1/js/ff/reports/double/month.js?v={{ FF_VERSION }}" nonce="{{ JS_NONCE }}"></script>
<script type="text/javascript" src="v1/js/ff/reports/all.js?v={{ FF_BUILD_TIME }}" nonce="{{ JS_NONCE }}"></script>
<script type="text/javascript" src="v1/js/ff/reports/double/month.js?v={{ FF_BUILD_TIME }}" nonce="{{ JS_NONCE }}"></script>
{% endblock %}
{% block styles %}
<link rel="stylesheet" href="v1/css/bootstrap-sortable.css?v={{ FF_VERSION }}" type="text/css" media="all" nonce="{{ JS_NONCE }}">
<link rel="stylesheet" href="v1/css/bootstrap-sortable.css?v={{ FF_BUILD_TIME }}" type="text/css" media="all" nonce="{{ JS_NONCE }}">
{% endblock %}

View File

@@ -189,7 +189,7 @@
{% endblock %}
{% block styles %}
<link href="v1/css/bootstrap-multiselect.css?v={{ FF_VERSION }}" rel="stylesheet" type="text/css" nonce="{{ JS_NONCE }}">
<link href="v1/css/bootstrap-multiselect.css?v={{ FF_BUILD_TIME }}" rel="stylesheet" type="text/css" nonce="{{ JS_NONCE }}">
{% endblock %}
{% block scripts %}
@@ -202,7 +202,7 @@
var allSelectedText = "{{ trans('firefly.multi_select_all_selected')|escape('js') }}";
var filterPlaceholder = "{{ trans('firefly.multi_select_filter_placeholder')|escape('js') }}";
</script>
<script type="text/javascript" src="v1/js/lib/bootstrap-multiselect.js?v={{ FF_VERSION }}" nonce="{{ JS_NONCE }}"></script>
<script type="text/javascript" src="v1/js/ff/reports/all.js?v={{ FF_VERSION }}" nonce="{{ JS_NONCE }}"></script>
<script type="text/javascript" src="v1/js/ff/reports/index.js?v={{ FF_VERSION }}" nonce="{{ JS_NONCE }}"></script>
<script type="text/javascript" src="v1/js/lib/bootstrap-multiselect.js?v={{ FF_BUILD_TIME }}" nonce="{{ JS_NONCE }}"></script>
<script type="text/javascript" src="v1/js/ff/reports/all.js?v={{ FF_BUILD_TIME }}" nonce="{{ JS_NONCE }}"></script>
<script type="text/javascript" src="v1/js/ff/reports/index.js?v={{ FF_BUILD_TIME }}" nonce="{{ JS_NONCE }}"></script>
{% endblock %}

View File

@@ -245,12 +245,12 @@
{% endblock %}
{% block scripts %}
<script type="text/javascript" src="v1/js/lib/Chart.bundle.min.js?v={{ FF_VERSION }}" nonce="{{ JS_NONCE }}"></script>
<script type="text/javascript" src="v1/js/ff/charts.defaults.js?v={{ FF_VERSION }}" nonce="{{ JS_NONCE }}"></script>
<script type="text/javascript" src="v1/js/ff/charts.js?v={{ FF_VERSION }}" nonce="{{ JS_NONCE }}"></script>
<script type="text/javascript" src="v1/js/lib/bootstrap-sortable.js?v={{ FF_VERSION }}" nonce="{{ JS_NONCE }}"></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/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/lib/bootstrap-sortable.js?v={{ FF_BUILD_TIME }}" nonce="{{ JS_NONCE }}"></script>
<script type="text/javascript" src="v1/js/ff/reports/all.js?v={{ FF_VERSION }}" nonce="{{ JS_NONCE }}"></script>
<script type="text/javascript" src="v1/js/ff/reports/all.js?v={{ FF_BUILD_TIME }}" nonce="{{ JS_NONCE }}"></script>
<script type="text/javascript" nonce="{{ JS_NONCE }}">
// to report another URL:
var startDate = '{{ start.format('Ymd') }}';
@@ -280,10 +280,10 @@
var topIncomeUrl = '{{ route('report-data.tag.top-income', [accountIds, tagIds, start.format('Ymd'), end.format('Ymd')]) }}';
</script>
<script type="text/javascript" src="v1/js/ff/reports/tag/month.js?v={{ FF_VERSION }}" nonce="{{ JS_NONCE }}"></script>
<script type="text/javascript" src="v1/js/ff/reports/tag/month.js?v={{ FF_BUILD_TIME }}" nonce="{{ JS_NONCE }}"></script>
{% endblock %}
{% block styles %}
<link rel="stylesheet" href="v1/css/bootstrap-sortable.css?v={{ FF_VERSION }}" type="text/css" media="all" nonce="{{ JS_NONCE }}">
<link rel="stylesheet" href="v1/css/bootstrap-sortable.css?v={{ FF_BUILD_TIME }}" type="text/css" media="all" nonce="{{ JS_NONCE }}">
{% endblock %}

View File

@@ -212,6 +212,6 @@
var moveRuleGroupUrl = '{{ route('rule-groups.move') }}';
var duplicateRuleUrl = '{{ route('rules.duplicate') }}';
</script>
<script type="text/javascript" src="v1/js/lib/jquery-ui.min.js?v={{ FF_VERSION }}" nonce="{{ JS_NONCE }}"></script>
<script type="text/javascript" src="v1/js/ff/rules/index.js?v={{ FF_VERSION }}" nonce="{{ JS_NONCE }}"></script>
<script type="text/javascript" src="v1/js/lib/jquery-ui.min.js?v={{ FF_BUILD_TIME }}" nonce="{{ JS_NONCE }}"></script>
<script type="text/javascript" src="v1/js/ff/rules/index.js?v={{ FF_BUILD_TIME }}" nonce="{{ JS_NONCE }}"></script>
{% endblock %}

Some files were not shown because too many files have changed in this diff Show More