├── .gitattributes ├── tests ├── resources │ └── views │ │ └── dashboard.blade.php ├── ToolbarTest.php ├── BrowserTestCase.php ├── TestCase.php ├── ToolbarBrowserTest.php └── TelescopeFeatureTestCase.php ├── .gitignore ├── src ├── helpers.php ├── Http │ ├── assets.php │ ├── routes.php │ └── Controllers │ │ └── ToolbarController.php ├── ToolbarServiceProvider.php └── Toolbar.php ├── resources ├── icons │ ├── dumps.svg │ ├── session.svg │ ├── user.svg │ ├── refresh.svg │ ├── close.svg │ ├── search.svg │ ├── validator.svg │ ├── mail.svg │ ├── queries.svg │ ├── redirect.svg │ ├── models.svg │ ├── commands.svg │ ├── requests.svg │ ├── forward.svg │ ├── menu.svg │ ├── ajax.svg │ ├── cache.svg │ ├── schedule.svg │ ├── notifications.svg │ ├── views.svg │ ├── gates.svg │ ├── exceptions.svg │ ├── jobs.svg │ ├── events.svg │ ├── logs.svg │ ├── time.svg │ ├── http-client.svg │ ├── telescope.svg │ ├── memory.svg │ ├── config.svg │ ├── redis.svg │ ├── LICENSE.txt │ └── laravel.svg ├── views │ ├── collectors │ │ ├── redis.blade.php │ │ ├── commands.blade.php │ │ ├── events.blade.php │ │ ├── dumps.blade.php │ │ ├── time.blade.php │ │ ├── session.blade.php │ │ ├── memory.blade.php │ │ ├── user.blade.php │ │ ├── gates.blade.php │ │ ├── ajax.blade.php │ │ ├── config.blade.php │ │ ├── models.blade.php │ │ ├── jobs.blade.php │ │ ├── exceptions.blade.php │ │ ├── mail.blade.php │ │ ├── cache.blade.php │ │ ├── views.blade.php │ │ ├── notifications.blade.php │ │ ├── logs.blade.php │ │ ├── queries.blade.php │ │ └── request.blade.php │ ├── widget.blade.php │ ├── head.blade.php │ ├── item.blade.php │ ├── toolbar.blade.php │ └── base_js.blade.php └── css │ ├── custom.css │ ├── theme_light.css │ └── base.css ├── phpunit.xml.dist ├── license.md ├── composer.json ├── .github └── workflows │ └── run-tests.yml ├── readme.md └── config └── telescope-toolbar.php /.gitattributes: -------------------------------------------------------------------------------- 1 | *.blade.php linguist-language=PHP -------------------------------------------------------------------------------- /tests/resources/views/dashboard.blade.php: -------------------------------------------------------------------------------- 1 |
2 |

Basic view

3 |
4 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /vendor 2 | composer.phar 3 | composer.lock 4 | .DS_Store 5 | .phpunit.result.cache 6 | /tests/Browser 7 | /build -------------------------------------------------------------------------------- /src/helpers.php: -------------------------------------------------------------------------------- 1 | name('telescope-toolbar.baseJs'); 6 | Route::get('styling.css', 'ToolbarController@styling')->name('telescope-toolbar.styling'); -------------------------------------------------------------------------------- /src/Http/routes.php: -------------------------------------------------------------------------------- 1 | name('telescope-toolbar.render'); 6 | Route::get('show/{token}/{tab?}', 'ToolbarController@show')->name('telescope-toolbar.show'); -------------------------------------------------------------------------------- /resources/icons/dumps.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /resources/icons/session.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /resources/icons/user.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /resources/icons/refresh.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /resources/icons/close.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /resources/icons/search.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /resources/icons/validator.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /resources/icons/mail.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /resources/icons/queries.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /resources/icons/redirect.svg: -------------------------------------------------------------------------------- 1 | 2 | Redirect 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /resources/views/collectors/redis.blade.php: -------------------------------------------------------------------------------- 1 | 8 | @component('telescope-toolbar::item', ['name' => 'redis', 'link' => true]) 9 | 10 | @slot('icon') 11 | @ttIcon('redis') 12 | 13 | {{ $entries->count() }} 14 | 15 | @endslot 16 | 17 | 18 | @endcomponent -------------------------------------------------------------------------------- /resources/icons/models.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /resources/views/collectors/commands.blade.php: -------------------------------------------------------------------------------- 1 | 8 | @component('telescope-toolbar::item', ['name' => 'commands', 'link' => true]) 9 | 10 | @slot('icon') 11 | @ttIcon('commands') 12 | 13 | {{ $entries->count() }} 14 | 15 | @endslot 16 | 17 | 18 | @endcomponent -------------------------------------------------------------------------------- /resources/views/collectors/events.blade.php: -------------------------------------------------------------------------------- 1 | 8 | @component('telescope-toolbar::item', ['name' => 'events', 'link' => '#events']) 9 | 10 | @slot('icon') 11 | @ttIcon('events') 12 | 13 | {{ $entries->count() }} 14 | 15 | @endslot 16 | 17 | 18 | @endcomponent 19 | -------------------------------------------------------------------------------- /resources/views/widget.blade.php: -------------------------------------------------------------------------------- 1 | 2 |
3 | 4 | 9 | 10 | -------------------------------------------------------------------------------- /resources/icons/commands.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /resources/icons/requests.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /resources/icons/forward.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /resources/icons/menu.svg: -------------------------------------------------------------------------------- 1 | 2 | Menu 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /resources/icons/ajax.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /resources/icons/cache.svg: -------------------------------------------------------------------------------- 1 | 2 | Cache 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /resources/icons/schedule.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /resources/icons/notifications.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /resources/icons/views.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /resources/icons/gates.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /resources/icons/exceptions.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /resources/icons/jobs.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /resources/icons/events.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /resources/icons/logs.svg: -------------------------------------------------------------------------------- 1 | 2 | Logger 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /resources/icons/time.svg: -------------------------------------------------------------------------------- 1 | 2 | Time 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /resources/icons/http-client.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /resources/icons/telescope.svg: -------------------------------------------------------------------------------- 1 | 2 | telescope 3 | -------------------------------------------------------------------------------- /resources/icons/memory.svg: -------------------------------------------------------------------------------- 1 | 2 | Memory 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /resources/icons/config.svg: -------------------------------------------------------------------------------- 1 | 2 | Config 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /resources/views/collectors/dumps.blade.php: -------------------------------------------------------------------------------- 1 | 8 | @component('telescope-toolbar::item', ['name' => 'dump', 'link' => route('telescope') . '/dumps', 'status' => 'yellow']) 9 | 10 | @slot('icon') 11 | @ttIcon('dumps') 12 | 13 | {{ $entries->count() }} 14 | 15 | @endslot 16 | 17 | @slot("text") 18 | 19 | @foreach ($entries as $entry) 20 |
21 |
22 | {!! $entry->content['dump'] !!} 23 |
24 | 25 |
26 | 27 | @endforeach 28 | 29 | @endslot 30 | 31 | @endcomponent -------------------------------------------------------------------------------- /resources/views/head.blade.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | @if ($lightMode) 6 | 7 | @endif 8 | 9 | 16 | 17 | -------------------------------------------------------------------------------- /resources/views/item.blade.php: -------------------------------------------------------------------------------- 1 |
2 | @if(isset($link) && $link) 3 | @php 4 | $ttLink = route('telescope-toolbar.show', ['token' => $token, 'tab' => $name]); 5 | if ($link === true) { 6 | $link = $ttLink; 7 | } elseif (\Illuminate\Support\Str::startsWith($link, '#')) { 8 | $link = $ttLink . $link; 9 | } 10 | @endphp 11 | 12 | @endif 13 |
{{ $icon ?? '' }}
14 | @if(isset($link) && $link)
@endif 15 |
{{ $text ?? '' }}
16 |
17 | -------------------------------------------------------------------------------- /resources/views/collectors/time.blade.php: -------------------------------------------------------------------------------- 1 | first()->content; 4 | 5 | ?> 6 | 7 | @component('telescope-toolbar::item', ['name' => 'time', 'link' => true]) 8 | 9 | @slot('icon') 10 | 11 | @ttIcon('time') 12 | 13 | {{ $data['duration'] }} 14 | ms 15 | @endslot 16 | 17 | @slot('text') 18 | 19 |
20 | Request Duration 21 | {{ $data['duration'] }} ms 22 |
23 | 24 |
25 | Peak memory usage 26 | {{ $data['memory'] }} MB 27 |
28 | 29 | @endslot 30 | 31 | @endcomponent 32 | -------------------------------------------------------------------------------- /phpunit.xml.dist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | tests 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /resources/views/collectors/session.blade.php: -------------------------------------------------------------------------------- 1 | first()->content; 4 | 5 | $dumper = new \Symfony\Component\VarDumper\Dumper\HtmlDumper(); 6 | $varCloner = new \Symfony\Component\VarDumper\Cloner\VarCloner(); 7 | 8 | ?> 9 | 10 | @component('telescope-toolbar::item', ['name' => 'dump', 'link' => false]) 11 | 12 | @slot('icon') 13 | @ttIcon('session') 14 | Session 15 | @endslot 16 | 17 | @slot('text') 18 | 19 | @if(isset($data['session'])) 20 |
21 |
22 | 23 | {!! $dumper->dump($varCloner->cloneVar($data['session'])) !!} 24 | 25 |
26 |
27 | @endif 28 | 29 | 30 | @endslot 31 | 32 | @endcomponent 33 | -------------------------------------------------------------------------------- /resources/views/collectors/memory.blade.php: -------------------------------------------------------------------------------- 1 | first()->content; 4 | 5 | $memory = $data['memory'] ?? null; 6 | if (!$memory) { 7 | return; 8 | } 9 | 10 | $statusColor = null; 11 | if ($memory > 50) { 12 | $statusColor = 'yellow'; 13 | } elseif ($memory > 10) { 14 | $memory = round($memory); 15 | } 16 | ?> 17 | 18 | @component('telescope-toolbar::item', ['name' => 'memory', 'link' => true]) 19 | 20 | @slot('icon') 21 | 22 | @ttIcon('memory') 23 | 24 | {{ $memory }} 25 | MB 26 | @endslot 27 | 28 | @slot('text') 29 | 30 |
31 | Peak memory usage 32 | {{ $data['memory'] }} MB 33 |
34 | 35 | @endslot 36 | 37 | 38 | @endcomponent -------------------------------------------------------------------------------- /resources/views/collectors/user.blade.php: -------------------------------------------------------------------------------- 1 | first()->content['user'] ?? []; 4 | 5 | ?> 6 | 7 | @component('telescope-toolbar::item', ['name' => 'user', 'link' => true]) 8 | 9 | @slot('icon') 10 | 11 | @ttIcon('user') 12 | 13 | {{ $data['email'] ?? 'n/a' }} 14 | @endslot 15 | 16 | @slot('text') 17 | @if($data) 18 |
19 | @foreach ($data as $key => $value) 20 | @if (!empty($value)) 21 |
22 | {{ $key }} 23 | {{ $value }} 24 |
25 | @endif 26 | @endforeach 27 |
28 | @endif 29 | @endslot 30 | 31 | @endcomponent -------------------------------------------------------------------------------- /tests/ToolbarTest.php: -------------------------------------------------------------------------------- 1 | call('GET', 'web/plain'); 13 | 14 | $this->assertTrue(Str::contains($crawler->content(), 'Sfjs.loadToolbar')); 15 | $this->assertEquals(200, $crawler->getStatusCode()); 16 | } 17 | 18 | public function testItInjectsOnHtml() 19 | { 20 | $crawler = $this->call('GET', 'web/html'); 21 | 22 | $this->assertTrue(Str::contains($crawler->content(), 'Sfjs.loadToolbar')); 23 | $this->assertEquals(200, $crawler->getStatusCode()); 24 | } 25 | 26 | public function testItDoesntInjectOnJson() 27 | { 28 | $crawler = $this->call('GET', 'api/ping'); 29 | 30 | $this->assertFalse(Str::contains($crawler->content(), 'Sfjs.loadToolbar')); 31 | $this->assertEquals(200, $crawler->getStatusCode()); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /resources/icons/redis.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /license.md: -------------------------------------------------------------------------------- 1 | Copyright (C) 2019-present Fruitcake, Barry vd. Heuvel 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of 4 | this software and associated documentation files (the "Software"), to deal in 5 | the Software without restriction, including without limitation the rights to 6 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 7 | of the Software, and to permit persons to whom the Software is furnished to do 8 | so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in all 11 | copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | SOFTWARE. -------------------------------------------------------------------------------- /resources/views/collectors/gates.blade.php: -------------------------------------------------------------------------------- 1 | 8 | @component('telescope-toolbar::item', ['name' => 'gates', 'link' => true]) 9 | 10 | @slot('icon') 11 | @ttIcon('gates') 12 | 13 | {{ $entries->count() }} 14 | 15 | @endslot 16 | 17 | 18 | @slot('text') 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | @foreach ($entries as $entry) 29 | 30 | 33 | 36 | 37 | @endforeach 38 | 39 |
AbilityResult
31 | {{ \Illuminate\Support\Str::limit($entry->content['ability'], 60) }} 32 | 34 | {{ $entry->content['result'] }} 35 |
40 | 41 | @endslot 42 | 43 | @endcomponent -------------------------------------------------------------------------------- /resources/icons/LICENSE.txt: -------------------------------------------------------------------------------- 1 | Icons are from "Tabler Icons" (https://github.com/tabler/tabler-icons), a set of 2 | free MIT-licensed high-quality SVG icons. 3 | 4 | ----- 5 | 6 | MIT License 7 | 8 | Copyright (c) 2020-2022 Paweł Kuna 9 | 10 | Permission is hereby granted, free of charge, to any person obtaining a copy 11 | of this software and associated documentation files (the "Software"), to deal 12 | in the Software without restriction, including without limitation the rights 13 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 14 | copies of the Software, and to permit persons to whom the Software is 15 | furnished to do so, subject to the following conditions: 16 | 17 | The above copyright notice and this permission notice shall be included in all 18 | copies or substantial portions of the Software. 19 | 20 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 21 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 22 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 23 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 24 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 25 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 26 | SOFTWARE. 27 | -------------------------------------------------------------------------------- /resources/views/collectors/ajax.blade.php: -------------------------------------------------------------------------------- 1 | @component('telescope-toolbar::item', ['name' => 'ajax', 'additional_classes' => 'sf-toolbar-block-right']) 2 | 3 | @slot('icon') 4 | 5 | @ttIcon('ajax') 6 | 7 | 0 8 | 9 | @endslot 10 | 11 | @slot("text") 12 |
13 | 14 | 15 | (Clear) 16 | 17 |
18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 |
#ProfileMethodTypeStatusURLTime
33 |
34 | 35 | @endslot 36 | @endcomponent 37 | -------------------------------------------------------------------------------- /resources/views/collectors/config.blade.php: -------------------------------------------------------------------------------- 1 | @component('telescope-toolbar::item', ['name' => 'config', 'additional_classes' => 'sf-toolbar-block-right']) 2 | 3 | @slot('icon') 4 | 5 | @ttIcon('laravel') 6 | 7 | {{ app()->version() }} 8 | 9 | @endslot 10 | 11 | @slot("text") 12 |
13 |
14 | Environment 15 | {{ app()->environment() }} 16 |
17 | 18 |
19 | Debug 20 | {{ config('app.debug') ? 'enabled' : 'disabled' }} 21 |
22 | 23 |
24 |
25 | PHP version 26 | {{ phpversion() }} 27 |
28 |
29 | Laravel version 30 | {{ app()->version() }} 31 |
32 |
33 |
34 | 35 | @endslot 36 | @endcomponent 37 | -------------------------------------------------------------------------------- /tests/BrowserTestCase.php: -------------------------------------------------------------------------------- 1 | loadMigrationsFrom(__DIR__ . '/../vendor/laravel/telescope/database/migrations'); 23 | } 24 | 25 | /** 26 | * Get package providers. 27 | * 28 | * @param \Illuminate\Foundation\Application $app 29 | * 30 | * @return array 31 | */ 32 | protected function getPackageProviders($app) 33 | { 34 | return [TelescopeServiceProvider::class, ToolbarServiceProvider::class]; 35 | } 36 | 37 | /** 38 | * Get package aliases. 39 | * 40 | * @param \Illuminate\Foundation\Application $app 41 | * 42 | * @return array 43 | */ 44 | protected function getPackageAliases($app) 45 | { 46 | return ['Toolbar' => Toolbar::class]; 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /resources/css/custom.css: -------------------------------------------------------------------------------- 1 | .Whoops.container { 2 | z-index: 99998; 3 | } 4 | 5 | .sf-toolbar-block.sf-toolbar-block-fullwidth .sf-toolbar-info { 6 | max-width: none; 7 | width: 100%; 8 | position: fixed; 9 | box-sizing: border-box; 10 | left: 0; 11 | } 12 | 13 | .sf-toolbar-previews { 14 | table-layout: auto; 15 | width: 100%; 16 | } 17 | 18 | .sf-toolbar-previews td { 19 | background-color: #444; 20 | border-bottom: 1px solid #777; 21 | color: #F5F5F5; 22 | font-size: 12px; 23 | padding: 4px; 24 | } 25 | 26 | .sf-toolbar-previews td.monospace { 27 | font-family: SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace; 28 | font-size: 10px; 29 | } 30 | 31 | .sf-toolbar-previews td.sf-query { 32 | font-family: SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace; 33 | font-size: 11px; 34 | white-space: normal; 35 | vertical-align: middle; 36 | } 37 | 38 | .sf-toolbar-previews tr:last-child td { 39 | border-bottom: 0; 40 | } 41 | 42 | .sf-toolbar-previews th { 43 | background-color: #222; 44 | border-bottom: 0; 45 | color: #AAA; 46 | font-size: 11px; 47 | padding: 4px; 48 | } 49 | 50 | .sf-minitoolbar .open-button svg { 51 | max-height: 18px; 52 | margin-top: 4px; 53 | } 54 | .sf-toolbar-block-config svg path, 55 | .sf-toolbar-block-config svg .sf-svg-path { 56 | fill: #FF2929; 57 | } 58 | -------------------------------------------------------------------------------- /resources/views/collectors/models.blade.php: -------------------------------------------------------------------------------- 1 | 8 | @component('telescope-toolbar::item', ['name' => 'models', 'link' => true]) 9 | 10 | @slot('icon') 11 | @ttIcon('models') 12 | 13 | {{ $entries->count() }} 14 | 15 | @endslot 16 | 17 | @slot('text') 18 | 19 |
20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | @foreach ($entries as $entry) 31 | 32 | 35 | 36 | 41 | 42 | @endforeach 43 | 44 | 45 |
ActionModel
33 | {{ $entry->content['action'] }} 34 | 37 | 38 | {{ $entry->content['model'] }} 39 | 40 |
46 |
47 | 48 | @endslot 49 | 50 | @endcomponent -------------------------------------------------------------------------------- /resources/views/toolbar.blade.php: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 |
7 | 10 |
11 |
12 | 13 |
14 | 15 | @foreach (config('telescope-toolbar.collectors') as $type => $templates) 16 | @if(isset($entries[$type])) 17 | @foreach($templates as $template) 18 | @include($template, ['entries' => $entries[$type]]) 19 | @endforeach 20 | @endif 21 | @endforeach 22 | 23 | @include("telescope-toolbar::collectors.config") 24 | @include("telescope-toolbar::collectors.ajax") 25 | 26 | 29 |
30 | 31 | -------------------------------------------------------------------------------- /resources/views/collectors/jobs.blade.php: -------------------------------------------------------------------------------- 1 | 8 | @component('telescope-toolbar::item', ['name' => 'jobs', 'link' => true]) 9 | 10 | @slot('icon') 11 | @ttIcon('jobs') 12 | 13 | {{ $entries->count() }} 14 | 15 | @endslot 16 | 17 | @slot('text') 18 | 19 |
20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | @foreach ($entries as $entry) 30 | 31 | 36 | 37 | 43 | 44 | @endforeach 45 | 46 | 47 | 48 |
DetailsMessage
32 | 33 | view 34 | 35 | 38 | {{ \Illuminate\Support\Str::limit($entry->content['name'], 70) }}
39 | 40 | Connection: {{ $entry->content['connection'] }} | Queue: {{ $entry->content['queue'] }} 41 | 42 |
49 |
50 | @endslot 51 | @endcomponent -------------------------------------------------------------------------------- /resources/views/collectors/exceptions.blade.php: -------------------------------------------------------------------------------- 1 | 8 | @component('telescope-toolbar::item', ['name' => 'exceptions', 'link' => true, 'status' => 'red']) 9 | 10 | @slot('icon') 11 | @ttIcon('exceptions') 12 | 13 | {{ $entries->count() }} 14 | 15 | @endslot 16 | 17 | @slot('text') 18 | 19 |
20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | @foreach ($entries as $entry) 30 | 31 | 36 | 37 | 41 | 42 | 43 | @endforeach 44 | 45 | 46 |
DetailsMessage
32 | 33 | view 34 | 35 | 38 | {{ \Illuminate\Support\Str::limit($entry->content['class'], 70) }}
39 | {{ \Illuminate\Support\Str::limit($entry->content['message'], 100) }} 40 |
47 |
48 | @endslot 49 | 50 | @endcomponent -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "fruitcake/laravel-telescope-toolbar", 3 | "description": "Toolbar for Laravel Telescope based on Symfony Web Profiler", 4 | "keywords": [ 5 | "laravel", 6 | "telescope", 7 | "toolbar", 8 | "debugbar", 9 | "profiler", 10 | "debug", 11 | "webprofiler" 12 | ], 13 | "license": "MIT", 14 | "authors": [ 15 | { 16 | "name": "Fruitcake", 17 | "email": "info@fruitcake.nl" 18 | }, 19 | { 20 | "name": "Barry vd. Heuvel", 21 | "email": "barryvdh@gmail.com" 22 | } 23 | ], 24 | "require": { 25 | "php": "^8", 26 | "ext-json": "*", 27 | "laravel/framework": "^9|^10|^11|^12", 28 | "laravel/telescope": "^4|^5" 29 | }, 30 | "require-dev": { 31 | "orchestra/testbench-dusk": "^6|^7|^8|^9|^10" 32 | }, 33 | "autoload": { 34 | "psr-4": { 35 | "Fruitcake\\TelescopeToolbar\\": "src/" 36 | }, 37 | "files": [ 38 | "src/helpers.php" 39 | ] 40 | }, 41 | "autoload-dev": { 42 | "psr-4": { 43 | "Fruitcake\\TelescopeToolbar\\Tests\\": "tests" 44 | } 45 | }, 46 | "minimum-stability": "dev", 47 | "prefer-stable": true, 48 | "extra": { 49 | "branch-alias": { 50 | "dev-master": "1.4-dev" 51 | }, 52 | "laravel": { 53 | "providers": [ 54 | "Fruitcake\\TelescopeToolbar\\ToolbarServiceProvider" 55 | ], 56 | "aliases": { 57 | "Toolbar": "Fruitcake\\TelescopeToolbar\\Toolbar" 58 | } 59 | } 60 | }, 61 | "scripts": { 62 | "test": "phpunit" 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /resources/views/collectors/mail.blade.php: -------------------------------------------------------------------------------- 1 | 8 | @component('telescope-toolbar::item', ['name' => 'mail', 'link' => true]) 9 | 10 | @slot('icon') 11 | @ttIcon('mail') 12 | 13 | {{ $entries->count() }} 14 | 15 | @endslot 16 | 17 | @slot('text') 18 | 19 |
20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | @foreach ($entries as $entry) 30 | 31 | 36 | 37 | 46 | 47 | @endforeach 48 | 49 | 50 | 51 |
DetailsMessage
32 | 33 | view 34 | 35 | 38 | {{ \Illuminate\Support\Str::limit($entry->content['mailable'] ?: '-', 70) }}
39 | 40 | @if($entry->content['queued']) 41 | Queued | 42 | @endif 43 | Subject: {{ \Illuminate\Support\Str::limit($entry->content['subject'], 90) }} 44 | 45 |
52 |
53 | 54 | @endslot 55 | 56 | @endcomponent -------------------------------------------------------------------------------- /resources/views/collectors/cache.blade.php: -------------------------------------------------------------------------------- 1 | content['type']])) { 13 | $types[$entry->content['type']] = 0; 14 | } 15 | $types[$entry->content['type']]++; 16 | } 17 | 18 | ?> 19 | @component('telescope-toolbar::item', ['name' => 'queries', 'link' => true]) 20 | 21 | @slot('icon') 22 | @ttIcon('cache') 23 | 24 | {{ $calls }} 25 | 26 | @if (isset($types['missed'])) 27 | 28 | ({{ $types['missed'] }} miss) 29 | 30 | @endif 31 | @endslot 32 | 33 | @slot('text') 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | @foreach ($entries as $entry) 44 | 45 | 48 | 51 | 52 | @endforeach 53 | 54 |
KeyAction
46 | {{ \Illuminate\Support\Str::limit($entry->content['key'], 60) }} 47 | 49 | {{ $entry->content['type'] }} 50 |
55 | 56 | @endslot 57 | 58 | @endcomponent -------------------------------------------------------------------------------- /resources/icons/laravel.svg: -------------------------------------------------------------------------------- 1 | 2 | Logomark 3 | -------------------------------------------------------------------------------- /.github/workflows/run-tests.yml: -------------------------------------------------------------------------------- 1 | name: Unit Tests 2 | 3 | on: 4 | push: 5 | branches: 6 | - master 7 | pull_request: 8 | branches: 9 | - "*" 10 | 11 | jobs: 12 | php-tests: 13 | runs-on: ubuntu-latest 14 | 15 | timeout-minutes: 15 16 | 17 | env: 18 | COMPOSER_NO_INTERACTION: 1 19 | 20 | strategy: 21 | matrix: 22 | php: [8.4, 8.3, 8.2, 8.1, 8.0] 23 | laravel: ['9.*', '10.*', '11.*', '12.*'] 24 | dependency-version: [prefer-stable] 25 | exclude: 26 | - laravel: 10.* 27 | php: 8.0 28 | - laravel: 10.* 29 | php: 8.3 30 | - laravel: 10.* 31 | php: 8.4 32 | - laravel: 11.* 33 | php: 8.1 34 | - laravel: 11.* 35 | php: 8.0 36 | - laravel: 12.* 37 | php: 8.1 38 | - laravel: 12.* 39 | php: 8.0 40 | 41 | name: P${{ matrix.php }} - L${{ matrix.laravel }} - ${{ matrix.dependency-version }} 42 | 43 | steps: 44 | - name: Checkout code 45 | uses: actions/checkout@v2 46 | 47 | - name: Setup PHP 48 | uses: shivammathur/setup-php@v2 49 | with: 50 | php-version: ${{ matrix.php }} 51 | coverage: none 52 | tools: composer:v2 53 | 54 | - name: Install dependencies 55 | run: | 56 | composer require "laravel/framework:${{ matrix.laravel }}" --no-interaction --no-update 57 | composer update --${{ matrix.dependency-version }} --prefer-dist --no-progress 58 | 59 | - name: Update Dusk Chromedriver 60 | run: vendor/bin/dusk-updater detect --auto-update 61 | 62 | - name: Install Sqlite Database 63 | run: vendor/bin/testbench-dusk package:create-sqlite-db 64 | 65 | - name: Execute Unit Tests 66 | run: composer test 67 | 68 | - name: Upload Failed Screenshots 69 | uses: actions/upload-artifact@v4 70 | if: failure() 71 | with: 72 | name: screenshots 73 | path: tests/Browser/screenshots/* 74 | -------------------------------------------------------------------------------- /resources/views/collectors/views.blade.php: -------------------------------------------------------------------------------- 1 | content['name']; 10 | 11 | if (isset($views[$name])) { 12 | $views[$name]['num']++; 13 | } 14 | 15 | $views[$name] = [ 16 | 'id' => $entry->id, 17 | 'name' => $name, 18 | 'path' => $entry->content['path'] ?? '', 19 | 'num' => 1, 20 | ]; 21 | $total++; 22 | } 23 | 24 | $views = collect($views)->reverse(); 25 | 26 | ?> 27 | @component('telescope-toolbar::item', ['name' => 'views', 'link' => '#views']) 28 | 29 | @slot('icon') 30 | @ttIcon('views') 31 | 32 | {{ $total }} 33 | 34 | @endslot 35 | 36 | @slot('text') 37 | 38 |
39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | @foreach ($views as $view) 50 | 51 | 56 | 57 | 60 | 61 | 64 | 65 | 66 | @endforeach 67 | 68 | 69 |
NamePathNum
52 | 53 | {{ \Illuminate\Support\Str::limit($view['name'], 40) }} 54 | 55 | 58 | {{ \Illuminate\Support\Str::limit($view['path'], 40) }} 59 | 62 | {{ $view['num'] }} 63 |
70 |
71 | @endslot 72 | 73 | 74 | @endcomponent 75 | -------------------------------------------------------------------------------- /resources/views/collectors/notifications.blade.php: -------------------------------------------------------------------------------- 1 | 8 | @component('telescope-toolbar::item', ['name' => 'notifications', 'link' => true]) 9 | 10 | @slot('icon') 11 | @ttIcon('notifications') 12 | 13 | {{ $entries->count() }} 14 | 15 | @endslot 16 | 17 | @slot('text') 18 | 19 |
20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | @foreach ($entries as $entry) 31 | 32 | 37 | 38 | 46 | 47 | 53 | 54 | 55 | @endforeach 56 | 57 | 58 | 59 |
DetailsChannelMessage
33 | 34 | view 35 | 36 | 39 | {{ \Illuminate\Support\Str::limit($entry->content['channel'] ?: '-', 20) }} 40 | @if($entry->content['queued']) 41 |
queued 42 | @else 43 |
sync 44 | @endif 45 |
48 | {{ \Illuminate\Support\Str::limit($entry->content['notification'] ?: '-', 70) }}
49 | 50 | Recipient: {{ \Illuminate\Support\Str::limit($entry->content['notifiable'], 90) }} 51 | 52 |
60 |
61 | 62 | @endslot 63 | 64 | @endcomponent -------------------------------------------------------------------------------- /resources/views/collectors/logs.blade.php: -------------------------------------------------------------------------------- 1 | content['level']; 14 | 15 | if (in_array($level, ['debug', 'info'])) { 16 | $info++; 17 | } elseif (in_array($level, ['notice', 'warning'])) { 18 | $warnings++; 19 | } else { 20 | $errors++; 21 | } 22 | 23 | if (!isset($levels[$entry->content['level']])) { 24 | $levels[$entry->content['level']] = 0; 25 | } 26 | $levels[$entry->content['level']]++; 27 | 28 | $total++; 29 | } 30 | 31 | if ($errors) { 32 | $statusColor = 'red'; 33 | } elseif ($warnings) { 34 | $statusColor = 'yellow'; 35 | } else { 36 | $statusColor = null; 37 | } 38 | 39 | ?> 40 | @component('telescope-toolbar::item', ['name' => 'logs ', 'link' => true, 'status' => $statusColor]) 41 | 42 | @slot('icon') 43 | @ttIcon('logs') 44 | 45 | {{ $total }} 46 | 47 | @endslot 48 | 49 | @slot('text') 50 | 51 |
52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | @foreach ($entries as $entry) 63 | 64 | 69 | 70 | 73 | 74 | 77 | 78 | 79 | @endforeach 80 | 81 | 82 |
DetailsLevelMessage
65 | 66 | view 67 | 68 | 71 | {{ $entry->content['level'] }} 72 | 75 | {{ \Illuminate\Support\Str::limit($entry->content['message'], 90) }} 76 |
83 |
84 | @endslot 85 | 86 | 87 | @endcomponent -------------------------------------------------------------------------------- /tests/TestCase.php: -------------------------------------------------------------------------------- 1 | Toolbar::class]); 33 | } 34 | 35 | /** 36 | * Define environment setup. 37 | * 38 | * @param \Illuminate\Foundation\Application $app 39 | * 40 | * @return void 41 | */ 42 | protected function getEnvironmentSetUp($app) 43 | { 44 | parent::getEnvironmentSetUp($app); 45 | 46 | /** @var Router $router */ 47 | $router = $app['router']; 48 | 49 | $this->addWebRoutes($router); 50 | $this->addApiRoutes($router); 51 | $this->addViewPaths(); 52 | } 53 | 54 | /** 55 | * @param Router $router 56 | */ 57 | protected function addWebRoutes(Router $router) 58 | { 59 | $router->get('web/plain', [ 60 | 'uses' => function () { 61 | return 'PONG'; 62 | } 63 | ]); 64 | 65 | $router->get('web/html', [ 66 | 'uses' => function () { 67 | return 'Pong'; 68 | } 69 | ]); 70 | } 71 | 72 | /** 73 | * @param Router $router 74 | */ 75 | protected function addApiRoutes(Router $router) 76 | { 77 | $router->get('api/ping', [ 78 | 'uses' => function () { 79 | return response()->json(['status' => 'pong']); 80 | } 81 | ]); 82 | } 83 | 84 | protected function addViewPaths() 85 | { 86 | config(['view.paths' => array_merge(config('view.paths'), [__DIR__ . '/resources/views'])]); 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /tests/ToolbarBrowserTest.php: -------------------------------------------------------------------------------- 1 | set('app.debug', true); 21 | 22 | /** @var Router $router */ 23 | $router = $app['router']; 24 | 25 | $this->addWebRoutes($router); 26 | $this->addApiRoutes($router); 27 | 28 | // \Orchestra\Testbench\Dusk\Options::withoutUI(); 29 | } 30 | 31 | /** 32 | * @param Router $router 33 | */ 34 | protected function addWebRoutes(Router $router) 35 | { 36 | $router->get('web/plain', [ 37 | 'uses' => function () { 38 | return 'PONG'; 39 | } 40 | ]); 41 | 42 | $router->get('web/html', [ 43 | 'uses' => function () { 44 | return 'HTMLPONG'; 45 | } 46 | ]); 47 | } 48 | 49 | /** 50 | * @param Router $router 51 | */ 52 | protected function addApiRoutes(Router $router) 53 | { 54 | $router->get('api/ping', [ 55 | 'uses' => function () { 56 | return response()->json(['status' => 'pong']); 57 | } 58 | ]); 59 | } 60 | 61 | public function testItInjectsOnPlainText() 62 | { 63 | $this->browse(function ($browser) { 64 | $browser->visit('web/plain') 65 | ->assertSee('PONG') 66 | ->waitFor('.sf-toolbar-block') 67 | ->assertSee('GET /web/plain'); 68 | }); 69 | } 70 | 71 | public function testItInjectsOnHtml() 72 | { 73 | $this->browse(function ($browser) { 74 | $browser->visit('web/html') 75 | ->assertSee('HTMLPONG') 76 | ->waitFor('.sf-toolbar-block') 77 | ->assertSee('GET /web/html'); 78 | }); 79 | } 80 | 81 | public function testItDoesntInjectOnJson() 82 | { 83 | $this->browse(function ($browser) { 84 | $browser->visit('api/ping') 85 | ->assertSee('pong') 86 | ->assertSourceMissing('loadToolbar') 87 | ->assertDontSee('GET api/ping'); 88 | }); 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /resources/views/collectors/queries.blade.php: -------------------------------------------------------------------------------- 1 | content['slow'] ?? false) { 13 | $num_slow++; 14 | } 15 | $query_time += (float) str_replace(',', '', $query->content['time']) ?? 0; 16 | $queries[$query->content['hash'] ?? $query->content['sql']] = $query->content['sql']; 17 | } 18 | 19 | $num_duplicated = $num_queries - count($queries); 20 | if ($num_queries > 0 && $num_duplicated > $num_queries *.75) { 21 | $statusColor = 'yellow'; 22 | } else { 23 | $statusColor = null; 24 | } 25 | ?> 26 | @component('telescope-toolbar::item', ['name' => 'queries', 'link' => '#queries', 'status' => $statusColor, 'additional_classes' => 'sf-toolbar-block-fullwidth']) 27 | 28 | @slot('icon') 29 | @ttIcon('queries') 30 | 31 | {{ $num_queries }} 32 | 33 | 34 | in 35 | {{ round($query_time) }} 36 | ms 37 | 38 | 39 | @endslot 40 | 41 | @slot('text') 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | @foreach ($entries as $query) 53 | @php($path = str_replace(base_path(), '', $query->content['file'])) 54 | 55 | 58 | 59 | 63 | 64 | @endforeach 65 | 66 | 67 |
Query
{{ $num_queries }} queries, {{ $num_duplicated }} of which are duplicated and {{ $num_slow }} slow.
Duration
{{ number_format($query_time, 2) }} ms
56 | {{ $query->content['sql'] }} 57 | 60 | {{ number_format((float) str_replace(',', '', $query->content['time']), 2) }}ms
61 | {{ strlen($path) > 32 ? '..' . substr($path, -30) : $path }}:{{ $query->content['line'] }} 62 |
68 | 69 | @endslot 70 | 71 | @endcomponent 72 | -------------------------------------------------------------------------------- /resources/views/collectors/request.blade.php: -------------------------------------------------------------------------------- 1 | first()->content; 4 | 5 | $statusCode = $data['response_status']; 6 | if ($statusCode > 400) { 7 | $statusColor = 'red'; 8 | } elseif ($statusCode > 300) { 9 | $statusColor = 'yellow'; 10 | } else { 11 | $statusColor = 'green'; 12 | } 13 | ?> 14 | 15 | @component('telescope-toolbar::item', ['name' => 'request', 'link' => true]) 16 | 17 | @slot('icon') 18 | {{ $statusCode }} 19 | {{ $data['method'] }} {{ $data['uri'] }} 20 | @endslot 21 | 22 | @slot('text') 23 |
24 |
25 | HTTP status 26 | {{ $statusCode }} 27 |
28 | 29 | @if($data['method'] !== 'GET') 30 |
31 | Method 32 | {{ $data['method'] }} 33 |
34 | @endif 35 | 36 |
37 | Request URI 38 | {{ $data['method'] }} {{ $data['uri'] }} 39 |
40 | 41 |
42 | Controller Action 43 | 44 | {{ $data['controller_action'] }} 45 | 46 |
47 | 48 |
49 | Middleware 50 | 51 | {{ implode(', ', array_filter($data['middleware'])) ?: '-' }} 52 | 53 |
54 | 55 | @if(isset($data['response']['view'])) 56 |
57 | View 58 | 59 | {{ str_replace(base_path(), '', $data['response']['view']) }} 60 | 61 |
62 | @elseif(isset($data['response']) && is_string($data['response'])) 63 |
64 | Response 65 | 66 | {{ \Illuminate\Support\Str::limit($data['response'], 60) }} 67 | 68 |
69 | @endif 70 | 71 |
72 | @endslot 73 | 74 | @endcomponent 75 | -------------------------------------------------------------------------------- /tests/TelescopeFeatureTestCase.php: -------------------------------------------------------------------------------- 1 | detectEnvironment(function () { 56 | return 'self-testing'; 57 | }); 58 | } 59 | 60 | /** 61 | * @param \Illuminate\Foundation\Application $app 62 | * @return void 63 | */ 64 | protected function getEnvironmentSetUp($app) 65 | { 66 | $config = $app->get('config'); 67 | 68 | $config->set('logging.default', 'errorlog'); 69 | 70 | $config->set('database.default', 'testbench'); 71 | 72 | $config->set('telescope.storage.database.connection', 'testbench'); 73 | 74 | $config->set('database.connections.testbench', [ 75 | 'driver' => 'sqlite', 76 | 'database' => ':memory:', 77 | 'prefix' => '', 78 | ]); 79 | 80 | $app->when(DatabaseEntriesRepository::class) 81 | ->needs('$connection') 82 | ->give('testbench'); 83 | } 84 | 85 | protected function loadTelescopeEntries() 86 | { 87 | $this->terminateTelescope(); 88 | 89 | return EntryModel::all(); 90 | } 91 | 92 | public function terminateTelescope() 93 | { 94 | Telescope::store(app(EntriesRepository::class)); 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /resources/css/theme_light.css: -------------------------------------------------------------------------------- 1 | 2 | .sf-toolbarreset { 3 | background-color: #EEF1F3; 4 | box-shadow: 0px 1px 5px rgba(0, 0, 0, 0.2); 5 | color: #212529; 6 | } 7 | 8 | .sf-toolbarreset .hide-button, .sf-toolbarreset .hide-button:hover { 9 | background: #EEF1F3; 10 | color: var(--sf-toolbar-gray-800); 11 | } 12 | 13 | .sf-toolbar-block .sf-toolbar-value { 14 | color: #212529; 15 | } 16 | 17 | .sf-toolbar-block .sf-toolbar-label, 18 | .sf-toolbar-block .sf-toolbar-class-separator { 19 | color: #212529; 20 | } 21 | 22 | .sf-toolbar-block hr { 23 | border-top: 1px solid #212529; 24 | } 25 | 26 | .sf-toolbar-block .sf-toolbar-info-group { 27 | border-bottom: 1px solid #212529; 28 | } 29 | 30 | div.sf-toolbar .sf-toolbar-block .sf-toolbar-info-piece a { 31 | color: #3439bc; 32 | } 33 | 34 | .sf-toolbar-block .sf-toolbar-info-piece b { 35 | color: #212529; 36 | } 37 | 38 | .sf-toolbar-block:not(.sf-toolbar-block-dump) .sf-toolbar-info-piece span { 39 | color: #212529; 40 | } 41 | 42 | .sf-toolbar-block:not(.sf-toolbar-block-dump) .sf-toolbar-info-piece span.sf-toolbar-status { 43 | color: #FFF; 44 | } 45 | 46 | .sf-toolbar-block .sf-toolbar-info { 47 | background-color: #fff; 48 | color: #212529; 49 | } 50 | 51 | .sf-toolbar-block .sf-toolbar-status { 52 | background-color: #212529; 53 | } 54 | 55 | 56 | .sf-toolbar-block .sf-toolbar-icon { 57 | color: var(--sf-toolbar-gray-800); 58 | } 59 | 60 | .sf-toolbar-block:hover .sf-toolbar-icon, 61 | .sf-toolbar-block.hover .sf-toolbar-icon { 62 | background-color: #fff; 63 | border-bottom: 2px solid #4040c8; 64 | box-sizing: border-box; 65 | } 66 | 67 | .sf-toolbar-block:hover .sf-toolbar-info, 68 | .sf-toolbar-block.hover .sf-toolbar-info { 69 | box-shadow: 0px -2px 6px rgba(0,0,0,0.1); 70 | border-top-left-radius: 3px; 71 | border-top-right-radius: 3px; 72 | } 73 | 74 | .sf-toolbar-info-piece b.sf-toolbar-ajax-info { 75 | color: #212529; 76 | } 77 | 78 | .sf-toolbar-ajax-requests td, .sf-toolbar-previews td { 79 | background-color: #fff; 80 | border-bottom: 1px solid #212529; 81 | color: #212529; 82 | } 83 | 84 | .sf-toolbar-ajax-requests th, .sf-toolbar-previews th { 85 | background-color: #EEF1F3; 86 | color: #212529; 87 | } 88 | 89 | @keyframes sf-blink { 90 | 0% { background: #EEF1F3; } 91 | 50% { background: #444; } 92 | 100% { background: #EEF1F3; } 93 | } 94 | 95 | .sf-toolbar-block .sf-toolbar-info-piece-additional-detail { 96 | color: #EEF1F3; 97 | } 98 | 99 | .sf-error-toolbar .sf-toolbarreset { 100 | background: #EEF1F3; 101 | color: #212529; 102 | } 103 | 104 | .sf-error-toolbar .sf-toolbarreset a { 105 | color: #3439bc; 106 | } 107 | -------------------------------------------------------------------------------- /src/Http/Controllers/ToolbarController.php: -------------------------------------------------------------------------------- 1 | entriesRepository = $entriesRepository; 24 | 25 | $this->middleware(function($request, $next) { 26 | Telescope::stopRecording(); 27 | 28 | if ($request->hasSession()) { 29 | $request->session()->reflash(); 30 | } 31 | 32 | return $next($request); 33 | }); 34 | } 35 | 36 | public function render($token) 37 | { 38 | $this->prepareBlade($token); 39 | 40 | $options = $this->findBatchOptions($token); 41 | 42 | $entries = $this->entriesRepository->get(null, $options)->groupBy('type'); 43 | 44 | return View::make('telescope-toolbar::toolbar', [ 45 | 'entries' => $entries, 46 | ]); 47 | } 48 | 49 | public function show($token) 50 | { 51 | $options = $this->findBatchOptions($token); 52 | 53 | $request = $this->entriesRepository->get('request', $options)->first(); 54 | 55 | return redirect(route('telescope') . '/requests/' . $request->id); 56 | } 57 | 58 | public function baseJs() 59 | { 60 | $content = View::make('telescope-toolbar::base_js', [ 61 | 'excluded_ajax_paths' => config('telescope-toolbar.excluded_ajax_paths', '^/_tt'), 62 | ])->render(); 63 | 64 | $content = $this->stripSurroundingTags($content); 65 | 66 | return response($content, 200, [ 67 | 'Content-Type' => 'text/javascript', 68 | ])->setClientTtl(31536000); 69 | } 70 | 71 | public function styling(Request $request) 72 | { 73 | if ($request->get('lightMode')) { 74 | $files = ['theme_light.css']; 75 | } else { 76 | $files = [ 77 | 'base.css', 78 | 'custom.css', 79 | ]; 80 | } 81 | 82 | $content = ''; 83 | foreach ($files as $file) { 84 | $content .= File::get(__DIR__ . '/../../../resources/css/' . $file) . "\n"; 85 | } 86 | 87 | return response($content, 200, [ 88 | 'Content-Type' => 'text/css', 89 | ])->setClientTtl(31536000); 90 | } 91 | 92 | /** 93 | * Strip 677 | 678 | 679 | --------------------------------------------------------------------------------