├── .gitignore ├── LICENSE ├── README.md ├── composer.json ├── nginx-socket.conf ├── package.json ├── src ├── Commands │ └── Notifier.php ├── EventMap.php ├── Events │ └── Notify.php ├── Listeners │ └── NotifyListener.php ├── NotifierServiceProvider.php ├── SocketServer.php ├── SystemMessage.php ├── config │ └── notifier.php ├── helper_connector.php └── views │ ├── assets │ ├── vue-notes.asset.js │ └── vue-notes.min.js │ ├── connect.blade.php │ └── connect_and_show.blade.php └── webpack.mix.js /.gitignore: -------------------------------------------------------------------------------- 1 | /node_modules 2 | mix-manifest.json -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 Matvii 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, 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, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

2 | build passed 3 | code-intelligence 4 | license 5 | downloads 6 |

7 | 8 | ### Base concepts 9 | 10 | You don't need socket.io, pusher.js, jQuery, bootstrap, node.js, vue.js to start using this package. 11 | 12 | This package can be used for sending data synchronously to each user. 13 | 14 | This package sends data ONLY to named routes declared as `GET`. 15 | 16 | You will get your own socket server on back-end and your clients will connect to it directly, without any third-party requests to be send. 17 | 18 | You will have pretty notifications from scratch. 19 | 20 | To view available routes you can run `php artisan notifier:init show` command. It will display available routes in the table and initiate the socket server. 21 | 22 | | Code | Description | 23 | | --- | --- | 24 | | `event(new Notify($data));` | - send to all routes. | 25 | | `event(new Notify($data, $routes));` |- send to routes in `$routes` array. | 26 | | `event(new Notify($data, $routes, $users));` | - send to routes in `$routes` and only to users in `$users`.| 27 | 28 | ### Installation 29 | 30 | ``` 31 | composer require matviib/notifier 32 | ``` 33 | 34 | For Laravel < 5.5 add provider to config/app.php 35 | ```php 36 | MatviiB\Notifier\NotifierServiceProvider::class, 37 | ``` 38 | 39 | For publish notifier config file and js file for notifications out of the box: 40 | ```sh 41 | php artisan vendor:publish 42 | ``` 43 | and choose "Provider: MatviiB\Notifier\NotifierServiceProvider" if requested. 44 | 45 | ### Starting server 46 | 47 | Add worker daemon for ```php artisan notifier:init``` process with Supervisor, 48 | 49 | OR 50 | 51 | Just run ```php artisan notifier:init``` in terminal. 52 | 53 | If you use SSL you need add to your `nginx` configuration file to server block: 54 | ``` 55 | location /websocket { 56 | proxy_pass http://:; #server host and port 57 | proxy_http_version 1.1; 58 | proxy_set_header Upgrade $http_upgrade; 59 | proxy_set_header Connection "Upgrade"; 60 | 61 | # Timeout configuration. 62 | proxy_redirect off; 63 | proxy_connect_timeout 300; 64 | proxy_send_timeout 300; 65 | proxy_read_timeout 300; 66 | } 67 | ``` 68 | ### Usage 69 | 70 | At first you need to add `@include('notifier::connect')` before using `socket.addEventListener()` in your view or main layout to use it on ALL pages. 71 | 72 | If you want use notifications from the scratch you need to add `@include('notifier::connect_and_show')` to the view. 73 | 74 | Anywhere in your back-end add next event: 75 | 76 | `event(new Notify($data));` 77 | 78 | On front-end part add event listener 79 | ``` 80 | 85 | ``` 86 | 87 | ### Use built-in notifications. 88 | 89 | Built-in notifications is a vue.js with [vue-notifications](https://github.com/euvl/vue-notification) plugin. If you already use vue.js in application you can just add this plugin yourself. 90 | 91 | ##### Mapping `$data` parameter. 92 | 93 | | Parameter | Description | 94 | | --- | --- | 95 | | `'note' => 1,` | - use notes `true` | 96 | | `'type' => 'warn|success|error|info',` | - type of note | 97 | | `'title' => 'TEXT'` | - title of the note | 98 | | `'text' => 'Lorem ipsum'` | - note's body | 99 | 100 | ##### Positioning. 101 | In `config/notifier.php` you can modify position where notifications will be shown. 102 | 103 | ``` 104 | // Horizontal options: left, center, right 105 | // Vertical options: top, bottom 106 | 'position' => [ 107 | 'vertical' => 'bottom', 108 | 'horizontal' => 'right' 109 | ] 110 | ``` 111 | 112 | ## Security 113 | 114 | This package allows one way messages - only from server to client. 115 | 116 | All messages from client after connecting will be ignored. 117 | 118 | From server side messages protected with socket_pass parameter from notifier config. 119 | 120 | Channels to users protected with unique hash. 121 | 122 | 123 | ## Example with charts 124 | 125 | After installation add to web.php 126 | ``` 127 | Route::get('chart', function () { 128 | return view('chart'); 129 | })->name('chart'); 130 | ``` 131 | create view `/resources/views/chart.blade.php` 132 | 133 | ``` 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | Chart 142 | 143 | 144 | 145 | @include('notifier::connect') 146 | 147 | 168 | 169 | 170 | ``` 171 | In .env fix your APP_URL `APP_URL=http://<>` 172 | 173 | Create test command `php artisan make:command Test` 174 | ``` 175 | use MatviiB\Notifier\Events\Notify; 176 | 177 | ... 178 | 179 | protected $signature = 'test'; 180 | 181 | public function handle() 182 | { 183 | while ($i < 100) { 184 | $value = random_int(10, 100); 185 | $data['value'] = $value; 186 | event(new Notify($data, ['chart'])); 187 | usleep(rand(100000, 500000)); 188 | } 189 | } 190 | ``` 191 | Run: `php artisan notifier:init` 192 | 193 | Run in another shell: `php artisan test` 194 | 195 | Open `/chart` page. 196 | 197 | ### Usage Example 198 | Send new values to chart on some page synchronously to each user: 199 | 200 | `event(new Notify($data, ['chart']));` 201 | 202 | Or to users with `id` 3 and 5: `event(new Notify($data, ['chart'], [3, 5]));` 203 | 204 | ![laravel socket server](https://gitlab.com/MatviiB/assets/raw/master/ezgif.com-video-to-gif.gif) 205 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "matviib/notifier", 3 | "description": "NO LIBRARIES socket per page bridge for your Laravel application.", 4 | "keywords": [ 5 | "notifier", 6 | "laravel", 7 | "socket", 8 | "notifications", 9 | "notifier", 10 | "real-time", 11 | "composer-package", 12 | "composer-library", 13 | "laravel-5-package", 14 | "laravel5", 15 | "laravel55", 16 | "laravel-application", 17 | "laravel-5", 18 | "sockets", 19 | "socket-programming", 20 | "socket-server", 21 | "socket-communication", 22 | "socketserver", 23 | "sockets-easy", 24 | "socket-client", 25 | "socketstream" 26 | ], 27 | "type": "library", 28 | "homepage": "https://matviib.com/notifier", 29 | "version": "v1.3.1", 30 | "license": "MIT", 31 | "authors": [ 32 | { 33 | "name": "Matvii Bondar", 34 | "email": "matvii.bondar@gmail.com" 35 | } 36 | ], 37 | "autoload": { 38 | "psr-4": { 39 | "MatviiB\\Notifier\\": "src/" 40 | }, 41 | "files": ["src/helper_connector.php"] 42 | }, 43 | "extra": { 44 | "laravel": { 45 | "providers": [ 46 | "MatviiB\\Notifier\\NotifierServiceProvider" 47 | ] 48 | } 49 | }, 50 | "minimum-stability": "dev", 51 | "require": { 52 | "laravel/framework": "^5.0" 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /nginx-socket.conf: -------------------------------------------------------------------------------- 1 | server { 2 | location /websocket { 3 | proxy_pass http://:; #server host and port 4 | proxy_http_version 1.1; 5 | proxy_set_header Upgrade $http_upgrade; 6 | proxy_set_header Connection "Upgrade"; 7 | 8 | # Timeout configuration. 9 | proxy_redirect off; 10 | proxy_connect_timeout 300; 11 | proxy_send_timeout 300; 12 | proxy_read_timeout 300; 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "private": true, 3 | "scripts": { 4 | "prod": "npm run production", 5 | "production": "cross-env NODE_ENV=production node_modules/webpack/bin/webpack.js --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js" 6 | }, 7 | "devDependencies": { 8 | "cross-env": "^5.1", 9 | "laravel-mix": "^2.0", 10 | "vue": "^2.5.7", 11 | "vue-notification": "^1.3.10" 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/Commands/Notifier.php: -------------------------------------------------------------------------------- 1 | server = $socket; 95 | $this->router = $router; 96 | $this->routes = $this->getRoutes(); 97 | $this->connects = $this->per_pages = $this->per_users = []; 98 | 99 | 100 | if ($this->argument('show')) { 101 | $this->displayRoutes(); 102 | } 103 | 104 | $socket = $this->server->init(); 105 | 106 | while (true) { 107 | $read = $this->connects; 108 | $read[] = $socket; 109 | $write = $except = []; 110 | 111 | if (!stream_select($read, $write, $except, null)) { 112 | break; 113 | } 114 | 115 | if (in_array($socket, $read) && ($connection = stream_socket_accept($socket, -1))) { 116 | 117 | if ($info = $this->server->handshake($connection)) { 118 | $this->computeIncomingInfo($info, $connection); 119 | } 120 | 121 | unset($read[array_search($socket, $read)]); 122 | } 123 | 124 | foreach ($read as $connection) { 125 | 126 | $data = fread($connection, 100000); 127 | 128 | if (!$data) { 129 | $this->close($connection); 130 | continue; 131 | } 132 | 133 | $connection_request = explode(':', $this->server->decode($data)['payload']); 134 | $route = $connection_request[0]; 135 | 136 | if (isset($connection_request[1])) { 137 | $unique_id = $connection_request[1]; 138 | } 139 | 140 | if (in_array($route, array_column($this->routes, 'name'))) { 141 | $connection_key = array_search($connection, $this->connects); 142 | $this->per_pages[$connection_key] = $route; 143 | 144 | if (isset($unique_id) && Cache::has('notifier:' . $unique_id)) { 145 | $this->per_users[$connection_key] = Cache::get('notifier:' . $unique_id); 146 | } 147 | } else { 148 | $this->close($connection); 149 | continue; 150 | } 151 | 152 | unset($route, $unique_id, $connection_request); 153 | //$this->server->onMessage($connect, $data); 154 | } 155 | } 156 | 157 | fclose($socket); 158 | } 159 | 160 | /** 161 | * @param $info 162 | * @param $connection 163 | */ 164 | private function computeIncomingInfo($info, $connection) 165 | { 166 | if (isset($info['Socket-pass']) && $info['Socket-pass'] === config('notifier.socket_pass')) { 167 | $this->computeSystemMessage($info); 168 | } else { 169 | $this->connects[] =$connection; 170 | //$this->server->onOpen($connection, $info); 171 | } 172 | } 173 | 174 | /** 175 | * @param $info 176 | */ 177 | private function computeSystemMessage($info) 178 | { 179 | foreach ($this->connects as $key => $connection) { 180 | if (isset($this->per_pages[$key])) { 181 | if (isset($info['Routes'])) { 182 | $this->sendToRoutes($key, $connection, $info); 183 | } elseif (!isset($info['Route'])) { 184 | fwrite($connection, $this->server->encode($info['Payload'])); 185 | } 186 | } 187 | } 188 | } 189 | 190 | /** 191 | * @param $key 192 | * @param $connection 193 | * @param $info 194 | */ 195 | private function sendToRoutes($key, $connection, $info) 196 | { 197 | if (in_array($this->per_pages[$key], json_decode($info['Routes']))) { 198 | if (isset($info['Users'])) { 199 | $this->sendToUsers($key, $connection, $info); 200 | } else { 201 | fwrite($connection, $this->server->encode($info['Payload'])); 202 | } 203 | } 204 | } 205 | 206 | /** 207 | * @param $key 208 | * @param $connection 209 | * @param $info 210 | */ 211 | private function sendToUsers($key, $connection, $info) 212 | { 213 | if (isset($this->per_users[$key]) && in_array($this->per_users[$key], json_decode($info['Users']))) { 214 | fwrite($connection, $this->server->encode($info['Payload'])); 215 | } 216 | } 217 | 218 | /** 219 | * @param $connection 220 | */ 221 | private function close($connection) 222 | { 223 | fclose($connection); 224 | $connection_key = array_search($connection, $this->connects); 225 | unset($this->connects[$connection_key]); 226 | unset($this->per_pages[$connection_key]); 227 | unset($this->per_users[$connection_key]); 228 | } 229 | 230 | /** 231 | * Compile the routes into a displayable format. 232 | * 233 | * @return array 234 | */ 235 | private function getRoutes() 236 | { 237 | $result = []; 238 | 239 | foreach ($this->router->getRoutes() as $route) { 240 | 241 | $methods = $route->methods(); 242 | if (!in_array('GET', $methods)) { 243 | continue; 244 | } 245 | 246 | $name = $route->getName(); 247 | if (!$name || in_array($name, $this->except)) { 248 | continue; 249 | } 250 | 251 | $middleware = $this->getMiddleware($route); 252 | if (!in_array('web', $middleware)) { 253 | continue; 254 | } 255 | 256 | $result[] = [ 257 | 'method' => implode('|', $methods), 258 | 'name' => $name, 259 | 'middleware' => implode(',', $middleware), 260 | ]; 261 | } 262 | 263 | return $result; 264 | } 265 | 266 | /** 267 | * Display the route information on the console. 268 | * 269 | * @return void 270 | */ 271 | private function displayRoutes() 272 | { 273 | $this->table($this->headers, $this->routes); 274 | } 275 | 276 | /** 277 | * Get before filters. 278 | * 279 | * @param \Illuminate\Routing\Route $route 280 | * @return array 281 | */ 282 | private function getMiddleware($route) 283 | { 284 | return collect($route->gatherMiddleware())->map(function ($middleware) { 285 | return $middleware instanceof Closure ? 'Closure' : $middleware; 286 | })->toArray(); 287 | } 288 | } -------------------------------------------------------------------------------- /src/EventMap.php: -------------------------------------------------------------------------------- 1 | [ 14 | 'MatviiB\Notifier\Listeners\NotifyListener' 15 | ] 16 | ]; 17 | } -------------------------------------------------------------------------------- /src/Events/Notify.php: -------------------------------------------------------------------------------- 1 | data = $data; 34 | $this->routes = $routes; 35 | $this->users = $users; 36 | } 37 | 38 | /** 39 | * Get the channels the event should broadcast on. 40 | * 41 | * @return \Illuminate\Broadcasting\Channel|array 42 | */ 43 | public function broadcastOn() 44 | { 45 | // 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/Listeners/NotifyListener.php: -------------------------------------------------------------------------------- 1 | send($event->data, $event->routes, $event->users); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/NotifierServiceProvider.php: -------------------------------------------------------------------------------- 1 | app->runningInConsole()) { 20 | $this->commands([ 21 | Commands\Notifier::class 22 | ]); 23 | 24 | $this->publishes([ 25 | __DIR__ . '/config/notifier.php' => config_path('notifier.php'), 26 | ], 'config'); 27 | 28 | $this->publishes([ 29 | __DIR__ . '/views/assets/vue-notes.min.js' => public_path('vendor/notifier/vue-notes.min.js'), 30 | ], 'public'); 31 | } 32 | } 33 | 34 | /** 35 | * Register bindings in the container. 36 | * 37 | * @return void 38 | */ 39 | public function register() 40 | { 41 | require_once('helper_connector.php'); 42 | 43 | $events = $this->app->make(Dispatcher::class); 44 | 45 | foreach ($this->events as $event => $listeners) { 46 | foreach ($listeners as $listener) { 47 | $events->listen($event, $listener); 48 | } 49 | } 50 | 51 | $this->loadViewsFrom(__DIR__ . '/views', 'notifier'); 52 | } 53 | } -------------------------------------------------------------------------------- /src/SocketServer.php: -------------------------------------------------------------------------------- 1 | host = config('notifier.host'); 27 | $this->port = config('notifier.port'); 28 | } 29 | 30 | /** 31 | * Init socket server 32 | * 33 | * @return resource 34 | * @throws \Exception 35 | */ 36 | public function init() 37 | { 38 | $socket = stream_socket_server("tcp://" . $this->host . ":" . $this->port, $err_no, $err_str); 39 | 40 | if (!$socket) { 41 | throw new \Exception('Socket server error', ['error' => "$err_str ($err_no)"]); 42 | } 43 | 44 | return $socket; 45 | } 46 | 47 | /** 48 | * Get headers message with given $data. 49 | * 50 | * @param $data 51 | * @param $routes 52 | * @param $users 53 | * @return string 54 | */ 55 | public function getMessage($data, $routes = false, $users = false) 56 | { 57 | $request = "GET / HTTP/1.1\r\n" . 58 | "Host: " . $this->host . ":" . $this->port ."\r\n" . 59 | "Connection: Upgrade\r\n" . 60 | "Pragma: no-cache\r\n" . 61 | "Cache-Control: no-cache\r\n" . 62 | "Sec-WebSocket-Key: " . $this->getCode() . "\r\n" . 63 | "Socket-pass: ". config('notifier.socket_pass') . "\r\n" . 64 | "Payload: " . json_encode(['data' => $data]); 65 | 66 | if (isset($routes) && is_array($routes) && count($routes)) { 67 | $request .= "\r\n" . "Routes: " . json_encode($routes); 68 | } 69 | 70 | if (isset($users) && is_array($users) && count($users)) { 71 | $request .= "\r\n" . "Users: " . json_encode($users); 72 | } 73 | 74 | return $request; 75 | } 76 | 77 | /** 78 | * Accept (Upgrade) socket connection request. 79 | * 80 | * @param $sec_web_socket_key 81 | * @return string 82 | */ 83 | public function accept($sec_web_socket_key) 84 | { 85 | $sec_web_socket_accept = $this->getCode($sec_web_socket_key); 86 | 87 | return "HTTP/1.1 101 Web Socket Protocol Handshake\r\n" . 88 | "Upgrade: websocket\r\n" . 89 | "Connection: Upgrade\r\n" . 90 | "Sec-WebSocket-Accept:" . $sec_web_socket_accept . "\r\n\r\n"; 91 | } 92 | 93 | /** 94 | * Get code for validate socket connection. 95 | * 96 | * @param $sec_web_socket_key 97 | * @return string 98 | */ 99 | protected function getCode($sec_web_socket_key = false) 100 | { 101 | if ($sec_web_socket_key) { 102 | return $this->hash($sec_web_socket_key); 103 | } 104 | 105 | return $this->hash(str_random(16)); 106 | } 107 | 108 | /** 109 | * Generate hash for socket key accepting. 110 | * 111 | * @param $key 112 | * @return string 113 | */ 114 | private function hash($key) 115 | { 116 | $const_hash = '258EAFA5-E914-47DA-95CA-C5AB0DC85B11'; 117 | 118 | return base64_encode(pack('H*', sha1($key . $const_hash))); 119 | } 120 | 121 | 122 | /** 123 | * Handshake - connection validate 124 | * 125 | * @param $connect 126 | * @return array|bool 127 | */ 128 | public function handshake($connect) 129 | { 130 | $info = array(); 131 | 132 | $line = fgets($connect); 133 | $header = explode(' ', $line); 134 | 135 | $info['method'] = $header[0]; 136 | $info['uri'] = $header[1]; 137 | 138 | while ($line = rtrim(fgets($connect))) { 139 | if (preg_match('/\A(\S+): (.*)\z/', $line, $matches)) { 140 | $info[$matches[1]] = $matches[2]; 141 | } else { 142 | break; 143 | } 144 | } 145 | 146 | $address = explode(':', stream_socket_get_name($connect, true)); 147 | 148 | $info['ip'] = $address[0]; 149 | $info['port'] = $address[1]; 150 | 151 | if (empty($info['Sec-WebSocket-Key'])) { 152 | return false; 153 | } 154 | 155 | fwrite($connect, $this->accept($info['Sec-WebSocket-Key'])); 156 | 157 | return $info; 158 | } 159 | 160 | /** 161 | * Encode socket message 162 | * 163 | * @param $payload 164 | * @param string $type 165 | * @param bool $masked 166 | * @return string 167 | */ 168 | public function encode($payload, $type = 'text', $masked = false) 169 | { 170 | $frameHead = array(); 171 | $payloadLength = strlen($payload); 172 | 173 | switch ($type) { 174 | case 'text': 175 | // first byte indicates FIN, Text-Frame (10000001): 176 | $frameHead[0] = 129; 177 | break; 178 | 179 | case 'close': 180 | // first byte indicates FIN, Close Frame(10001000): 181 | $frameHead[0] = 136; 182 | break; 183 | 184 | case 'ping': 185 | // first byte indicates FIN, Ping frame (10001001): 186 | $frameHead[0] = 137; 187 | break; 188 | 189 | case 'pong': 190 | // first byte indicates FIN, Pong frame (10001010): 191 | $frameHead[0] = 138; 192 | break; 193 | } 194 | 195 | // set mask and payload length (using 1, 3 or 9 bytes) 196 | if ($payloadLength > 65535) { 197 | $payloadLengthBin = str_split(sprintf('%064b', $payloadLength), 8); 198 | $frameHead[1] = ($masked === true) ? 255 : 127; 199 | for ($i = 0; $i < 8; $i++) { 200 | $frameHead[$i + 2] = bindec($payloadLengthBin[$i]); 201 | } 202 | // most significant bit MUST be 0 203 | if ($frameHead[2] > 127) { 204 | return array('type' => '', 'payload' => '', 'error' => 'frame too large (1004)'); 205 | } 206 | } elseif ($payloadLength > 125) { 207 | $payloadLengthBin = str_split(sprintf('%016b', $payloadLength), 8); 208 | $frameHead[1] = ($masked === true) ? 254 : 126; 209 | $frameHead[2] = bindec($payloadLengthBin[0]); 210 | $frameHead[3] = bindec($payloadLengthBin[1]); 211 | } else { 212 | $frameHead[1] = ($masked === true) ? $payloadLength + 128 : $payloadLength; 213 | } 214 | 215 | // convert frame-head to string: 216 | foreach (array_keys($frameHead) as $i) { 217 | $frameHead[$i] = chr($frameHead[$i]); 218 | } 219 | if ($masked === true) { 220 | // generate a random mask: 221 | $mask = array(); 222 | for ($i = 0; $i < 4; $i++) { 223 | $mask[$i] = chr(rand(0, 255)); 224 | } 225 | 226 | $frameHead = array_merge($frameHead, $mask); 227 | } 228 | $frame = implode('', $frameHead); 229 | 230 | // append payload to frame: 231 | for ($i = 0; $i < $payloadLength; $i++) { 232 | $frame .= ($masked === true) ? $payload[$i] ^ $mask[$i % 4] : $payload[$i]; 233 | } 234 | 235 | return $frame; 236 | } 237 | 238 | /** 239 | * Decode socket message 240 | * 241 | * @param $data 242 | * @return array|bool 243 | */ 244 | public function decode($data) 245 | { 246 | $unmaskedPayload = ''; 247 | $decodedData = array(); 248 | 249 | // estimate frame type: 250 | $firstByteBinary = sprintf('%08b', ord($data[0])); 251 | $secondByteBinary = sprintf('%08b', ord($data[1])); 252 | $opcode = bindec(substr($firstByteBinary, 4, 4)); 253 | $isMasked = ($secondByteBinary[0] == '1') ? true : false; 254 | $payloadLength = ord($data[1]) & 127; 255 | 256 | // unmasked frame is received: 257 | if (!$isMasked) { 258 | return array('type' => '', 'payload' => '', 'error' => 'protocol error (1002)'); 259 | } 260 | 261 | switch ($opcode) { 262 | // text frame: 263 | case 1: 264 | $decodedData['type'] = 'text'; 265 | break; 266 | 267 | case 2: 268 | $decodedData['type'] = 'binary'; 269 | break; 270 | 271 | // connection close frame: 272 | case 8: 273 | $decodedData['type'] = 'close'; 274 | break; 275 | 276 | // ping frame: 277 | case 9: 278 | $decodedData['type'] = 'ping'; 279 | break; 280 | 281 | // pong frame: 282 | case 10: 283 | $decodedData['type'] = 'pong'; 284 | break; 285 | 286 | default: 287 | return array('type' => '', 'payload' => '', 'error' => 'unknown opcode (1003)'); 288 | } 289 | 290 | if ($payloadLength === 126) { 291 | $mask = substr($data, 4, 4); 292 | $payloadOffset = 8; 293 | $dataLength = bindec(sprintf('%08b', ord($data[2])) . sprintf('%08b', ord($data[3]))) + $payloadOffset; 294 | } elseif ($payloadLength === 127) { 295 | $mask = substr($data, 10, 4); 296 | $payloadOffset = 14; 297 | $tmp = ''; 298 | for ($i = 0; $i < 8; $i++) { 299 | $tmp .= sprintf('%08b', ord($data[$i + 2])); 300 | } 301 | $dataLength = bindec($tmp) + $payloadOffset; 302 | unset($tmp); 303 | } else { 304 | $mask = substr($data, 2, 4); 305 | $payloadOffset = 6; 306 | $dataLength = $payloadLength + $payloadOffset; 307 | } 308 | 309 | /** 310 | * We have to check for large frames here. socket_recv cuts at 1024 bytes 311 | * so if websocket-frame is > 1024 bytes we have to wait until whole 312 | * data is transferd. 313 | */ 314 | if (strlen($data) < $dataLength) { 315 | return false; 316 | } 317 | 318 | if ($isMasked) { 319 | for ($i = $payloadOffset; $i < $dataLength; $i++) { 320 | $j = $i - $payloadOffset; 321 | if (isset($data[$i])) { 322 | $unmaskedPayload .= $data[$i] ^ $mask[$j % 4]; 323 | } 324 | } 325 | $decodedData['payload'] = $unmaskedPayload; 326 | } else { 327 | $payloadOffset = $payloadOffset - 4; 328 | $decodedData['payload'] = substr($data, $payloadOffset); 329 | } 330 | 331 | return $decodedData; 332 | } 333 | 334 | /** 335 | * Action when new connection established 336 | * 337 | * @param $connect 338 | * @param bool $info 339 | * @return void 340 | */ 341 | public function onOpen($connect, $info = false) 342 | { 343 | // echo "open" . PHP_EOL; 344 | } 345 | 346 | /** 347 | * Action when connection was closed 348 | * 349 | * @param $connect 350 | * @return void 351 | */ 352 | public function onClose($connect) 353 | { 354 | // echo "close" . PHP_EOL; 355 | } 356 | 357 | /** 358 | * Action when message recieved 359 | * 360 | * @param $connect 361 | * @param $data 362 | * @return void 363 | */ 364 | public function onMessage($connect, $data) 365 | { 366 | // echo $this->decode($data)['payload'] . PHP_EOL; 367 | } 368 | } -------------------------------------------------------------------------------- /src/SystemMessage.php: -------------------------------------------------------------------------------- 1 | server = new SocketServer(); 23 | } 24 | 25 | /** 26 | * @param $data 27 | * @param bool $routes 28 | * @param bool $users 29 | */ 30 | public function send($data, $routes = false, $users = false) 31 | { 32 | try { 33 | $this->create()->connect()->write($data, $routes, $users)->close(); 34 | } catch (\Exception $e) { 35 | $error_code = socket_last_error(); 36 | $error_msg = socket_strerror($error_code); 37 | 38 | \Log::error('Error while send system message', ['error' => $error_msg . "[$error_code]"]); 39 | } 40 | } 41 | 42 | /** 43 | * @return $this 44 | */ 45 | private function create() 46 | { 47 | $this->socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP); 48 | 49 | return $this; 50 | } 51 | 52 | /** 53 | * @return $this 54 | */ 55 | private function connect() 56 | { 57 | socket_connect($this->socket , $this->server->host, $this->server->port); 58 | 59 | return $this; 60 | } 61 | 62 | /** 63 | * @param $data 64 | * @param $routes 65 | * @param $users 66 | * @return $this 67 | */ 68 | private function write($data, $routes, $users) 69 | { 70 | $message = $this->server->getMessage($data, $routes, $users); 71 | 72 | socket_send($this->socket, $message, strlen($message), 0); 73 | 74 | return $this; 75 | } 76 | 77 | /** 78 | * Close socket connection for this message. 79 | */ 80 | private function close() 81 | { 82 | socket_close($this->socket); 83 | } 84 | } -------------------------------------------------------------------------------- /src/config/notifier.php: -------------------------------------------------------------------------------- 1 | ". 17 | | 18 | | Horizontal options: left, center, right 19 | | Vertical options: top, bottom 20 | | 21 | | Default is "top right". 22 | | Example: 23 | | 24 | */ 25 | 'host' => env('SOCKET_HOST', parse_url(env('APP_URL'), PHP_URL_HOST)), 26 | 'port' => env('SOCKET_PORT', '3000'), 27 | 'connection' => env('SOCKET_CONNECTION', (parse_url(env('APP_URL'), PHP_URL_SCHEME)) === 'https') ? 'wss' : 'ws', 28 | 'socket_pass' => env('SOCKET_PASS', 'secret'), 29 | 30 | 'position' => [ 31 | 'vertical' => 'top', 32 | 'horizontal' => 'right' 33 | ] 34 | ]; -------------------------------------------------------------------------------- /src/helper_connector.php: -------------------------------------------------------------------------------- 1 | getName()) { 6 | if (config('notifier.connection') === 'wss') { 7 | $connection = 'var socket=new WebSocket("' . config('notifier.connection') . '://' . config('notifier.host') . '/websocket");'; 8 | } else { 9 | $connection = 'var socket=new WebSocket("' . config('notifier.connection') . '://' . config('notifier.host') . ':' . config('notifier.port') . '");'; 10 | } 11 | 12 | echo ''; 13 | } 14 | } 15 | 16 | function getUniqueId() 17 | { 18 | if ($user_id = \Auth::id()) { 19 | $unique_id = uniqid(); 20 | 21 | \Cache::put( 22 | 'notifier:' . $unique_id, 23 | $user_id, 24 | config('session.lifetime') 25 | ); 26 | 27 | return ':' . $unique_id; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/views/assets/vue-notes.asset.js: -------------------------------------------------------------------------------- 1 | window.Vue = require('vue'); 2 | window.vueNotification = require('vue-notification').default; 3 | 4 | Vue.use(vueNotification); 5 | const note = new Vue({el: '#notes'}); 6 | 7 | socket.addEventListener('message', function (event) { 8 | let data = JSON.parse(event.data).data; 9 | if (data.note) { 10 | note.$notify({ 11 | type: data.type ? data.type : 'success', 12 | title: data.title ? data.title : 'Note:', 13 | text: data.text ? data.text : '' 14 | }); 15 | } 16 | }); -------------------------------------------------------------------------------- /src/views/assets/vue-notes.min.js: -------------------------------------------------------------------------------- 1 | !function(e){var t={};function n(r){if(t[r])return t[r].exports;var i=t[r]={i:r,l:!1,exports:{}};return e[r].call(i.exports,i,i.exports,n),i.l=!0,i.exports}n.m=e,n.c=t,n.d=function(e,t,r){n.o(e,t)||Object.defineProperty(e,t,{configurable:!1,enumerable:!0,get:r})},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="/",n(n.s=2)}([function(e,t){var n;n=function(){return this}();try{n=n||Function("return this")()||(0,eval)("this")}catch(e){"object"==typeof window&&(n=window)}e.exports=n},function(e,t,n){"use strict";(function(t,n){var r=Object.freeze({});function i(e){return void 0===e||null===e}function o(e){return void 0!==e&&null!==e}function a(e){return!0===e}function s(e){return"string"==typeof e||"number"==typeof e||"symbol"==typeof e||"boolean"==typeof e}function c(e){return null!==e&&"object"==typeof e}var u=Object.prototype.toString;function l(e){return"[object Object]"===u.call(e)}function f(e){return"[object RegExp]"===u.call(e)}function p(e){var t=parseFloat(String(e));return t>=0&&Math.floor(t)===t&&isFinite(e)}function d(e){return null==e?"":"object"==typeof e?JSON.stringify(e,null,2):String(e)}function v(e){var t=parseFloat(e);return isNaN(t)?e:t}function h(e,t){for(var n=Object.create(null),r=e.split(","),i=0;i-1)return e.splice(n,1)}}var _=Object.prototype.hasOwnProperty;function b(e,t){return _.call(e,t)}function x(e){var t=Object.create(null);return function(n){return t[n]||(t[n]=e(n))}}var w=/-(\w)/g,$=x(function(e){return e.replace(w,function(e,t){return t?t.toUpperCase():""})}),C=x(function(e){return e.charAt(0).toUpperCase()+e.slice(1)}),k=/\B([A-Z])/g,A=x(function(e){return e.replace(k,"-$1").toLowerCase()});var O=Function.prototype.bind?function(e,t){return e.bind(t)}:function(e,t){function n(n){var r=arguments.length;return r?r>1?e.apply(t,arguments):e.call(t,n):e.call(t)}return n._length=e.length,n};function T(e,t){t=t||0;for(var n=e.length-t,r=new Array(n);n--;)r[n]=e[n+t];return r}function S(e,t){for(var n in t)e[n]=t[n];return e}function E(e){for(var t={},n=0;n0,Y=G&&G.indexOf("edge/")>0,Q=(G&&G.indexOf("android"),G&&/iphone|ipad|ipod|ios/.test(G)||"ios"===q),ee=(G&&/chrome\/\d+/.test(G),{}.watch),te=!1;if(W)try{var ne={};Object.defineProperty(ne,"passive",{get:function(){te=!0}}),window.addEventListener("test-passive",null,ne)}catch(e){}var re=function(){return void 0===z&&(z=!W&&!J&&void 0!==t&&"server"===t.process.env.VUE_ENV),z},ie=W&&window.__VUE_DEVTOOLS_GLOBAL_HOOK__;function oe(e){return"function"==typeof e&&/native code/.test(e.toString())}var ae,se="undefined"!=typeof Symbol&&oe(Symbol)&&"undefined"!=typeof Reflect&&oe(Reflect.ownKeys);ae="undefined"!=typeof Set&&oe(Set)?Set:function(){function e(){this.set=Object.create(null)}return e.prototype.has=function(e){return!0===this.set[e]},e.prototype.add=function(e){this.set[e]=!0},e.prototype.clear=function(){this.set=Object.create(null)},e}();var ce=j,ue=0,le=function(){this.id=ue++,this.subs=[]};le.prototype.addSub=function(e){this.subs.push(e)},le.prototype.removeSub=function(e){g(this.subs,e)},le.prototype.depend=function(){le.target&&le.target.addDep(this)},le.prototype.notify=function(){for(var e=this.subs.slice(),t=0,n=e.length;t-1)if(o&&!b(i,"default"))a=!1;else if(""===a||a===A(e)){var c=Ue(String,i.type);(c<0||s0&&(ft((u=e(u,(n||"")+"_"+c))[0])&&ft(f)&&(r[l]=ye(f.text+u[0].text),u.shift()),r.push.apply(r,u)):s(u)?ft(f)?r[l]=ye(f.text+u):""!==u&&r.push(ye(u)):ft(u)&&ft(f)?r[l]=ye(f.text+u.text):(a(t._isVList)&&o(u.tag)&&i(u.key)&&o(n)&&(u.key="__vlist"+n+"_"+c+"__"),r.push(u)));return r}(e):void 0}function ft(e){return o(e)&&o(e.text)&&!1===e.isComment}function pt(e,t){return(e.__esModule||se&&"Module"===e[Symbol.toStringTag])&&(e=e.default),c(e)?t.extend(e):e}function dt(e){return e.isComment&&e.asyncFactory}function vt(e){if(Array.isArray(e))for(var t=0;tEt&&kt[n].id>e.id;)n--;kt.splice(n+1,0,e)}else kt.push(e);Tt||(Tt=!0,tt(jt))}}(this)},It.prototype.run=function(){if(this.active){var e=this.get();if(e!==this.value||c(e)||this.deep){var t=this.value;if(this.value=e,this.user)try{this.cb.call(this.vm,e,t)}catch(e){Ve(e,this.vm,'callback for watcher "'+this.expression+'"')}else this.cb.call(this.vm,e,t)}}},It.prototype.evaluate=function(){this.value=this.get(),this.dirty=!1},It.prototype.depend=function(){for(var e=this.deps.length;e--;)this.deps[e].depend()},It.prototype.teardown=function(){if(this.active){this.vm._isBeingDestroyed||g(this.vm._watchers,this);for(var e=this.deps.length;e--;)this.deps[e].removeSub(this);this.active=!1}};var Lt={enumerable:!0,configurable:!0,get:j,set:j};function Mt(e,t,n){Lt.get=function(){return this[t][n]},Lt.set=function(e){this[t][n]=e},Object.defineProperty(e,n,Lt)}function Pt(e){e._watchers=[];var t=e.$options;t.props&&function(e,t){var n=e.$options.propsData||{},r=e._props={},i=e.$options._propKeys=[];e.$parent&&$e(!1);var o=function(o){i.push(o);var a=Re(o,t,n,e);Te(r,o,a),o in e||Mt(e,"_props",o)};for(var a in t)o(a);$e(!0)}(e,t.props),t.methods&&function(e,t){e.$options.props;for(var n in t)e[n]=null==t[n]?j:O(t[n],e)}(e,t.methods),t.data?function(e){var t=e.$options.data;l(t=e._data="function"==typeof t?function(e,t){pe();try{return e.call(t,t)}catch(e){return Ve(e,t,"data()"),{}}finally{de()}}(t,e):t||{})||(t={});var n=Object.keys(t),r=e.$options.props,i=(e.$options.methods,n.length);for(;i--;){var o=n[i];0,r&&b(r,o)||B(o)||Mt(e,"_data",o)}Oe(t,!0)}(e):Oe(e._data={},!0),t.computed&&function(e,t){var n=e._computedWatchers=Object.create(null),r=re();for(var i in t){var o=t[i],a="function"==typeof o?o:o.get;0,r||(n[i]=new It(e,a||j,j,Dt)),i in e||Ft(e,i,o)}}(e,t.computed),t.watch&&t.watch!==ee&&function(e,t){for(var n in t){var r=t[n];if(Array.isArray(r))for(var i=0;i=0||n.indexOf(e[i])<0)&&r.push(e[i]);return r}return e}function dn(e){this._init(e)}function vn(e){e.cid=0;var t=1;e.extend=function(e){e=e||{};var n=this,r=n.cid,i=e._Ctor||(e._Ctor={});if(i[r])return i[r];var o=e.name||n.options.name;var a=function(e){this._init(e)};return(a.prototype=Object.create(n.prototype)).constructor=a,a.cid=t++,a.options=De(n.options,e),a.super=n,a.options.props&&function(e){var t=e.options.props;for(var n in t)Mt(e.prototype,"_props",n)}(a),a.options.computed&&function(e){var t=e.options.computed;for(var n in t)Ft(e.prototype,n,t[n])}(a),a.extend=n.extend,a.mixin=n.mixin,a.use=n.use,F.forEach(function(e){a[e]=n[e]}),o&&(a.options.components[o]=a),a.superOptions=n.options,a.extendOptions=e,a.sealedOptions=S({},a.options),i[r]=a,a}}function hn(e){return e&&(e.Ctor.options.name||e.tag)}function mn(e,t){return Array.isArray(e)?e.indexOf(t)>-1:"string"==typeof e?e.split(",").indexOf(t)>-1:!!f(e)&&e.test(t)}function yn(e,t){var n=e.cache,r=e.keys,i=e._vnode;for(var o in n){var a=n[o];if(a){var s=hn(a.componentOptions);s&&!t(s)&&gn(n,o,r,i)}}}function gn(e,t,n,r){var i=e[t];!i||r&&i.tag===r.tag||i.componentInstance.$destroy(),e[t]=null,g(n,t)}!function(e){e.prototype._init=function(e){var t=this;t._uid=ln++,t._isVue=!0,e&&e._isComponent?function(e,t){var n=e.$options=Object.create(e.constructor.options),r=t._parentVnode;n.parent=t.parent,n._parentVnode=r,n._parentElm=t._parentElm,n._refElm=t._refElm;var i=r.componentOptions;n.propsData=i.propsData,n._parentListeners=i.listeners,n._renderChildren=i.children,n._componentTag=i.tag,t.render&&(n.render=t.render,n.staticRenderFns=t.staticRenderFns)}(t,e):t.$options=De(fn(t.constructor),e||{},t),t._renderProxy=t,t._self=t,function(e){var t=e.$options,n=t.parent;if(n&&!t.abstract){for(;n.$options.abstract&&n.$parent;)n=n.$parent;n.$children.push(e)}e.$parent=n,e.$root=n?n.$root:e,e.$children=[],e.$refs={},e._watcher=null,e._inactive=null,e._directInactive=!1,e._isMounted=!1,e._isDestroyed=!1,e._isBeingDestroyed=!1}(t),function(e){e._events=Object.create(null),e._hasHookEvent=!1;var t=e.$options._parentListeners;t&&yt(e,t)}(t),function(e){e._vnode=null,e._staticTrees=null;var t=e.$options,n=e.$vnode=t._parentVnode,i=n&&n.context;e.$slots=gt(t._renderChildren,i),e.$scopedSlots=r,e._c=function(t,n,r,i){return un(e,t,n,r,i,!1)},e.$createElement=function(t,n,r,i){return un(e,t,n,r,i,!0)};var o=n&&n.data;Te(e,"$attrs",o&&o.attrs||r,null,!0),Te(e,"$listeners",t._parentListeners||r,null,!0)}(t),Ct(t,"beforeCreate"),function(e){var t=Bt(e.$options.inject,e);t&&($e(!1),Object.keys(t).forEach(function(n){Te(e,n,t[n])}),$e(!0))}(t),Pt(t),function(e){var t=e.$options.provide;t&&(e._provided="function"==typeof t?t.call(e):t)}(t),Ct(t,"created"),t.$options.el&&t.$mount(t.$options.el)}}(dn),function(e){var t={get:function(){return this._data}},n={get:function(){return this._props}};Object.defineProperty(e.prototype,"$data",t),Object.defineProperty(e.prototype,"$props",n),e.prototype.$set=Se,e.prototype.$delete=Ee,e.prototype.$watch=function(e,t,n){if(l(t))return Ht(this,e,t,n);(n=n||{}).user=!0;var r=new It(this,e,t,n);return n.immediate&&t.call(this,r.value),function(){r.teardown()}}}(dn),function(e){var t=/^hook:/;e.prototype.$on=function(e,n){if(Array.isArray(e))for(var r=0,i=e.length;r1?T(n):n;for(var r=T(arguments,1),i=0,o=n.length;iparseInt(this.max)&&gn(a,s[0],s,this._vnode)),t.data.keepAlive=!0}return t||e&&e[0]}}};!function(e){var t={get:function(){return H}};Object.defineProperty(e,"config",t),e.util={warn:ce,extend:S,mergeOptions:De,defineReactive:Te},e.set=Se,e.delete=Ee,e.nextTick=tt,e.options=Object.create(null),F.forEach(function(t){e.options[t+"s"]=Object.create(null)}),e.options._base=e,S(e.options.components,bn),function(e){e.use=function(e){var t=this._installedPlugins||(this._installedPlugins=[]);if(t.indexOf(e)>-1)return this;var n=T(arguments,1);return n.unshift(this),"function"==typeof e.install?e.install.apply(e,n):"function"==typeof e&&e.apply(null,n),t.push(e),this}}(e),function(e){e.mixin=function(e){return this.options=De(this.options,e),this}}(e),vn(e),function(e){F.forEach(function(t){e[t]=function(e,n){return n?("component"===t&&l(n)&&(n.name=n.name||e,n=this.options._base.extend(n)),"directive"===t&&"function"==typeof n&&(n={bind:n,update:n}),this.options[t+"s"][e]=n,n):this.options[t+"s"][e]}})}(e)}(dn),Object.defineProperty(dn.prototype,"$isServer",{get:re}),Object.defineProperty(dn.prototype,"$ssrContext",{get:function(){return this.$vnode&&this.$vnode.ssrContext}}),Object.defineProperty(dn,"FunctionalRenderContext",{value:en}),dn.version="2.5.16";var xn=h("style,class"),wn=h("input,textarea,option,select,progress"),$n=function(e,t,n){return"value"===n&&wn(e)&&"button"!==t||"selected"===n&&"option"===e||"checked"===n&&"input"===e||"muted"===n&&"video"===e},Cn=h("contenteditable,draggable,spellcheck"),kn=h("allowfullscreen,async,autofocus,autoplay,checked,compact,controls,declare,default,defaultchecked,defaultmuted,defaultselected,defer,disabled,enabled,formnovalidate,hidden,indeterminate,inert,ismap,itemscope,loop,multiple,muted,nohref,noresize,noshade,novalidate,nowrap,open,pauseonexit,readonly,required,reversed,scoped,seamless,selected,sortable,translate,truespeed,typemustmatch,visible"),An="http://www.w3.org/1999/xlink",On=function(e){return":"===e.charAt(5)&&"xlink"===e.slice(0,5)},Tn=function(e){return On(e)?e.slice(6,e.length):""},Sn=function(e){return null==e||!1===e};function En(e){for(var t=e.data,n=e,r=e;o(r.componentInstance);)(r=r.componentInstance._vnode)&&r.data&&(t=jn(r.data,t));for(;o(n=n.parent);)n&&n.data&&(t=jn(t,n.data));return function(e,t){if(o(e)||o(t))return Nn(e,In(t));return""}(t.staticClass,t.class)}function jn(e,t){return{staticClass:Nn(e.staticClass,t.staticClass),class:o(e.class)?[e.class,t.class]:t.class}}function Nn(e,t){return e?t?e+" "+t:e:t||""}function In(e){return Array.isArray(e)?function(e){for(var t,n="",r=0,i=e.length;r-1?ir(e,t,n):kn(t)?Sn(n)?e.removeAttribute(t):(n="allowfullscreen"===t&&"EMBED"===e.tagName?"true":t,e.setAttribute(t,n)):Cn(t)?e.setAttribute(t,Sn(n)||"false"===n?"false":"true"):On(t)?Sn(n)?e.removeAttributeNS(An,Tn(t)):e.setAttributeNS(An,t,n):ir(e,t,n)}function ir(e,t,n){if(Sn(n))e.removeAttribute(t);else{if(Z&&!X&&"TEXTAREA"===e.tagName&&"placeholder"===t&&!e.__ieph){var r=function(t){t.stopImmediatePropagation(),e.removeEventListener("input",r)};e.addEventListener("input",r),e.__ieph=!0}e.setAttribute(t,n)}}var or={create:nr,update:nr};function ar(e,t){var n=t.elm,r=t.data,a=e.data;if(!(i(r.staticClass)&&i(r.class)&&(i(a)||i(a.staticClass)&&i(a.class)))){var s=En(t),c=n._transitionClasses;o(c)&&(s=Nn(s,In(c))),s!==n._prevClass&&(n.setAttribute("class",s),n._prevClass=s)}}var sr,cr,ur,lr,fr,pr,dr={create:ar,update:ar},vr=/[\w).+\-_$\]]/;function hr(e){var t,n,r,i,o,a=!1,s=!1,c=!1,u=!1,l=0,f=0,p=0,d=0;for(r=0;r=0&&" "===(h=e.charAt(v));v--);h&&vr.test(h)||(u=!0)}}else void 0===i?(d=r+1,i=e.slice(0,r).trim()):m();function m(){(o||(o=[])).push(e.slice(d,r).trim()),d=r+1}if(void 0===i?i=e.slice(0,r).trim():0!==d&&m(),o)for(r=0;r-1?{exp:e.slice(0,lr),key:'"'+e.slice(lr+1)+'"'}:{exp:e,key:null};cr=e,lr=fr=pr=0;for(;!Sr();)Er(ur=Tr())?Nr(ur):91===ur&&jr(ur);return{exp:e.slice(0,fr),key:e.slice(fr+1,pr)}}(e);return null===n.key?e+"="+t:"$set("+n.exp+", "+n.key+", "+t+")"}function Tr(){return cr.charCodeAt(++lr)}function Sr(){return lr>=sr}function Er(e){return 34===e||39===e}function jr(e){var t=1;for(fr=lr;!Sr();)if(Er(e=Tr()))Nr(e);else if(91===e&&t++,93===e&&t--,0===t){pr=lr;break}}function Nr(e){for(var t=e;!Sr()&&(e=Tr())!==t;);}var Ir,Lr="__r",Mr="__c";function Pr(e,t,n,r,i){var o;t=(o=t)._withTask||(o._withTask=function(){Xe=!0;var e=o.apply(null,arguments);return Xe=!1,e}),n&&(t=function(e,t,n){var r=Ir;return function i(){null!==e.apply(null,arguments)&&Dr(t,i,n,r)}}(t,e,r)),Ir.addEventListener(e,t,te?{capture:r,passive:i}:r)}function Dr(e,t,n,r){(r||Ir).removeEventListener(e,t._withTask||t,n)}function Fr(e,t){if(!i(e.data.on)||!i(t.data.on)){var n=t.data.on||{},r=e.data.on||{};Ir=t.elm,function(e){if(o(e[Lr])){var t=Z?"change":"input";e[t]=[].concat(e[Lr],e[t]||[]),delete e[Lr]}o(e[Mr])&&(e.change=[].concat(e[Mr],e.change||[]),delete e[Mr])}(n),st(n,r,Pr,Dr,t.context),Ir=void 0}}var Rr={create:Fr,update:Fr};function Hr(e,t){if(!i(e.data.domProps)||!i(t.data.domProps)){var n,r,a=t.elm,s=e.data.domProps||{},c=t.data.domProps||{};for(n in o(c.__ob__)&&(c=t.data.domProps=S({},c)),s)i(c[n])&&(a[n]="");for(n in c){if(r=c[n],"textContent"===n||"innerHTML"===n){if(t.children&&(t.children.length=0),r===s[n])continue;1===a.childNodes.length&&a.removeChild(a.childNodes[0])}if("value"===n){a._value=r;var u=i(r)?"":String(r);Br(a,u)&&(a.value=u)}else a[n]=r}}}function Br(e,t){return!e.composing&&("OPTION"===e.tagName||function(e,t){var n=!0;try{n=document.activeElement!==e}catch(e){}return n&&e.value!==t}(e,t)||function(e,t){var n=e.value,r=e._vModifiers;if(o(r)){if(r.lazy)return!1;if(r.number)return v(n)!==v(t);if(r.trim)return n.trim()!==t.trim()}return n!==t}(e,t))}var Ur={create:Hr,update:Hr},Vr=x(function(e){var t={},n=/:(.+)/;return e.split(/;(?![^(]*\))/g).forEach(function(e){if(e){var r=e.split(n);r.length>1&&(t[r[0].trim()]=r[1].trim())}}),t});function zr(e){var t=Kr(e.style);return e.staticStyle?S(e.staticStyle,t):t}function Kr(e){return Array.isArray(e)?E(e):"string"==typeof e?Vr(e):e}var Wr,Jr=/^--/,qr=/\s*!important$/,Gr=function(e,t,n){if(Jr.test(t))e.style.setProperty(t,n);else if(qr.test(n))e.style.setProperty(t,n.replace(qr,""),"important");else{var r=Xr(t);if(Array.isArray(n))for(var i=0,o=n.length;i-1?t.split(/\s+/).forEach(function(t){return e.classList.add(t)}):e.classList.add(t);else{var n=" "+(e.getAttribute("class")||"")+" ";n.indexOf(" "+t+" ")<0&&e.setAttribute("class",(n+t).trim())}}function ti(e,t){if(t&&(t=t.trim()))if(e.classList)t.indexOf(" ")>-1?t.split(/\s+/).forEach(function(t){return e.classList.remove(t)}):e.classList.remove(t),e.classList.length||e.removeAttribute("class");else{for(var n=" "+(e.getAttribute("class")||"")+" ",r=" "+t+" ";n.indexOf(r)>=0;)n=n.replace(r," ");(n=n.trim())?e.setAttribute("class",n):e.removeAttribute("class")}}function ni(e){if(e){if("object"==typeof e){var t={};return!1!==e.css&&S(t,ri(e.name||"v")),S(t,e),t}return"string"==typeof e?ri(e):void 0}}var ri=x(function(e){return{enterClass:e+"-enter",enterToClass:e+"-enter-to",enterActiveClass:e+"-enter-active",leaveClass:e+"-leave",leaveToClass:e+"-leave-to",leaveActiveClass:e+"-leave-active"}}),ii=W&&!X,oi="transition",ai="animation",si="transition",ci="transitionend",ui="animation",li="animationend";ii&&(void 0===window.ontransitionend&&void 0!==window.onwebkittransitionend&&(si="WebkitTransition",ci="webkitTransitionEnd"),void 0===window.onanimationend&&void 0!==window.onwebkitanimationend&&(ui="WebkitAnimation",li="webkitAnimationEnd"));var fi=W?window.requestAnimationFrame?window.requestAnimationFrame.bind(window):setTimeout:function(e){return e()};function pi(e){fi(function(){fi(e)})}function di(e,t){var n=e._transitionClasses||(e._transitionClasses=[]);n.indexOf(t)<0&&(n.push(t),ei(e,t))}function vi(e,t){e._transitionClasses&&g(e._transitionClasses,t),ti(e,t)}function hi(e,t,n){var r=yi(e,t),i=r.type,o=r.timeout,a=r.propCount;if(!i)return n();var s=i===oi?ci:li,c=0,u=function(){e.removeEventListener(s,l),n()},l=function(t){t.target===e&&++c>=a&&u()};setTimeout(function(){c0&&(n=oi,l=a,f=o.length):t===ai?u>0&&(n=ai,l=u,f=c.length):f=(n=(l=Math.max(a,u))>0?a>u?oi:ai:null)?n===oi?o.length:c.length:0,{type:n,timeout:l,propCount:f,hasTransform:n===oi&&mi.test(r[si+"Property"])}}function gi(e,t){for(;e.length1}function Ci(e,t){!0!==t.data.show&&bi(t)}var ki=function(e){var t,n,r={},c=e.modules,u=e.nodeOps;for(t=0;tv?_(e,i(n[y+1])?null:n[y+1].elm,n,d,y,r):d>y&&x(0,t,p,v)}(c,d,v,n,s):o(v)?(o(e.text)&&u.setTextContent(c,""),_(c,null,v,0,v.length-1,n)):o(d)?x(0,d,0,d.length-1):o(e.text)&&u.setTextContent(c,""):e.text!==t.text&&u.setTextContent(c,t.text),o(p)&&o(l=p.hook)&&o(l=l.postpatch)&&l(e,t)}}}function k(e,t,n){if(a(n)&&o(e.parent))e.parent.data.pendingInsert=t;else for(var r=0;r-1,a.selected!==o&&(a.selected=o);else if(L(Ei(a),r))return void(e.selectedIndex!==s&&(e.selectedIndex=s));i||(e.selectedIndex=-1)}}function Si(e,t){return t.every(function(t){return!L(t,e)})}function Ei(e){return"_value"in e?e._value:e.value}function ji(e){e.target.composing=!0}function Ni(e){e.target.composing&&(e.target.composing=!1,Ii(e.target,"input"))}function Ii(e,t){var n=document.createEvent("HTMLEvents");n.initEvent(t,!0,!0),e.dispatchEvent(n)}function Li(e){return!e.componentInstance||e.data&&e.data.transition?e:Li(e.componentInstance._vnode)}var Mi={model:Ai,show:{bind:function(e,t,n){var r=t.value,i=(n=Li(n)).data&&n.data.transition,o=e.__vOriginalDisplay="none"===e.style.display?"":e.style.display;r&&i?(n.data.show=!0,bi(n,function(){e.style.display=o})):e.style.display=r?o:"none"},update:function(e,t,n){var r=t.value;!r!=!t.oldValue&&((n=Li(n)).data&&n.data.transition?(n.data.show=!0,r?bi(n,function(){e.style.display=e.__vOriginalDisplay}):xi(n,function(){e.style.display="none"})):e.style.display=r?e.__vOriginalDisplay:"none")},unbind:function(e,t,n,r,i){i||(e.style.display=e.__vOriginalDisplay)}}},Pi={name:String,appear:Boolean,css:Boolean,mode:String,type:String,enterClass:String,leaveClass:String,enterToClass:String,leaveToClass:String,enterActiveClass:String,leaveActiveClass:String,appearClass:String,appearActiveClass:String,appearToClass:String,duration:[Number,String,Object]};function Di(e){var t=e&&e.componentOptions;return t&&t.Ctor.options.abstract?Di(vt(t.children)):e}function Fi(e){var t={},n=e.$options;for(var r in n.propsData)t[r]=e[r];var i=n._parentListeners;for(var o in i)t[$(o)]=i[o];return t}function Ri(e,t){if(/\d-keep-alive$/.test(t.tag))return e("keep-alive",{props:t.componentOptions.propsData})}var Hi={name:"transition",props:Pi,abstract:!0,render:function(e){var t=this,n=this.$slots.default;if(n&&(n=n.filter(function(e){return e.tag||dt(e)})).length){0;var r=this.mode;0;var i=n[0];if(function(e){for(;e=e.parent;)if(e.data.transition)return!0}(this.$vnode))return i;var o=Di(i);if(!o)return i;if(this._leaving)return Ri(e,i);var a="__transition-"+this._uid+"-";o.key=null==o.key?o.isComment?a+"comment":a+o.tag:s(o.key)?0===String(o.key).indexOf(a)?o.key:a+o.key:o.key;var c=(o.data||(o.data={})).transition=Fi(this),u=this._vnode,l=Di(u);if(o.data.directives&&o.data.directives.some(function(e){return"show"===e.name})&&(o.data.show=!0),l&&l.data&&!function(e,t){return t.key===e.key&&t.tag===e.tag}(o,l)&&!dt(l)&&(!l.componentInstance||!l.componentInstance._vnode.isComment)){var f=l.data.transition=S({},c);if("out-in"===r)return this._leaving=!0,ct(f,"afterLeave",function(){t._leaving=!1,t.$forceUpdate()}),Ri(e,i);if("in-out"===r){if(dt(o))return u;var p,d=function(){p()};ct(c,"afterEnter",d),ct(c,"enterCancelled",d),ct(f,"delayLeave",function(e){p=e})}}return i}}},Bi=S({tag:String,moveClass:String},Pi);function Ui(e){e.elm._moveCb&&e.elm._moveCb(),e.elm._enterCb&&e.elm._enterCb()}function Vi(e){e.data.newPos=e.elm.getBoundingClientRect()}function zi(e){var t=e.data.pos,n=e.data.newPos,r=t.left-n.left,i=t.top-n.top;if(r||i){e.data.moved=!0;var o=e.elm.style;o.transform=o.WebkitTransform="translate("+r+"px,"+i+"px)",o.transitionDuration="0s"}}delete Bi.mode;var Ki={Transition:Hi,TransitionGroup:{props:Bi,render:function(e){for(var t=this.tag||this.$vnode.data.tag||"span",n=Object.create(null),r=this.prevChildren=this.children,i=this.$slots.default||[],o=this.children=[],a=Fi(this),s=0;s-1?Rn[e]=t.constructor===window.HTMLUnknownElement||t.constructor===window.HTMLElement:Rn[e]=/HTMLUnknownElement/.test(t.toString())},S(dn.options.directives,Mi),S(dn.options.components,Ki),dn.prototype.__patch__=W?ki:j,dn.prototype.$mount=function(e,t){return function(e,t,n){return e.$el=t,e.$options.render||(e.$options.render=me),Ct(e,"beforeMount"),new It(e,function(){e._update(e._render(),n)},j,null,!0),n=!1,null==e.$vnode&&(e._isMounted=!0,Ct(e,"mounted")),e}(this,e=e&&W?Bn(e):void 0,t)},W&&setTimeout(function(){H.devtools&&ie&&ie.emit("init",dn)},0);var Wi=/\{\{((?:.|\n)+?)\}\}/g,Ji=/[-.*+?^${}()|[\]\/\\]/g,qi=x(function(e){var t=e[0].replace(Ji,"\\$&"),n=e[1].replace(Ji,"\\$&");return new RegExp(t+"((?:.|\\n)+?)"+n,"g")});function Gi(e,t){var n=t?qi(t):Wi;if(n.test(e)){for(var r,i,o,a=[],s=[],c=n.lastIndex=0;r=n.exec(e);){(i=r.index)>c&&(s.push(o=e.slice(c,i)),a.push(JSON.stringify(o)));var u=hr(r[1].trim());a.push("_s("+u+")"),s.push({"@binding":u}),c=i+r[0].length}return c\/=]+)(?:\s*(=)\s*(?:"([^"]*)"+|'([^']*)'+|([^\s"'=<>`]+)))?/,io="[a-zA-Z_][\\w\\-\\.]*",oo="((?:"+io+"\\:)?"+io+")",ao=new RegExp("^<"+oo),so=/^\s*(\/?)>/,co=new RegExp("^<\\/"+oo+"[^>]*>"),uo=/^]+>/i,lo=/^",""":'"',"&":"&"," ":"\n"," ":"\t"},yo=/&(?:lt|gt|quot|amp);/g,go=/&(?:lt|gt|quot|amp|#10|#9);/g,_o=h("pre,textarea",!0),bo=function(e,t){return e&&_o(e)&&"\n"===t[0]};function xo(e,t){var n=t?go:yo;return e.replace(n,function(e){return mo[e]})}var wo,$o,Co,ko,Ao,Oo,To,So,Eo=/^@|^v-on:/,jo=/^v-|^@|^:/,No=/([^]*?)\s+(?:in|of)\s+([^]*)/,Io=/,([^,\}\]]*)(?:,([^,\}\]]*))?$/,Lo=/^\(|\)$/g,Mo=/:(.*)$/,Po=/^:|^v-bind:/,Do=/\.[^.]+/g,Fo=x(Qi);function Ro(e,t,n){return{type:1,tag:e,attrsList:t,attrsMap:function(e){for(var t={},n=0,r=e.length;n]*>)","i")),p=e.replace(f,function(e,n,r){return u=r.length,vo(l)||"noscript"===l||(n=n.replace(//g,"$1").replace(//g,"$1")),bo(l,n)&&(n=n.slice(1)),t.chars&&t.chars(n),""});c+=e.length-p.length,e=p,A(l,c-u,c)}else{var d=e.indexOf("<");if(0===d){if(lo.test(e)){var v=e.indexOf("--\x3e");if(v>=0){t.shouldKeepComment&&t.comment(e.substring(4,v)),$(v+3);continue}}if(fo.test(e)){var h=e.indexOf("]>");if(h>=0){$(h+2);continue}}var m=e.match(uo);if(m){$(m[0].length);continue}var y=e.match(co);if(y){var g=c;$(y[0].length),A(y[1],g,c);continue}var _=C();if(_){k(_),bo(r,e)&&$(1);continue}}var b=void 0,x=void 0,w=void 0;if(d>=0){for(x=e.slice(d);!(co.test(x)||ao.test(x)||lo.test(x)||fo.test(x)||(w=x.indexOf("<",1))<0);)d+=w,x=e.slice(d);b=e.substring(0,d),$(d)}d<0&&(b=e,e=""),t.chars&&b&&t.chars(b)}if(e===n){t.chars&&t.chars(e);break}}function $(t){c+=t,e=e.substring(t)}function C(){var t=e.match(ao);if(t){var n,r,i={tagName:t[1],attrs:[],start:c};for($(t[0].length);!(n=e.match(so))&&(r=e.match(ro));)$(r[0].length),i.attrs.push(r);if(n)return i.unarySlash=n[1],$(n[0].length),i.end=c,i}}function k(e){var n=e.tagName,c=e.unarySlash;o&&("p"===r&&no(n)&&A(r),s(n)&&r===n&&A(n));for(var u=a(n)||!!c,l=e.attrs.length,f=new Array(l),p=0;p=0&&i[a].lowerCasedTag!==s;a--);else a=0;if(a>=0){for(var u=i.length-1;u>=a;u--)t.end&&t.end(i[u].tag,n,o);i.length=a,r=a&&i[a-1].tag}else"br"===s?t.start&&t.start(e,[],!0,n,o):"p"===s&&(t.start&&t.start(e,[],!1,n,o),t.end&&t.end(e,n,o))}A()}(e,{warn:wo,expectHTML:t.expectHTML,isUnaryTag:t.isUnaryTag,canBeLeftOpenTag:t.canBeLeftOpenTag,shouldDecodeNewlines:t.shouldDecodeNewlines,shouldDecodeNewlinesForHref:t.shouldDecodeNewlinesForHref,shouldKeepComment:t.comments,start:function(e,o,u){var l=r&&r.ns||So(e);Z&&"svg"===l&&(o=function(e){for(var t=[],n=0;n-1"+("true"===o?":("+t+")":":_q("+t+","+o+")")),$r(e,"change","var $$a="+t+",$$el=$event.target,$$c=$$el.checked?("+o+"):("+a+");if(Array.isArray($$a)){var $$v="+(r?"_n("+i+")":i)+",$$i=_i($$a,$$v);if($$el.checked){$$i<0&&("+Or(t,"$$a.concat([$$v])")+")}else{$$i>-1&&("+Or(t,"$$a.slice(0,$$i).concat($$a.slice($$i+1))")+")}}else{"+Or(t,"$$c")+"}",null,!0)}(e,r,i);else if("input"===o&&"radio"===a)!function(e,t,n){var r=n&&n.number,i=Cr(e,"value")||"null";_r(e,"checked","_q("+t+","+(i=r?"_n("+i+")":i)+")"),$r(e,"change",Or(t,i),null,!0)}(e,r,i);else if("input"===o||"textarea"===o)!function(e,t,n){var r=e.attrsMap.type,i=n||{},o=i.lazy,a=i.number,s=i.trim,c=!o&&"range"!==r,u=o?"change":"range"===r?Lr:"input",l="$event.target.value";s&&(l="$event.target.value.trim()"),a&&(l="_n("+l+")");var f=Or(t,l);c&&(f="if($event.target.composing)return;"+f),_r(e,"value","("+t+")"),$r(e,u,f,null,!0),(s||a)&&$r(e,"blur","$forceUpdate()")}(e,r,i);else if(!H.isReservedTag(o))return Ar(e,r,i),!1;return!0},text:function(e,t){t.value&&_r(e,"textContent","_s("+t.value+")")},html:function(e,t){t.value&&_r(e,"innerHTML","_s("+t.value+")")}},isPreTag:function(e){return"pre"===e},isUnaryTag:eo,mustUseProp:$n,canBeLeftOpenTag:to,isReservedTag:Dn,getTagNamespace:Fn,staticKeys:function(e){return e.reduce(function(e,t){return e.concat(t.staticKeys||[])},[]).join(",")}(qo)},Yo=x(function(e){return h("type,tag,attrsList,attrsMap,plain,parent,children,attrs"+(e?","+e:""))});function Qo(e,t){e&&(Go=Yo(t.staticKeys||""),Zo=t.isReservedTag||N,function e(t){t.static=function(e){if(2===e.type)return!1;if(3===e.type)return!0;return!(!e.pre&&(e.hasBindings||e.if||e.for||m(e.tag)||!Zo(e.tag)||function(e){for(;e.parent;){if("template"!==(e=e.parent).tag)return!1;if(e.for)return!0}return!1}(e)||!Object.keys(e).every(Go)))}(t);if(1===t.type){if(!Zo(t.tag)&&"slot"!==t.tag&&null==t.attrsMap["inline-template"])return;for(var n=0,r=t.children.length;n|^function\s*\(/,ta=/^[A-Za-z_$][\w$]*(?:\.[A-Za-z_$][\w$]*|\['[^']*?']|\["[^"]*?"]|\[\d+]|\[[A-Za-z_$][\w$]*])*$/,na={esc:27,tab:9,enter:13,space:32,up:38,left:37,right:39,down:40,delete:[8,46]},ra={esc:"Escape",tab:"Tab",enter:"Enter",space:" ",up:["Up","ArrowUp"],left:["Left","ArrowLeft"],right:["Right","ArrowRight"],down:["Down","ArrowDown"],delete:["Backspace","Delete"]},ia=function(e){return"if("+e+")return null;"},oa={stop:"$event.stopPropagation();",prevent:"$event.preventDefault();",self:ia("$event.target !== $event.currentTarget"),ctrl:ia("!$event.ctrlKey"),shift:ia("!$event.shiftKey"),alt:ia("!$event.altKey"),meta:ia("!$event.metaKey"),left:ia("'button' in $event && $event.button !== 0"),middle:ia("'button' in $event && $event.button !== 1"),right:ia("'button' in $event && $event.button !== 2")};function aa(e,t,n){var r=t?"nativeOn:{":"on:{";for(var i in e)r+='"'+i+'":'+sa(i,e[i])+",";return r.slice(0,-1)+"}"}function sa(e,t){if(!t)return"function(){}";if(Array.isArray(t))return"["+t.map(function(t){return sa(e,t)}).join(",")+"]";var n=ta.test(t.value),r=ea.test(t.value);if(t.modifiers){var i="",o="",a=[];for(var s in t.modifiers)if(oa[s])o+=oa[s],na[s]&&a.push(s);else if("exact"===s){var c=t.modifiers;o+=ia(["ctrl","shift","alt","meta"].filter(function(e){return!c[e]}).map(function(e){return"$event."+e+"Key"}).join("||"))}else a.push(s);return a.length&&(i+=function(e){return"if(!('button' in $event)&&"+e.map(ca).join("&&")+")return null;"}(a)),o&&(i+=o),"function($event){"+i+(n?"return "+t.value+"($event)":r?"return ("+t.value+")($event)":t.value)+"}"}return n||r?t.value:"function($event){"+t.value+"}"}function ca(e){var t=parseInt(e,10);if(t)return"$event.keyCode!=="+t;var n=na[e],r=ra[e];return"_k($event.keyCode,"+JSON.stringify(e)+","+JSON.stringify(n)+",$event.key,"+JSON.stringify(r)+")"}var ua={on:function(e,t){e.wrapListeners=function(e){return"_g("+e+","+t.value+")"}},bind:function(e,t){e.wrapData=function(n){return"_b("+n+",'"+e.tag+"',"+t.value+","+(t.modifiers&&t.modifiers.prop?"true":"false")+(t.modifiers&&t.modifiers.sync?",true":"")+")"}},cloak:j},la=function(e){this.options=e,this.warn=e.warn||yr,this.transforms=gr(e.modules,"transformCode"),this.dataGenFns=gr(e.modules,"genData"),this.directives=S(S({},ua),e.directives);var t=e.isReservedTag||N;this.maybeComponent=function(e){return!t(e.tag)},this.onceId=0,this.staticRenderFns=[]};function fa(e,t){var n=new la(t);return{render:"with(this){return "+(e?pa(e,n):'_c("div")')+"}",staticRenderFns:n.staticRenderFns}}function pa(e,t){if(e.staticRoot&&!e.staticProcessed)return da(e,t);if(e.once&&!e.onceProcessed)return va(e,t);if(e.for&&!e.forProcessed)return function(e,t,n,r){var i=e.for,o=e.alias,a=e.iterator1?","+e.iterator1:"",s=e.iterator2?","+e.iterator2:"";0;return e.forProcessed=!0,(r||"_l")+"(("+i+"),function("+o+a+s+"){return "+(n||pa)(e,t)+"})"}(e,t);if(e.if&&!e.ifProcessed)return ha(e,t);if("template"!==e.tag||e.slotTarget){if("slot"===e.tag)return function(e,t){var n=e.slotName||'"default"',r=ga(e,t),i="_t("+n+(r?","+r:""),o=e.attrs&&"{"+e.attrs.map(function(e){return $(e.name)+":"+e.value}).join(",")+"}",a=e.attrsMap["v-bind"];!o&&!a||r||(i+=",null");o&&(i+=","+o);a&&(i+=(o?"":",null")+","+a);return i+")"}(e,t);var n;if(e.component)n=function(e,t,n){var r=t.inlineTemplate?null:ga(t,n,!0);return"_c("+e+","+ma(t,n)+(r?","+r:"")+")"}(e.component,e,t);else{var r=e.plain?void 0:ma(e,t),i=e.inlineTemplate?null:ga(e,t,!0);n="_c('"+e.tag+"'"+(r?","+r:"")+(i?","+i:"")+")"}for(var o=0;o':'
',ka.innerHTML.indexOf(" ")>0}var Ta=!!W&&Oa(!1),Sa=!!W&&Oa(!0),Ea=x(function(e){var t=Bn(e);return t&&t.innerHTML}),ja=dn.prototype.$mount;dn.prototype.$mount=function(e,t){if((e=e&&Bn(e))===document.body||e===document.documentElement)return this;var n=this.$options;if(!n.render){var r=n.template;if(r)if("string"==typeof r)"#"===r.charAt(0)&&(r=Ea(r));else{if(!r.nodeType)return this;r=r.innerHTML}else e&&(r=function(e){if(e.outerHTML)return e.outerHTML;var t=document.createElement("div");return t.appendChild(e.cloneNode(!0)),t.innerHTML}(e));if(r){0;var i=Aa(r,{shouldDecodeNewlines:Ta,shouldDecodeNewlinesForHref:Sa,delimiters:n.delimiters,comments:n.comments},this),o=i.render,a=i.staticRenderFns;n.render=o,n.staticRenderFns=a}}return ja.call(this,e,t)},dn.compile=Aa,e.exports=dn}).call(t,n(0),n(4).setImmediate)},function(e,t,n){e.exports=n(3)},function(e,t,n){window.Vue=n(1),window.vueNotification=n(7).default,Vue.use(vueNotification);var r=new Vue({el:"#notes"});socket.addEventListener("message",function(e){var t=JSON.parse(e.data).data;t.note&&r.$notify({type:t.type?t.type:"success",title:t.title?t.title:"Note:",text:t.text?t.text:""})})},function(e,t,n){(function(e){var r=void 0!==e&&e||"undefined"!=typeof self&&self||window,i=Function.prototype.apply;function o(e,t){this._id=e,this._clearFn=t}t.setTimeout=function(){return new o(i.call(setTimeout,r,arguments),clearTimeout)},t.setInterval=function(){return new o(i.call(setInterval,r,arguments),clearInterval)},t.clearTimeout=t.clearInterval=function(e){e&&e.close()},o.prototype.unref=o.prototype.ref=function(){},o.prototype.close=function(){this._clearFn.call(r,this._id)},t.enroll=function(e,t){clearTimeout(e._idleTimeoutId),e._idleTimeout=t},t.unenroll=function(e){clearTimeout(e._idleTimeoutId),e._idleTimeout=-1},t._unrefActive=t.active=function(e){clearTimeout(e._idleTimeoutId);var t=e._idleTimeout;t>=0&&(e._idleTimeoutId=setTimeout(function(){e._onTimeout&&e._onTimeout()},t))},n(5),t.setImmediate="undefined"!=typeof self&&self.setImmediate||void 0!==e&&e.setImmediate||this&&this.setImmediate,t.clearImmediate="undefined"!=typeof self&&self.clearImmediate||void 0!==e&&e.clearImmediate||this&&this.clearImmediate}).call(t,n(0))},function(e,t,n){(function(e,t){!function(e,n){"use strict";if(!e.setImmediate){var r,i,o,a,s,c=1,u={},l=!1,f=e.document,p=Object.getPrototypeOf&&Object.getPrototypeOf(e);p=p&&p.setTimeout?p:e,"[object process]"==={}.toString.call(e.process)?r=function(e){t.nextTick(function(){v(e)})}:!function(){if(e.postMessage&&!e.importScripts){var t=!0,n=e.onmessage;return e.onmessage=function(){t=!1},e.postMessage("","*"),e.onmessage=n,t}}()?e.MessageChannel?((o=new MessageChannel).port1.onmessage=function(e){v(e.data)},r=function(e){o.port2.postMessage(e)}):f&&"onreadystatechange"in f.createElement("script")?(i=f.documentElement,r=function(e){var t=f.createElement("script");t.onreadystatechange=function(){v(e),t.onreadystatechange=null,i.removeChild(t),t=null},i.appendChild(t)}):r=function(e){setTimeout(v,0,e)}:(a="setImmediate$"+Math.random()+"$",s=function(t){t.source===e&&"string"==typeof t.data&&0===t.data.indexOf(a)&&v(+t.data.slice(a.length))},e.addEventListener?e.addEventListener("message",s,!1):e.attachEvent("onmessage",s),r=function(t){e.postMessage(a+t,"*")}),p.setImmediate=function(e){"function"!=typeof e&&(e=new Function(""+e));for(var t=new Array(arguments.length-1),n=0;n1)for(var n=1;n1&&void 0!==arguments[1]?arguments[1]:{};this.installed||(this.installed=!0,this.params=t,e.component("notifications",i.a),e.prototype.$notify=function(e){"string"==typeof e&&(e={title:"",text:e}),"object"===(void 0===e?"undefined":a(e))&&o.a.$emit("add",e)})}};t.default=s},function(e,t,n){n(17);var r=n(0)(n(5),n(15),null,null);e.exports=r.exports},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.default={name:"CssGroup",props:["name"]}},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var r=n(2),i=n(1),o=n(9),a=n(7),s=n(13),c=n.n(s),u=n(12),l=n.n(u),f=n(8);var p=0,d=2,v={name:"Notifications",components:{VelocityGroup:c.a,CssGroup:l.a},props:{group:{type:String,default:""},width:{type:[Number,String],default:300},reverse:{type:Boolean,default:!1},position:{type:[String,Array],default:function(){return a.a.position}},classes:{type:String,default:"vue-notification"},animationType:{type:String,default:"css",validator:function(e){return"css"===e||"velocity"===e}},animation:{type:Object,default:function(){return a.a.velocityAnimation}},animationName:{type:String,default:a.a.cssAnimation},speed:{type:Number,default:300},cooldown:{type:Number,default:0},duration:{type:Number,default:3e3},delay:{type:Number,default:0},max:{type:Number,default:1/0}},data:function(){return{list:[],velocity:r.default.params.velocity}},mounted:function(){i.a.$on("add",this.addItem)},computed:{actualWidth:function(){return n.i(f.a)(this.width)},isVA:function(){return"velocity"===this.animationType},componentName:function(){return this.isVA?"VelocityGroup":"CssGroup"},styles:function(){var e,t,r,i=n.i(o.a)(this.position),a=i.x,s=i.y,c=this.actualWidth.value,u=this.actualWidth.type,l=(r="0px",(t=s)in(e={width:c+u})?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e);return"center"===a?l.left="calc(50% - "+c/2+u+")":l[a]="0px",l},active:function(){return this.list.filter(function(e){return e.state!==d})},botToTop:function(){return this.styles.hasOwnProperty("bottom")}},methods:{addItem:function(e){var t=this;if(e.group=e.group||"",this.group===e.group)if(e.clean||e.clear)this.destroyAll();else{var r="number"==typeof e.duration?e.duration:this.duration,i="number"==typeof e.speed?e.speed:this.speed,a=e.title,s=e.text,c=e.type,u=e.data,l={id:n.i(o.b)(),title:a,text:s,type:c,state:p,speed:i,length:r+2*i,data:u};r>=0&&(l.timer=setTimeout(function(){t.destroy(l)},l.length));var f=-1;(this.reverse?!this.botToTop:this.botToTop)?(this.list.push(l),this.active.length>this.max&&(f=0)):(this.list.unshift(l),this.active.length>this.max&&(f=this.active.length-1)),-1!==f&&this.destroy(this.active[f])}},notifyClass:function(e){return["notification",this.classes,e.type]},notifyWrapperStyle:function(e){return this.isVA?null:{transition:"all "+e.speed+"ms"}},destroy:function(e){clearTimeout(e.timer),e.state=d,this.isVA||this.clean()},destroyAll:function(){this.active.forEach(this.destroy)},getAnimation:function(e,t){var n=this.animation[e];return"function"==typeof n?n.call(this,t):n},enter:function(e){var t=e.el,n=e.complete,r=this.getAnimation("enter",t);this.velocity(t,r,{duration:this.speed,complete:n})},leave:function(e){var t=e.el,n=e.complete,r=this.getAnimation("leave",t);this.velocity(t,r,{duration:this.speed,complete:n})},clean:function(){this.list=this.list.filter(function(e){return e.state!==d})}}};t.default=v},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.default={name:"VelocityGroup",methods:{enter:function(e,t){this.$emit("enter",{el:e,complete:t})},leave:function(e,t){this.$emit("leave",{el:e,complete:t})},afterLeave:function(){this.$emit("afterLeave")}}}},function(e,t,n){"use strict";t.a={position:["top","right"],cssAnimation:"vn-fade",velocityAnimation:{enter:function(e){return{height:[e.clientHeight,0],opacity:[1,0]}},leave:{height:0,opacity:[0,1]}}}},function(e,t,n){"use strict";var r="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},i=[{name:"px",regexp:new RegExp("^[-+]?[0-9]*.?[0-9]+px$")},{name:"%",regexp:new RegExp("^[-+]?[0-9]*.?[0-9]+%$")},{name:"px",regexp:new RegExp("^[-+]?[0-9]*.?[0-9]+$")}];t.a=function(e){switch(void 0===e?"undefined":r(e)){case"number":return{type:"px",value:e};case"string":return function(e){if("auto"===e)return{type:e,value:0};for(var t=0;tn.parts.length&&(r.parts.length=n.parts.length)}else{var a=[];for(i=0;i 2 | 6 |
7 | 8 | {{ notifier_js() }} 9 | 10 | -------------------------------------------------------------------------------- /webpack.mix.js: -------------------------------------------------------------------------------- 1 | let mix = require('laravel-mix'); 2 | 3 | mix.js('src/views/assets/vue-notes.asset.js', 'src/views/assets/vue-notes.min.js'); 4 | --------------------------------------------------------------------------------