├── .babelrc
├── .gitignore
├── LICENSE
├── README.md
├── composer.json
├── config
└── redis-manager.php
├── package.json
├── public
├── css
│ └── app.css
├── fonts
│ └── vendor
│ │ ├── element-ui
│ │ └── lib
│ │ │ └── theme-chalk
│ │ │ ├── element-icons.ttf
│ │ │ └── element-icons.woff
│ │ └── font-awesome
│ │ ├── fontawesome-webfont.eot
│ │ ├── fontawesome-webfont.svg
│ │ ├── fontawesome-webfont.ttf
│ │ ├── fontawesome-webfont.woff
│ │ └── fontawesome-webfont.woff2
├── img
│ └── logo.svg
├── js
│ └── app.js
└── mix-manifest.json
├── resources
├── assets
│ ├── img
│ │ └── logo.svg
│ ├── js
│ │ ├── app.js
│ │ ├── components
│ │ │ ├── App.vue
│ │ │ ├── Charts
│ │ │ │ └── LineChart.js
│ │ │ ├── Layout.vue
│ │ │ └── Siderbar.vue
│ │ ├── elementui.js
│ │ ├── pages
│ │ │ ├── Console.vue
│ │ │ ├── Info.vue
│ │ │ ├── Keys.vue
│ │ │ ├── create
│ │ │ │ ├── Hash.vue
│ │ │ │ ├── Index.vue
│ │ │ │ ├── List.vue
│ │ │ │ ├── Set.vue
│ │ │ │ ├── String.vue
│ │ │ │ └── Zset.vue
│ │ │ ├── edit
│ │ │ │ ├── Hash.vue
│ │ │ │ ├── Index.vue
│ │ │ │ ├── List.vue
│ │ │ │ ├── Set.vue
│ │ │ │ ├── String.vue
│ │ │ │ └── Zset.vue
│ │ │ └── metrics
│ │ │ │ ├── CPU.vue
│ │ │ │ ├── Clients.vue
│ │ │ │ ├── Index.vue
│ │ │ │ ├── Memory.vue
│ │ │ │ └── Throughput.vue
│ │ ├── redis.js
│ │ └── router.js
│ └── sass
│ │ └── app.scss
└── views
│ └── app.blade.php
├── routes
└── web.php
├── src
├── DataType
│ ├── DataType.php
│ ├── Hashes.php
│ ├── Lists.php
│ ├── Sets.php
│ ├── SortedSets.php
│ └── Strings.php
├── Formatter
│ └── Information.php
├── Http
│ ├── Controllers
│ │ └── RedisController.php
│ └── Middleware
│ │ └── Authenticate.php
├── RedisManager.php
└── RedisManagerServiceProvider.php
└── webpack.mix.js
/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "presets": ["env"],
3 | "plugins": [
4 | [
5 | "component",
6 | [
7 | {
8 | "libraryName": "element-ui",
9 | "styleLibraryName": "theme-chalk"
10 | }
11 | ]
12 | ]
13 | ]
14 | }
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | /vendor
2 | /node_modules
3 | composer.lock
4 | .DS_Store
5 | Thumbs.db
6 | phpunit.xml
7 | /.idea
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2015 Jens Segers
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy of
6 | this software and associated documentation files (the "Software"), to deal in
7 | the Software without restriction, including without limitation the rights to
8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
9 | the Software, and to permit persons to whom the Software is furnished to do so,
10 | subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |

2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 | `Redis-manager` gives your laravel application a redis web administration interface that allows you to easily manipulate the most commonly used data types for redis (strings, hashes, lists, sets, sorted sets).
16 |
17 | It also provides a web-style command-line tool that works like redis-cli that can run most of the redis commands.
18 |
19 | `Redis-manager` allows you to easily monitor several redis system status, including memory usage, cpu usage, and the throughput of each command.
20 |
21 | Here is the living [demo](https://zsong.me/redis-manager/)
22 |
23 | > redis-manager reads laravel's redis configuration located in the `config/database.php`
24 |
25 | # Installation
26 |
27 | You may use Composer to install Redis-manager into your Laravel project:
28 |
29 | ```shell
30 | composer require encore/redis-manager
31 |
32 | ```
33 |
34 | After installing `redis-manager`, publish its assets using the vendor:publish Artisan command:
35 |
36 | ```shell
37 | php artisan vendor:publish --provider="Encore\RedisManager\RedisManagerServiceProvider"
38 | ```
39 |
40 | After installation, open `http://your-server/redis-manager` to access `redis-manager`.
41 |
42 | ## Configuration
43 |
44 | The config file was published at `config/redis-manager.php`, and the default contents of the configuration:
45 | ```php
46 | 'redis-manager',
60 |
61 | /*
62 | |--------------------------------------------------------------------------
63 | | Redis Manager Middleware
64 | |--------------------------------------------------------------------------
65 | |
66 | | The Redis Manager's route middleware.
67 | |
68 | */
69 |
70 | 'middleware' => [],
71 |
72 | /*
73 | |--------------------------------------------------------------------------
74 | | Redis Manager Results Per Page
75 | |--------------------------------------------------------------------------
76 | |
77 | | Here you can configure for the number of results will show in the
78 | | Redis Manager search page.
79 | |
80 | */
81 |
82 | 'results_per_page' => 50,
83 |
84 | /*
85 | |--------------------------------------------------------------------------
86 | | Redis Manager Disable Commands
87 | |--------------------------------------------------------------------------
88 | |
89 | | The commands listed here was disabled when you use Redis Manager Console
90 | | to run commands. Feel free to add commands here which you do not want
91 | | users to use.
92 | |
93 | */
94 |
95 | 'disable_commands' => [
96 | 'flushdb'
97 | ]
98 | ];
99 |
100 | ```
101 |
102 | ## Authentication
103 |
104 | By default, you will only be able to access `redis-manager` in the `local` environment. To define a more specific access policy for it, you should use the `RedisManager::auth` method. The auth method accepts a callback which should return `true` or `false`, indicating whether the user should have access to `redis-manager`:
105 |
106 | ```php
107 | RedisManager::auth(function ($request) {
108 | // return true / false;
109 | });
110 | ```
111 |
112 | ## License
113 |
114 | `Redis manager` is open-sourced software licensed under the [MIT license](http://opensource.org/licenses/MIT)
115 |
--------------------------------------------------------------------------------
/composer.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "encore/redis-manager",
3 | "description": "Redis manager for laravel",
4 | "type": "library",
5 | "keywords": ["laravel", "redis", "manager"],
6 | "homepage": "https://github.com/z-song/redis-manager",
7 | "license": "MIT",
8 | "authors": [
9 | {
10 | "name": "z-song",
11 | "email": "zosong@126.com"
12 | }
13 | ],
14 | "require": {
15 | "php": ">=7.0.0",
16 | "illuminate/contracts": "~5.5",
17 | "illuminate/support": "~5.5",
18 | "predis/predis": "^1.1"
19 | },
20 | "require-dev": {
21 | "phpunit/phpunit": "~6.0",
22 | "laravel/laravel": "~5.5"
23 | },
24 | "autoload": {
25 | "psr-4": {
26 | "Encore\\RedisManager\\": "src/"
27 | }
28 | },
29 | "extra": {
30 | "laravel": {
31 | "providers": [
32 | "Encore\\RedisManager\\RedisManagerServiceProvider"
33 | ]
34 |
35 | }
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/config/redis-manager.php:
--------------------------------------------------------------------------------
1 | 'redis-manager',
15 |
16 | /*
17 | |--------------------------------------------------------------------------
18 | | Redis Manager Middleware
19 | |--------------------------------------------------------------------------
20 | |
21 | | The Redis Manager's route middleware.
22 | |
23 | */
24 |
25 | 'middleware' => ['web'],
26 |
27 | /*
28 | |--------------------------------------------------------------------------
29 | | Redis Manager Results Per Page
30 | |--------------------------------------------------------------------------
31 | |
32 | | Here you can configure for the number of results will show in the
33 | | Redis Manager search page.
34 | |
35 | */
36 |
37 | 'results_per_page' => 50,
38 |
39 | /*
40 | |--------------------------------------------------------------------------
41 | | Redis Manager Disable Commands
42 | |--------------------------------------------------------------------------
43 | |
44 | | The commands listed here was disabled when you use Redis Manager Console
45 | | to run commands. Feel free to add commands here which you do not want
46 | | users to use.
47 | |
48 | */
49 |
50 | 'disable_commands' => [
51 | 'flushdb',
52 | ],
53 | ];
54 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "private": true,
3 | "scripts": {
4 | "dev": "npm run development",
5 | "development": "cross-env NODE_ENV=development node_modules/webpack/bin/webpack.js --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js",
6 | "watch": "cross-env NODE_ENV=development node_modules/webpack/bin/webpack.js --watch --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js",
7 | "watch-poll": "npm run watch -- --watch-poll",
8 | "hot": "cross-env NODE_ENV=development node_modules/webpack-dev-server/bin/webpack-dev-server.js --inline --hot --config=node_modules/laravel-mix/setup/webpack.config.js",
9 | "prod": "npm run production",
10 | "production": "cross-env NODE_ENV=production node_modules/webpack/bin/webpack.js --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js",
11 | "profile": "cross-env NODE_ENV=development node_modules/webpack/bin/webpack.js --profile --config=node_modules/laravel-mix/setup/webpack.config.js"
12 | },
13 | "dependencies": {
14 | "axios": "^0.15.3",
15 | "chart.js": "^2.7.1",
16 | "element-ui": "^2.0.0",
17 | "font-awesome": "^4.7.0",
18 | "lodash": "^4.16.2",
19 | "vue": "^2.2.0",
20 | "vue-chartjs": "^3.0.2",
21 | "vue-router": "^2.2.0"
22 | },
23 | "devDependencies": {
24 | "babel-plugin-component": "^0.10.1",
25 | "babel-preset-env": "^1.6.1",
26 | "cross-env": "^5.0.1",
27 | "es6-promise": "^4.0.5",
28 | "laravel-mix": "^1.4.2"
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/public/css/app.css:
--------------------------------------------------------------------------------
1 | /*!
2 | * Font Awesome 4.7.0 by @davegandy - http://fontawesome.io - @fontawesome
3 | * License - http://fontawesome.io/license (Font: SIL OFL 1.1, CSS: MIT License)
4 | */@font-face{font-family:FontAwesome;src:url(/fonts/vendor/font-awesome/fontawesome-webfont.eot?674f50d287a8c48dc19ba404d20fe713);src:url(/fonts/vendor/font-awesome/fontawesome-webfont.eot?674f50d287a8c48dc19ba404d20fe713) format("embedded-opentype"),url(/fonts/vendor/font-awesome/fontawesome-webfont.woff2?af7ae505a9eed503f8b8e6982036873e) format("woff2"),url(/fonts/vendor/font-awesome/fontawesome-webfont.woff?fee66e712a8a08eef5805a46892932ad) format("woff"),url(/fonts/vendor/font-awesome/fontawesome-webfont.ttf?b06871f281fee6b241d60582ae9369b9) format("truetype"),url(/fonts/vendor/font-awesome/fontawesome-webfont.svg?912ec66d7572ff821749319396470bde) format("svg");font-weight:400;font-style:normal}.fa{display:inline-block;font:normal normal normal 14px/1 FontAwesome;font-size:inherit;text-rendering:auto;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.fa-lg{font-size:1.33333333em;line-height:.75em;vertical-align:-15%}.fa-2x{font-size:2em}.fa-3x{font-size:3em}.fa-4x{font-size:4em}.fa-5x{font-size:5em}.fa-fw{width:1.28571429em;text-align:center}.fa-ul{padding-left:0;margin-left:2.14285714em;list-style-type:none}.fa-ul>li{position:relative}.fa-li{position:absolute;left:-2.14285714em;width:2.14285714em;top:.14285714em;text-align:center}.fa-li.fa-lg{left:-1.85714286em}.fa-border{padding:.2em .25em .15em;border:.08em solid #eee;border-radius:.1em}.fa-pull-left{float:left}.fa-pull-right{float:right}.fa.fa-pull-left{margin-right:.3em}.fa.fa-pull-right{margin-left:.3em}.pull-right{float:right}.pull-left{float:left}.fa.pull-left{margin-right:.3em}.fa.pull-right{margin-left:.3em}.fa-spin{-webkit-animation:fa-spin 2s infinite linear;animation:fa-spin 2s infinite linear}.fa-pulse{-webkit-animation:fa-spin 1s infinite steps(8);animation:fa-spin 1s infinite steps(8)}@-webkit-keyframes fa-spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}to{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}@keyframes fa-spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}to{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}.fa-rotate-90{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=1)";-webkit-transform:rotate(90deg);transform:rotate(90deg)}.fa-rotate-180{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=2)";-webkit-transform:rotate(180deg);transform:rotate(180deg)}.fa-rotate-270{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=3)";-webkit-transform:rotate(270deg);transform:rotate(270deg)}.fa-flip-horizontal{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=0, mirror=1)";-webkit-transform:scaleX(-1);transform:scaleX(-1)}.fa-flip-vertical{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=2, mirror=1)";-webkit-transform:scaleY(-1);transform:scaleY(-1)}:root .fa-flip-horizontal,:root .fa-flip-vertical,:root .fa-rotate-90,:root .fa-rotate-180,:root .fa-rotate-270{-webkit-filter:none;filter:none}.fa-stack{position:relative;display:inline-block;width:2em;height:2em;line-height:2em;vertical-align:middle}.fa-stack-1x,.fa-stack-2x{position:absolute;left:0;width:100%;text-align:center}.fa-stack-1x{line-height:inherit}.fa-stack-2x{font-size:2em}.fa-inverse{color:#fff}.fa-glass:before{content:"\F000"}.fa-music:before{content:"\F001"}.fa-search:before{content:"\F002"}.fa-envelope-o:before{content:"\F003"}.fa-heart:before{content:"\F004"}.fa-star:before{content:"\F005"}.fa-star-o:before{content:"\F006"}.fa-user:before{content:"\F007"}.fa-film:before{content:"\F008"}.fa-th-large:before{content:"\F009"}.fa-th:before{content:"\F00A"}.fa-th-list:before{content:"\F00B"}.fa-check:before{content:"\F00C"}.fa-close:before,.fa-remove:before,.fa-times:before{content:"\F00D"}.fa-search-plus:before{content:"\F00E"}.fa-search-minus:before{content:"\F010"}.fa-power-off:before{content:"\F011"}.fa-signal:before{content:"\F012"}.fa-cog:before,.fa-gear:before{content:"\F013"}.fa-trash-o:before{content:"\F014"}.fa-home:before{content:"\F015"}.fa-file-o:before{content:"\F016"}.fa-clock-o:before{content:"\F017"}.fa-road:before{content:"\F018"}.fa-download:before{content:"\F019"}.fa-arrow-circle-o-down:before{content:"\F01A"}.fa-arrow-circle-o-up:before{content:"\F01B"}.fa-inbox:before{content:"\F01C"}.fa-play-circle-o:before{content:"\F01D"}.fa-repeat:before,.fa-rotate-right:before{content:"\F01E"}.fa-refresh:before{content:"\F021"}.fa-list-alt:before{content:"\F022"}.fa-lock:before{content:"\F023"}.fa-flag:before{content:"\F024"}.fa-headphones:before{content:"\F025"}.fa-volume-off:before{content:"\F026"}.fa-volume-down:before{content:"\F027"}.fa-volume-up:before{content:"\F028"}.fa-qrcode:before{content:"\F029"}.fa-barcode:before{content:"\F02A"}.fa-tag:before{content:"\F02B"}.fa-tags:before{content:"\F02C"}.fa-book:before{content:"\F02D"}.fa-bookmark:before{content:"\F02E"}.fa-print:before{content:"\F02F"}.fa-camera:before{content:"\F030"}.fa-font:before{content:"\F031"}.fa-bold:before{content:"\F032"}.fa-italic:before{content:"\F033"}.fa-text-height:before{content:"\F034"}.fa-text-width:before{content:"\F035"}.fa-align-left:before{content:"\F036"}.fa-align-center:before{content:"\F037"}.fa-align-right:before{content:"\F038"}.fa-align-justify:before{content:"\F039"}.fa-list:before{content:"\F03A"}.fa-dedent:before,.fa-outdent:before{content:"\F03B"}.fa-indent:before{content:"\F03C"}.fa-video-camera:before{content:"\F03D"}.fa-image:before,.fa-photo:before,.fa-picture-o:before{content:"\F03E"}.fa-pencil:before{content:"\F040"}.fa-map-marker:before{content:"\F041"}.fa-adjust:before{content:"\F042"}.fa-tint:before{content:"\F043"}.fa-edit:before,.fa-pencil-square-o:before{content:"\F044"}.fa-share-square-o:before{content:"\F045"}.fa-check-square-o:before{content:"\F046"}.fa-arrows:before{content:"\F047"}.fa-step-backward:before{content:"\F048"}.fa-fast-backward:before{content:"\F049"}.fa-backward:before{content:"\F04A"}.fa-play:before{content:"\F04B"}.fa-pause:before{content:"\F04C"}.fa-stop:before{content:"\F04D"}.fa-forward:before{content:"\F04E"}.fa-fast-forward:before{content:"\F050"}.fa-step-forward:before{content:"\F051"}.fa-eject:before{content:"\F052"}.fa-chevron-left:before{content:"\F053"}.fa-chevron-right:before{content:"\F054"}.fa-plus-circle:before{content:"\F055"}.fa-minus-circle:before{content:"\F056"}.fa-times-circle:before{content:"\F057"}.fa-check-circle:before{content:"\F058"}.fa-question-circle:before{content:"\F059"}.fa-info-circle:before{content:"\F05A"}.fa-crosshairs:before{content:"\F05B"}.fa-times-circle-o:before{content:"\F05C"}.fa-check-circle-o:before{content:"\F05D"}.fa-ban:before{content:"\F05E"}.fa-arrow-left:before{content:"\F060"}.fa-arrow-right:before{content:"\F061"}.fa-arrow-up:before{content:"\F062"}.fa-arrow-down:before{content:"\F063"}.fa-mail-forward:before,.fa-share:before{content:"\F064"}.fa-expand:before{content:"\F065"}.fa-compress:before{content:"\F066"}.fa-plus:before{content:"\F067"}.fa-minus:before{content:"\F068"}.fa-asterisk:before{content:"\F069"}.fa-exclamation-circle:before{content:"\F06A"}.fa-gift:before{content:"\F06B"}.fa-leaf:before{content:"\F06C"}.fa-fire:before{content:"\F06D"}.fa-eye:before{content:"\F06E"}.fa-eye-slash:before{content:"\F070"}.fa-exclamation-triangle:before,.fa-warning:before{content:"\F071"}.fa-plane:before{content:"\F072"}.fa-calendar:before{content:"\F073"}.fa-random:before{content:"\F074"}.fa-comment:before{content:"\F075"}.fa-magnet:before{content:"\F076"}.fa-chevron-up:before{content:"\F077"}.fa-chevron-down:before{content:"\F078"}.fa-retweet:before{content:"\F079"}.fa-shopping-cart:before{content:"\F07A"}.fa-folder:before{content:"\F07B"}.fa-folder-open:before{content:"\F07C"}.fa-arrows-v:before{content:"\F07D"}.fa-arrows-h:before{content:"\F07E"}.fa-bar-chart-o:before,.fa-bar-chart:before{content:"\F080"}.fa-twitter-square:before{content:"\F081"}.fa-facebook-square:before{content:"\F082"}.fa-camera-retro:before{content:"\F083"}.fa-key:before{content:"\F084"}.fa-cogs:before,.fa-gears:before{content:"\F085"}.fa-comments:before{content:"\F086"}.fa-thumbs-o-up:before{content:"\F087"}.fa-thumbs-o-down:before{content:"\F088"}.fa-star-half:before{content:"\F089"}.fa-heart-o:before{content:"\F08A"}.fa-sign-out:before{content:"\F08B"}.fa-linkedin-square:before{content:"\F08C"}.fa-thumb-tack:before{content:"\F08D"}.fa-external-link:before{content:"\F08E"}.fa-sign-in:before{content:"\F090"}.fa-trophy:before{content:"\F091"}.fa-github-square:before{content:"\F092"}.fa-upload:before{content:"\F093"}.fa-lemon-o:before{content:"\F094"}.fa-phone:before{content:"\F095"}.fa-square-o:before{content:"\F096"}.fa-bookmark-o:before{content:"\F097"}.fa-phone-square:before{content:"\F098"}.fa-twitter:before{content:"\F099"}.fa-facebook-f:before,.fa-facebook:before{content:"\F09A"}.fa-github:before{content:"\F09B"}.fa-unlock:before{content:"\F09C"}.fa-credit-card:before{content:"\F09D"}.fa-feed:before,.fa-rss:before{content:"\F09E"}.fa-hdd-o:before{content:"\F0A0"}.fa-bullhorn:before{content:"\F0A1"}.fa-bell:before{content:"\F0F3"}.fa-certificate:before{content:"\F0A3"}.fa-hand-o-right:before{content:"\F0A4"}.fa-hand-o-left:before{content:"\F0A5"}.fa-hand-o-up:before{content:"\F0A6"}.fa-hand-o-down:before{content:"\F0A7"}.fa-arrow-circle-left:before{content:"\F0A8"}.fa-arrow-circle-right:before{content:"\F0A9"}.fa-arrow-circle-up:before{content:"\F0AA"}.fa-arrow-circle-down:before{content:"\F0AB"}.fa-globe:before{content:"\F0AC"}.fa-wrench:before{content:"\F0AD"}.fa-tasks:before{content:"\F0AE"}.fa-filter:before{content:"\F0B0"}.fa-briefcase:before{content:"\F0B1"}.fa-arrows-alt:before{content:"\F0B2"}.fa-group:before,.fa-users:before{content:"\F0C0"}.fa-chain:before,.fa-link:before{content:"\F0C1"}.fa-cloud:before{content:"\F0C2"}.fa-flask:before{content:"\F0C3"}.fa-cut:before,.fa-scissors:before{content:"\F0C4"}.fa-copy:before,.fa-files-o:before{content:"\F0C5"}.fa-paperclip:before{content:"\F0C6"}.fa-floppy-o:before,.fa-save:before{content:"\F0C7"}.fa-square:before{content:"\F0C8"}.fa-bars:before,.fa-navicon:before,.fa-reorder:before{content:"\F0C9"}.fa-list-ul:before{content:"\F0CA"}.fa-list-ol:before{content:"\F0CB"}.fa-strikethrough:before{content:"\F0CC"}.fa-underline:before{content:"\F0CD"}.fa-table:before{content:"\F0CE"}.fa-magic:before{content:"\F0D0"}.fa-truck:before{content:"\F0D1"}.fa-pinterest:before{content:"\F0D2"}.fa-pinterest-square:before{content:"\F0D3"}.fa-google-plus-square:before{content:"\F0D4"}.fa-google-plus:before{content:"\F0D5"}.fa-money:before{content:"\F0D6"}.fa-caret-down:before{content:"\F0D7"}.fa-caret-up:before{content:"\F0D8"}.fa-caret-left:before{content:"\F0D9"}.fa-caret-right:before{content:"\F0DA"}.fa-columns:before{content:"\F0DB"}.fa-sort:before,.fa-unsorted:before{content:"\F0DC"}.fa-sort-desc:before,.fa-sort-down:before{content:"\F0DD"}.fa-sort-asc:before,.fa-sort-up:before{content:"\F0DE"}.fa-envelope:before{content:"\F0E0"}.fa-linkedin:before{content:"\F0E1"}.fa-rotate-left:before,.fa-undo:before{content:"\F0E2"}.fa-gavel:before,.fa-legal:before{content:"\F0E3"}.fa-dashboard:before,.fa-tachometer:before{content:"\F0E4"}.fa-comment-o:before{content:"\F0E5"}.fa-comments-o:before{content:"\F0E6"}.fa-bolt:before,.fa-flash:before{content:"\F0E7"}.fa-sitemap:before{content:"\F0E8"}.fa-umbrella:before{content:"\F0E9"}.fa-clipboard:before,.fa-paste:before{content:"\F0EA"}.fa-lightbulb-o:before{content:"\F0EB"}.fa-exchange:before{content:"\F0EC"}.fa-cloud-download:before{content:"\F0ED"}.fa-cloud-upload:before{content:"\F0EE"}.fa-user-md:before{content:"\F0F0"}.fa-stethoscope:before{content:"\F0F1"}.fa-suitcase:before{content:"\F0F2"}.fa-bell-o:before{content:"\F0A2"}.fa-coffee:before{content:"\F0F4"}.fa-cutlery:before{content:"\F0F5"}.fa-file-text-o:before{content:"\F0F6"}.fa-building-o:before{content:"\F0F7"}.fa-hospital-o:before{content:"\F0F8"}.fa-ambulance:before{content:"\F0F9"}.fa-medkit:before{content:"\F0FA"}.fa-fighter-jet:before{content:"\F0FB"}.fa-beer:before{content:"\F0FC"}.fa-h-square:before{content:"\F0FD"}.fa-plus-square:before{content:"\F0FE"}.fa-angle-double-left:before{content:"\F100"}.fa-angle-double-right:before{content:"\F101"}.fa-angle-double-up:before{content:"\F102"}.fa-angle-double-down:before{content:"\F103"}.fa-angle-left:before{content:"\F104"}.fa-angle-right:before{content:"\F105"}.fa-angle-up:before{content:"\F106"}.fa-angle-down:before{content:"\F107"}.fa-desktop:before{content:"\F108"}.fa-laptop:before{content:"\F109"}.fa-tablet:before{content:"\F10A"}.fa-mobile-phone:before,.fa-mobile:before{content:"\F10B"}.fa-circle-o:before{content:"\F10C"}.fa-quote-left:before{content:"\F10D"}.fa-quote-right:before{content:"\F10E"}.fa-spinner:before{content:"\F110"}.fa-circle:before{content:"\F111"}.fa-mail-reply:before,.fa-reply:before{content:"\F112"}.fa-github-alt:before{content:"\F113"}.fa-folder-o:before{content:"\F114"}.fa-folder-open-o:before{content:"\F115"}.fa-smile-o:before{content:"\F118"}.fa-frown-o:before{content:"\F119"}.fa-meh-o:before{content:"\F11A"}.fa-gamepad:before{content:"\F11B"}.fa-keyboard-o:before{content:"\F11C"}.fa-flag-o:before{content:"\F11D"}.fa-flag-checkered:before{content:"\F11E"}.fa-terminal:before{content:"\F120"}.fa-code:before{content:"\F121"}.fa-mail-reply-all:before,.fa-reply-all:before{content:"\F122"}.fa-star-half-empty:before,.fa-star-half-full:before,.fa-star-half-o:before{content:"\F123"}.fa-location-arrow:before{content:"\F124"}.fa-crop:before{content:"\F125"}.fa-code-fork:before{content:"\F126"}.fa-chain-broken:before,.fa-unlink:before{content:"\F127"}.fa-question:before{content:"\F128"}.fa-info:before{content:"\F129"}.fa-exclamation:before{content:"\F12A"}.fa-superscript:before{content:"\F12B"}.fa-subscript:before{content:"\F12C"}.fa-eraser:before{content:"\F12D"}.fa-puzzle-piece:before{content:"\F12E"}.fa-microphone:before{content:"\F130"}.fa-microphone-slash:before{content:"\F131"}.fa-shield:before{content:"\F132"}.fa-calendar-o:before{content:"\F133"}.fa-fire-extinguisher:before{content:"\F134"}.fa-rocket:before{content:"\F135"}.fa-maxcdn:before{content:"\F136"}.fa-chevron-circle-left:before{content:"\F137"}.fa-chevron-circle-right:before{content:"\F138"}.fa-chevron-circle-up:before{content:"\F139"}.fa-chevron-circle-down:before{content:"\F13A"}.fa-html5:before{content:"\F13B"}.fa-css3:before{content:"\F13C"}.fa-anchor:before{content:"\F13D"}.fa-unlock-alt:before{content:"\F13E"}.fa-bullseye:before{content:"\F140"}.fa-ellipsis-h:before{content:"\F141"}.fa-ellipsis-v:before{content:"\F142"}.fa-rss-square:before{content:"\F143"}.fa-play-circle:before{content:"\F144"}.fa-ticket:before{content:"\F145"}.fa-minus-square:before{content:"\F146"}.fa-minus-square-o:before{content:"\F147"}.fa-level-up:before{content:"\F148"}.fa-level-down:before{content:"\F149"}.fa-check-square:before{content:"\F14A"}.fa-pencil-square:before{content:"\F14B"}.fa-external-link-square:before{content:"\F14C"}.fa-share-square:before{content:"\F14D"}.fa-compass:before{content:"\F14E"}.fa-caret-square-o-down:before,.fa-toggle-down:before{content:"\F150"}.fa-caret-square-o-up:before,.fa-toggle-up:before{content:"\F151"}.fa-caret-square-o-right:before,.fa-toggle-right:before{content:"\F152"}.fa-eur:before,.fa-euro:before{content:"\F153"}.fa-gbp:before{content:"\F154"}.fa-dollar:before,.fa-usd:before{content:"\F155"}.fa-inr:before,.fa-rupee:before{content:"\F156"}.fa-cny:before,.fa-jpy:before,.fa-rmb:before,.fa-yen:before{content:"\F157"}.fa-rouble:before,.fa-rub:before,.fa-ruble:before{content:"\F158"}.fa-krw:before,.fa-won:before{content:"\F159"}.fa-bitcoin:before,.fa-btc:before{content:"\F15A"}.fa-file:before{content:"\F15B"}.fa-file-text:before{content:"\F15C"}.fa-sort-alpha-asc:before{content:"\F15D"}.fa-sort-alpha-desc:before{content:"\F15E"}.fa-sort-amount-asc:before{content:"\F160"}.fa-sort-amount-desc:before{content:"\F161"}.fa-sort-numeric-asc:before{content:"\F162"}.fa-sort-numeric-desc:before{content:"\F163"}.fa-thumbs-up:before{content:"\F164"}.fa-thumbs-down:before{content:"\F165"}.fa-youtube-square:before{content:"\F166"}.fa-youtube:before{content:"\F167"}.fa-xing:before{content:"\F168"}.fa-xing-square:before{content:"\F169"}.fa-youtube-play:before{content:"\F16A"}.fa-dropbox:before{content:"\F16B"}.fa-stack-overflow:before{content:"\F16C"}.fa-instagram:before{content:"\F16D"}.fa-flickr:before{content:"\F16E"}.fa-adn:before{content:"\F170"}.fa-bitbucket:before{content:"\F171"}.fa-bitbucket-square:before{content:"\F172"}.fa-tumblr:before{content:"\F173"}.fa-tumblr-square:before{content:"\F174"}.fa-long-arrow-down:before{content:"\F175"}.fa-long-arrow-up:before{content:"\F176"}.fa-long-arrow-left:before{content:"\F177"}.fa-long-arrow-right:before{content:"\F178"}.fa-apple:before{content:"\F179"}.fa-windows:before{content:"\F17A"}.fa-android:before{content:"\F17B"}.fa-linux:before{content:"\F17C"}.fa-dribbble:before{content:"\F17D"}.fa-skype:before{content:"\F17E"}.fa-foursquare:before{content:"\F180"}.fa-trello:before{content:"\F181"}.fa-female:before{content:"\F182"}.fa-male:before{content:"\F183"}.fa-gittip:before,.fa-gratipay:before{content:"\F184"}.fa-sun-o:before{content:"\F185"}.fa-moon-o:before{content:"\F186"}.fa-archive:before{content:"\F187"}.fa-bug:before{content:"\F188"}.fa-vk:before{content:"\F189"}.fa-weibo:before{content:"\F18A"}.fa-renren:before{content:"\F18B"}.fa-pagelines:before{content:"\F18C"}.fa-stack-exchange:before{content:"\F18D"}.fa-arrow-circle-o-right:before{content:"\F18E"}.fa-arrow-circle-o-left:before{content:"\F190"}.fa-caret-square-o-left:before,.fa-toggle-left:before{content:"\F191"}.fa-dot-circle-o:before{content:"\F192"}.fa-wheelchair:before{content:"\F193"}.fa-vimeo-square:before{content:"\F194"}.fa-try:before,.fa-turkish-lira:before{content:"\F195"}.fa-plus-square-o:before{content:"\F196"}.fa-space-shuttle:before{content:"\F197"}.fa-slack:before{content:"\F198"}.fa-envelope-square:before{content:"\F199"}.fa-wordpress:before{content:"\F19A"}.fa-openid:before{content:"\F19B"}.fa-bank:before,.fa-institution:before,.fa-university:before{content:"\F19C"}.fa-graduation-cap:before,.fa-mortar-board:before{content:"\F19D"}.fa-yahoo:before{content:"\F19E"}.fa-google:before{content:"\F1A0"}.fa-reddit:before{content:"\F1A1"}.fa-reddit-square:before{content:"\F1A2"}.fa-stumbleupon-circle:before{content:"\F1A3"}.fa-stumbleupon:before{content:"\F1A4"}.fa-delicious:before{content:"\F1A5"}.fa-digg:before{content:"\F1A6"}.fa-pied-piper-pp:before{content:"\F1A7"}.fa-pied-piper-alt:before{content:"\F1A8"}.fa-drupal:before{content:"\F1A9"}.fa-joomla:before{content:"\F1AA"}.fa-language:before{content:"\F1AB"}.fa-fax:before{content:"\F1AC"}.fa-building:before{content:"\F1AD"}.fa-child:before{content:"\F1AE"}.fa-paw:before{content:"\F1B0"}.fa-spoon:before{content:"\F1B1"}.fa-cube:before{content:"\F1B2"}.fa-cubes:before{content:"\F1B3"}.fa-behance:before{content:"\F1B4"}.fa-behance-square:before{content:"\F1B5"}.fa-steam:before{content:"\F1B6"}.fa-steam-square:before{content:"\F1B7"}.fa-recycle:before{content:"\F1B8"}.fa-automobile:before,.fa-car:before{content:"\F1B9"}.fa-cab:before,.fa-taxi:before{content:"\F1BA"}.fa-tree:before{content:"\F1BB"}.fa-spotify:before{content:"\F1BC"}.fa-deviantart:before{content:"\F1BD"}.fa-soundcloud:before{content:"\F1BE"}.fa-database:before{content:"\F1C0"}.fa-file-pdf-o:before{content:"\F1C1"}.fa-file-word-o:before{content:"\F1C2"}.fa-file-excel-o:before{content:"\F1C3"}.fa-file-powerpoint-o:before{content:"\F1C4"}.fa-file-image-o:before,.fa-file-photo-o:before,.fa-file-picture-o:before{content:"\F1C5"}.fa-file-archive-o:before,.fa-file-zip-o:before{content:"\F1C6"}.fa-file-audio-o:before,.fa-file-sound-o:before{content:"\F1C7"}.fa-file-movie-o:before,.fa-file-video-o:before{content:"\F1C8"}.fa-file-code-o:before{content:"\F1C9"}.fa-vine:before{content:"\F1CA"}.fa-codepen:before{content:"\F1CB"}.fa-jsfiddle:before{content:"\F1CC"}.fa-life-bouy:before,.fa-life-buoy:before,.fa-life-ring:before,.fa-life-saver:before,.fa-support:before{content:"\F1CD"}.fa-circle-o-notch:before{content:"\F1CE"}.fa-ra:before,.fa-rebel:before,.fa-resistance:before{content:"\F1D0"}.fa-empire:before,.fa-ge:before{content:"\F1D1"}.fa-git-square:before{content:"\F1D2"}.fa-git:before{content:"\F1D3"}.fa-hacker-news:before,.fa-y-combinator-square:before,.fa-yc-square:before{content:"\F1D4"}.fa-tencent-weibo:before{content:"\F1D5"}.fa-qq:before{content:"\F1D6"}.fa-wechat:before,.fa-weixin:before{content:"\F1D7"}.fa-paper-plane:before,.fa-send:before{content:"\F1D8"}.fa-paper-plane-o:before,.fa-send-o:before{content:"\F1D9"}.fa-history:before{content:"\F1DA"}.fa-circle-thin:before{content:"\F1DB"}.fa-header:before{content:"\F1DC"}.fa-paragraph:before{content:"\F1DD"}.fa-sliders:before{content:"\F1DE"}.fa-share-alt:before{content:"\F1E0"}.fa-share-alt-square:before{content:"\F1E1"}.fa-bomb:before{content:"\F1E2"}.fa-futbol-o:before,.fa-soccer-ball-o:before{content:"\F1E3"}.fa-tty:before{content:"\F1E4"}.fa-binoculars:before{content:"\F1E5"}.fa-plug:before{content:"\F1E6"}.fa-slideshare:before{content:"\F1E7"}.fa-twitch:before{content:"\F1E8"}.fa-yelp:before{content:"\F1E9"}.fa-newspaper-o:before{content:"\F1EA"}.fa-wifi:before{content:"\F1EB"}.fa-calculator:before{content:"\F1EC"}.fa-paypal:before{content:"\F1ED"}.fa-google-wallet:before{content:"\F1EE"}.fa-cc-visa:before{content:"\F1F0"}.fa-cc-mastercard:before{content:"\F1F1"}.fa-cc-discover:before{content:"\F1F2"}.fa-cc-amex:before{content:"\F1F3"}.fa-cc-paypal:before{content:"\F1F4"}.fa-cc-stripe:before{content:"\F1F5"}.fa-bell-slash:before{content:"\F1F6"}.fa-bell-slash-o:before{content:"\F1F7"}.fa-trash:before{content:"\F1F8"}.fa-copyright:before{content:"\F1F9"}.fa-at:before{content:"\F1FA"}.fa-eyedropper:before{content:"\F1FB"}.fa-paint-brush:before{content:"\F1FC"}.fa-birthday-cake:before{content:"\F1FD"}.fa-area-chart:before{content:"\F1FE"}.fa-pie-chart:before{content:"\F200"}.fa-line-chart:before{content:"\F201"}.fa-lastfm:before{content:"\F202"}.fa-lastfm-square:before{content:"\F203"}.fa-toggle-off:before{content:"\F204"}.fa-toggle-on:before{content:"\F205"}.fa-bicycle:before{content:"\F206"}.fa-bus:before{content:"\F207"}.fa-ioxhost:before{content:"\F208"}.fa-angellist:before{content:"\F209"}.fa-cc:before{content:"\F20A"}.fa-ils:before,.fa-shekel:before,.fa-sheqel:before{content:"\F20B"}.fa-meanpath:before{content:"\F20C"}.fa-buysellads:before{content:"\F20D"}.fa-connectdevelop:before{content:"\F20E"}.fa-dashcube:before{content:"\F210"}.fa-forumbee:before{content:"\F211"}.fa-leanpub:before{content:"\F212"}.fa-sellsy:before{content:"\F213"}.fa-shirtsinbulk:before{content:"\F214"}.fa-simplybuilt:before{content:"\F215"}.fa-skyatlas:before{content:"\F216"}.fa-cart-plus:before{content:"\F217"}.fa-cart-arrow-down:before{content:"\F218"}.fa-diamond:before{content:"\F219"}.fa-ship:before{content:"\F21A"}.fa-user-secret:before{content:"\F21B"}.fa-motorcycle:before{content:"\F21C"}.fa-street-view:before{content:"\F21D"}.fa-heartbeat:before{content:"\F21E"}.fa-venus:before{content:"\F221"}.fa-mars:before{content:"\F222"}.fa-mercury:before{content:"\F223"}.fa-intersex:before,.fa-transgender:before{content:"\F224"}.fa-transgender-alt:before{content:"\F225"}.fa-venus-double:before{content:"\F226"}.fa-mars-double:before{content:"\F227"}.fa-venus-mars:before{content:"\F228"}.fa-mars-stroke:before{content:"\F229"}.fa-mars-stroke-v:before{content:"\F22A"}.fa-mars-stroke-h:before{content:"\F22B"}.fa-neuter:before{content:"\F22C"}.fa-genderless:before{content:"\F22D"}.fa-facebook-official:before{content:"\F230"}.fa-pinterest-p:before{content:"\F231"}.fa-whatsapp:before{content:"\F232"}.fa-server:before{content:"\F233"}.fa-user-plus:before{content:"\F234"}.fa-user-times:before{content:"\F235"}.fa-bed:before,.fa-hotel:before{content:"\F236"}.fa-viacoin:before{content:"\F237"}.fa-train:before{content:"\F238"}.fa-subway:before{content:"\F239"}.fa-medium:before{content:"\F23A"}.fa-y-combinator:before,.fa-yc:before{content:"\F23B"}.fa-optin-monster:before{content:"\F23C"}.fa-opencart:before{content:"\F23D"}.fa-expeditedssl:before{content:"\F23E"}.fa-battery-4:before,.fa-battery-full:before,.fa-battery:before{content:"\F240"}.fa-battery-3:before,.fa-battery-three-quarters:before{content:"\F241"}.fa-battery-2:before,.fa-battery-half:before{content:"\F242"}.fa-battery-1:before,.fa-battery-quarter:before{content:"\F243"}.fa-battery-0:before,.fa-battery-empty:before{content:"\F244"}.fa-mouse-pointer:before{content:"\F245"}.fa-i-cursor:before{content:"\F246"}.fa-object-group:before{content:"\F247"}.fa-object-ungroup:before{content:"\F248"}.fa-sticky-note:before{content:"\F249"}.fa-sticky-note-o:before{content:"\F24A"}.fa-cc-jcb:before{content:"\F24B"}.fa-cc-diners-club:before{content:"\F24C"}.fa-clone:before{content:"\F24D"}.fa-balance-scale:before{content:"\F24E"}.fa-hourglass-o:before{content:"\F250"}.fa-hourglass-1:before,.fa-hourglass-start:before{content:"\F251"}.fa-hourglass-2:before,.fa-hourglass-half:before{content:"\F252"}.fa-hourglass-3:before,.fa-hourglass-end:before{content:"\F253"}.fa-hourglass:before{content:"\F254"}.fa-hand-grab-o:before,.fa-hand-rock-o:before{content:"\F255"}.fa-hand-paper-o:before,.fa-hand-stop-o:before{content:"\F256"}.fa-hand-scissors-o:before{content:"\F257"}.fa-hand-lizard-o:before{content:"\F258"}.fa-hand-spock-o:before{content:"\F259"}.fa-hand-pointer-o:before{content:"\F25A"}.fa-hand-peace-o:before{content:"\F25B"}.fa-trademark:before{content:"\F25C"}.fa-registered:before{content:"\F25D"}.fa-creative-commons:before{content:"\F25E"}.fa-gg:before{content:"\F260"}.fa-gg-circle:before{content:"\F261"}.fa-tripadvisor:before{content:"\F262"}.fa-odnoklassniki:before{content:"\F263"}.fa-odnoklassniki-square:before{content:"\F264"}.fa-get-pocket:before{content:"\F265"}.fa-wikipedia-w:before{content:"\F266"}.fa-safari:before{content:"\F267"}.fa-chrome:before{content:"\F268"}.fa-firefox:before{content:"\F269"}.fa-opera:before{content:"\F26A"}.fa-internet-explorer:before{content:"\F26B"}.fa-television:before,.fa-tv:before{content:"\F26C"}.fa-contao:before{content:"\F26D"}.fa-500px:before{content:"\F26E"}.fa-amazon:before{content:"\F270"}.fa-calendar-plus-o:before{content:"\F271"}.fa-calendar-minus-o:before{content:"\F272"}.fa-calendar-times-o:before{content:"\F273"}.fa-calendar-check-o:before{content:"\F274"}.fa-industry:before{content:"\F275"}.fa-map-pin:before{content:"\F276"}.fa-map-signs:before{content:"\F277"}.fa-map-o:before{content:"\F278"}.fa-map:before{content:"\F279"}.fa-commenting:before{content:"\F27A"}.fa-commenting-o:before{content:"\F27B"}.fa-houzz:before{content:"\F27C"}.fa-vimeo:before{content:"\F27D"}.fa-black-tie:before{content:"\F27E"}.fa-fonticons:before{content:"\F280"}.fa-reddit-alien:before{content:"\F281"}.fa-edge:before{content:"\F282"}.fa-credit-card-alt:before{content:"\F283"}.fa-codiepie:before{content:"\F284"}.fa-modx:before{content:"\F285"}.fa-fort-awesome:before{content:"\F286"}.fa-usb:before{content:"\F287"}.fa-product-hunt:before{content:"\F288"}.fa-mixcloud:before{content:"\F289"}.fa-scribd:before{content:"\F28A"}.fa-pause-circle:before{content:"\F28B"}.fa-pause-circle-o:before{content:"\F28C"}.fa-stop-circle:before{content:"\F28D"}.fa-stop-circle-o:before{content:"\F28E"}.fa-shopping-bag:before{content:"\F290"}.fa-shopping-basket:before{content:"\F291"}.fa-hashtag:before{content:"\F292"}.fa-bluetooth:before{content:"\F293"}.fa-bluetooth-b:before{content:"\F294"}.fa-percent:before{content:"\F295"}.fa-gitlab:before{content:"\F296"}.fa-wpbeginner:before{content:"\F297"}.fa-wpforms:before{content:"\F298"}.fa-envira:before{content:"\F299"}.fa-universal-access:before{content:"\F29A"}.fa-wheelchair-alt:before{content:"\F29B"}.fa-question-circle-o:before{content:"\F29C"}.fa-blind:before{content:"\F29D"}.fa-audio-description:before{content:"\F29E"}.fa-volume-control-phone:before{content:"\F2A0"}.fa-braille:before{content:"\F2A1"}.fa-assistive-listening-systems:before{content:"\F2A2"}.fa-american-sign-language-interpreting:before,.fa-asl-interpreting:before{content:"\F2A3"}.fa-deaf:before,.fa-deafness:before,.fa-hard-of-hearing:before{content:"\F2A4"}.fa-glide:before{content:"\F2A5"}.fa-glide-g:before{content:"\F2A6"}.fa-sign-language:before,.fa-signing:before{content:"\F2A7"}.fa-low-vision:before{content:"\F2A8"}.fa-viadeo:before{content:"\F2A9"}.fa-viadeo-square:before{content:"\F2AA"}.fa-snapchat:before{content:"\F2AB"}.fa-snapchat-ghost:before{content:"\F2AC"}.fa-snapchat-square:before{content:"\F2AD"}.fa-pied-piper:before{content:"\F2AE"}.fa-first-order:before{content:"\F2B0"}.fa-yoast:before{content:"\F2B1"}.fa-themeisle:before{content:"\F2B2"}.fa-google-plus-circle:before,.fa-google-plus-official:before{content:"\F2B3"}.fa-fa:before,.fa-font-awesome:before{content:"\F2B4"}.fa-handshake-o:before{content:"\F2B5"}.fa-envelope-open:before{content:"\F2B6"}.fa-envelope-open-o:before{content:"\F2B7"}.fa-linode:before{content:"\F2B8"}.fa-address-book:before{content:"\F2B9"}.fa-address-book-o:before{content:"\F2BA"}.fa-address-card:before,.fa-vcard:before{content:"\F2BB"}.fa-address-card-o:before,.fa-vcard-o:before{content:"\F2BC"}.fa-user-circle:before{content:"\F2BD"}.fa-user-circle-o:before{content:"\F2BE"}.fa-user-o:before{content:"\F2C0"}.fa-id-badge:before{content:"\F2C1"}.fa-drivers-license:before,.fa-id-card:before{content:"\F2C2"}.fa-drivers-license-o:before,.fa-id-card-o:before{content:"\F2C3"}.fa-quora:before{content:"\F2C4"}.fa-free-code-camp:before{content:"\F2C5"}.fa-telegram:before{content:"\F2C6"}.fa-thermometer-4:before,.fa-thermometer-full:before,.fa-thermometer:before{content:"\F2C7"}.fa-thermometer-3:before,.fa-thermometer-three-quarters:before{content:"\F2C8"}.fa-thermometer-2:before,.fa-thermometer-half:before{content:"\F2C9"}.fa-thermometer-1:before,.fa-thermometer-quarter:before{content:"\F2CA"}.fa-thermometer-0:before,.fa-thermometer-empty:before{content:"\F2CB"}.fa-shower:before{content:"\F2CC"}.fa-bath:before,.fa-bathtub:before,.fa-s15:before{content:"\F2CD"}.fa-podcast:before{content:"\F2CE"}.fa-window-maximize:before{content:"\F2D0"}.fa-window-minimize:before{content:"\F2D1"}.fa-window-restore:before{content:"\F2D2"}.fa-times-rectangle:before,.fa-window-close:before{content:"\F2D3"}.fa-times-rectangle-o:before,.fa-window-close-o:before{content:"\F2D4"}.fa-bandcamp:before{content:"\F2D5"}.fa-grav:before{content:"\F2D6"}.fa-etsy:before{content:"\F2D7"}.fa-imdb:before{content:"\F2D8"}.fa-ravelry:before{content:"\F2D9"}.fa-eercast:before{content:"\F2DA"}.fa-microchip:before{content:"\F2DB"}.fa-snowflake-o:before{content:"\F2DC"}.fa-superpowers:before{content:"\F2DD"}.fa-wpexplorer:before{content:"\F2DE"}.fa-meetup:before{content:"\F2E0"}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);border:0}.sr-only-focusable:active,.sr-only-focusable:focus{position:static;width:auto;height:auto;margin:0;overflow:visible;clip:auto}
5 | /*# sourceMappingURL=app.css.map*/
--------------------------------------------------------------------------------
/public/fonts/vendor/element-ui/lib/theme-chalk/element-icons.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/z-song/redis-manager/7888a01db0a78056e04dce757ea396d1d2f6e0fb/public/fonts/vendor/element-ui/lib/theme-chalk/element-icons.ttf
--------------------------------------------------------------------------------
/public/fonts/vendor/element-ui/lib/theme-chalk/element-icons.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/z-song/redis-manager/7888a01db0a78056e04dce757ea396d1d2f6e0fb/public/fonts/vendor/element-ui/lib/theme-chalk/element-icons.woff
--------------------------------------------------------------------------------
/public/fonts/vendor/font-awesome/fontawesome-webfont.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/z-song/redis-manager/7888a01db0a78056e04dce757ea396d1d2f6e0fb/public/fonts/vendor/font-awesome/fontawesome-webfont.eot
--------------------------------------------------------------------------------
/public/fonts/vendor/font-awesome/fontawesome-webfont.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/z-song/redis-manager/7888a01db0a78056e04dce757ea396d1d2f6e0fb/public/fonts/vendor/font-awesome/fontawesome-webfont.ttf
--------------------------------------------------------------------------------
/public/fonts/vendor/font-awesome/fontawesome-webfont.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/z-song/redis-manager/7888a01db0a78056e04dce757ea396d1d2f6e0fb/public/fonts/vendor/font-awesome/fontawesome-webfont.woff
--------------------------------------------------------------------------------
/public/fonts/vendor/font-awesome/fontawesome-webfont.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/z-song/redis-manager/7888a01db0a78056e04dce757ea396d1d2f6e0fb/public/fonts/vendor/font-awesome/fontawesome-webfont.woff2
--------------------------------------------------------------------------------
/public/img/logo.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/public/mix-manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "/js/app.js": "/js/app.js?id=e6bc45bd5d6373fb5e32",
3 | "/css/app.css": "/css/app.css?id=67967ba67a8828022cac",
4 | "/js/app.js.map": "/js/app.js.map?id=cb6c7470a2d39a7d8325",
5 | "/css/app.css.map": "/css/app.css.map?id=3303343d4ed19631681f"
6 | }
--------------------------------------------------------------------------------
/resources/assets/img/logo.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/resources/assets/js/app.js:
--------------------------------------------------------------------------------
1 |
2 | import Vue from 'vue';
3 | import router from './router';
4 | import Redis from './redis';
5 | import './elementui';
6 | import App from './components/App.vue';
7 |
8 | Vue.prototype.$redis = Redis.create();
9 |
10 | window.Bus = new Vue({ name: 'Bus' });
11 |
12 | const app = new Vue({
13 | el: '#app',
14 | router,
15 | render: h => h(App),
16 | });
17 |
--------------------------------------------------------------------------------
/resources/assets/js/components/App.vue:
--------------------------------------------------------------------------------
1 |
6 |
7 |
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/resources/assets/js/components/Charts/LineChart.js:
--------------------------------------------------------------------------------
1 | import { Line, mixins } from 'vue-chartjs'
2 | const { reactiveProp } = mixins
3 |
4 | export default {
5 | extends: Line,
6 | mixins: [reactiveProp],
7 | props: ['options'],
8 | mounted () {
9 | this.renderChart(this.chartData, this.options)
10 | }
11 | }
--------------------------------------------------------------------------------
/resources/assets/js/components/Layout.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
58 |
59 |
--------------------------------------------------------------------------------
/resources/assets/js/components/Siderbar.vue:
--------------------------------------------------------------------------------
1 |
2 |
31 |
32 |
41 |
44 |
--------------------------------------------------------------------------------
/resources/assets/js/elementui.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue';
2 |
3 | import {
4 | Button, Select, Option, Input, Dropdown, DropdownMenu, DropdownItem, Menu,
5 | MenuItem, Submenu, ButtonGroup, Table, TableColumn, Tag, Row, Col, Card,
6 | Alert, Form, FormItem, InputNumber, Dialog, Header, Container, Aside, Main,
7 | Loading, MessageBox, Message
8 | } from 'element-ui'
9 |
10 | Vue.use(Button);
11 | Vue.use(Select);
12 | Vue.use(Option);
13 | Vue.use(Input);
14 | Vue.use(Dropdown);
15 | Vue.use(DropdownMenu);
16 | Vue.use(DropdownItem);
17 | Vue.use(Menu);
18 | Vue.use(MenuItem);
19 | Vue.use(Submenu);
20 | Vue.use(ButtonGroup);
21 | Vue.use(Table);
22 | Vue.use(TableColumn);
23 | Vue.use(Tag);
24 | Vue.use(Row);
25 | Vue.use(Col);
26 | Vue.use(Card);
27 | Vue.use(Alert);
28 | Vue.use(Form);
29 | Vue.use(FormItem);
30 | Vue.use(InputNumber);
31 | Vue.use(Dialog);
32 | Vue.use(Header);
33 | Vue.use(Container);
34 | Vue.use(Aside);
35 | Vue.use(Aside);
36 | Vue.use(Main);
37 |
38 | Vue.use(Loading.directive);
39 |
40 | Vue.prototype.$loading = Loading.service;
41 | Vue.prototype.$confirm = MessageBox.confirm;
42 | Vue.prototype.$message = Message;
--------------------------------------------------------------------------------
/resources/assets/js/pages/Console.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
25 |
26 |
27 |
28 |
29 |
{{ result.command }}
30 |
{{ result.data | pretty }}
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 | <
80 |
81 |
--------------------------------------------------------------------------------
/resources/assets/js/pages/Info.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
6 |
7 |
8 |
9 | Server
10 |
11 |
12 |
13 |
14 | {{ key }} |
15 | {{ val }} |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 | Clients
25 |
26 |
27 |
28 |
29 | {{ key }} |
30 | {{ val }} |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 | Stats
40 |
41 |
42 |
43 |
44 | {{ key }} |
45 | {{ val }} |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 | Replication
55 |
56 |
57 |
58 |
59 | {{ key }} |
60 | {{ val }} |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 | Memory
72 |
73 |
74 |
75 |
76 | {{ key }} |
77 | {{ val }} |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 | CPU
87 |
88 |
89 |
90 |
91 | {{ key }} |
92 | {{ val }} |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 | Keyspace
102 |
103 |
104 |
105 |
106 | {{ key }} |
107 | {{ val }} |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 | Persistence
117 |
118 |
119 |
120 |
121 | {{ key }} |
122 | {{ val }} |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 | Cluster
132 |
133 |
134 |
135 |
136 | {{ key }} |
137 | {{ val }} |
138 |
139 |
140 |
141 |
142 |
143 |
144 |
145 |
146 |
147 |
148 |
180 |
216 |
--------------------------------------------------------------------------------
/resources/assets/js/pages/Keys.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
30 |
31 |
32 |
39 |
42 |
43 |
46 |
47 |
50 |
51 | {{ scope.row.type }}
52 |
53 |
54 |
55 |
58 |
59 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
83 |
84 |
--------------------------------------------------------------------------------
/resources/assets/js/pages/create/Hash.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
16 |
17 |
18 | Remove
19 |
20 |
21 |
22 | Add Field
23 |
24 |
25 |
26 | Submit
27 | Reset
28 |
29 |
30 |
31 |
32 |
45 |
110 |
--------------------------------------------------------------------------------
/resources/assets/js/pages/create/Index.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | Create
9 |
10 |
11 | {{ current() }}
12 |
13 |
14 | {{ type.toUpperCase() }}
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
30 |
31 |
63 |
64 |
--------------------------------------------------------------------------------
/resources/assets/js/pages/create/List.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
18 |
19 |
20 | Remove
21 |
22 |
23 |
24 | Add Member
25 |
26 |
27 |
28 | Submit
29 | Reset
30 |
31 |
32 |
33 |
34 |
35 |
36 |
49 |
116 |
--------------------------------------------------------------------------------
/resources/assets/js/pages/create/Set.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
17 | {{member}}
18 |
19 |
28 |
29 | + New Member
30 |
31 |
32 | Submit
33 | Reset
34 |
35 |
36 |
37 |
38 |
59 |
146 |
--------------------------------------------------------------------------------
/resources/assets/js/pages/create/String.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 | Create
15 | Reset
16 |
17 |
18 |
19 |
20 |
25 |
77 |
--------------------------------------------------------------------------------
/resources/assets/js/pages/create/Zset.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
17 |
18 |
19 | Remove
20 |
21 |
22 |
23 | Add Member
24 |
25 |
26 |
27 | Submit
28 | Reset
29 |
30 |
31 |
32 |
33 |
46 |
116 |
--------------------------------------------------------------------------------
/resources/assets/js/pages/edit/Hash.vue:
--------------------------------------------------------------------------------
1 |
2 |
70 |
71 |
90 |
230 |
--------------------------------------------------------------------------------
/resources/assets/js/pages/edit/Index.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Edit {{ current() }} {{ this.$route.query.key }}
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
29 |
30 |
89 |
90 |
--------------------------------------------------------------------------------
/resources/assets/js/pages/edit/List.vue:
--------------------------------------------------------------------------------
1 |
2 |
73 |
74 |
75 |
88 |
234 |
--------------------------------------------------------------------------------
/resources/assets/js/pages/edit/Set.vue:
--------------------------------------------------------------------------------
1 |
2 |
39 |
40 |
61 |
149 |
--------------------------------------------------------------------------------
/resources/assets/js/pages/edit/String.vue:
--------------------------------------------------------------------------------
1 |
2 |
25 |
26 |
36 |
93 |
--------------------------------------------------------------------------------
/resources/assets/js/pages/edit/Zset.vue:
--------------------------------------------------------------------------------
1 |
2 |
70 |
71 |
86 |
217 |
--------------------------------------------------------------------------------
/resources/assets/js/pages/metrics/CPU.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CPU
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
157 |
158 |
--------------------------------------------------------------------------------
/resources/assets/js/pages/metrics/Clients.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Clients
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
157 |
158 |
--------------------------------------------------------------------------------
/resources/assets/js/pages/metrics/Index.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/resources/assets/js/pages/metrics/Memory.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | memory
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
164 |
165 |
--------------------------------------------------------------------------------
/resources/assets/js/pages/metrics/Throughput.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Throughput
5 |
6 |
7 |
8 |
9 |
10 | Command |
11 | calls |
12 | usec |
13 | usec_per_call |
14 |
15 |
16 |
17 |
18 |
19 | {{ command }} |
20 | {{ info.calls }} |
21 | {{ info.usec }} |
22 | {{ info.usec_per_call }} |
23 |
24 |
25 |
26 |
27 |
28 |
60 |
90 |
--------------------------------------------------------------------------------
/resources/assets/js/redis.js:
--------------------------------------------------------------------------------
1 |
2 | import axios from 'axios';
3 |
4 | export default class {
5 |
6 | constructor() {
7 | this.$http = axios.create({baseURL: window.basePath + '/api/'});
8 |
9 | this.conn = 'default';
10 | }
11 |
12 | static create() {
13 | return new this;
14 | }
15 |
16 | getConnection() {
17 | return localStorage.getItem('conn') || 'default'
18 | }
19 |
20 | connections() {
21 | return this.$http.get('/connections');
22 | }
23 |
24 | info(section = null) {
25 | return this.$http.get('/info', {
26 | params: {section, conn: this.getConnection() },
27 | });
28 | }
29 |
30 | expire(key, seconds) {
31 | const params = {
32 | key,
33 | seconds,
34 | conn: this.getConnection()
35 | }
36 |
37 | return this.$http.put('/expire', params);
38 | }
39 |
40 | get(key) {
41 | return this.$http.get('/key', {
42 | params: { key, conn: this.getConnection() },
43 | });
44 | }
45 |
46 | del(keys) {
47 | return this.$http.delete('/keys', {
48 | params: { keys, conn: this.getConnection() },
49 | });
50 | }
51 |
52 | set(key, value) {
53 | const params = {
54 | type: 'string',
55 | key,
56 | value,
57 | conn: this.getConnection(),
58 | };
59 |
60 | return this.$http.post('/keys', params);
61 | }
62 |
63 | setex(key, seconds, value) {
64 | const params = {
65 | type: 'string',
66 | key,
67 | value,
68 | seconds,
69 | conn: this.getConnection(),
70 | };
71 |
72 | return this.$http.post('/keys', params);
73 | }
74 |
75 | hgetall(key) {
76 | return this.get(key);
77 | }
78 |
79 | hmset(key, dic, seconds = null) {
80 | const params = {
81 | type: 'hash',
82 | key,
83 | dic,
84 | seconds,
85 | conn: this.getConnection(),
86 | };
87 |
88 | return this.$http.post('/keys', params);
89 | }
90 |
91 | hset(key, name, value) {
92 | const dic = {
93 | name,
94 | value,
95 | };
96 |
97 | return this.hmset(key, [dic], null);
98 | }
99 |
100 | hdel(key, field) {
101 |
102 | const type = 'hash'
103 | const conn = this.getConnection()
104 |
105 | return this.$http.delete('/keys/item', {
106 | params: { key, field, type, conn },
107 | });
108 | }
109 |
110 | smembers(key) {
111 | return this.get(key);
112 | }
113 |
114 | sadd(key, members, seconds) {
115 | const params = {
116 | type: 'set',
117 | key,
118 | members,
119 | seconds,
120 | conn: this.getConnection(),
121 | };
122 |
123 | return this.$http.post('/keys', params);
124 | }
125 |
126 | srem(key, member) {
127 | const params = {
128 | type: 'set',
129 | action: 'srem',
130 | key,
131 | member,
132 | conn: this.getConnection(),
133 | };
134 |
135 | return this.$http.put('/keys', params);
136 | }
137 |
138 | lall(key) {
139 | return this.get(key)
140 | }
141 |
142 | lpush(key, members, seconds) {
143 | const params = {
144 | type: 'list',
145 | action: 'lpush',
146 | key,
147 | members,
148 | seconds,
149 | conn: this.getConnection(),
150 | };
151 |
152 | return this.$http.put('/keys', params);
153 | }
154 |
155 | rpush(key, members, seconds) {
156 | const params = {
157 | type: 'list',
158 | action: 'rpush',
159 | key,
160 | members,
161 | seconds,
162 | conn: this.getConnection(),
163 | };
164 |
165 | return this.$http.put('/keys', params);
166 | }
167 |
168 | lstore(key, members, seconds) {
169 | const params = {
170 | type: 'list',
171 | action: 'rpush',
172 | key,
173 | members,
174 | seconds,
175 | conn: this.getConnection(),
176 | };
177 |
178 | return this.$http.post('/keys', params);
179 | }
180 |
181 | ldel(key, index) {
182 |
183 | const type = 'list'
184 | const conn = this.getConnection()
185 |
186 | return this.$http.delete('/keys/item', {
187 | params: { key, index, type, conn },
188 | });
189 | }
190 |
191 | lset(key, index, value) {
192 | const params = {
193 | type: 'list',
194 | action: 'lset',
195 | key,
196 | value,
197 | index,
198 | conn: this.getConnection(),
199 | };
200 |
201 | return this.$http.put('/keys', params);
202 | }
203 |
204 | zall(key) {
205 | return this.get(key);
206 | }
207 |
208 | zadd(key, members, seconds = null) {
209 | const params = {
210 | type: 'zset',
211 | key,
212 | members,
213 | seconds,
214 | conn: this.getConnection(),
215 | };
216 |
217 | return this.$http.post('/keys', params);
218 | }
219 |
220 | zrem(key, member) {
221 | const params = {
222 | type: 'zset',
223 | action: 'zrem',
224 | key,
225 | member,
226 | conn: this.getConnection(),
227 | };
228 |
229 | return this.$http.put('/keys', params);
230 | }
231 |
232 | zset(key, member, score) {
233 | const params = {
234 | type: 'zset',
235 | action: 'zset',
236 | key,
237 | member,
238 | score,
239 | conn: this.getConnection(),
240 | };
241 |
242 | return this.$http.put('/keys', params);
243 | }
244 |
245 | scan(pattern) {
246 | const params = {
247 | pattern,
248 | conn: this.getConnection(),
249 | };
250 |
251 | return this.$http.get('/scan', { params });
252 | }
253 |
254 | eval(command, db = null) {
255 | const params = {
256 | command,
257 | db,
258 | conn: this.getConnection(),
259 | };
260 |
261 | return this.$http.post('/eval', params);
262 | }
263 |
264 | }
265 |
--------------------------------------------------------------------------------
/resources/assets/js/router.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue';
2 | import Router from 'vue-router';
3 |
4 | Vue.use(Router);
5 |
6 | export default new Router({
7 | mode: 'history',
8 | base: window.basePath,
9 | routes: [
10 | { path: '/', component: require('./pages/Keys.vue'), },
11 | {
12 | path: '/create',
13 | component: require('./pages/create/Index.vue'),
14 | children: [
15 | { path: '/', redirect: 'string' },
16 | { path: 'string', component: require('./pages/create/String.vue') },
17 | { path: 'hash', component: require('./pages/create/Hash.vue') },
18 | { path: 'list', component: require('./pages/create/List.vue') },
19 | { path: 'set', component: require('./pages/create/Set.vue') },
20 | { path: 'zset', component: require('./pages/create/Zset.vue') },
21 | ],
22 | },
23 | {
24 | path: '/edit',
25 | component: require('./pages/edit/Index.vue'),
26 | children: [
27 | { path: '/', redirect: 'string' },
28 | { path: 'string', component: require('./pages/edit/String.vue') },
29 | { path: 'hash', component: require('./pages/edit/Hash.vue') },
30 | { path: 'list', component: require('./pages/edit/List.vue') },
31 | { path: 'set', component: require('./pages/edit/Set.vue') },
32 | { path: 'zset', component: require('./pages/edit/Zset.vue') },
33 | ],
34 | },
35 | { path: '/info', component: require('./pages/Info.vue'), },
36 | { path: '/console', component: require('./pages/Console.vue'), },
37 | {
38 | path: '/metrics',
39 | component: require('./pages/metrics/Index.vue'),
40 | children: [
41 | { path: '/', redirect: 'memory', },
42 | { path: 'memory', component: require('./pages/metrics/Memory.vue'), },
43 | { path: 'cpu', component: require('./pages/metrics/Cpu.vue'), },
44 | { path: 'clients', component: require('./pages/metrics/Clients.vue'), },
45 | { path: 'throughput', component: require('./pages/metrics/Throughput.vue'), },],
46 | },
47 | ],
48 | });
49 |
--------------------------------------------------------------------------------
/resources/assets/sass/app.scss:
--------------------------------------------------------------------------------
1 |
2 | @import "~font-awesome/css/font-awesome";
3 |
4 | /* theme color */
5 | $--color-primary: teal;
--------------------------------------------------------------------------------
/resources/views/app.blade.php:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 | {{ config('app.name', 'Laravel') }}
12 |
13 |
14 |
15 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/routes/web.php:
--------------------------------------------------------------------------------
1 | 'api'], function (Router $router) {
7 | $router->get('/connections', 'RedisController@connections');
8 | $router->get('/scan', 'RedisController@scan');
9 | $router->delete('/keys', 'RedisController@destroy');
10 | $router->post('/keys', 'RedisController@store');
11 | $router->put('/keys', 'RedisController@update');
12 | $router->get('/key', 'RedisController@key');
13 | $router->get('/info', 'RedisController@info');
14 | $router->delete('/keys/item', 'RedisController@remove');
15 | $router->put('/expire', 'RedisController@expire');
16 | $router->post('/eval', 'RedisController@eval');
17 | });
18 |
19 | Route::get('/{view?}', 'RedisController@index')->where('view', '(.*)');
20 |
--------------------------------------------------------------------------------
/src/DataType/DataType.php:
--------------------------------------------------------------------------------
1 | connection = $connection;
22 | }
23 |
24 | /**
25 | * Get redis connection.
26 | *
27 | * @return Connection
28 | */
29 | public function getConnection()
30 | {
31 | return $this->connection;
32 | }
33 |
34 | /**
35 | * @param string $key
36 | *
37 | * @return mixed
38 | */
39 | abstract public function fetch(string $key);
40 |
41 | /**
42 | * @param array $params
43 | *
44 | * @return mixed
45 | */
46 | abstract public function update(array $params);
47 |
48 | /**
49 | * @param array $params
50 | *
51 | * @return mixed
52 | */
53 | abstract public function store(array $params);
54 |
55 | /**
56 | * Returns the remaining time to live of a key that has a timeout.
57 | *
58 | * @param string $key
59 | *
60 | * @return int
61 | */
62 | public function ttl($key)
63 | {
64 | return $this->getConnection()->ttl($key);
65 | }
66 |
67 | /**
68 | * Set a timeout on key.
69 | *
70 | * @param string $key
71 | * @param int $expire
72 | *
73 | * @return void
74 | */
75 | public function setTtl($key, $expire)
76 | {
77 | if (is_null($expire)) {
78 | return;
79 | }
80 |
81 | $expire = (int) $expire;
82 |
83 | if ($expire > 0) {
84 | $this->getConnection()->expire($key, $expire);
85 | } else {
86 | $this->getConnection()->persist($key);
87 | }
88 | }
89 | }
90 |
--------------------------------------------------------------------------------
/src/DataType/Hashes.php:
--------------------------------------------------------------------------------
1 | getConnection()->hgetall($key);
13 | }
14 |
15 | /**
16 | * {@inheritdoc}
17 | */
18 | public function update(array $params)
19 | {
20 | $key = array_get($params, 'key');
21 |
22 | if (array_has($params, 'field')) {
23 | $field = array_get($params, 'field');
24 | $value = array_get($params, 'value');
25 |
26 | $this->getConnection()->hset($key, $field, $value);
27 | }
28 |
29 | if (array_has($params, '_editable')) {
30 | $value = array_get($params, 'value');
31 | $field = array_get($params, 'pk');
32 |
33 | $this->getConnection()->hset($key, $field, $value);
34 | }
35 | }
36 |
37 | /**
38 | * {@inheritdoc}
39 | */
40 | public function store(array $params)
41 | {
42 | $key = array_get($params, 'key');
43 | $seconds = array_get($params, 'seconds');
44 | $dic = array_get($params, 'dic');
45 |
46 | $fields = [];
47 |
48 | foreach ($dic as $item) {
49 | $fields[$item['name']] = $item['value'];
50 | }
51 |
52 | $this->getConnection()->hmset($key, $fields);
53 |
54 | if ($seconds > 0) {
55 | $this->getConnection()->expire($key, $seconds);
56 | }
57 | }
58 |
59 | /**
60 | * Remove a field from a hash.
61 | *
62 | * @param array $params
63 | *
64 | * @return int
65 | */
66 | public function remove(array $params)
67 | {
68 | $key = array_get($params, 'key');
69 | $field = array_get($params, 'field');
70 |
71 | return $this->getConnection()->hdel($key, [$field]);
72 | }
73 | }
74 |
--------------------------------------------------------------------------------
/src/DataType/Lists.php:
--------------------------------------------------------------------------------
1 | getConnection()->lrange($key, 0, -1);
13 | }
14 |
15 | /**
16 | * {@inheritdoc}
17 | */
18 | public function update(array $params)
19 | {
20 | $key = array_get($params, 'key');
21 |
22 | $action = array_get($params, 'action');
23 |
24 | if (in_array($action, ['lpush', 'rpush'])) {
25 | $members = array_get($params, 'members');
26 | $this->getConnection()->{$action}($key, $members);
27 | }
28 |
29 | if ($action == 'lset') {
30 | $value = array_get($params, 'value');
31 | $index = array_get($params, 'index');
32 |
33 | $this->getConnection()->lset($key, $index, $value);
34 | }
35 | }
36 |
37 | /**
38 | * {@inheritdoc}
39 | */
40 | public function store(array $params)
41 | {
42 | $key = array_get($params, 'key');
43 | $members = array_get($params, 'members');
44 | $expire = array_get($params, 'expire');
45 | $action = array_get($params, 'action', 'rpush');
46 |
47 | $members = array_column($members, 'value');
48 |
49 | $this->getConnection()->{$action}($key, $members);
50 |
51 | if ($expire > 0) {
52 | $this->getConnection()->expire($key, $expire);
53 | }
54 | }
55 |
56 | /**
57 | * Remove a member from list by index.
58 | *
59 | * @param array $params
60 | *
61 | * @return mixed
62 | */
63 | public function remove(array $params)
64 | {
65 | $key = array_get($params, 'key');
66 | $index = array_get($params, 'index');
67 |
68 | $lua = <<<'LUA'
69 | redis.call('lset', KEYS[1], ARGV[1], '__DELETED__');
70 | redis.call('lrem', KEYS[1], 1, '__DELETED__');
71 | LUA;
72 |
73 | return $this->getConnection()->eval($lua, 1, $key, $index);
74 | }
75 | }
76 |
--------------------------------------------------------------------------------
/src/DataType/Sets.php:
--------------------------------------------------------------------------------
1 | getConnection()->smembers($key);
13 | }
14 |
15 | /**
16 | * {@inheritdoc}
17 | */
18 | public function update(array $params)
19 | {
20 | $key = array_get($params, 'key');
21 | $member = array_get($params, 'member');
22 | $action = array_get($params, 'action');
23 |
24 | if ($action === 'srem') {
25 | $this->getConnection()->srem($key, $member);
26 | }
27 |
28 | if ($action === 'sadd') {
29 | $this->getConnection()->sadd($key, [$member]);
30 | }
31 | }
32 |
33 | /**
34 | * {@inheritdoc}
35 | */
36 | public function store(array $params)
37 | {
38 | $key = array_get($params, 'key');
39 | $members = array_get($params, 'members');
40 | $seconds = array_get($params, 'seconds');
41 |
42 | $this->getConnection()->sadd($key, $members);
43 |
44 | if ($seconds > 0) {
45 | $this->getConnection()->expire($key, $seconds);
46 | } else {
47 | $this->getConnection()->persist($key);
48 | }
49 | }
50 |
51 | /**
52 | * Remove a member from a set.
53 | *
54 | * @param array $params
55 | *
56 | * @return int
57 | */
58 | public function remove(array $params)
59 | {
60 | $key = array_get($params, 'key');
61 | $member = array_get($params, 'member');
62 |
63 | return $this->getConnection()->srem($key, $member);
64 | }
65 | }
66 |
--------------------------------------------------------------------------------
/src/DataType/SortedSets.php:
--------------------------------------------------------------------------------
1 | getConnection()->zrange($key, 0, -1, ['WITHSCORES' => true]);
13 | }
14 |
15 | /**
16 | * {@inheritdoc}
17 | */
18 | public function update(array $params)
19 | {
20 | $key = array_get($params, 'key');
21 | $member = array_get($params, 'member');
22 | $action = array_get($params, 'action');
23 |
24 | if ($action === 'zrem') {
25 | $this->getConnection()->zrem($key, $member);
26 | }
27 |
28 | if ($action === 'zset') {
29 | $score = array_get($params, 'score');
30 | $this->getConnection()->zadd($key, [$member => $score]);
31 | }
32 | }
33 |
34 | /**
35 | * {@inheritdoc}
36 | */
37 | public function store(array $params)
38 | {
39 | $key = array_get($params, 'key');
40 | $members = array_get($params, 'members');
41 | $expire = array_get($params, 'expire');
42 |
43 | $fields = [];
44 |
45 | foreach ($members as $member) {
46 | $fields[$member['member']] = $member['score'];
47 | }
48 |
49 | $this->getConnection()->zadd($key, $fields);
50 |
51 | if ($expire > 0) {
52 | $this->getConnection()->expire($key, $expire);
53 | }
54 | }
55 |
56 | /**
57 | * Remove a member from a sorted set.
58 | *
59 | * @param array $params
60 | *
61 | * @return int
62 | */
63 | public function remove(array $params)
64 | {
65 | $key = array_get($params, 'key');
66 | $member = array_get($params, 'member');
67 |
68 | return $this->getConnection()->zrem($key, $member);
69 | }
70 | }
71 |
--------------------------------------------------------------------------------
/src/DataType/Strings.php:
--------------------------------------------------------------------------------
1 | getConnection()->get($key);
13 | }
14 |
15 | /**
16 | * {@inheritdoc}
17 | */
18 | public function update(array $params)
19 | {
20 | $this->store($params);
21 | }
22 |
23 | /**
24 | * {@inheritdoc}
25 | */
26 | public function store(array $params)
27 | {
28 | $key = array_get($params, 'key');
29 | $value = array_get($params, 'value');
30 | $seconds = array_get($params, 'seconds');
31 |
32 | $this->getConnection()->set($key, $value);
33 |
34 | if ($seconds > 0) {
35 | $this->getConnection()->expire($key, $seconds);
36 | }
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/src/Formatter/Information.php:
--------------------------------------------------------------------------------
1 | static::formatBytes($info['Memory']['used_memory']),
18 | 'used_memory_rss' => static::formatBytes($info['Memory']['used_memory_rss']),
19 | 'used_memory_peak' => static::formatBytes($info['Memory']['used_memory_peak']),
20 | ];
21 |
22 | return $info;
23 | }
24 |
25 | /**
26 | * Format commandstats information.
27 | *
28 | * @param array $info
29 | *
30 | * @return static
31 | */
32 | public static function commandstats($info)
33 | {
34 | $commands = collect($info['Commandstats'])->mapWithKeys(function ($value, $key) {
35 | preg_match('/calls=(\d+),usec=(\d+),usec_per_call=(.*)/', $value, $match);
36 |
37 | list($_, $calls, $usec, $usec_per_call) = $match;
38 |
39 | return [substr($key, 8) => compact('calls', 'usec', 'usec_per_call')];
40 | });
41 |
42 | return $commands;
43 | }
44 |
45 | /**
46 | * Format cpu information.
47 | *
48 | * @param array $info
49 | *
50 | * @return mixed
51 | */
52 | public static function cpu($info)
53 | {
54 | return $info['CPU'];
55 | }
56 |
57 | /**
58 | * Format clients information.
59 | *
60 | * @param array $info
61 | *
62 | * @return mixed
63 | */
64 | public static function clients($info)
65 | {
66 | return $info['Clients'];
67 | }
68 |
69 | /**
70 | * Format bytes to MB size.
71 | *
72 | * @param int $bytes
73 | * @param int $precision
74 | *
75 | * @return float
76 | */
77 | public static function formatBytes($bytes, $precision = 2)
78 | {
79 | $bytes = $bytes / (1024 * 1024);
80 |
81 | return round($bytes, $precision);
82 | }
83 |
84 | /**
85 | * @param $method
86 | * @param $arguments
87 | *
88 | * @return mixed
89 | */
90 | public static function __callStatic($method, $arguments)
91 | {
92 | return $arguments[0];
93 | }
94 | }
95 |
--------------------------------------------------------------------------------
/src/Http/Controllers/RedisController.php:
--------------------------------------------------------------------------------
1 | middleware(Authenticate::class);
20 | }
21 |
22 | /**
23 | * Index page.
24 | *
25 | * @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
26 | */
27 | public function index()
28 | {
29 | return view('redis-manager::app');
30 | }
31 |
32 | /**
33 | * Get redis connections.
34 | *
35 | * @return Collection
36 | */
37 | public function connections()
38 | {
39 | $config = config('database.redis');
40 |
41 | return collect($config)->filter(function ($conn) {
42 | return is_array($conn);
43 | })->keys();
44 | }
45 |
46 | /**
47 | * @param Request $request
48 | *
49 | * @return array|\Predis\Pipeline\Pipeline
50 | */
51 | public function scan(Request $request)
52 | {
53 | $manager = $this->manager();
54 |
55 | return $manager->scan(
56 | $request->get('pattern', '*'),
57 | $request->get('count', config('redis-manager.results_per_page', 50))
58 | );
59 | }
60 |
61 | /**
62 | * @param Request $request
63 | *
64 | * @return array
65 | */
66 | public function info(Request $request)
67 | {
68 | $section = $request->get('section');
69 |
70 | return $this->manager()->getInformation($section);
71 | }
72 |
73 | /**
74 | * @param Request $request
75 | *
76 | * @return mixed
77 | */
78 | public function store(Request $request)
79 | {
80 | $type = $request->get('type');
81 |
82 | return $this->manager()->{$type}()->store($request->all());
83 | }
84 |
85 | /**
86 | * @param Request $request
87 | *
88 | * @return int
89 | */
90 | public function destroy(Request $request)
91 | {
92 | return $this->manager()->del($request->get('keys'));
93 | }
94 |
95 | /**
96 | * @param Request $request
97 | *
98 | * @return array
99 | */
100 | public function key(Request $request)
101 | {
102 | return $this->manager()->fetch($request->get('key'));
103 | }
104 |
105 | /**
106 | * @param Request $request
107 | *
108 | * @return mixed
109 | */
110 | public function remove(Request $request)
111 | {
112 | $type = $request->get('type');
113 |
114 | return $this->manager()->{$type}()->remove($request->all());
115 | }
116 |
117 | /**
118 | * @param Request $request
119 | *
120 | * @return mixed
121 | */
122 | public function update(Request $request)
123 | {
124 | return $this->manager()->update($request);
125 | }
126 |
127 | /**
128 | * @param Request $request
129 | *
130 | * @return int
131 | */
132 | public function expire(Request $request)
133 | {
134 | return $this->manager()->expire($request->get('key'), $request->get('seconds'));
135 | }
136 |
137 | /**
138 | * Execute a redis command.
139 | *
140 | * @param Request $request
141 | *
142 | * @return array
143 | */
144 | public function eval(Request $request)
145 | {
146 | $command = $request->get('command');
147 | $db = $request->get('db');
148 |
149 | try {
150 | $result = $this->manager()->execute($command, $db);
151 | } catch (\Exception $exception) {
152 | return [
153 | 'success' => false,
154 | 'data' => $exception->getMessage(),
155 | 'command' => $command,
156 | ];
157 | }
158 |
159 | if (is_string($result) && Str::startsWith($result, ['ERR ', 'WRONGTYPE '])) {
160 | return [
161 | 'success' => false,
162 | 'data' => $result,
163 | 'command' => $command,
164 | ];
165 | }
166 |
167 | return [
168 | 'success' => true,
169 | 'data' => $result,
170 | 'command' => $command,
171 | ];
172 | }
173 |
174 | /**
175 | * Get the redis manager instance.
176 | *
177 | * @return RedisManager
178 | */
179 | protected function manager()
180 | {
181 | $conn = \request()->get('conn');
182 |
183 | return RedisManager::instance($conn);
184 | }
185 | }
186 |
--------------------------------------------------------------------------------
/src/Http/Middleware/Authenticate.php:
--------------------------------------------------------------------------------
1 | Strings::class,
29 | 'hash' => Hashes::class,
30 | 'set' => Sets::class,
31 | 'zset' => SortedSets::class,
32 | 'list' => Lists::class,
33 | ];
34 |
35 | /**
36 | * @var RedisManager
37 | */
38 | protected static $instance;
39 |
40 | /**
41 | * @var string
42 | */
43 | protected $connection;
44 |
45 | /**
46 | * The callback that should be used to authenticate redis-manager users.
47 | *
48 | * @var \Closure
49 | */
50 | public static $authUsing;
51 |
52 | /**
53 | * Get instance of redis manager.
54 | *
55 | * @param string $connection
56 | *
57 | * @return RedisManager
58 | */
59 | public static function instance($connection = 'default')
60 | {
61 | if (!static::$instance instanceof self) {
62 | static::$instance = new static($connection);
63 | }
64 |
65 | return static::$instance;
66 | }
67 |
68 | /**
69 | * RedisManager constructor.
70 | *
71 | * @param string $connection
72 | */
73 | public function __construct($connection = 'default')
74 | {
75 | $this->connection = $connection;
76 | }
77 |
78 | /**
79 | * Determine if the given request can access redis-manager.
80 | *
81 | * @param \Illuminate\Http\Request $request
82 | *
83 | * @return bool
84 | */
85 | public static function check($request)
86 | {
87 | return (static::$authUsing ?: function () {
88 | return app()->environment('local');
89 | })($request);
90 | }
91 |
92 | /**
93 | * Set the callback that should be used to authenticate redis-manager users.
94 | *
95 | * @param \Closure $callback
96 | *
97 | * @return static
98 | */
99 | public static function auth(\Closure $callback)
100 | {
101 | static::$authUsing = $callback;
102 |
103 | return new static();
104 | }
105 |
106 | /**
107 | * @return Lists
108 | */
109 | public function list()
110 | {
111 | return new Lists($this->getConnection());
112 | }
113 |
114 | /**
115 | * @return Strings
116 | */
117 | public function string()
118 | {
119 | return new Strings($this->getConnection());
120 | }
121 |
122 | /**
123 | * @return Hashes
124 | */
125 | public function hash()
126 | {
127 | return new Hashes($this->getConnection());
128 | }
129 |
130 | /**
131 | * @return Sets
132 | */
133 | public function set()
134 | {
135 | return new Sets($this->getConnection());
136 | }
137 |
138 | /**
139 | * @return SortedSets
140 | */
141 | public function zset()
142 | {
143 | return new SortedSets($this->getConnection());
144 | }
145 |
146 | /**
147 | * Get connection collections.
148 | *
149 | * @return Collection
150 | */
151 | public function getConnections()
152 | {
153 | return collect(config('database.redis'))->filter(function ($conn) {
154 | return is_array($conn);
155 | });
156 | }
157 |
158 | /**
159 | * Get a registered connection instance.
160 | *
161 | * @param string $connection
162 | *
163 | * @return Connection
164 | */
165 | public function getConnection($connection = null)
166 | {
167 | if ($connection) {
168 | $this->connection = $connection;
169 | }
170 |
171 | return Redis::connection($this->connection);
172 | }
173 |
174 | /**
175 | * Get information of redis instance.
176 | *
177 | * @param mixed $section
178 | *
179 | * @return array
180 | */
181 | public function getInformation($section = null)
182 | {
183 | if ($section) {
184 | $info = $this->getConnection()->info($section);
185 |
186 | return Information::$section($info);
187 | }
188 |
189 | return $this->getConnection()->info();
190 | }
191 |
192 | /**
193 | * Scan keys in redis by giving pattern.
194 | *
195 | * @param string $pattern
196 | * @param int $count
197 | *
198 | * @return array|\Predis\Pipeline\Pipeline
199 | */
200 | public function scan($pattern = '*', $count = 100)
201 | {
202 | $client = $this->getConnection();
203 | $keys = [];
204 |
205 | foreach (new Keyspace($client->client(), $pattern) as $item) {
206 | $keys[] = $item;
207 |
208 | if (count($keys) == $count) {
209 | break;
210 | }
211 | }
212 |
213 | $script = <<<'LUA'
214 | local type = redis.call('type', KEYS[1])
215 | local ttl = redis.call('ttl', KEYS[1])
216 |
217 | return {KEYS[1], type, ttl}
218 | LUA;
219 |
220 | $keys = $client->pipeline(function (Pipeline $pipe) use ($keys, $script) {
221 | foreach ($keys as $key) {
222 | $pipe->eval($script, 1, $key);
223 | }
224 | });
225 |
226 | return collect($keys)->map(function ($key) {
227 | return [
228 | 'key' => $key[0],
229 | 'type' => (string) $key[1],
230 | 'ttl' => $key[2],
231 | ];
232 | });
233 | }
234 |
235 | /**
236 | * Fetch value of a giving key.
237 | *
238 | * @param string $key
239 | *
240 | * @return array
241 | */
242 | public function fetch($key)
243 | {
244 | if (!$this->getConnection()->exists($key)) {
245 | return [];
246 | }
247 |
248 | $type = $this->getConnection()->type($key)->__toString();
249 |
250 | /** @var DataType $class */
251 | $class = $this->{$type}();
252 |
253 | $value = $class->fetch($key);
254 | $expire = $class->ttl($key);
255 |
256 | return compact('key', 'value', 'expire', 'type');
257 | }
258 |
259 | /**
260 | * Update a specified key.
261 | *
262 | * @param Request $request
263 | *
264 | * @return bool
265 | */
266 | public function update(Request $request)
267 | {
268 | $key = $request->get('key');
269 | $type = $request->get('type');
270 |
271 | /** @var DataType $class */
272 | $class = $this->{$type}();
273 |
274 | $class->update($request->all());
275 |
276 | $class->setTtl($key, $request->get('ttl'));
277 | }
278 |
279 | /**
280 | * Remove the specified key.
281 | *
282 | * @param array $keys
283 | *
284 | * @return int
285 | */
286 | public function del($keys)
287 | {
288 | return $this->getConnection()->del($keys);
289 | }
290 |
291 | /**
292 | * 运行redis命令.
293 | *
294 | * @param string $command
295 | *
296 | * @throws \Exception
297 | *
298 | * @return mixed
299 | */
300 | public function execute($command, $db)
301 | {
302 | $command = explode(' ', trim($command));
303 |
304 | if ($this->commandDisabled($command[0])) {
305 | throw new \Exception("Command [{$command[0]}] is disabled!");
306 | }
307 |
308 | $client = $this->getConnection();
309 |
310 | if ($db !== null) {
311 | $client->select($db);
312 | }
313 |
314 | return $client->executeRaw($command);
315 | }
316 |
317 | /**
318 | * Determine if giving command is disabled.
319 | *
320 | * @param string $command
321 | *
322 | * @return bool
323 | */
324 | protected function commandDisabled(string $command)
325 | {
326 | $disabled = config('redis-manager.disable_commands');
327 |
328 | $disabled = array_map('strtoupper', (array) $disabled);
329 |
330 | return in_array(strtoupper($command), $disabled);
331 | }
332 |
333 | /**
334 | * @param $key
335 | * @param int $seconds
336 | *
337 | * @return int
338 | */
339 | public function expire($key, $seconds = -1)
340 | {
341 | if ($seconds > 0) {
342 | return $this->getConnection()->expire($key, $seconds);
343 | } else {
344 | return $this->getConnection()->persist($key);
345 | }
346 | }
347 | }
348 |
--------------------------------------------------------------------------------
/src/RedisManagerServiceProvider.php:
--------------------------------------------------------------------------------
1 | registerRoutes();
16 | $this->registerResources();
17 |
18 | $this->definePublishing();
19 | }
20 |
21 | /**
22 | * Register the Redis manager routes.
23 | *
24 | * @return void
25 | */
26 | protected function registerRoutes()
27 | {
28 | Route::group([
29 | 'prefix' => config('redis-manager.base_path', 'redis-manager'),
30 | 'namespace' => 'Encore\RedisManager\Http\Controllers',
31 | 'middleware' => config('redis-manager.middleware', 'web'),
32 | ], function () {
33 | $this->loadRoutesFrom(__DIR__.'/../routes/web.php');
34 | });
35 | }
36 |
37 | /**
38 | * Register the Redis manager resources.
39 | *
40 | * @return void
41 | */
42 | protected function registerResources()
43 | {
44 | $this->loadViewsFrom(__DIR__.'/../resources/views', 'redis-manager');
45 | }
46 |
47 | /**
48 | * Define the publishing.
49 | *
50 | * @return void
51 | */
52 | public function definePublishing()
53 | {
54 | $this->publishes([
55 | __DIR__.'/../public' => public_path('vendor/redis-manager'),
56 | ], 'redis-manager-assets');
57 |
58 | $this->publishes([
59 | __DIR__.'/../public/fonts' => public_path('fonts'),
60 | ], 'redis-manager-assets');
61 |
62 | if ($this->app->runningInConsole()) {
63 | $this->publishes([
64 | __DIR__.'/../config/redis-manager.php' => config_path('redis-manager.php'),
65 | ], 'redis-manager-config');
66 | }
67 | }
68 | }
69 |
--------------------------------------------------------------------------------
/webpack.mix.js:
--------------------------------------------------------------------------------
1 | const mix = require('laravel-mix');
2 | const webpack = require('webpack');
3 |
4 | /*
5 | |--------------------------------------------------------------------------
6 | | Mix Asset Management
7 | |--------------------------------------------------------------------------
8 | |
9 | | Mix provides a clean, fluent API for defining some Webpack build steps
10 | | for your Laravel application. By default, we are compiling the Sass
11 | | file for the application as well as bundling up all the JS files.
12 | |
13 | */
14 |
15 | mix.setPublicPath('public')
16 | .js('resources/assets/js/app.js', 'public/js')
17 | .sass('resources/assets/sass/app.scss', 'public/css')
18 | .copy('resources/assets/img', 'public/img')
19 | .sourceMaps()
20 | .version()
21 |
22 | .copy('public/fonts', '../../../public/fonts')
23 | .copy('public', '../../../public/vendor/redis-manager');
24 |
25 | mix.webpackConfig({
26 | plugins: [
27 | new webpack.IgnorePlugin(/^\.\/locale$/, /moment$/)
28 | ],
29 | devtool: "source-map",
30 | resolve: {
31 | alias: {
32 | 'vue$': 'vue/dist/vue.runtime.esm.js'
33 | }
34 | }
35 | });
36 |
--------------------------------------------------------------------------------