diff --git a/app/Http/Controllers/Chart/ExpenseReportController.php b/app/Http/Controllers/Chart/ExpenseReportController.php
new file mode 100644
index 0000000000..acc7485d1c
--- /dev/null
+++ b/app/Http/Controllers/Chart/ExpenseReportController.php
@@ -0,0 +1,269 @@
+.
+ */
+declare(strict_types=1);
+
+namespace FireflyIII\Http\Controllers\Chart;
+
+use Carbon\Carbon;
+use FireflyIII\Generator\Chart\Basic\GeneratorInterface;
+use FireflyIII\Helpers\Collector\JournalCollectorInterface;
+use FireflyIII\Http\Controllers\Controller;
+use FireflyIII\Models\Account;
+use FireflyIII\Models\AccountType;
+use FireflyIII\Models\Transaction;
+use FireflyIII\Models\TransactionType;
+use FireflyIII\Repositories\Account\AccountRepositoryInterface;
+use FireflyIII\Support\CacheProperties;
+use Illuminate\Support\Collection;
+use Navigation;
+use Response;
+
+/**
+ * Separate controller because many helper functions are shared.
+ *
+ * Class ExpenseReportController
+ */
+class ExpenseReportController extends Controller
+{
+    /** @var AccountRepositoryInterface */
+    protected $accountRepository;
+    /** @var GeneratorInterface */
+    protected $generator;
+
+    /**
+     *
+     */
+    public function __construct()
+    {
+        parent::__construct();
+        $this->middleware(
+            function ($request, $next) {
+                $this->generator         = app(GeneratorInterface::class);
+                $this->accountRepository = app(AccountRepositoryInterface::class);
+
+                return $next($request);
+            }
+        );
+    }
+
+
+    /**
+     * @param Collection $accounts
+     * @param Collection $expense
+     * @param Carbon     $start
+     * @param Carbon     $end
+     *
+     * @return \Illuminate\Http\JsonResponse
+     */
+    public function mainChart(Collection $accounts, Collection $expense, Carbon $start, Carbon $end)
+    {
+
+        $cache = new CacheProperties;
+        $cache->addProperty('chart.expense.report.main');
+        $cache->addProperty($accounts);
+        $cache->addProperty($expense);
+        $cache->addProperty($start);
+        $cache->addProperty($end);
+        if ($cache->has()) {
+            // return Response::json($cache->get()); // @codeCoverageIgnore
+        }
+
+        $format       = Navigation::preferredCarbonLocalizedFormat($start, $end);
+        $function     = Navigation::preferredEndOfPeriod($start, $end);
+        $chartData    = [];
+        $currentStart = clone $start;
+        $combined     = $this->combineAccounts($expense);
+
+        // make "all" set:
+        $all = new Collection;
+        foreach ($combined as $name => $combi) {
+            $all = $all->merge($combi);
+        }
+
+        // prep chart data:
+        foreach ($combined as $name => $combi) {
+            // first is always expense account:
+            /** @var Account $exp */
+            $exp                          = $combi->first();
+            $chartData[$exp->id . '-in']  = [
+                'label'   => $name . ' (' . strtolower(strval(trans('firefly.income'))) . ')',
+                'type'    => 'bar',
+                'yAxisID' => 'y-axis-0',
+                'entries' => [],
+            ];
+            $chartData[$exp->id . '-out'] = [
+                'label'   => $name . ' (' . strtolower(strval(trans('firefly.expenses'))) . ')',
+                'type'    => 'bar',
+                'yAxisID' => 'y-axis-0',
+                'entries' => [],
+            ];
+            // total in, total out:
+            $chartData[$exp->id . '-total-in']  = [
+                'label'   => $name . ' (' . strtolower(strval(trans('firefly.sum_of_income'))) . ')',
+                'type'    => 'line',
+                'fill'    => false,
+                'yAxisID' => 'y-axis-1',
+                'entries' => [],
+            ];
+            $chartData[$exp->id . '-total-out'] = [
+                'label'   => $name . ' (' . strtolower(strval(trans('firefly.sum_of_expenses'))) . ')',
+                'type'    => 'line',
+                'fill'    => false,
+                'yAxisID' => 'y-axis-1',
+                'entries' => [],
+            ];
+        }
+
+        $sumOfIncome  = [];
+        $sumOfExpense = [];
+
+        while ($currentStart < $end) {
+            $currentEnd = clone $currentStart;
+            $currentEnd = $currentEnd->$function();
+
+            // get expenses grouped by opposing name:
+            $expenses = $this->groupByName($this->getExpenses($accounts, $all, $currentStart, $currentEnd));
+            $income   = $this->groupByName($this->getIncome($accounts, $all, $currentStart, $currentEnd));
+            $label    = $currentStart->formatLocalized($format);
+
+            foreach ($combined as $name => $combi) {
+                // first is always expense account:
+                /** @var Account $exp */
+                $exp            = $combi->first();
+                $labelIn        = $exp->id . '-in';
+                $labelOut       = $exp->id . '-out';
+                $labelSumIn     = $exp->id . '-total-in';
+                $labelSumOut    = $exp->id . '-total-out';
+                $currentIncome  = $income[$name] ?? '0';
+                $currentExpense = $expenses[$name] ?? '0';
+
+                // add to sum:
+                $sumOfIncome[$exp->id]  = $sumOfIncome[$exp->id] ?? '0';
+                $sumOfExpense[$exp->id] = $sumOfExpense[$exp->id] ?? '0';
+                $sumOfIncome[$exp->id]  = bcadd($sumOfIncome[$exp->id], $currentIncome);
+                $sumOfExpense[$exp->id] = bcadd($sumOfExpense[$exp->id], $currentExpense);
+
+                // add to chart:
+                $chartData[$labelIn]['entries'][$label]     = $currentIncome;
+                $chartData[$labelOut]['entries'][$label]    = $currentExpense;
+                $chartData[$labelSumIn]['entries'][$label]  = $sumOfIncome[$exp->id];
+                $chartData[$labelSumOut]['entries'][$label] = $sumOfExpense[$exp->id];
+            }
+            $currentStart = clone $currentEnd;
+            $currentStart->addDay();
+        }
+        // remove all empty entries to prevent cluttering:
+        $newSet = [];
+        foreach ($chartData as $key => $entry) {
+            if (0 === !array_sum($entry['entries'])) {
+                $newSet[$key] = $chartData[$key];
+            }
+        }
+        if (0 === count($newSet)) {
+            $newSet = $chartData; // @codeCoverageIgnore
+        }
+        $data = $this->generator->multiSet($newSet);
+        $cache->store($data);
+
+        return Response::json($data);
+    }
+
+    /**
+     * @param Collection $accounts
+     *
+     * @return array
+     */
+    protected function combineAccounts(Collection $accounts): array
+    {
+        $combined = [];
+        /** @var Account $expenseAccount */
+        foreach ($accounts as $expenseAccount) {
+            $collection = new Collection;
+            $collection->push($expenseAccount);
+
+            $revenue = $this->accountRepository->findByName($expenseAccount->name, [AccountType::REVENUE]);
+            if (!is_null($revenue->id)) {
+                $collection->push($revenue);
+            }
+            $combined[$expenseAccount->name] = $collection;
+        }
+
+        return $combined;
+    }
+
+    /**
+     * @param Collection $accounts
+     * @param Collection $opposing
+     * @param Carbon     $start
+     * @param Carbon     $end
+     *
+     * @return Collection
+     */
+    private function getExpenses(Collection $accounts, Collection $opposing, Carbon $start, Carbon $end): Collection
+    {
+        /** @var JournalCollectorInterface $collector */
+        $collector = app(JournalCollectorInterface::class);
+        $collector->setAccounts($accounts)->setRange($start, $end)->setTypes([TransactionType::WITHDRAWAL])->setOpposingAccounts($opposing);
+
+        $transactions = $collector->getJournals();
+
+        return $transactions;
+    }
+
+    /**
+     * @param Collection $accounts
+     * @param Collection $opposing
+     * @param Carbon     $start
+     * @param Carbon     $end
+     *
+     * @return Collection
+     */
+    private function getIncome(Collection $accounts, Collection $opposing, Carbon $start, Carbon $end): Collection
+    {
+        /** @var JournalCollectorInterface $collector */
+        /** @var JournalCollectorInterface $collector */
+        $collector = app(JournalCollectorInterface::class);
+        $collector->setAccounts($accounts)->setRange($start, $end)->setTypes([TransactionType::DEPOSIT])->setOpposingAccounts($opposing);
+
+        $transactions = $collector->getJournals();
+
+        return $transactions;
+    }
+
+    /**
+     * @param Collection $set
+     *
+     * @return array
+     */
+    private function groupByName(Collection $set): array
+    {
+        // group by opposing account name.
+        $grouped = [];
+        /** @var Transaction $transaction */
+        foreach ($set as $transaction) {
+            $name           = $transaction->opposing_account_name;
+            $grouped[$name] = $grouped[$name] ?? '0';
+            $grouped[$name] = bcadd($transaction->transaction_amount, $grouped[$name]);
+        }
+
+        return $grouped;
+    }
+}
diff --git a/app/Http/Controllers/Report/ExpenseController.php b/app/Http/Controllers/Report/ExpenseController.php
index b23fbf8cf8..26566c82ac 100644
--- a/app/Http/Controllers/Report/ExpenseController.php
+++ b/app/Http/Controllers/Report/ExpenseController.php
@@ -28,6 +28,7 @@ use FireflyIII\Helpers\Collector\JournalCollectorInterface;
 use FireflyIII\Http\Controllers\Controller;
 use FireflyIII\Models\Account;
 use FireflyIII\Models\AccountType;
+use FireflyIII\Models\Transaction;
 use FireflyIII\Models\TransactionType;
 use FireflyIII\Repositories\Account\AccountRepositoryInterface;
 use FireflyIII\Support\CacheProperties;
@@ -88,13 +89,13 @@ class ExpenseController extends Controller
             $all = $all->merge($combi);
         }
         // now find spent / earned:
-        $spent  = $this->spentByBudget($accounts, $all, $start, $end);
+        $spent = $this->spentByBudget($accounts, $all, $start, $end);
         // join arrays somehow:
         $together = [];
         foreach ($spent as $categoryId => $spentInfo) {
             if (!isset($together[$categoryId])) {
                 $together[$categoryId]['spent']       = $spentInfo;
-                $together[$categoryId]['budget']    = $spentInfo['name'];
+                $together[$categoryId]['budget']      = $spentInfo['name'];
                 $together[$categoryId]['grand_total'] = '0';
             }
             $together[$categoryId]['grand_total'] = bcadd($spentInfo['grand_total'], $together[$categoryId]['grand_total']);
@@ -150,7 +151,7 @@ class ExpenseController extends Controller
         unset($spentInfo);
         foreach ($earned as $categoryId => $earnedInfo) {
             if (!isset($together[$categoryId])) {
-                $together[$categoryId]['earned']       = $earnedInfo;
+                $together[$categoryId]['earned']      = $earnedInfo;
                 $together[$categoryId]['category']    = $earnedInfo['name'];
                 $together[$categoryId]['grand_total'] = '0';
             }
@@ -210,6 +211,76 @@ class ExpenseController extends Controller
 
     }
 
+    public function topExpense(Collection $accounts, Collection $expense, Carbon $start, Carbon $end)
+    {
+        // Properties for cache:
+        $cache = new CacheProperties;
+        $cache->addProperty($start);
+        $cache->addProperty($end);
+        $cache->addProperty('expense-budget');
+        $cache->addProperty($accounts->pluck('id')->toArray());
+        $cache->addProperty($expense->pluck('id')->toArray());
+        if ($cache->has()) {
+            //return $cache->get(); // @codeCoverageIgnore
+        }
+        $combined = $this->combineAccounts($expense);
+        $all      = new Collection;
+        foreach ($combined as $name => $combi) {
+            $all = $all->merge($combi);
+        }
+        // get all expenses in period:
+        /** @var JournalCollectorInterface $collector */
+        $collector = app(JournalCollectorInterface::class);
+        $collector->setRange($start, $end)->setTypes([TransactionType::WITHDRAWAL])->setAccounts($accounts);
+        $collector->setOpposingAccounts($all);
+        $set    = $collector->getJournals();
+        $sorted = $set->sortBy(
+            function (Transaction $transaction) {
+                return floatval($transaction->transaction_amount);
+            }
+        );
+        $result = view('reports.partials.top-transactions', compact('sorted'))->render();
+        $cache->store($result);
+
+        return $result;
+    }
+
+
+
+    public function topIncome(Collection $accounts, Collection $expense, Carbon $start, Carbon $end)
+    {
+        // Properties for cache:
+        $cache = new CacheProperties;
+        $cache->addProperty($start);
+        $cache->addProperty($end);
+        $cache->addProperty('expense-budget');
+        $cache->addProperty($accounts->pluck('id')->toArray());
+        $cache->addProperty($expense->pluck('id')->toArray());
+        if ($cache->has()) {
+            return $cache->get(); // @codeCoverageIgnore
+        }
+        $combined = $this->combineAccounts($expense);
+        $all      = new Collection;
+        foreach ($combined as $name => $combi) {
+            $all = $all->merge($combi);
+        }
+        // get all expenses in period:
+        /** @var JournalCollectorInterface $collector */
+        $collector = app(JournalCollectorInterface::class);
+        $collector->setRange($start, $end)->setTypes([TransactionType::DEPOSIT])->setAccounts($accounts);
+        $collector->setOpposingAccounts($all);
+        $set    = $collector->getJournals();
+        $sorted = $set->sortByDesc(
+            function (Transaction $transaction) {
+                return floatval($transaction->transaction_amount);
+            }
+        );
+        $result = view('reports.partials.top-transactions', compact('sorted'))->render();
+        $cache->store($result);
+
+        return $result;
+    }
+
     /**
      * @param Collection $accounts
      *
@@ -348,7 +419,7 @@ class ExpenseController extends Controller
         $sum = [];
         // loop to support multi currency
         foreach ($set as $transaction) {
-            $currencyId   = $transaction->transaction_currency_id;
+            $currencyId = $transaction->transaction_currency_id;
             $budgetName = $transaction->transaction_budget_name;
             $budgetId   = intval($transaction->transaction_budget_id);
             // if null, grab from journal:
@@ -369,7 +440,7 @@ class ExpenseController extends Controller
                     'per_currency' => [
                         $currencyId => [
                             'sum'      => '0',
-                            'budget' => [
+                            'budget'   => [
                                 'id'   => $budgetId,
                                 'name' => $budgetName,
                             ],
diff --git a/config/firefly.php b/config/firefly.php
index 0ecf8112a6..05c58b89d6 100644
--- a/config/firefly.php
+++ b/config/firefly.php
@@ -54,7 +54,7 @@ return [
     'import_pre'           => [
         'bunq'    => 'FireflyIII\Support\Import\Prerequisites\BunqPrerequisites',
         'spectre' => 'FireflyIII\Support\Import\Prerequisites\SpectrePrerequisites',
-        'plaid'   => 'FireflyIII\Support\Import\Prerequisites\PlairPrerequisites',
+        'plaid'   => 'FireflyIII\Support\Import\Prerequisites\PlaidPrerequisites',
     ],
     'import_info'          => [
         'bunq'    => 'FireflyIII\Support\Import\Information\BunqInformation',
diff --git a/public/js/ff/reports/account/all.js b/public/js/ff/reports/account/all.js
deleted file mode 100644
index 539b599256..0000000000
--- a/public/js/ff/reports/account/all.js
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * all.js
- * Copyright (c) 2017 thegrumpydictator@gmail.com
- *
- * This file is part of Firefly III.
- *
- * Firefly III is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * Firefly III 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 General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Firefly III.  If not, see .
- */
-
-function loadAjaxPartial(holder, uri) {
-    "use strict";
-    $.get(uri).done(function (data) {
-        displayAjaxPartial(data, holder);
-    }).fail(function () {
-        failAjaxPartial(uri, holder);
-    });
-}
-
-function failAjaxPartial(uri, holder) {
-    "use strict";
-    var holderObject = $('#' + holder);
-    holderObject.parent().find('.overlay').remove();
-    holderObject.addClass('general-chart-error');
-
-}
-
-function displayAjaxPartial(data, holder) {
-    "use strict";
-    var obj = $('#' + holder);
-    obj.html(data);
-    obj.parent().find('.overlay').remove();
-
-    // call some often needed recalculations and what-not:
-
-    // find a sortable table and make it sortable:
-    if (typeof $.bootstrapSortable === "function") {
-        $.bootstrapSortable(true);
-    }
-
-    // find the info click things and respond to them:
-    triggerInfoClick();
-
-    // trigger list thing
-    listLengthInitial();
-
-}
\ No newline at end of file
diff --git a/public/js/ff/reports/account/month.js b/public/js/ff/reports/account/month.js
index 099cf9a906..a3068ce4ab 100644
--- a/public/js/ff/reports/account/month.js
+++ b/public/js/ff/reports/account/month.js
@@ -36,5 +36,6 @@ function drawChart() {
 
     // month view:
     // draw account chart
-    lineChart(mainUri, 'in-out-chart');
+    // month view:
+    doubleYChart(mainUri, 'in-out-chart');
 }
\ No newline at end of file
diff --git a/public/js/ff/reports/all.js b/public/js/ff/reports/all.js
new file mode 100644
index 0000000000..493a82fe4d
--- /dev/null
+++ b/public/js/ff/reports/all.js
@@ -0,0 +1,136 @@
+function loadAjaxPartial(holder, uri) {
+    "use strict";
+    $.get(uri).done(function (data) {
+        displayAjaxPartial(data, holder);
+    }).fail(function () {
+        failAjaxPartial(uri, holder);
+    });
+}
+
+function failAjaxPartial(uri, holder) {
+    "use strict";
+    var holderObject = $('#' + holder);
+    holderObject.parent().find('.overlay').remove();
+    holderObject.addClass('general-chart-error');
+
+}
+
+
+function createCookie(name, value, days) {
+    "use strict";
+    var expires;
+
+    if (days) {
+        var date = new Date();
+        date.setTime(date.getTime() + (days * 24 * 60 * 60 * 1000));
+        expires = "; expires=" + date.toGMTString();
+    } else {
+        expires = "";
+    }
+    document.cookie = encodeURIComponent(name) + "=" + encodeURIComponent(value) + expires + "; path=/";
+}
+
+function readCookie(name) {
+    "use strict";
+    var nameEQ = encodeURIComponent(name) + "=";
+    var ca = document.cookie.split(';');
+    for (var i = 0; i < ca.length; i++) {
+        var c = ca[i];
+        while (c.charAt(0) === ' ') {
+            c = c.substring(1, c.length);
+        }
+        if (c.indexOf(nameEQ) === 0) {
+            return decodeURIComponent(c.substring(nameEQ.length, c.length));
+        }
+    }
+    return null;
+}
+
+
+function triggerInfoClick() {
+    "use strict";
+    // find the little info buttons and respond to them.
+    $('.firefly-info-button').unbind('click').click(clickInfoButton);
+}
+
+function clickInfoButton(e) {
+    "use strict";
+    // find all data tags, regardless of what they are:
+    var element = $(e.target);
+    var attributes = element.data();
+
+    // set wait cursor
+    $('body').addClass('waiting');
+
+    // add some more elements:
+    attributes.startDate = startDate;
+    attributes.endDate = endDate;
+    attributes.accounts = accountIds;
+
+    $.getJSON('popup/general', {attributes: attributes}).done(respondInfoButton).fail(errorInfoButton);
+}
+
+function errorInfoButton() {
+    "use strict";
+    // remove wait cursor
+    $('body').removeClass('waiting');
+    alert('Apologies. The requested data is not (yet) available.');
+}
+
+function respondInfoButton(data) {
+    "use strict";
+    // remove wait cursor
+    $('body').removeClass('waiting');
+    $('#defaultModal').empty().html(data.html).modal('show');
+
+}
+
+function displayAjaxPartial(data, holder) {
+    "use strict";
+    var obj = $('#' + holder);
+    obj.html(data);
+    obj.parent().find('.overlay').remove();
+
+    // call some often needed recalculations and what-not:
+
+    // find a sortable table and make it sortable:
+    if (typeof $.bootstrapSortable === "function") {
+        $.bootstrapSortable(true);
+    }
+
+    // find the info click things and respond to them:
+    triggerInfoClick();
+
+    // trigger list thing
+    listLengthInitial();
+
+    // budget thing in year and multi year report:
+    $('.budget-chart-activate').unbind('click').on('click', clickBudgetChart);
+
+    // category thing in year and multi year report:
+    $('.category-chart-activate').unbind('click').on('click', clickCategoryChart);
+}
+
+function clickCategoryChart(e) {
+    "use strict";
+    var link = $(e.target);
+    var categoryId = link.data('category');
+    $('#category_help').remove();
+
+    var URL = 'chart/category/report-period/' + categoryId + '/' + accountIds + '/' + startDate + '/' + endDate;
+    var container = 'category_chart';
+    columnChart(URL, container);
+    return false;
+}
+
+function clickBudgetChart(e) {
+    "use strict";
+    var link = $(e.target);
+    var budgetId = link.data('budget');
+    $('#budget_help').remove();
+
+    var URL = 'chart/budget/period/' + budgetId + '/' + accountIds + '/' + startDate + '/' + endDate;
+    var container = 'budget_chart';
+    columnChart(URL, container);
+    return false;
+}
\ No newline at end of file
diff --git a/public/js/ff/reports/audit/all.js b/public/js/ff/reports/audit/all.js
index 52f5dc9320..cfc4913105 100644
--- a/public/js/ff/reports/audit/all.js
+++ b/public/js/ff/reports/audit/all.js
@@ -86,35 +86,3 @@ function showOnlyColumns(checkboxes) {
         }
     }
 }
-
-
-function createCookie(name, value, days) {
-    "use strict";
-    var expires;
-
-    if (days) {
-        var date = new Date();
-        date.setTime(date.getTime() + (days * 24 * 60 * 60 * 1000));
-        expires = "; expires=" + date.toGMTString();
-    } else {
-        expires = "";
-    }
-    document.cookie = encodeURIComponent(name) + "=" + encodeURIComponent(value) + expires + "; path=/";
-}
-
-function readCookie(name) {
-    "use strict";
-    var nameEQ = encodeURIComponent(name) + "=";
-    var ca = document.cookie.split(';');
-    for (var i = 0; i < ca.length; i++) {
-        var c = ca[i];
-        while (c.charAt(0) === ' ') {
-            c = c.substring(1, c.length);
-        }
-        if (c.indexOf(nameEQ) === 0) {
-            return decodeURIComponent(c.substring(nameEQ.length, c.length));
-        }
-    }
-    return null;
-}
-
diff --git a/public/js/ff/reports/budget/all.js b/public/js/ff/reports/budget/all.js
deleted file mode 100644
index 5a99dc19ab..0000000000
--- a/public/js/ff/reports/budget/all.js
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- * all.js
- * Copyright (c) 2017 thegrumpydictator@gmail.com
- *
- * This file is part of Firefly III.
- *
- * Firefly III is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * Firefly III 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 General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Firefly III.  If not, see .
- */
-
diff --git a/public/js/ff/reports/category/all.js b/public/js/ff/reports/category/all.js
deleted file mode 100644
index 5a99dc19ab..0000000000
--- a/public/js/ff/reports/category/all.js
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- * all.js
- * Copyright (c) 2017 thegrumpydictator@gmail.com
- *
- * This file is part of Firefly III.
- *
- * Firefly III is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * Firefly III 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 General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Firefly III.  If not, see .
- */
-
diff --git a/public/js/ff/reports/default/all.js b/public/js/ff/reports/default/all.js
index dd49e9ec04..fab470e48e 100644
--- a/public/js/ff/reports/default/all.js
+++ b/public/js/ff/reports/default/all.js
@@ -33,108 +33,3 @@ $(function () {
     loadAjaxPartial('incomeVsExpenseReport', incExpReportUri);
 
 });
-
-function triggerInfoClick() {
-    "use strict";
-    // find the little info buttons and respond to them.
-    $('.firefly-info-button').unbind('click').click(clickInfoButton);
-}
-
-function clickInfoButton(e) {
-    "use strict";
-    // find all data tags, regardless of what they are:
-    var element = $(e.target);
-    var attributes = element.data();
-
-    // set wait cursor
-    $('body').addClass('waiting');
-
-    // add some more elements:
-    attributes.startDate = startDate;
-    attributes.endDate = endDate;
-    attributes.accounts = accountIds;
-
-    $.getJSON('popup/general', {attributes: attributes}).done(respondInfoButton).fail(errorInfoButton);
-}
-
-function errorInfoButton() {
-    "use strict";
-    // remove wait cursor
-    $('body').removeClass('waiting');
-    alert('Apologies. The requested data is not (yet) available.');
-}
-
-function respondInfoButton(data) {
-    "use strict";
-    // remove wait cursor
-    $('body').removeClass('waiting');
-    $('#defaultModal').empty().html(data.html).modal('show');
-
-}
-
-function loadAjaxPartial(holder, uri) {
-    "use strict";
-    $.get(uri).done(function (data) {
-        displayAjaxPartial(data, holder);
-    }).fail(function () {
-        failAjaxPartial(uri, holder);
-    });
-}
-
-function displayAjaxPartial(data, holder) {
-    "use strict";
-    var obj = $('#' + holder);
-    obj.html(data);
-    obj.parent().find('.overlay').remove();
-
-    // call some often needed recalculations and what-not:
-
-    // find a sortable table and make it sortable:
-    if (typeof $.bootstrapSortable === "function") {
-        $.bootstrapSortable(true);
-    }
-
-    // find the info click things and respond to them:
-    triggerInfoClick();
-
-    // trigger list thing
-    listLengthInitial();
-
-    // budget thing in year and multi year report:
-    $('.budget-chart-activate').unbind('click').on('click', clickBudgetChart);
-
-    // category thing in year and multi year report:
-    $('.category-chart-activate').unbind('click').on('click', clickCategoryChart);
-}
-
-function failAjaxPartial(uri, holder) {
-    "use strict";
-    var holderObject = $('#' + holder);
-    holderObject.parent().find('.overlay').remove();
-    holderObject.addClass('general-chart-error');
-
-}
-
-function clickCategoryChart(e) {
-    "use strict";
-    var link = $(e.target);
-    var categoryId = link.data('category');
-    $('#category_help').remove();
-
-    var URL = 'chart/category/report-period/' + categoryId + '/' + accountIds + '/' + startDate + '/' + endDate;
-    var container = 'category_chart';
-    columnChart(URL, container);
-    return false;
-}
-
-function clickBudgetChart(e) {
-    "use strict";
-    var link = $(e.target);
-    var budgetId = link.data('budget');
-    $('#budget_help').remove();
-
-    var URL = 'chart/budget/period/' + budgetId + '/' + accountIds + '/' + startDate + '/' + endDate;
-    var container = 'budget_chart';
-    columnChart(URL, container);
-    return false;
-}
\ No newline at end of file
diff --git a/public/js/ff/reports/index.js b/public/js/ff/reports/index.js
index d15de74232..ff041cbef9 100644
--- a/public/js/ff/reports/index.js
+++ b/public/js/ff/reports/index.js
@@ -179,33 +179,3 @@ function preSelectDate(e) {
 }
 
 
-function createCookie(name, value, days) {
-    "use strict";
-    var expires;
-
-    if (days) {
-        var date = new Date();
-        date.setTime(date.getTime() + (days * 24 * 60 * 60 * 1000));
-        expires = "; expires=" + date.toGMTString();
-    } else {
-        expires = "";
-    }
-    document.cookie = encodeURIComponent(name) + "=" + encodeURIComponent(value) + expires + "; path=/";
-}
-
-function readCookie(name) {
-    "use strict";
-    var nameEQ = encodeURIComponent(name) + "=";
-    var ca = document.cookie.split(';');
-    for (var i = 0; i < ca.length; i++) {
-        var c = ca[i];
-        while (c.charAt(0) === ' ') {
-            c = c.substring(1, c.length);
-        }
-        if (c.indexOf(nameEQ) === 0) {
-            return decodeURIComponent(c.substring(nameEQ.length, c.length));
-        }
-    }
-    return null;
-}
-
diff --git a/public/js/ff/reports/tag/all.js b/public/js/ff/reports/tag/all.js
deleted file mode 100644
index 5a99dc19ab..0000000000
--- a/public/js/ff/reports/tag/all.js
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- * all.js
- * Copyright (c) 2017 thegrumpydictator@gmail.com
- *
- * This file is part of Firefly III.
- *
- * Firefly III is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * Firefly III 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 General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Firefly III.  If not, see .
- */
-
diff --git a/resources/views/reports/account/report.twig b/resources/views/reports/account/report.twig
index 4dbaf2b5f1..b03f054604 100644
--- a/resources/views/reports/account/report.twig
+++ b/resources/views/reports/account/report.twig
@@ -127,7 +127,7 @@
     
 
 
-    
+    
     
 
 {% endblock %}
diff --git a/resources/views/reports/audit/report.twig b/resources/views/reports/audit/report.twig
index 5716f4dc08..740b28913a 100644
--- a/resources/views/reports/audit/report.twig
+++ b/resources/views/reports/audit/report.twig
@@ -86,5 +86,6 @@
     
+    
     
 {% endblock %}
diff --git a/resources/views/reports/budget/month.twig b/resources/views/reports/budget/month.twig
index e79e09b4af..a52cd09552 100644
--- a/resources/views/reports/budget/month.twig
+++ b/resources/views/reports/budget/month.twig
@@ -260,7 +260,7 @@
     
 
 
-    
+    
     
 
 {% endblock %}
diff --git a/resources/views/reports/category/month.twig b/resources/views/reports/category/month.twig
index bb4506523e..55ba6f5f3d 100644
--- a/resources/views/reports/category/month.twig
+++ b/resources/views/reports/category/month.twig
@@ -397,7 +397,7 @@
     
 
 
-    
+    
     
 
 {% endblock %}
diff --git a/resources/views/reports/default/month.twig b/resources/views/reports/default/month.twig
index b6b0aa5b50..9b0bddad9e 100644
--- a/resources/views/reports/default/month.twig
+++ b/resources/views/reports/default/month.twig
@@ -171,6 +171,7 @@
         var accountChartUri = '{{ route('chart.account.report', [accountIds, start.format('Ymd'), end.format('Ymd')]) }}';
 
     
+    
     
     
 {% endblock %}
diff --git a/resources/views/reports/default/multi-year.twig b/resources/views/reports/default/multi-year.twig
index 6b94ad6ebe..96acae16a0 100644
--- a/resources/views/reports/default/multi-year.twig
+++ b/resources/views/reports/default/multi-year.twig
@@ -222,6 +222,7 @@
         var categoryIncomeUri = '{{ route('report-data.category.income', [accountIds, start.format('Ymd'), end.format('Ymd')]) }}';
 
     
+    
     
     
 {% endblock %}
diff --git a/resources/views/reports/default/year.twig b/resources/views/reports/default/year.twig
index 802152bdc2..821fb90e8c 100644
--- a/resources/views/reports/default/year.twig
+++ b/resources/views/reports/default/year.twig
@@ -217,7 +217,7 @@
 
 
     
-
+    
     
     
 
diff --git a/resources/views/reports/index.twig b/resources/views/reports/index.twig
index fd1bcd0b0c..aa2b563864 100644
--- a/resources/views/reports/index.twig
+++ b/resources/views/reports/index.twig
@@ -179,5 +179,6 @@
         var filterPlaceholder = "{{ trans('firefly.multi_select_filter_placeholder')|escape('js') }}";
     
     
+    
     
 {% endblock %}
diff --git a/resources/views/reports/partials/exp-budgets.twig b/resources/views/reports/partials/exp-budgets.twig
index de59cc258e..992570d1dc 100644
--- a/resources/views/reports/partials/exp-budgets.twig
+++ b/resources/views/reports/partials/exp-budgets.twig
@@ -1,8 +1,8 @@
 
     
     
-        | {{ 'category'|_ }}- | {{ 'spent'|_ }}+ | {{ 'category'|_ }}+ | {{ 'spent'|_ }} | 
     
     
diff --git a/resources/views/reports/partials/exp-categories.twig b/resources/views/reports/partials/exp-categories.twig
index aff8d62089..e700cf4268 100644
--- a/resources/views/reports/partials/exp-categories.twig
+++ b/resources/views/reports/partials/exp-categories.twig
@@ -1,9 +1,9 @@
 
     
     
-        | {{ 'category'|_ }}- | {{ 'spent'|_ }}- | {{ 'earned'|_ }}+ | {{ 'category'|_ }}+ | {{ 'spent'|_ }}+ | {{ 'earned'|_ }} | 
     
     
diff --git a/resources/views/reports/partials/exp-not-grouped.twig b/resources/views/reports/partials/exp-not-grouped.twig
index bc454b7d44..85a5a667c8 100644
--- a/resources/views/reports/partials/exp-not-grouped.twig
+++ b/resources/views/reports/partials/exp-not-grouped.twig
@@ -3,8 +3,8 @@
     
     
         | {{ 'name'|_ }}- | {{ 'spent'|_ }}- | {{ 'earned'|_ }}+ | {{ 'spent'|_ }}+ | {{ 'earned'|_ }} | 
     
     
diff --git a/resources/views/reports/partials/top-transactions.twig b/resources/views/reports/partials/top-transactions.twig
new file mode 100644
index 0000000000..e068286fd1
--- /dev/null
+++ b/resources/views/reports/partials/top-transactions.twig
@@ -0,0 +1,24 @@
+
+    
+    
+        | {{ 'account'|_ }}+ | {{ 'description'|_ }}+ | {{ 'date'|_ }}+ | {{ 'amount'|_ }}+ | 
+    
+    
+    {% for transaction in sorted %}
+        
+            | +                {{ transaction.opposing_account_name }}
++ | {{ transaction.description }}+ | +                {{ transaction.date.formatLocalized(monthAndDayFormat) }}
++ | {{ transaction|transactionAmount }}+ | 
+    {% endfor %}
+    
+
diff --git a/resources/views/reports/tag/month.twig b/resources/views/reports/tag/month.twig
index 54153b91ba..e4139f5dbb 100644
--- a/resources/views/reports/tag/month.twig
+++ b/resources/views/reports/tag/month.twig
@@ -422,8 +422,7 @@
         var mainUri = '{{ route('chart.tag.main', [accountIds, tagTags, start.format('Ymd'), end.format('Ymd')]) }}';
     
 
-
-    
+    
     
 
 {% endblock %}
diff --git a/routes/web.php b/routes/web.php
index 3e46cf739e..5cb2d597d6 100755
--- a/routes/web.php
+++ b/routes/web.php
@@ -623,8 +623,8 @@ Route::group(
     Route::get('budget/{accountList}/{expenseList}/{start_date}/{end_date}', ['uses' => 'ExpenseController@budget', 'as' => 'budget']);
 
     //expense earned top X
-    Route::get('expenses/{accountList}/{expenseList}/{start_date}/{end_date}', ['uses' => 'ExpenseController@topX', 'as' => 'expenses']);
-    Route::get('income/{accountList}/{expenseList}/{start_date}/{end_date}', ['uses' => 'ExpenseController@topXPeriod', 'as' => 'income']);
+    Route::get('expenses/{accountList}/{expenseList}/{start_date}/{end_date}', ['uses' => 'ExpenseController@topExpense', 'as' => 'expenses']);
+    Route::get('income/{accountList}/{expenseList}/{start_date}/{end_date}', ['uses' => 'ExpenseController@topIncome', 'as' => 'income']);
 
 }
 );