exception_notification_server 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
 - data/.document +5 -0
 - data/.gitignore +51 -0
 - data/.ruby-gemset +1 -0
 - data/.ruby-version +1 -0
 - data/Gemfile +23 -0
 - data/Gemfile.lock +162 -0
 - data/LICENSE.txt +20 -0
 - data/README.rdoc +19 -0
 - data/Rakefile +59 -0
 - data/VERSION +1 -0
 - data/app/assets/images/exception_notification_server/.keep +0 -0
 - data/app/assets/javascripts/exception_notification_server/application.js.coffee +8 -0
 - data/app/assets/javascripts/exception_notification_server/flot/excanvas.js +1428 -0
 - data/app/assets/javascripts/exception_notification_server/flot/jquery.flot.js +3168 -0
 - data/app/assets/javascripts/exception_notification_server/flot/jquery.flot.resize.js +59 -0
 - data/app/assets/javascripts/exception_notification_server/flot/jquery.flot.time.js +432 -0
 - data/app/assets/javascripts/exception_notification_server/jquery.sparkline.js +3054 -0
 - data/app/assets/javascripts/exception_notification_server/main.js.coffee +6 -0
 - data/app/assets/javascripts/exception_notification_server/pages/notifications.js.coffee +15 -0
 - data/app/assets/stylesheets/exception_notification_server/application.css.sass +4 -0
 - data/app/assets/stylesheets/exception_notification_server/layout.css.sass +97 -0
 - data/app/assets/stylesheets/exception_notification_server/notifications.css.sass +19 -0
 - data/app/controllers/exception_notification_server/application_controller.rb +20 -0
 - data/app/controllers/exception_notification_server/notifications_controller.rb +97 -0
 - data/app/helpers/exception_notification_server/application_helper.rb +46 -0
 - data/app/models/exception_notification_server/notification.rb +69 -0
 - data/app/views/exception_notification_server/notifications/_notifications.html.haml +37 -0
 - data/app/views/exception_notification_server/notifications/index.html.haml +7 -0
 - data/app/views/exception_notification_server/notifications/index.js.haml +2 -0
 - data/app/views/exception_notification_server/notifications/show.html.haml +76 -0
 - data/app/views/layouts/exception_notification_server/application.html.haml +17 -0
 - data/config/routes.rb +10 -0
 - data/exception_notification_server.gemspec +162 -0
 - data/lib/exception_notification_server/engine.rb +10 -0
 - data/lib/exception_notification_server/version.rb +3 -0
 - data/lib/exception_notification_server.rb +21 -0
 - data/lib/generators/exception_notification_server/install_generator.rb +33 -0
 - data/lib/generators/exception_notification_server/templates/exception_notification_server.rb +5 -0
 - data/lib/generators/exception_notification_server/templates/migration.rb +26 -0
 - data/lib/tasks/exception_notification_server_tasks.rake +4 -0
 - data/readme.md +5 -0
 - data/test/dummy/README.rdoc +28 -0
 - data/test/dummy/Rakefile +6 -0
 - data/test/dummy/app/assets/images/.keep +0 -0
 - data/test/dummy/app/assets/javascripts/application.js +13 -0
 - data/test/dummy/app/assets/stylesheets/application.css +15 -0
 - data/test/dummy/app/controllers/application_controller.rb +5 -0
 - data/test/dummy/app/controllers/concerns/.keep +0 -0
 - data/test/dummy/app/helpers/application_helper.rb +2 -0
 - data/test/dummy/app/mailers/.keep +0 -0
 - data/test/dummy/app/models/.keep +0 -0
 - data/test/dummy/app/models/concerns/.keep +0 -0
 - data/test/dummy/app/views/layouts/application.html.erb +14 -0
 - data/test/dummy/bin/bundle +3 -0
 - data/test/dummy/bin/rails +4 -0
 - data/test/dummy/bin/rake +4 -0
 - data/test/dummy/config/application.rb +22 -0
 - data/test/dummy/config/boot.rb +5 -0
 - data/test/dummy/config/database.yml +25 -0
 - data/test/dummy/config/environment.rb +5 -0
 - data/test/dummy/config/environments/development.rb +37 -0
 - data/test/dummy/config/environments/production.rb +82 -0
 - data/test/dummy/config/environments/test.rb +39 -0
 - data/test/dummy/config/initializers/assets.rb +8 -0
 - data/test/dummy/config/initializers/backtrace_silencers.rb +7 -0
 - data/test/dummy/config/initializers/cookies_serializer.rb +3 -0
 - data/test/dummy/config/initializers/filter_parameter_logging.rb +4 -0
 - data/test/dummy/config/initializers/inflections.rb +16 -0
 - data/test/dummy/config/initializers/mime_types.rb +4 -0
 - data/test/dummy/config/initializers/session_store.rb +3 -0
 - data/test/dummy/config/initializers/wrap_parameters.rb +14 -0
 - data/test/dummy/config/locales/en.yml +23 -0
 - data/test/dummy/config/routes.rb +3 -0
 - data/test/dummy/config/secrets.yml +22 -0
 - data/test/dummy/config.ru +4 -0
 - data/test/dummy/db/test.sqlite3 +0 -0
 - data/test/dummy/lib/assets/.keep +0 -0
 - data/test/dummy/log/.keep +0 -0
 - data/test/dummy/public/404.html +67 -0
 - data/test/dummy/public/422.html +67 -0
 - data/test/dummy/public/500.html +66 -0
 - data/test/dummy/public/favicon.ico +0 -0
 - data/test/exception_notification_server_test.rb +7 -0
 - data/test/integration/navigation_test.rb +9 -0
 - data/test/test_helper.rb +15 -0
 - metadata +357 -0
 
| 
         @@ -0,0 +1,15 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            $ ->
         
     | 
| 
      
 2 
     | 
    
         
            +
              $('body.notifications_show').each ->
         
     | 
| 
      
 3 
     | 
    
         
            +
                options =
         
     | 
| 
      
 4 
     | 
    
         
            +
                  series:
         
     | 
| 
      
 5 
     | 
    
         
            +
                    bars:
         
     | 
| 
      
 6 
     | 
    
         
            +
                      show: true
         
     | 
| 
      
 7 
     | 
    
         
            +
                      barWidth: 86400000
         
     | 
| 
      
 8 
     | 
    
         
            +
                      align: 'center'
         
     | 
| 
      
 9 
     | 
    
         
            +
                  yaxes:
         
     | 
| 
      
 10 
     | 
    
         
            +
                    min: 0
         
     | 
| 
      
 11 
     | 
    
         
            +
                  xaxis:
         
     | 
| 
      
 12 
     | 
    
         
            +
                    mode: 'time',
         
     | 
| 
      
 13 
     | 
    
         
            +
                    timeformat: "%m/%d/%y",
         
     | 
| 
      
 14 
     | 
    
         
            +
                    tickSize: [7, "day"],
         
     | 
| 
      
 15 
     | 
    
         
            +
                $('.graph').plot([$('.graph').data('values')], options)
         
     | 
| 
         @@ -0,0 +1,97 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            body
         
     | 
| 
      
 2 
     | 
    
         
            +
              background: #f3f3f3 url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGQAAABkCAYAAABw4pVUAAAgAElEQVR4nK19d0CO3xv3x+04jsfjEbL3KnvvkZ2s7D1LpEIosyRRVkhKiCghIaSIlmRnj6zsvbM37x/n+71v53vfz6Pf+77nr3uccZ3rXOec61zrAAAKLLCjl1vtkACg7gsLcv7WLob/pKfn50l/vlf7+V54d13oovtvmT9Tge4rpUerbPTVL21jBx1nquofPuU91SqX0P6E4d/nkilL5DaHHrvFJib1J3/m9YrbpTcFw9xci2jPqQNVcC7dGUIBoNrEVAIA4R2ume2+O0/Id87jjQxz5aVWMqyTVwxR9QUAki45SVrfn5S4LPW5Po4BwEnvvJp5NNON3o102Y5dVAXGmwdoIg4AKsZls4HzPTX/z75GjZb7v03vP84XBuTAyhUspZM3ybtqpxSyPE3/5tUcGf6KM1fKeb/6GAgAtCcZNGzAEQNymEoXNKcAYHvqOnu5qjur6BJP5sXuZXvs3QyjviwWYDEflk/y2nKeAkDFCGsCAM86rtEcPCGVMThKvhtuFQaAUd3C6Y+bNeRCkTN7k//mT09+K1QamjRfQPSVcrkYAMzo30fO5+MeIRW7kiIBQMcuv2QkWf3IkI407q9qw1hqXrGjqkNnmuURvi2fskiA59n4g+SQ3UMCACPLQWjLr7GNMKPa6g0MALLbvJSkzo6ayHM4YU3H1cxLASD0bAydHNpGbq/Sq8sUAH6u7qbqU9eew+jmEfslACgfwGfkqOuOcr4a7aLFMllJ7w0lJyfK0/R0SYNRii7pBQYADTvsIQBQu0dzk9R/5ewgBgCv974yivwUx0w6tzxjG7JOkG3vJbKhbRjL/7oJ89pcVHNar2eguZ4d12xXN3+43E6hMHcGAF+3/1K1XXHbFaHuo+HRcn324yfJ+c1citHO/WayyFEFyLgNGXKZXh5HhUF7tbaFqo0xi54rMDbbzQBgRPXJMp5Tlo5R98/5UrrRqeRdbRwln9dIAPAmo93fp9x/0vKq7mZpz3JrIu7n3Xo5qs/3TIhhkX8vtnJ4oBkA7HMaKwEA8T0iIGDU5lVmANDSz5IG1mghU3/C8mQDAOS1Lsb0twsTAPjYY7rRPe+FR4S8jN3o4MB+lq6R4+W2+dbcAoI7Lp9DVm5x0l+9UU+uw7pQKAGAyfk9pOMzKbv1czkxzEwT97/wk75Ud6yJBABDx/Yxe1lmCAGAIju60uQdnJI2xnJEOJk10M2ZX05uoPz4D/Jz/hW84Y8378nIPu17g80d2UoCAF11vXQbg2Wg3QMqG+3s7bcxKor76L2cPA0aKtcd2KmZlLjkPgWA/H6H2YHJNU0O8qUz2zXbu13bXZevV3lyb9Io/ZyJVxgA1PLMpjUeZ0uTJvYQkDywwjwp6EVX+du393XoqU3jyMnUZKMrQMVOthQAilWboGp/kM1kk8yIkHz9y6imVB8XM7nho8UXyP+7RPYkiTMLMACY8iOJAMBs90tmEW9Lspgqy1TAeh4eSQFg957BOd5HAABm21RI3/D4kBkARLqXkim/WeFHpGnfiyY37Zg1TeT8d9dOk59TPWMZALgHD5GR5RxqpzmYZexthO8x7eN1R9Zt1QPApMIlhb5d/Wmec+ZmwrZHFADsylkLg9CvVCABgLY18pAqWctyXGGQlCEAM7/gE3Y7T10BmbMPXWCb/AuTuX3OspB9MXoA2FNJkgCg3Rdfo9Re6aCTtDhqvklYRoxbRWOOLNT7ZNjQn31qsNtxyQwAJtc9KNTbqLUfBYCacXzfrFnfR4a74Zhfct6jy04LlLxyf4pm+79+ck7z6ZHNVAq9Ipd//ZEzRH5XWrDECWfl72njavx96W7st5uObNdQRbljN4hcTVS1VRIAbN3EZOD6fCPCgD5485X5JT3JEc895gTfxEOX3pDri3L9brSsRxdbAgALetmqOpXn1F653Ob5VqploX1YCynxRQo7OGa6GQA0i8pgJPdGal0rWD/xsDb7fte2JXEfV1wPAI8eLZLxc71iUbl952bNdZHX+tGGjrvk2dm7cCCtVPYdA4CX7zqxWbPt2LaayTJ8jnvyGV8lbg3oYXIJWTUkohQA5N7aiq3oPoABQG2L2aTgkiLS7c/fyZD64uYflHFV7lyr71VlIO5cNGM+Fufpucp1hPzWkZDfb5T/oEk94z/MlussUXqhtGZWf7M//yck7tMsl//LUNY0+pJ0+ulTAeELPxaT++zYorVJ4imQmUb36r00cbT8+3cCAKe8xrHRUy4wAAgu9oVOnKDsm9ddo4nUqLxQ/kHwb/6/xYiRMuAks4nRqeNWvo/q35qiS1WAZ+O90FDbLXPk95+dlZlzpzynlgG+1eX/0U23EgCYtqeY9PSBK0sZrD0Ykbf6seTpyRQAWlxW2nuca66Kqjfo0+T/BwPOyP8Xt+0uz5iq91cyANi7bzXLP/qaAP+zWHeTg3P8XoRMCKs8nSkALL1TSAKAVjN6S1YOmzVnmuPiDnL7rpOtlTzrrIpLAFDj/WXNEa9Sr7aqwisWP6SGhVLZWd1XAWFHXcYp620PzlVUbtOc+Huelxt3WXiDAIB7M4O4v6TfoI1dJ1MAqJ1yR/53/msmA4COvSvo9WdDSYX6Ddj0N4tyxJWUWx0gIzPtejrx+3Zc1ce2z8I1EV7B5jlba3FA6PuUAs1Mrhw9LJRZs25NJWn+gSp0RvJiFf4SgzvRURs75UxCsLPkTZK4YxBJeDFDBnRyHjWrOCp2BQWA3kt+EwB4+TgfBQCPtT+MzrLPJ5yFDtVa/J79yrouf0vSm96kAWBiSgsZrp1x4/XXdOUlh9YZJhF1dO8Sud5HvXtLAPAqb25663kzYTCs6zvLsK+aUEH6fU+X43PXuZnOmjDEXuxBbsT4GO3XieU/5XKzFrtrt3d7pp0eADqXf0MB4N1FJyJdui9dfsM3sZh2j1gzEq5q5CuO8f3ks8TK2RzVpLwCp4rTAxfH0vxB4mExuyVR5S9aeKZmRwKr3zUpyDSWMoIemxy4p/aVZYQE5WkvTXVaSgFg2bv5AqJuZr2Q62nx04o8qNbYJCFNDc1FvHyT5Dq6xzwQ8nunKJwYzjU7KwHAutZcrDHG44cEABm+8Yb2y6cLgHiF+9F9p2vrAOBiiU4EAMYNW0faFGopdPRHZG253PfAV+wkW6k5OJ5RCmdRstxm4jzAjjXM1ZICQIlGI+R/31Y/kTsQrXsiwNTn60kCAP4RM4VBulSlEgWAzT3vUgDodfNUjtn1FndusJj8pSgATD5WUWjvSGwho/Xs+PXc6H5zaMl8YjOju/z/dZW1BAC8OxSgtvdrSy/3uSg47H5ugLAmN+tWlY5yWCptfv1Fog+7awIQ3PWBAGi7eh50s3k5Vji7o4oKp1pb8kH3zCeXGbo/iV0btInu7r5Mn3jZSxo6VumMVa/lqqnbzVx9sOwz5o6AgPQ8IcJ7oPVCozPC7+5P3sYXVwoArcJi6LoGQygAzI3eYRY8+IswwIstFtDYu7EquGK/XZd6Br3Rvargy0oMziMlHE7Rz1xdUAIAu1+KyKVJ7lTpyuUqAi6Lnagi11fv+x99uXiO8YNY7aakzoDH1PHZU/rcozu9uM9Zc/Ns7d1Frvjs6B/yc/zhKqrBmzB8+f92CtdIy7I4J2ZzwDnHovLtg14KsDg1LSO/J+XSMwAIr31QYmlWrE+vMLolq4rZs8fZCsLnRchwL8hVz2gf5s4fr7/qnE9G5vrzS+U6ZjT11J9ymCT/a1HFVrXUjpzbhlq/26QMhoMLz5RyZyUrPeK4ruuxDQIVVHPdIg9KSDWuX9h98aZAibSOqwQA50OX6QAg4PUtueH0FuJBsvXjIcxv6lSyMXwnBYBd/8xA67F3JJS7ywDgZpyOZaWcIjfDOIcilXGT2zMkVSMAEFzIUUD4wTNrpdLNi6sQ59PG//+ZIP6XZFH+rgQA+5s9pgDgU8lXAoDSW2KkXXuyCAAkbpAIAAy9ZFy3JKcV/lPMPOrXIot/OgtI75zST0Cst/dSM/wnna62R+78PNurZsmPuGT1h+dvCgDx5W+ZBOCAo4Vcvl5xvu9czPgkt5vew1aGaUR+a9oxUz0j/0wnnCYZXdMBILR7kFx3n0CdTHjJtcNYn16xctnEJC+z2GkvpYw3l6QiP27QWG9/Vb37D1VkjKwxOvi5K9aUevgnUQA4cvYo50yX/pDeOJxUpMB7HRkmPRymAwCrpclsUqa9btK+6ZwqO05WrZd3F1elN1vySgv6JBrtbOW0yop27lYUTTsgAlpohHpgHqRba3amV3aySaQWGMB1ElMcCxIAOHInRFpuHaaCvVfgADazSznpxC8u6gnN3vFXlrbmaGchj0vqCXbVzZ2MHlbFAABdK/2WXAPVB+bAfpZy//LmWm10kJxqThLwYG/VRcSL2ZbfdMSVEKGBS6u363te0f112o/+EEpu+k+V87VyvG2yTHzn0Wzx4mqaSGnfZYi0d90QCQBmXuYDvzdKUW6FjGlPH9X/nSOuqc/qAN2904UlX6/kv7LKs+K5PqXuOH626mR1Tp41Q3OVok3rT9U1eVNQBfPK1YqQ8fOAcGrwdteEzaFuT2UWRi+UCS3XPmsGALmGdiXoUPwJvXymvpxxu3t5FUXOD/NlTdd75Fxm//8hTbLtJzk8HC0BwIzM2ToAqGGoyfbXf8BKDj8vwDjJLkZAQPjQTPl/m8bLSNL7RgJxXM4sQvtWqEqqxDfTHKR2sco5427wfbku61NFmf+aHsKA5Ns1Um57R9m+EgC0nlBJLr+6/FO6o3BZqfenTGmPWVsydjk/09DqH0lEYENaKrKYXP5UUi5e7kW4WqnTv4EyK35O0auoPWZehLCHrKn2W8rO3CYgKq+1RY6ouNpuRbHzfO4bXVCH7dKCdt1Zdv1U+m3KbgkAfCd/ZUXjvOT6rjSuzvy3TjfKdbVPfStNCpip2udi6vFD2acqLeU+66JE+VVyVIj+Qv5dBAAOphcTubX8jVS4iKz9jRReU1YCAJenU+nKg/0pAAwJoBIA3M/1TsBvg+pc4VVnlhkd8mMjA4A7Lq3VK8rKnmNzfHha9mWPjPzSpQya63zWBbWlyaxFY8rUPFqaGup9EwA4sesQrf8zjuS+N14CgOXV3Ei56o3IiXvczOZC1kc1wM7RRuFtOjrU5JI5fdx5GUne5fvQBStmsXxFIPdjQrhiohPmXFjVzudHfeT6Lze4QzZMDaIAMNRxGQOAa0XXkkVTZ+tqftOzHZ2uUwBo3yBGc5X59PUPff/B+0UEZK5t+nd50p+pPxS9uPtwhZ+OTLFhbkFBhf+bv1ryOaP1jzpkqQeAq9O46nbAFG1d9rXvM1TILoq2Jjd/n8ztOgAIdApXlc1VcxBrcINLvacG7JVebfmUc3upP5LnwYaqctE9uwvtFbM4Qlfd4YdRi4D9FABu5D3LJdczK4rlHZcm6QDg9O89whSr7aY3CuBNPz7lNsU01qTITsxV+rmoo2b5B6leQjtWdtUkADhaqpwOALZ9ns88Zu2jnfo+Va31DxdZSHVu2PyVeK5ERFIAOOEhmuaMLqtwftNjq8r1HJrvLlNxm24KG/7ie28GANbbNvIN/wmRy8SltJXu/FIOkj1eOzLHKT3/384/vy69p8dH8UPU14sPJXu7mmYA0KnNHLKtzTHNjue6Vo4BwO60/TJiDV6l6PpTXeWZ0TOqocGmy129T9R8PQCsKDCetjw/Ws6fEjPgr9R4qH05aX8fzkqmDdrLZhoaE5uYtQbvXCWFAR32vqTkUF6xvTqQvZ/NNbclBwqtVrXx7M55oU/X230klsmi/UBmUDm5/t/dFdGGhXMU2f8zWyhPiybR8cttGADs6ria3djRgAHAvf3amsc/U82UUDK//gYlX8jcmzoAeFh9LtlpXkHo5CcPN+H9V9W5EgB8qMT10CdvbhManOW1nmU1WSF8O3bjJgOA3oZP9OKDVEVQeOiIwXZUsNQm2Vdfu2VuuZ2FG7iOebPlAQYABz5EqJiOxsUqkSvvztCtLgNF26rtp1Ub/dVbwXyJuD6fpi/aySbE55dm3/2sScHdmkSR6kstNdf6XOOKKIQ01ofce82l32P69TOJ9PRXtnRufIrUprAbAYC9Lsr+4zD7FvFbOEnpX/2ZtaSkzh5yhi4L9uoBIMmlqtGDU/Pjfsz35iRds/M3/nq4mvvzpCpPgLerAQAct/fUxeWOkKbYztWsx2mjtQ4ABkRv08cv2qKZZ/nSPVLcunha5aAHCTjjSfeFTmLXD84miRe30uV97c2TfeqYXDryXD0ptQ4UDdyGWfMD2t3N400iekDuUNJxMD+zrNjUQc47v9RECQDWdtuuIo4Pl4wbCzrMdVeW5ttzuHJk5m7vv06x8mUaych5mdBBOn5f2253x8UpLKbldhW1lX88ULWEDOtWhTYoU1u66eImA/zJLJnsCPmmqF0XTJSf32AXTU3iqtfn9dazewHipp66pIjRg2C7os8EePN8rvR/vd5/sYuWXGwnGnpPHSu3d334OFor9pkwGHkLzGNT9rr+nWGaMDPezDnxLYtZcZkBwM+8gTJwm8aslfeCk9sU62+zy6JOwKesWkR/2/o0tS+1j15cncYmdissIyukAbdT8ivZWi7jUM6VfD1+m1YtP5D+fnfgr7Nuf8vVFABmDfU3fEtcIW3M0snI6Ou4VbP8l0JcULl+QQ+aUIArixa0CFXkSEVfC30Y4czlZA/d6tKRPa9R28wXmsj0OTDYbOuZrgwA9oQfE4hgy8y2FABG+BnIipuzyMEj3YQ6Or8QxVOZRfNIGDHhi1HqyDuIcxJbu6wXKgqoZa0CbtD+pYoVSFXC8oZ9ohbN85PMRb7ELcRDppZLKb30ABB12pF5rN2vA4Dfvz8qA3bLRercsRLJN7Q+AYAWh/vQm4tzS9nBBQgAHHs9XQWv0/1I3U3vS0b7sS10jr6mQ2MGANGOjQQkDJoyVT9oouJS0NeuAgWAsGt3hT7uT2qv6PnT+pqkdAefIfTr+GxNwvD1XC2UtYkdRgHgx9YvUr/2TZR/o15uJwBwYUB9k9O304QhBgCYzJ4JDZY/3JcBwPdeXyUAkNZy81PzzPsC1czc/ClH6tetdvY0fj9nJR2ti7C+nbaz6804T+9plUCtUgeyL53sZRjW3v2gCffmBty6fulavvQ9sC8kD36+m1zmtL5AtrDcjbnatzAAxP7a8j+dyf5M6w8yoazupcT6BHSSv+2s2NE4Hu58Fq3Iy4zQZkU/n+OylgjJQvg/olEvkpB7KQGAW+cTyEVdJ3q9PVfxTkz20uxUwTWKDv3tGE718cN1qrx+Nn4qwDOzAkVDPIlKN3dw1e6cd6fYHafrcj0XvowSCOd51YHCwPWqYm8GAGFxKZoDmujvIwHAy8+KVNeqcmWh/dHrd8nv0yvlkutZMaOjIqdykqS8y4uw/s9Hy/1pVHiwGjcxzfiptM7pwbTv92IMAN4Ofyx0IquXaLKz78v/ZgX/PamwkH+L63UzADi+WfvU3p7aqr67VOpJAWB+WRfp7P54ku/EdwYABZ4UI0/tRdZ7Rjn1IAIAm3Mhx3B/aRFPz6ZvZmMmshyVsWnO95zGCVESAPTqdlTasUFcbWofsdQ3ajXS9LnLNeWQ0SWqenR9BgB9y+/I8dT1crybo7xJrgvJMU9uJ+zTZZkMpO1Ifj7w38ptvma147OnE42g9ervNnR+cVSGt0KjIwwAXpXrY7LNaTX36QFg1Rpfs6/R86WsfIX/ehi9Ni6vMKjtmyhGFxltMykArF2ykK7ezI0hQoe1pDU7f1HV2zO+r8HJaiqrlzbaKIzDFsWRoMXb1OPQ59cjAgCn+iny/Q59lc1sfvxnCQCmWdeX//ddEK8HgAGHFb1zcJV2rOJxT1q4dmPi11Lb98TsSgRZcoZbvNhdGcLauiSoADq120dy2t9LKK+veFACgLbLx+prWu+ixyotoSujEoU8yzc1ZdKiL3TqJe4MM2XJE8niH46x7r5XDABq9nlHXq0QKfjVLW7c7RndU0Ds1lpDNJFZqkgvCQA2R3+X24+Jz0UazpZyRJQehSKVfCWClDZnXwnWTbyt5pGDSDJpcZNvnJY13uaYV/9cvgEFgHSLkZpLR4d/1tZegcNFwWbjZnLHDt0VLSnvhaTL8LkVW/U/nxtWTRgjDY2dZXxmhOQV+j9q2gDzOVUrsnNj77MfzdWG3P+mXTVvkTkt+RJ78kqYKKp3KEkSbEuxljO+y/Ae2zzIaF1PvP/j5dXG3lZmT302dmfD+7dV6RMAwLE/I+e7daAW/W2ksfNFnUSIeyHi7s+VWT/7epLVRc9IxT4tJkM67JGBnbVuB31/pRVt2z0mx1LVAa39SbVqlqL91zUruXPhF4fJdYVe4iap3l5biK+3v4CASX5MNZhni/czCUdSKU4oJZakqAhMl71FAgCbb1XkOnoOrCW02ZRGa9YfPGSpIaRaJN0zfJ80/egBNZFd6XlX/jjIr6lmJfencMOFmElLuPQzvjmRcnHTl68f5tKMO6L9bOXxXYVOtI3eSwBgQ+BpTUppso1ba/TuqBg0NGXxAuW1HFlcs2z5bRz5oe9KEAC4eaChLCXYcVp0f5tagkuwFwXmlb+3/PpSbjOp0ypNYlz83l4CgO4vx2vCsPj+OgkAno5IlGFe2+MD8x9TRHNW1z1XWf19ZdxYVeWblimHtYByLnR0tWRVnktbN0oLdvjrACDU7bPRqThi4kZ9YkSW/H9imrbPYdv+aZrfo/Ncl9bXfSYBwHHXNzniel6eNM5R+XUpLSBhaUKC3qfoQ4EAp37yo/vGTGd5LjQxOnuqvzqu+jdxwl6ZAIPOhtOBa9tpDsQys94q+KJnnhLFTJe7fxIQMn45t4oYZKsYqM1Y4GBY11Gxge0Qeo81X7jWqL59WcXWclnnPYd0GR+MK6j+m8ZbP1Dl7eY9zQAAESU/yMj4+vwOuZKfBz6wdC0olFm0jRsQFKb2+gaX12i2vWSX8cPw6P1PiY3kIyDvTuzZvxLFrkaHJQBYv0FtFDFrwOSc4WBRlBKdYW0BbSC7JZZUfd/o29N80RYnYVAqd0imbr8lub6VJxXD6UlrXdi41m21648fJHy/fcNa6FCTHeGaS8nbakvlcvvdd+ua31eWxNV7Qtn19e/k9p/qttCkKVkUACocUJut/jfl6j5GE9av5TaoZki9aqOEvJ2eXRHqbzSksBT/9TQLPnWYAMD5GQdZcOtG4gCN2rmPWXlbsJK75tGH/R7JjeRe35QAwOCHiq6ifLEFoizmchWTG2LofcV/Tud4S7I8FUTzT+Kq3mGx041SSsMsbtwwdIdo8N0xyVYPAKfOvCZHFvQQynuFK1Lcnz08hH9n6vEls0v7hoZZlstlmCvb+es+jP1sFI4gC1c9APzoyPuddaQoG+C22uQg5g9RTvXhOj5AfrZB9OB9xXt4p+6VCm8ji//HpsFx60rhw8fzah3xv+nwjfsMAOKaigfLqFrvpJHBntKUdbH0aVntU+n5DVWp+Q5FSbMyV0GpyAaFouO6l9QBwDnn25odj+vKz0sFeu4V4M0dYc7K9H1ndPl5Pa86yxcjOhnVa3nUAADzZoyjAEBGDeKHVYcAgXu8+nyeyWXmc6YXNVzmZ4nj05dr5nUxz6bPgh10AJBUuBmLe8Kt4SekrFPnL/3inUlKL1nS2yhVpFRprj86VrTn2j3cSd7cPnRRzg1RbU/RyfG2Jf59vw9tbuvfdPh8vLAUMstLqvz9ep4RBuHg6t5yB7sPUlvN285RDNkOPy8rPzcsstEoDo60CSNLw5xp78SSbOTZUaTbx3ImB+je9MOs0qS99PT86sr+m7+Uqv5dd+qSuuZzSYmV0TTi9FiGI1cvSgBQ5b7at6FF0DO5M8NWch309ivc4uNgrQ5sWXqI5npefbfC4bic6yDqCGbf1tl6iRtd+oMw8qVKpnS7S0s9AGTFKizqooJXhI733WgllD0ztA898Ps1S/rlJy02XNOcHQGHvjAACPbgPoxFF3GFWjfynrqY6yQAcIysxpYMm0znWhYg+94qLGqVfHfZdFJJk2h6u4XKfQsZvl1vu1wROhZeOpKQzso5a9KmyXTiArX784FfhWinzXlJ90g+U3HAmfvwtXQoZACAaLseZp4Xa7FVx/iaW7cQN6Ben7GJLF+nbb7ZcBhfBj6SArrUz6LN7/56oh1vPQ8vo2Jn17kzcmwdmb0uSK73beo1oY1qqS5S2pYMkzP+TXoDo/87jrMnA+cco7nbB5Gl/UIIAFyu9VjO36D6VMm11FdS8iwPqNPth520upBoCNKxmYvw/qLTEfLi8TjNgU2q+9Fg3eEfScGcgQVY/pMNKQC0OriXNozncbEc7o9gm+/HkrSZpeVKHkw6TlvXryXdqarNdZSf4EsAgL3nUXFsV83R76S3ubXIzTk0X6PpZjN3i6Lr7jv1FABirqX+z7ZQ3XceljYO5AFdrPKXpiMPO8iwDr1eiAFA46Q9qnr99mrHuPo3bZrGbXB/VNaecX9LzULb6/tGPlK12631WvXy6etlZvPJSm91Zxgr+vAfV5Dvu4awsnX2sNEH0yQAaGdmXFZ0OZz7e1jEpJCjvxS9RIlWCgNwsjU383m5nwsCh/jwyAgXgyvIVGMxvozQhrn9ZK5rqe0hdT3nq5qJ9/x3SeNTnQgAeI0VrTzW59/G6NITKgTkLtmetEm6rIn8fYdFvUjV3OqgbQCwsHURKWBwcZLqUoYBQJ+FC1S4uXxmr6psdgLX7XTuskzfrfUF2vaxJXsY7KLKZ7tFHUEIKWbaMavGBVnJnXx/pQBx9i4hv9d+fE882b7ep7mcXV6qLHNbZpxRW/attJMmTA1k90tvzTE1NkziZ4gFfdRyqY0XueQg17cJcltTnTdowhblz0X5FrM95LxXCnLNp924QDK31iEKAM8iqa0hA78AAB4aSURBVNxOtfWenCgyrtNZlO8/XX8oB8fWjmrzomMJirS47MJuct46XbkEutsuLuvSL9Y2yZVTozWjJZ8ODn91I7syyE/6ek9xWuzqO4C2/pksICG57GsZkLtLTUdW8/nCfRJLXcgmu4dwy8iJhQYa5WoSupRgAGBIaCN36Mw+HlTm5WPFonBrT26oMDPXPjlfmep9FQ5wuRVLKUxY74w30tmJV1iCHaHnn46Q886zS9UkmpNnHknfQywFZNZ7ItEi10LYrAPa4iCTKdy/KLvSz4EAwKd6cTKyklo4qBDnlmrJhg87rAcAi/FcPTp9QYh+sdMaQm5OkPM3vtuOC++si6sGlAXyM8hTVx6qqG+kgelq84AwKzYWljt9u/vjHHWmXIF0AgCttyZKVZK4JUn5PiVV1JbxtiUpUTKfXGdgRyWSUcdnnhIADJjuxd7YcWOD1mGvjLZvPuAYPdV/1v+kOQWA7DeryWELtUORnOL3fKOVL00yC0/szt6EJynG0o/qUgBIdOXi9X7lFPfgfifKyvm8l/OgLu0zh+TYIXNWFbVFxu/9YggLK9+VegBo+WyakHfDfK5d7NyqmYCsFlmZmsg7ESzJA7ysbQ2uHz/gKi2O32pY1+2LdLSyvVwuPpkPkF1KmDAT5uu44mpeO+Pq15+NTwvtS72aUgDYlM0PsZ3G8mNDB/pIBefcC3PNUj6V5nWPK3Fc2rTCko3ZzBXu9+aPEhrN90OJZmCbHML2nmoiA9v4pRiw69c4xR99QT119M+NqwoS70QxsOavNzXY4GrehQHg1dYyrFVgkB4A5rhv0gHAoXxiNNQ9j9eR1/3v08odg41S2bb7x6WWY/bI7c9DY01E1jMoZxzvZss062uz9RgNnXHF6Ez5cOQcnZTGBZs/nB0FfPjmTRPq9PsjwhEAPC4zgvg9N6Md7CyknROnmJ5tGXWViJ+nR+1SBINW9Vnd3TweYc07iezItPuqznad4ErnXlU7ZF5Zs0TIe+mAmuKuDhTN9zvqLAVAnxm+E6lzuAr4VB/uHOTRlc/UbcVLyu3nr7g9xwyDh0sLo8iPqB0rwLtxDfcScC2sfP91cCMFgLA178mLvefJz4vxpOeN/kK5Ro9E8X+XUSel5nHfSbfJFgbUehVqcp32iR4mip5PPVQ2yfLFNQ9ynxd+01Y+jbxMfC9wM9Jzjg9VSMr+fUiGxX51ODXfpW05Pmx1Y13Pwg3Z3SKzNREd1a4Vq/ytKRlzqoAOACqeL6o7W1AvwBT2jrOb7GJb4r5+o1HqnFVdsS7c/EWU5FYI50tgrn1P2GKvo7onu4LYtbxKcAS/KUq8GPf+U03i+VLCVQWGBVcjVcuL2/fHbPCq65oIv3uS++AVODCe1Kik4dn0n3Ri4WgZsOY3q0izlyibdbmowwIy7PN9Yvb+o0wa07HvjdnRfGrDg5fz0unhx7XI8ERXTQQvK3tGVWbyhCBWrHWWss9UT5eipoiq63k71KsAAMxs3UkPALbhpQQcJNRwytFm/20qt03r8SFEG4fvxj0nzk5dDAAwNHmnsgZ3UbxHM6dXYM9fKaJj6vlAAoC9Vwbrg6qK4f+sf/AgY1n+imPNsu7rybBPtYR8S83MGQC0ufdRhbAL1evK32o48ghxR50U0bqVlC0NXN9YCqDcA3iNzQ+TlBjSfTKzm3mKRTskcHu0zgVIv9uKYaBlmQkCcp5vOSC1suLuEE8HzWAAEOgQRQCgarirlH/LG/JjWLpQJs0nTLKUutDek4N0i4fW04Tn/RoeC6zb9kDj8HbprR0GY3mJMGLTOIkOSDmg61NjpsHnAvf3ONZlBE3skqqLP1NLAoD+J+pJGxqUFqiDFasjAcCv3G6SfWV3AgAD23I/i9OVXaTKoU+lYb1a/JWihu4G9XpdjDUODdQUaP6ZRjTv/tf6Gn5SgtHM9VmkOSM996wv9u9zi7a1pJKLaqk5pMPbTbZVvYcSQW9Y17P0xS5RopxQ54nxFab5I2tWpUAbocCgs/0V5VRsAg39qYhIXo8eSgGg2En1JgsAx/dulvNm2EyU88wcUruwnbUSQ6rXXksZIcfLKmzh6oY35eelvYPMvtjXl04Er5DrnO5i3DznfJgYwu/sEa5Ucn6s+L2Y5/opWU84QQHA4Q63K8gdF0wAYPjISDp40DcBF8En7aUJ9QeyrSes2fr66mBmv/v+lOIOr2J1rmpHxf437c43T5q+oNpfCQuXQg5SAHDuNsDoNPqRVZEtGj2MjF0mzoQ37/qqANwyROFu5uzYYgCA5iXsaakOwzWp4oJtIwEBi1bZCUDrXhYhCz5z791ClX2lQSMVZZM11ILANldXGkWMy+Ci5NWm0jIhbO86XAcAw+OOmgHAIrcagsNqmeWp0uoAV0PtMO4H2a/FUOPazrAl0pKsDvrzuXnMsIJtXppcRvu13/53A/QHN5SZMqTvC9pi/SJV5yIfV2dbJnFxwojZiQQAuhxrY7TyMJ/8Rg9WV1YEkIA0RdeReipDfnadqCixxuVvKIq5l3IXu8P+PN7h08raDqr+DqYDW/6Zhs0dLrc3YM0V1UBb9Som//cfUdPsrndtATfZTX8Rfchu1SB0mTiD5Kq8kcUOmSHnL9LXhK3voNs8glyet7tNTrnX2WZCJcmNjhjVY3xZeEvukN8WxdBN/76r0TYyrm8i5rWCjK6tG7ZwC7/MRdyc6OcZHnTNbfYkfZMdeaTIf9Sw/6Zaz/hZZuAC9QY6aS0PUPO2dGWjiAk+NZ2mpzRUwVu12lu5zK4hin6lRd8m9MDKDdLVeoqKuVM8ZzpmfuDq2nW92rF2JZf+da8T0kffGJNTaeeAZian4v+aLswcoULKjrHcMKBu5Dn2qXhVzfYeWeuF7/vGrJGO2s/RtvGKH0jKOW+lAGBzWGGDl1imkRFp91Rlkv6ImvrfdCt5icGizgQCL8641PLmZ6vB7hNlFXW+hC4EAB5M6M6iFxg3uJbTqsb7VdTtPLm9PHINSzyVDK8aqUZy1Wh1iKI/U+Lla9LRYtpxFxPLLjQsKCPGsaqdxT25Hq8YoULAzAWLWdWPhVmAm7YY3VQqOumSZhmydQud09vXULO/OgiB7z3TQsMy9YyHDJlfeSyxzH3dJG4muhUjI9dsp4M9y8u47z3Lnq5t1YrgxcHW5Pb4InoAiHS8K1QUUVAdRmnVjzi6ZZDI3TjYcjY2X55ukuXLa+z+IBdWMEq9hj60VNyK514T/cRTN07T7GToIjvD00hO7ZY1h0k7pmjn+zfd731Pk6Lz377KDencnpOr84y7I/SefFxz+X3bjOt71idsE4SotU++YVffqqNDAECrA9qu1wDw+ME2MmfsQynhcW1Wxi9SFMwua7vcpC57YWZVMmjIZ7Jppit1W7fHON8M4FdnLoy028AdK0eVXEanZdb9n9bKb2Nmk40LSwtIm7buoeQSVVVuu/hIxfpPV1wxX7rVKkGRRI8zfWL+Uvoiq/9OlCZ/TLjJ4vqNJACQMovHgg+J4W7Ss6vHy+2f7TOLAsCIqooH8vTp6n3vWoEdBAB0tyJITD21i/jJyIUy7i3TzCUcfeotAcChedyk/pfdy/+rEKz/puw8AYphnHWWlNrVi2S99ZKeejhIABA0UPHgtUo8z/rPVCSpadb+dI4Hv+Zi66FBPP8o4xfLbPzAA25+qmpBZ0+9JJl9/sRKgVOlTXEnoR8dM5oqdl+6U9Jvg/pEz+KUqySWBWw1z9ddMYT2GzqbPanMrU/u7+SDYDk4UrfK6p7JQXfv34ZaxOWh6+cNlyo41RIGbFwd5Z6qX1Zh/Ll/Zxv5o+2En4qYIn0wm7FaDE10ezh33mmrUzbRtLWOcvnQlHT2PjPR5JJS8qQSbfr5Vy48XPXqmNypPvV6kIJ3XAkArAzvaYi06iNM5+WznsmI7mg+gdX7WYj+POLMPn+2FxCz9mFj/egMRWLtYcElrH0CxL2rwfW8DADKNYvXnPmBk79I3eqsZwCw7ZDS1+hdt2i/Cwf/ykof7P3of1Zi/dPCfda861LpYgvlIq0PPyLl5+C2/hQA2o0ao0L49Nn8yqOHI5Srj1xbKVEQllRoZXKZi+swVQ8AIzZxvfrgsnqTgxoRevOviNh1YQvxzIgwOF7m0lqP/ecIAJSZay5VGKrElD9cdqhmXe6JSiCA9AItafusvoTcOUabzhlhcnkfljJB/p9SpgMBgN4eXGTk3pkH4D9n01puf0N35U6vhdZcWAmLuMHs8IfFOgAIyyjKbJ/kERBY7kkKScviMWsfxKxgUac+kl6J9SQpu5sOAJ5uVSIB3Yk8Kz+/fcGpccF1JcpClnMHoxTj1qyHSXFCy6qMza7gx76dpsSi0ykCALNtbem56ds0B7DEKoNoVNeUW8zcHsc5ufIHc+4E+m9q16iT9P7wBV1qzHVNIms6t6tJzWmLo6Kw8VLzONPE1XifnzzCdZ5wG1WX2FUsKtOOdVhkp+rAhFMhKmSs87f6KwVnN1fMbrzMHjC3VB4DvbKZ+h6Nlbf5zW5PrTbQmslLScOpfnT64Tlk0jYuZl/dl+vvaw/saAYAr75nS1bzDfRN9kepR+oP0nqdjSF3vrJkdlzO4jQaS443tLWUt/xfkPE3XKXT22uYndnlZLCro8SOGVxpvsnV4d8U+ziIjgoabVq+9aqEYvX+rL0Su3xRpFpx1Pa2EsFzw97dJiueX1aR7ZTu+Fg1eIFZncirzAGk85llLOon92ryu8w9XPdbr5cpMOQlt0SJGynKxrx38TIT8w6TvsdrB9Q/MLezvmHbuhIAJI3NI30dUE6AY46D4hVbfl+UUL9T/Au5zsK/uULqrUH0HFv9Uls+Va8Zj063ZKO4l3VLaEIaLCpP8dBMiSh3+oOf1PosX3IKLJqgGtn4rEY098B0CQDyDubhNl5+Li6XH3w9U0aWp3u0HgD6jrXRnC2Wre6ovrf+wRG0c/lpwqZdZr2u2tCo1R5yxw7EOJiktosLucnNmys6Zs2U4Aa7l9VRWOFURXe9qLO3UN/o1a3oBLfLdGcNfidJ39a5tWdEEheJtN5bWCp4m7tArPiqfXGAVmp6Oor6LqjH2pifpVNmaksUAACZt9YKP/ccVQJF9rtaRP6nr3yATG7kJ9W9lCL/n53WQIWsYfWizebm12ZbmwwQI/KM7aZstBUi+ab+3bOfXOfA/K45smp59zhdNdAbifpb2fbNCQDkOqLhCvCf5ODJiS45D+i59p0NAPCxwhtazqyUMGDtgxS/EWc3dXirYINxD9wBgZEK/hokrJB6RnHnl7i0oyoAFx3kzpSpFfUGAPCcUkGF/K4bhxEA8IxXdPT5TwWz3mFP9QBgd+uXgBSbbTxSdh3rxaqpbRa2WeBkfuzMJABQbyWPUdg1aDyb7a6+fg4A1k2IIp55FD/Ekb6SyVn1vs8tFZL6P+NRWAvkU+5NafRQOxrQ6KIxdLv9UP3AJZuEdnbNN24s8d+UPtCMzfZeRTLSczE0sVZEBVd+VyHWxR+rAOxxWQyR13bCG/rx8TQCAHuacO3cza1+KgDsP3M+/d3pLQQAFp/n0tZ1OzhX9mFVMuv9YSBpcXWs3Jn29TMoADyxL6wb25MH5LTJLcblbb24umJTbMkN4novOCLn2Xf5gjRgU4rZyn4P5HqTxlaSMmbxWZg2I+qvTIdTPrUvh7Hk6TGNvpz4kQHAXlKFOCaKopCkuAChrgcleGCeikWHkwY9i1IAeB7zT6yVUaGJUm+XfqyszzxSzZc7c57Y9Z4BQKW++wgAOD3oLcq4Dq7QAcDJlcG05Foep/BiZnUZIdXqe8qDumdINju0bYYU20m0x5pv5CD2b9oXlirXkeIxllSt8UDIb/6Euxskp3E9+9BoH5NLWtrPN3L7Xr4OZgCwbPk+KayGaNrjEm9CpfpP6nA0VTpTt6pqwI5H8MgUnkn2Uv+hChdZunE78t7ylOYAV2/1n+s9xkRulBFZoUOEXMjCV30A/P+d+qz1Mrqm5iTdHKaW1EZ2WKMHgBupOyUAqPZHsPu6v0Qt34lOC4X2ffKsk8JH/nG901nRUWdjkSNS2T6XiWcvfnI/PeW1tLfnDJmjjO+rvjvFud8s5pk4UnOQZzSsK2Xv3KgHgEOh/7F3/lHjGB1pWMVgJW5yZyqpA6oAwJDlhIwspu08DwCxYw5Sx36hhU9u5LZWXRurLd/ltodyx9GsjzxmSPhhUR8+c0iiqp3AUZNU33wO8+v5Uo6Zy/9eZ5c3SViuHUqR1s8fkBVPeuR4ieoee4h9dXwr1Jt4aowAT/gadeCFy1uOkqGOJ/RzBvOrNs7Hpwn7Z4GQGB1GvHliEuCmv5Q46GtuK+v0wP7c4M3rzTrqU185MPUoO4VrHZvtEupNLdNBOjujrfztUKM44f+NgVRFRSc6XiLHz4nidrdX6tj0plIRWkwa00TcF6M8RMeZT2PGCe9JtebRGckN5HYtt/JgPKkZCvwxLmUJAHRMmJ8j7m9268EyDC9aagfm3Bz+Hy/c2EJ35A9H7ZsZAGDW+ZYCAnq+fiC/b/ihWJVEnFDC/m0bWJmmnxhuAABW2Z9t91Y7Xv6Zxp/m9yFGDOLubs2szqvyhxSsRGdXO0e69ln716U03UeJEF0jkLPjlvOViyPHVuU3OgemJjH745xjbFjxPd9cLw+X6/+cpb3u3zikvmf+3+TxVgmSU6TdIOnHpp0EAM4OdKfPd9uQMb9rizZcoxVRknPlf/T3y/YrV1S4DCio6nBayDyBwoL2X6C2v5SgAL9CFRexDc1uSZluPVSsbOeaYqB+kqp4IoXfUZRKHTPFmdIpg4dtmjJPtM/NSxIU86TWiknpq/nTWAeni5qn5Pyjpv51zzJvcdnogPt6zte+TWFlBLN4rdggP+mlvkyy7Z6i8rfOaTyIQakwLk1/Uec2iVlbXN1uxOEmtEeBL+TQI0Xo9i59ID3sZFop1fFhQ1Le10E4OwSai/rvjLYFFY/VWSdMIsYG9dlqf67L7rq3ErtfT3GF63CutArwzYUmaSIx3TvR/M/3Wt+Nuz0DwK4dinSirhOXdJdMePPXJdKtuaJyOFWbe5ktqynGIh5aJoqVSistNVvL2dvNCyA9n8S5stXr1okDXds1T464nRGditHZC9YUA4CsCeJmn+oxhc6rKbKe+4/v0UX35/dTpb/hVxdVa8D1Dzb0IxsRM5Yk1/4u5c3m/nuVD3Cn0a4Dd7DG3bmR3L3R71XIHmKlSKNLpHkQ9MxW5amdV2QEToxea7KPXe25dnFEdC46sIVoGpqynd+6dqK8GKrQnin+i0Xj1rGNr7wkAEidpFz/YfvVnhzbz40fugSUNArD0TdLybnHHymGn+fmOOm76mtSwuOkX0Yp5Ez6drO0QjYmZ0/R4vxmzqEu/OrrKl/E2Xb4Pr8h0+mSti7837RvR3tVZ+K2vqUranMfjE1rX7FHs5VLtmIcOAu/NmS8Jvy1R96Svy+O6W4OAD1KtSEAsOmaEoe48yYn+dn7bDsKAD02+pEdsUdleKa3m8Haddggw799aEnNGRswJ0LFAAR3vcEN7+JnK/3bnB1gdrTzEgMA/PLlYpJqNjXYAe9QmjIjhHw9ztfEmNPlyPmjRIW48C/KTQDtmyg3K/See0ak0kPzNJFTvV2wUKfl24pCh+Y83fJX//XozUlCHauGvGJV60bTxt24k2XtR6XZhix/TURVOa7EJnEN5zr2gaPekpcDNpLiESNztHrsG6yONVlmCpcS22bySBMeTt1V/Yiu0En3u+wQBfbZ+jNkzRBFlPBrU0tpg3c10mrVFE12bvOgRGlH33v6mJtuAgLW/Dz+V+6nbfE5bMdzLnqvH5kqdDQwQfS7u1iTX2fa64P2XR7WPxS9yY0fVmQP7qnyfe7WUO8YzEU7n2Mrs5k1lEhvs8LsCAC0b8N1+mueNqDstNro2usfrmnM/il/7d+K30qYxBse5f46kGXc22jXmey8y6hhw6Q8h+i2fVOlwe4BOgBouFOtkIpcFKtLmeagy9NKWwRdzn3BX4ELnhYmEMD5za1Jr4jRUnTgbbbDWX1F35/pQ8MyZMYGfh/5yCsT6WVaWtXeeR2/I76xX2MVob2dZmeIHS2e2pOP7xAIrufQVFWdlku4C1u5C+rrMACgcyaP4Ttgv9oSdGxIc7n+Ps8Ud3P4juJRQx0b7VQhs+ni59z8ZTiPShAR6Gtwb1mX9TQTb0aOSi1tdP1fZO8q7hmpCp+/5L0SvcFwup1iSzzVSqJRf48BDwAf1r0S8ukq1JMe7z7M9oaX+Ct39N+UsYprRPeeCyFXb4zRdxw4x2i/AvdyiXTZrT2NzpyBI5WLBGZP6inDeW6mj36M0w/6ZFR19tr/udjGJKuq8uyoFW3aYmTFsiE5ikVypr1yt+6hV8Yt0P9Nr4OP0xqPE6QNrIyq/b35R+vc23O9jC5XEwH4+MLcmTP/DO1L5AGg3mHlllDnpmrd+6rViuv389ILaZnp9mTYl5dCOx9sjVuvF2qgeIdd7bmCrSnanfZvqNyW2qfbYLmuHiFHpB6ZyuU3UsRiFvqtijZ+Tm+dzJ77cwf85TpFrrMyjlNalbG/SNP0Bfove0MZAGRcLCADWaZoWWnVtogcCyPdY7inr1/4Gf3UFZzLuGHRWyo9lA/IuSK92NBS6gg8j525uVA3miBlBdyV7Cd/ZClBi0pYZo9WzYbnvvOYWaQ329hDxyYeeKOC7SSJpQAwuqcS7qJ8bUZ+taom5D36ROGmupqlCQO1sW5F+X1E//UqeCf+FONQDstqJS+XF/K70TUdj5of2c4P4m5t/jEU2XdWuQ0noPoW9nUZd8gZc2sXGRfXhp6s6aW39Oc66/1Tzwt7zfMtXBcRNq0nO9fgsfDP2TudHLxRTDXlJ1/movxEq8Nyu3EXnjGPt28IAOQpvI1mT2xDrzutz/EAG0tjbPqRR1IBWuvoJmHAPg7jfpGdXx2kvme/C//K7D1B8pxMl24G5WIznrqQvH1FxVTTNCU4wpsPnJEwxPJZ8Ks3j7QdnJEl42LO5tEGAJgb5mt0CX06wI+8ssnP2/nhpb5OaPdTtcfo0z9cFG6mXJQRnXD1EAOAMlvmCAPSbwW3LM+VsI6+SufyorLTFst1+B0KZI1cUzQ5uX3N+ZUO7rZrzV1Liq7Ul6fWkS5858HvWX4l3u5Fd+55dXPyVQH29kV5bMdH5ooRd+7BalnZn+ldLb6v5plykJx1TZcqF95N90RAhdBn40qQ9m2qUbvzPE7kjyDuPGpT3ksT+ecGKjqjfo/FwG3HXs1ho9tdJhi107ie989k7yY6ZFZcQZlnHi553eB2TgDA7ycXf4fofwh1ZxfgwWK+v0qmFU94kA/jWrP35nwmLH1YVEDSjKOhf92vfq9SblrzfztIGujPZWpDX3NN5fPcHFGBgYsF+B7dsjQ6+/wqqI0vTo6O4sYTp9Kk4p8vqMpeOj5SemI3hnj5RMv9/ZgySz/oV8L/NMtbXfsnal/6lP0C4qx7NBbfnxi/129lyk/NRut2Uosq1vYNM2uWdUSoq7fjJ1q9BTffn+voKAxCmPsUCQACZoSy2/20A5ItCa5OrP648bPvqywBnpZ1ue9gl0x+a9qTK3z2++9XwgDaN8kS6j6YqzqJtlGur3Bbv0fVF1u3An8l5MqN/eiaWwtVhFVl91navMULWnSCRI6/sDE0tO7Lqib+w2ZfbaKEf6hY14lltDV9PcPscxcMq6JDzT/m2ia1xNscUUBkGA95tKMIFxi+ieIatBKTAunKLvwAenCshXTAepaMBN+uxgWQgzbkrN3h68VrjBym+SsxhNe2Zb+9m5M5TxTFWaOMRkYJDwDOv2lGjxcLYyOneuomTA0kj+6fZZNz66WRy/nlBH7/WRGMpTvtXVXtLG7QnW503EbhPmkiLRjgwYbFnNcEpsYlC6l20Z9CQ7fiROlkbgPnVJaWXWpybQaAjUbCykZEzDFzChC9V609D0rSnOLShrLBtMZ4a3Yy64jRgfD/rej991sYv9R+00k7OV+vkBOq+k5/UdTKjdy4mdPOjzy42roJDUje+QE5skQEgANPD8j1t9mUR7d3tvrM0plw65Q9scWpTUnjV4cgIj1C2uq1VZhurs35yJ5tevevQF2vTwXk5n6wiQHAvrAyJt0dgqfkzOBsdY8rwsBODW+nGuieTQOkvBOUg2j0s1L/T5xbkx656WZ/rlbQbe8s4KDc2AoSAPi8VqTTVV1a0cklhqnaDFr8U9d+TF16tY+LlHzTnOxPVQwi/g/t+mmB3wVFwgAAAABJRU5ErkJggg==)
         
     | 
| 
      
 3 
     | 
    
         
            +
              header
         
     | 
| 
      
 4 
     | 
    
         
            +
                background-color: #f8f8f8
         
     | 
| 
      
 5 
     | 
    
         
            +
                border-color: #e7e7e7
         
     | 
| 
      
 6 
     | 
    
         
            +
                top: 0
         
     | 
| 
      
 7 
     | 
    
         
            +
                z-index: 1000
         
     | 
| 
      
 8 
     | 
    
         
            +
                position: fixed
         
     | 
| 
      
 9 
     | 
    
         
            +
                right: 0
         
     | 
| 
      
 10 
     | 
    
         
            +
                left: 0
         
     | 
| 
      
 11 
     | 
    
         
            +
                border-width: 0 0 1px
         
     | 
| 
      
 12 
     | 
    
         
            +
                min-height: 50px
         
     | 
| 
      
 13 
     | 
    
         
            +
                max-height: 50px
         
     | 
| 
      
 14 
     | 
    
         
            +
                .logo
         
     | 
| 
      
 15 
     | 
    
         
            +
                  display: block
         
     | 
| 
      
 16 
     | 
    
         
            +
                  float: left
         
     | 
| 
      
 17 
     | 
    
         
            +
                  width: 168px
         
     | 
| 
      
 18 
     | 
    
         
            +
                  margin: 0px 10px
         
     | 
| 
      
 19 
     | 
    
         
            +
                  font-size: 18px
         
     | 
| 
      
 20 
     | 
    
         
            +
                  font-family: Armata
         
     | 
| 
      
 21 
     | 
    
         
            +
                  font-weight: 400
         
     | 
| 
      
 22 
     | 
    
         
            +
                  line-height: 50px
         
     | 
| 
      
 23 
     | 
    
         
            +
                  text-decoration: none
         
     | 
| 
      
 24 
     | 
    
         
            +
                  color: #b1003e
         
     | 
| 
      
 25 
     | 
    
         
            +
                  &:focus, &:visited
         
     | 
| 
      
 26 
     | 
    
         
            +
                    color: #b1003e
         
     | 
| 
      
 27 
     | 
    
         
            +
                  &:hover
         
     | 
| 
      
 28 
     | 
    
         
            +
                    color: #5e5e5e
         
     | 
| 
      
 29 
     | 
    
         
            +
                  @media (max-width: 800px)
         
     | 
| 
      
 30 
     | 
    
         
            +
                    margin: 0px auto
         
     | 
| 
      
 31 
     | 
    
         
            +
                    float: none
         
     | 
| 
      
 32 
     | 
    
         
            +
              & > div.content
         
     | 
| 
      
 33 
     | 
    
         
            +
                margin: 60px auto 0px
         
     | 
| 
      
 34 
     | 
    
         
            +
                width: 1280px
         
     | 
| 
      
 35 
     | 
    
         
            +
                @media (max-width: 1280px)
         
     | 
| 
      
 36 
     | 
    
         
            +
                  width: 100%
         
     | 
| 
      
 37 
     | 
    
         
            +
              a
         
     | 
| 
      
 38 
     | 
    
         
            +
                color: #b1003e
         
     | 
| 
      
 39 
     | 
    
         
            +
                &:hover, &:focus
         
     | 
| 
      
 40 
     | 
    
         
            +
                  color: #2a6496
         
     | 
| 
      
 41 
     | 
    
         
            +
                &:visited
         
     | 
| 
      
 42 
     | 
    
         
            +
                  color: #4b001a
         
     | 
| 
      
 43 
     | 
    
         
            +
              table
         
     | 
| 
      
 44 
     | 
    
         
            +
                width: 100%
         
     | 
| 
      
 45 
     | 
    
         
            +
                background-color: #fff
         
     | 
| 
      
 46 
     | 
    
         
            +
                border: 1px solid #ddd
         
     | 
| 
      
 47 
     | 
    
         
            +
                border-collapse: collapse
         
     | 
| 
      
 48 
     | 
    
         
            +
                border-spacing: 0
         
     | 
| 
      
 49 
     | 
    
         
            +
                tr
         
     | 
| 
      
 50 
     | 
    
         
            +
                  th, td
         
     | 
| 
      
 51 
     | 
    
         
            +
                    padding: 8px
         
     | 
| 
      
 52 
     | 
    
         
            +
                    border: 1px solid #ddd
         
     | 
| 
      
 53 
     | 
    
         
            +
                    line-height: 1.428571429
         
     | 
| 
      
 54 
     | 
    
         
            +
                    text-align: left
         
     | 
| 
      
 55 
     | 
    
         
            +
                  th
         
     | 
| 
      
 56 
     | 
    
         
            +
                    border-bottom: 2px solid #ddd
         
     | 
| 
      
 57 
     | 
    
         
            +
                  td
         
     | 
| 
      
 58 
     | 
    
         
            +
                    background-color: #f9f9f9
         
     | 
| 
      
 59 
     | 
    
         
            +
                    vertical-align: top
         
     | 
| 
      
 60 
     | 
    
         
            +
                    border-top: 1px solid #ddd
         
     | 
| 
      
 61 
     | 
    
         
            +
                  &:hover td
         
     | 
| 
      
 62 
     | 
    
         
            +
                    background-color: #f5f5f5
         
     | 
| 
      
 63 
     | 
    
         
            +
              .pagination
         
     | 
| 
      
 64 
     | 
    
         
            +
                margin-top: 10px
         
     | 
| 
      
 65 
     | 
    
         
            +
                text-align: center
         
     | 
| 
      
 66 
     | 
    
         
            +
                float: left
         
     | 
| 
      
 67 
     | 
    
         
            +
                width: 100%
         
     | 
| 
      
 68 
     | 
    
         
            +
                ul.pagination
         
     | 
| 
      
 69 
     | 
    
         
            +
                  float: left
         
     | 
| 
      
 70 
     | 
    
         
            +
                  margin: 0px
         
     | 
| 
      
 71 
     | 
    
         
            +
                  padding: 0px
         
     | 
| 
      
 72 
     | 
    
         
            +
                  text-align: center
         
     | 
| 
      
 73 
     | 
    
         
            +
                  li
         
     | 
| 
      
 74 
     | 
    
         
            +
                    float: left
         
     | 
| 
      
 75 
     | 
    
         
            +
                    list-style: none
         
     | 
| 
      
 76 
     | 
    
         
            +
                    margin: 0px 4px
         
     | 
| 
      
 77 
     | 
    
         
            +
                    a
         
     | 
| 
      
 78 
     | 
    
         
            +
                      text-decoration: none
         
     | 
| 
      
 79 
     | 
    
         
            +
                    &.disabled a
         
     | 
| 
      
 80 
     | 
    
         
            +
                      cursor: default
         
     | 
| 
      
 81 
     | 
    
         
            +
                    &.active a
         
     | 
| 
      
 82 
     | 
    
         
            +
                      cursor: default
         
     | 
| 
      
 83 
     | 
    
         
            +
                      text-decoration: underline
         
     | 
| 
      
 84 
     | 
    
         
            +
              pre
         
     | 
| 
      
 85 
     | 
    
         
            +
                word-wrap: break-word
         
     | 
| 
      
 86 
     | 
    
         
            +
              @media (max-width: 300px)
         
     | 
| 
      
 87 
     | 
    
         
            +
                .hide-xs
         
     | 
| 
      
 88 
     | 
    
         
            +
                  display: none
         
     | 
| 
      
 89 
     | 
    
         
            +
              @media (max-width: 500px)
         
     | 
| 
      
 90 
     | 
    
         
            +
                .hide-sm
         
     | 
| 
      
 91 
     | 
    
         
            +
                  display: none
         
     | 
| 
      
 92 
     | 
    
         
            +
              @media (max-width: 800px)
         
     | 
| 
      
 93 
     | 
    
         
            +
                .hide-md
         
     | 
| 
      
 94 
     | 
    
         
            +
                  display: none
         
     | 
| 
      
 95 
     | 
    
         
            +
              @media (max-width: 1100px)
         
     | 
| 
      
 96 
     | 
    
         
            +
                .hide-lg
         
     | 
| 
      
 97 
     | 
    
         
            +
                  display: none
         
     | 
| 
         @@ -0,0 +1,19 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            .notifications_controller
         
     | 
| 
      
 2 
     | 
    
         
            +
              .filter
         
     | 
| 
      
 3 
     | 
    
         
            +
                float: left
         
     | 
| 
      
 4 
     | 
    
         
            +
                width: 100%
         
     | 
| 
      
 5 
     | 
    
         
            +
                margin-bottom: 10px
         
     | 
| 
      
 6 
     | 
    
         
            +
                select
         
     | 
| 
      
 7 
     | 
    
         
            +
                  float: left
         
     | 
| 
      
 8 
     | 
    
         
            +
                  width: 30%
         
     | 
| 
      
 9 
     | 
    
         
            +
                  margin-right: 3%
         
     | 
| 
      
 10 
     | 
    
         
            +
                  &:last-child
         
     | 
| 
      
 11 
     | 
    
         
            +
                    float: right
         
     | 
| 
      
 12 
     | 
    
         
            +
                    margin-right: 0
         
     | 
| 
      
 13 
     | 
    
         
            +
              .inline-value
         
     | 
| 
      
 14 
     | 
    
         
            +
                font-weight: normal
         
     | 
| 
      
 15 
     | 
    
         
            +
                font-size: 16px
         
     | 
| 
      
 16 
     | 
    
         
            +
                display: inline
         
     | 
| 
      
 17 
     | 
    
         
            +
              .graph
         
     | 
| 
      
 18 
     | 
    
         
            +
                width: 100%
         
     | 
| 
      
 19 
     | 
    
         
            +
                height: 200px
         
     | 
| 
         @@ -0,0 +1,20 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module ExceptionNotificationServer
         
     | 
| 
      
 2 
     | 
    
         
            +
              class ApplicationController < ActionController::Base
         
     | 
| 
      
 3 
     | 
    
         
            +
                before_action :redirect_to_root, unless: :admin?
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
                add_flash_types :error, :success, :info
         
     | 
| 
      
 6 
     | 
    
         
            +
             
     | 
| 
      
 7 
     | 
    
         
            +
                def redirect_to_root
         
     | 
| 
      
 8 
     | 
    
         
            +
                  respond_to do |format|
         
     | 
| 
      
 9 
     | 
    
         
            +
                    format.js { render js: "window.location = '#{Rails.application.routes.url_helpers.root_url}';" }
         
     | 
| 
      
 10 
     | 
    
         
            +
                    format.all { redirect_to Rails.application.routes.url_helpers.root_url }
         
     | 
| 
      
 11 
     | 
    
         
            +
                  end
         
     | 
| 
      
 12 
     | 
    
         
            +
                end
         
     | 
| 
      
 13 
     | 
    
         
            +
             
     | 
| 
      
 14 
     | 
    
         
            +
                protected
         
     | 
| 
      
 15 
     | 
    
         
            +
             
     | 
| 
      
 16 
     | 
    
         
            +
                def admin?
         
     | 
| 
      
 17 
     | 
    
         
            +
                  ExceptionNotificationServer.configuration.access_callback.present? ? ExceptionNotificationServer.configuration.access_callback.try(:call, self) : true
         
     | 
| 
      
 18 
     | 
    
         
            +
                end
         
     | 
| 
      
 19 
     | 
    
         
            +
              end
         
     | 
| 
      
 20 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,97 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module ExceptionNotificationServer
         
     | 
| 
      
 2 
     | 
    
         
            +
              class NotificationsController < ExceptionNotificationServer::ApplicationController
         
     | 
| 
      
 3 
     | 
    
         
            +
                http_basic_authenticate_with name: ExceptionNotificationServer.configuration.name,
         
     | 
| 
      
 4 
     | 
    
         
            +
                                             password: ExceptionNotificationServer.configuration.password, only: :create
         
     | 
| 
      
 5 
     | 
    
         
            +
                respond_to :html, :json, :js
         
     | 
| 
      
 6 
     | 
    
         
            +
             
     | 
| 
      
 7 
     | 
    
         
            +
                before_filter :load_notification, only: [:show, :update, :investigate, :fix, :renew]
         
     | 
| 
      
 8 
     | 
    
         
            +
                skip_before_filter :redirect_to_root, only: [:create]
         
     | 
| 
      
 9 
     | 
    
         
            +
             
     | 
| 
      
 10 
     | 
    
         
            +
                def index
         
     | 
| 
      
 11 
     | 
    
         
            +
                  params[:env] ||= Rails.env
         
     | 
| 
      
 12 
     | 
    
         
            +
                  params[:status] ||= :new
         
     | 
| 
      
 13 
     | 
    
         
            +
                  @notifications = Notification.base_notifications(params[:status])
         
     | 
| 
      
 14 
     | 
    
         
            +
                                   .application(params[:application])
         
     | 
| 
      
 15 
     | 
    
         
            +
                                   .env(params[:env])
         
     | 
| 
      
 16 
     | 
    
         
            +
                                   .includes(:childrens)
         
     | 
| 
      
 17 
     | 
    
         
            +
                                   .joins('LEFT JOIN "exception_notification_server_notifications" "ensn" on "ensn"."parent_id" = "exception_notification_server_notifications"."id"')
         
     | 
| 
      
 18 
     | 
    
         
            +
                                   .group('"exception_notification_server_notifications"."id"')
         
     | 
| 
      
 19 
     | 
    
         
            +
                                   .order('count(ensn.id) DESC')
         
     | 
| 
      
 20 
     | 
    
         
            +
                                   .paginate(page: params[:page], per_page: 10)
         
     | 
| 
      
 21 
     | 
    
         
            +
                  # .where('last month')
         
     | 
| 
      
 22 
     | 
    
         
            +
                  respond_with @notifications
         
     | 
| 
      
 23 
     | 
    
         
            +
                end
         
     | 
| 
      
 24 
     | 
    
         
            +
             
     | 
| 
      
 25 
     | 
    
         
            +
                def create
         
     | 
| 
      
 26 
     | 
    
         
            +
                  @notification = Notification.create(notification_params)
         
     | 
| 
      
 27 
     | 
    
         
            +
                  respond_with @notification
         
     | 
| 
      
 28 
     | 
    
         
            +
                rescue
         
     | 
| 
      
 29 
     | 
    
         
            +
                  render nothing: true
         
     | 
| 
      
 30 
     | 
    
         
            +
                end
         
     | 
| 
      
 31 
     | 
    
         
            +
             
     | 
| 
      
 32 
     | 
    
         
            +
                def show
         
     | 
| 
      
 33 
     | 
    
         
            +
                  require 'coderay'
         
     | 
| 
      
 34 
     | 
    
         
            +
                  respond_with @notification
         
     | 
| 
      
 35 
     | 
    
         
            +
                end
         
     | 
| 
      
 36 
     | 
    
         
            +
             
     | 
| 
      
 37 
     | 
    
         
            +
                def update
         
     | 
| 
      
 38 
     | 
    
         
            +
                  @notification.send("update#{'_recursive' if params[:recursive]}", notification_params_update)
         
     | 
| 
      
 39 
     | 
    
         
            +
                  respond_with @notification
         
     | 
| 
      
 40 
     | 
    
         
            +
                end
         
     | 
| 
      
 41 
     | 
    
         
            +
             
     | 
| 
      
 42 
     | 
    
         
            +
                def investigate
         
     | 
| 
      
 43 
     | 
    
         
            +
                  params[:recursive] = true
         
     | 
| 
      
 44 
     | 
    
         
            +
                  params[:notification] ||= {}
         
     | 
| 
      
 45 
     | 
    
         
            +
                  params[:notification][:status] = :investigating
         
     | 
| 
      
 46 
     | 
    
         
            +
                  update
         
     | 
| 
      
 47 
     | 
    
         
            +
                end
         
     | 
| 
      
 48 
     | 
    
         
            +
             
     | 
| 
      
 49 
     | 
    
         
            +
                def fix
         
     | 
| 
      
 50 
     | 
    
         
            +
                  params[:recursive] = true
         
     | 
| 
      
 51 
     | 
    
         
            +
                  params[:notification] ||= {}
         
     | 
| 
      
 52 
     | 
    
         
            +
                  params[:notification][:status] = :fixed
         
     | 
| 
      
 53 
     | 
    
         
            +
                  update
         
     | 
| 
      
 54 
     | 
    
         
            +
                end
         
     | 
| 
      
 55 
     | 
    
         
            +
             
     | 
| 
      
 56 
     | 
    
         
            +
                def renew
         
     | 
| 
      
 57 
     | 
    
         
            +
                  params[:recursive] = true
         
     | 
| 
      
 58 
     | 
    
         
            +
                  params[:notification] ||= {}
         
     | 
| 
      
 59 
     | 
    
         
            +
                  params[:notification][:status] = :new
         
     | 
| 
      
 60 
     | 
    
         
            +
                  update
         
     | 
| 
      
 61 
     | 
    
         
            +
                end
         
     | 
| 
      
 62 
     | 
    
         
            +
             
     | 
| 
      
 63 
     | 
    
         
            +
                protected
         
     | 
| 
      
 64 
     | 
    
         
            +
             
     | 
| 
      
 65 
     | 
    
         
            +
                def load_notification
         
     | 
| 
      
 66 
     | 
    
         
            +
                  @notification = Notification.find(params[:id])
         
     | 
| 
      
 67 
     | 
    
         
            +
                rescue ActiveRecord::RecordNotFound
         
     | 
| 
      
 68 
     | 
    
         
            +
                  flash[:alert] = "Can't find notification with id #{params[:id]}."
         
     | 
| 
      
 69 
     | 
    
         
            +
                  respond_to do |format|
         
     | 
| 
      
 70 
     | 
    
         
            +
                    format.js { render js: "window.location = '#{notifications_url}';" }
         
     | 
| 
      
 71 
     | 
    
         
            +
                    format.html { redirect_to notifications_path }
         
     | 
| 
      
 72 
     | 
    
         
            +
                  end
         
     | 
| 
      
 73 
     | 
    
         
            +
                end
         
     | 
| 
      
 74 
     | 
    
         
            +
             
     | 
| 
      
 75 
     | 
    
         
            +
                def notification_params
         
     | 
| 
      
 76 
     | 
    
         
            +
                  {
         
     | 
| 
      
 77 
     | 
    
         
            +
                    application: params[:application],
         
     | 
| 
      
 78 
     | 
    
         
            +
                    env: params[:env],
         
     | 
| 
      
 79 
     | 
    
         
            +
                    status: params[:status],
         
     | 
| 
      
 80 
     | 
    
         
            +
                    server: params[:server],
         
     | 
| 
      
 81 
     | 
    
         
            +
                    process: params[:process],
         
     | 
| 
      
 82 
     | 
    
         
            +
                    rails_root: params[:rails_root],
         
     | 
| 
      
 83 
     | 
    
         
            +
                    exception_class: params[:exception][:error_class],
         
     | 
| 
      
 84 
     | 
    
         
            +
                    exception_message: params[:exception][:message],
         
     | 
| 
      
 85 
     | 
    
         
            +
                    backtrace: params[:exception][:backtrace],
         
     | 
| 
      
 86 
     | 
    
         
            +
                    data: params[:data],
         
     | 
| 
      
 87 
     | 
    
         
            +
                    request: params[:request],
         
     | 
| 
      
 88 
     | 
    
         
            +
                    session: params[:session],
         
     | 
| 
      
 89 
     | 
    
         
            +
                    environment: params[:environment]
         
     | 
| 
      
 90 
     | 
    
         
            +
                  }.delete_if { |_, value| value.blank? }
         
     | 
| 
      
 91 
     | 
    
         
            +
                end
         
     | 
| 
      
 92 
     | 
    
         
            +
             
     | 
| 
      
 93 
     | 
    
         
            +
                def notification_params_update
         
     | 
| 
      
 94 
     | 
    
         
            +
                  params.require(:notification).permit!
         
     | 
| 
      
 95 
     | 
    
         
            +
                end
         
     | 
| 
      
 96 
     | 
    
         
            +
              end
         
     | 
| 
      
 97 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,46 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module ExceptionNotificationServer
         
     | 
| 
      
 2 
     | 
    
         
            +
              module ApplicationHelper
         
     | 
| 
      
 3 
     | 
    
         
            +
                def pretty_json(data, lines = nil)
         
     | 
| 
      
 4 
     | 
    
         
            +
                  json = JSON.pretty_generate(data).html_safe
         
     | 
| 
      
 5 
     | 
    
         
            +
                  json_colored = CodeRay.scan(json, :json).span(css: :style, line_numbers: :inline, line_number_anchors: false)
         
     | 
| 
      
 6 
     | 
    
         
            +
                  return "<pre>\n#{json_colored}</pre>".html_safe if lines.nil? || json.count("\n") < lines
         
     | 
| 
      
 7 
     | 
    
         
            +
                  "<pre>\n#{json_colored.match(/([^\n]*\n){#{lines}}/m)}</span></pre>".html_safe
         
     | 
| 
      
 8 
     | 
    
         
            +
                rescue
         
     | 
| 
      
 9 
     | 
    
         
            +
                  data
         
     | 
| 
      
 10 
     | 
    
         
            +
                end
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
                def status_options(options)
         
     | 
| 
      
 13 
     | 
    
         
            +
                  options_for_select(Notification::STATUSES.map { |status| [status.to_s.humanize, status] }, options[:selected])
         
     | 
| 
      
 14 
     | 
    
         
            +
                end
         
     | 
| 
      
 15 
     | 
    
         
            +
             
     | 
| 
      
 16 
     | 
    
         
            +
                def application_options(options)
         
     | 
| 
      
 17 
     | 
    
         
            +
                  options_for_select(Notification.group(:application).pluck(:application).map { |application| [application.humanize, application] }, options[:selected])
         
     | 
| 
      
 18 
     | 
    
         
            +
                end
         
     | 
| 
      
 19 
     | 
    
         
            +
             
     | 
| 
      
 20 
     | 
    
         
            +
                def environment_options(options)
         
     | 
| 
      
 21 
     | 
    
         
            +
                  default_environment = %w(production staging development test)
         
     | 
| 
      
 22 
     | 
    
         
            +
                  options_for_select((default_environment + Notification.group(:env).pluck(:env)).uniq.map { |env| [env.humanize, env] }, options[:selected])
         
     | 
| 
      
 23 
     | 
    
         
            +
                end
         
     | 
| 
      
 24 
     | 
    
         
            +
             
     | 
| 
      
 25 
     | 
    
         
            +
                def time_format
         
     | 
| 
      
 26 
     | 
    
         
            +
                  ExceptionNotificationServer.configuration.time_format
         
     | 
| 
      
 27 
     | 
    
         
            +
                end
         
     | 
| 
      
 28 
     | 
    
         
            +
             
     | 
| 
      
 29 
     | 
    
         
            +
                def logo_string
         
     | 
| 
      
 30 
     | 
    
         
            +
                  <<-Text
         
     | 
| 
      
 31 
     | 
    
         
            +
             ______                    _   _             _   _       _   _  __ _           _   _              _____
         
     | 
| 
      
 32 
     | 
    
         
            +
            |  ____|                  | | (_)           | \\ | |     | | (_)/ _(_)         | | (_)            / ____|
         
     | 
| 
      
 33 
     | 
    
         
            +
            | |__  __  _____ ___ _ __ | |_ _  ___  _ __ |  \\| | ___ | |_ _| |_ _  ___ __ _| |_ _  ___  _ __ | (___   ___ _ ____   _____ _ __
         
     | 
| 
      
 34 
     | 
    
         
            +
            |  __| \\ \\/ / __/ _ \\ \'_ \\| __| |/ _ \\| \'_ \\| . ` |/ _ \\| __| |  _| |/ __/ _\` | __| |/ _ \\| \'_ \\ \\___ \\ / _ \\ \'__\\ \\ / / _ \\ \'__|
         
     | 
| 
      
 35 
     | 
    
         
            +
            | |____ >  < (_|  __/ |_) | |_| | (_) | | | | |\\  | (_) | |_| | | | | (_| (_| | |_| | (_) | | | |____) |  __/ |   \\ V /  __/ |
         
     | 
| 
      
 36 
     | 
    
         
            +
            |______/_/\\_\\___\\___| .__/ \\__|_|\\___/|_| |_|_| \\_|\\___/ \\__|_|_| |_|\\___\\__,_|\\__|_|\\___/|_| |_|_____/ \\___|_|    \\_/ \\___|_|
         
     | 
| 
      
 37 
     | 
    
         
            +
                                | |
         
     | 
| 
      
 38 
     | 
    
         
            +
                                |_|
         
     | 
| 
      
 39 
     | 
    
         
            +
                  Text
         
     | 
| 
      
 40 
     | 
    
         
            +
                end
         
     | 
| 
      
 41 
     | 
    
         
            +
             
     | 
| 
      
 42 
     | 
    
         
            +
                def author
         
     | 
| 
      
 43 
     | 
    
         
            +
                  'Author: Anatoliy Varanitsa'
         
     | 
| 
      
 44 
     | 
    
         
            +
                end
         
     | 
| 
      
 45 
     | 
    
         
            +
              end
         
     | 
| 
      
 46 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,69 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module ExceptionNotificationServer
         
     | 
| 
      
 2 
     | 
    
         
            +
              class Notification < ActiveRecord::Base
         
     | 
| 
      
 3 
     | 
    
         
            +
                serialize :backtrace, Array
         
     | 
| 
      
 4 
     | 
    
         
            +
                serialize :data, Hash
         
     | 
| 
      
 5 
     | 
    
         
            +
                serialize :request, Hash
         
     | 
| 
      
 6 
     | 
    
         
            +
                serialize :session, Hash
         
     | 
| 
      
 7 
     | 
    
         
            +
                serialize :environment, Hash
         
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
      
 9 
     | 
    
         
            +
                belongs_to :parent, class: ExceptionNotificationServer::Notification
         
     | 
| 
      
 10 
     | 
    
         
            +
                has_many :childrens, class: ExceptionNotificationServer::Notification, foreign_key: :parent_id
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
                scope :base_notifications, ->(status = nil) { status.present? ? where(parent: nil, status: status) : where(parent: nil) }
         
     | 
| 
      
 13 
     | 
    
         
            +
                STATUSES = [:new, :investigating, :fixed].freeze
         
     | 
| 
      
 14 
     | 
    
         
            +
                STATUSES.each do |status|
         
     | 
| 
      
 15 
     | 
    
         
            +
                  scope "#{status}_notifications", -> { where(status: status) }
         
     | 
| 
      
 16 
     | 
    
         
            +
                end
         
     | 
| 
      
 17 
     | 
    
         
            +
                scope :application, ->(application = nil) { application.present? ? where(application: application) : all }
         
     | 
| 
      
 18 
     | 
    
         
            +
                scope :env, ->(env = nil) { where(env: env || Rails.env) }
         
     | 
| 
      
 19 
     | 
    
         
            +
             
     | 
| 
      
 20 
     | 
    
         
            +
                before_create do
         
     | 
| 
      
 21 
     | 
    
         
            +
                  self.status = :new
         
     | 
| 
      
 22 
     | 
    
         
            +
                  self.exception_hash = gen_exception_hash
         
     | 
| 
      
 23 
     | 
    
         
            +
                  self.parent_id = Notification.where(exception_hash: exception_hash, status: [:new, :investigating]).first.try(:id)
         
     | 
| 
      
 24 
     | 
    
         
            +
                end
         
     | 
| 
      
 25 
     | 
    
         
            +
             
     | 
| 
      
 26 
     | 
    
         
            +
                def similar
         
     | 
| 
      
 27 
     | 
    
         
            +
                  parent_id.nil? ? childrens : Notification.where(arel_table[:id].eq(parent_id).or(arel_table[:parent_id].eq(parent_id).and(arel_table[:id].eq(id).not)))
         
     | 
| 
      
 28 
     | 
    
         
            +
                end
         
     | 
| 
      
 29 
     | 
    
         
            +
             
     | 
| 
      
 30 
     | 
    
         
            +
                def similar_count(from = nil)
         
     | 
| 
      
 31 
     | 
    
         
            +
                  return childrens.length + 1 if from.nil?
         
     | 
| 
      
 32 
     | 
    
         
            +
                  childrens.count { |notification| notification.created_at >= from } + (created_at >= from ? 1 : 0)
         
     | 
| 
      
 33 
     | 
    
         
            +
                end
         
     | 
| 
      
 34 
     | 
    
         
            +
             
     | 
| 
      
 35 
     | 
    
         
            +
                def similar_count_sparkline(from = 1.month.ago.beginning_of_day)
         
     | 
| 
      
 36 
     | 
    
         
            +
                  graph_data(from).values
         
     | 
| 
      
 37 
     | 
    
         
            +
                end
         
     | 
| 
      
 38 
     | 
    
         
            +
             
     | 
| 
      
 39 
     | 
    
         
            +
                def similar_count_flot(from = 3.month.ago.beginning_of_day)
         
     | 
| 
      
 40 
     | 
    
         
            +
                  graph_data(from).to_a
         
     | 
| 
      
 41 
     | 
    
         
            +
                end
         
     | 
| 
      
 42 
     | 
    
         
            +
             
     | 
| 
      
 43 
     | 
    
         
            +
                def last_time
         
     | 
| 
      
 44 
     | 
    
         
            +
                  [self, *childrens].sort_by(&:created_at).last.created_at
         
     | 
| 
      
 45 
     | 
    
         
            +
                end
         
     | 
| 
      
 46 
     | 
    
         
            +
             
     | 
| 
      
 47 
     | 
    
         
            +
                def update_recursive(updates)
         
     | 
| 
      
 48 
     | 
    
         
            +
                  base_id = parent_id || id
         
     | 
| 
      
 49 
     | 
    
         
            +
                  Notification.where(arel_table[:id].eq(base_id).or(arel_table[:parent_id].eq(base_id))).update_all(updates) if base_id.present?
         
     | 
| 
      
 50 
     | 
    
         
            +
                end
         
     | 
| 
      
 51 
     | 
    
         
            +
             
     | 
| 
      
 52 
     | 
    
         
            +
                protected
         
     | 
| 
      
 53 
     | 
    
         
            +
             
     | 
| 
      
 54 
     | 
    
         
            +
                def graph_data(from)
         
     | 
| 
      
 55 
     | 
    
         
            +
                  result = from.to_datetime.step(Time.zone.now.to_datetime, 1).map { |time| [time.beginning_of_day.to_i * 1000, 0] }.to_h
         
     | 
| 
      
 56 
     | 
    
         
            +
                  childrens.each { |notification| result[notification.created_at.beginning_of_day.to_i * 1000] += 1 if notification.created_at >= from }
         
     | 
| 
      
 57 
     | 
    
         
            +
                  result[created_at.beginning_of_day.to_i * 1000] += 1 if created_at >= from
         
     | 
| 
      
 58 
     | 
    
         
            +
                  result
         
     | 
| 
      
 59 
     | 
    
         
            +
                end
         
     | 
| 
      
 60 
     | 
    
         
            +
             
     | 
| 
      
 61 
     | 
    
         
            +
                def arel_table
         
     | 
| 
      
 62 
     | 
    
         
            +
                  self.class.arel_table
         
     | 
| 
      
 63 
     | 
    
         
            +
                end
         
     | 
| 
      
 64 
     | 
    
         
            +
             
     | 
| 
      
 65 
     | 
    
         
            +
                def gen_exception_hash
         
     | 
| 
      
 66 
     | 
    
         
            +
                  Digest::SHA1.hexdigest("#{application}#{exception_class}#{exception_message}#{backtrace.to_s.gsub(rails_root, '')}")
         
     | 
| 
      
 67 
     | 
    
         
            +
                end
         
     | 
| 
      
 68 
     | 
    
         
            +
              end
         
     | 
| 
      
 69 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,37 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            :ruby
         
     | 
| 
      
 2 
     | 
    
         
            +
              count = local_assigns.fetch :count, true
         
     | 
| 
      
 3 
     | 
    
         
            +
              last_time = local_assigns.fetch :last_time, true
         
     | 
| 
      
 4 
     | 
    
         
            +
              env = local_assigns.fetch :env, false
         
     | 
| 
      
 5 
     | 
    
         
            +
            %table
         
     | 
| 
      
 6 
     | 
    
         
            +
              %thead
         
     | 
| 
      
 7 
     | 
    
         
            +
                %tr
         
     | 
| 
      
 8 
     | 
    
         
            +
                  %th
         
     | 
| 
      
 9 
     | 
    
         
            +
                  %th.hide-md Class
         
     | 
| 
      
 10 
     | 
    
         
            +
                  %th Message
         
     | 
| 
      
 11 
     | 
    
         
            +
                  %th.hide-md.hide-lg{style: 'width: 100px'} Server
         
     | 
| 
      
 12 
     | 
    
         
            +
                  %th.hide-md.hide-lg Process
         
     | 
| 
      
 13 
     | 
    
         
            +
                  - if env
         
     | 
| 
      
 14 
     | 
    
         
            +
                    %th.hide-md.hide-lg Environment
         
     | 
| 
      
 15 
     | 
    
         
            +
                  %th.hide-md Created at
         
     | 
| 
      
 16 
     | 
    
         
            +
                  - if last_time
         
     | 
| 
      
 17 
     | 
    
         
            +
                    %th.hide-md Last time
         
     | 
| 
      
 18 
     | 
    
         
            +
                  - if count
         
     | 
| 
      
 19 
     | 
    
         
            +
                    %th Last 30 days
         
     | 
| 
      
 20 
     | 
    
         
            +
                    %th Total count
         
     | 
| 
      
 21 
     | 
    
         
            +
              %tbody
         
     | 
| 
      
 22 
     | 
    
         
            +
                - notifications.each do |notification|
         
     | 
| 
      
 23 
     | 
    
         
            +
                  %tr
         
     | 
| 
      
 24 
     | 
    
         
            +
                    %td= link_to notification.id, notification_path(notification)
         
     | 
| 
      
 25 
     | 
    
         
            +
                    %td.hide-md= link_to notification.exception_class, notification_path(notification)
         
     | 
| 
      
 26 
     | 
    
         
            +
                    %td= link_to notification.exception_message, notification_path(notification)
         
     | 
| 
      
 27 
     | 
    
         
            +
                    %td.hide-md.hide-lg= link_to notification.server, notification_path(notification)
         
     | 
| 
      
 28 
     | 
    
         
            +
                    %td.hide-md.hide-lg= link_to notification.process, notification_path(notification)
         
     | 
| 
      
 29 
     | 
    
         
            +
                    - if env
         
     | 
| 
      
 30 
     | 
    
         
            +
                      %td.hide-md.hide-lg= link_to notification.env, notification_path(notification)
         
     | 
| 
      
 31 
     | 
    
         
            +
                    %td.hide-md= notification.created_at.strftime(time_format)
         
     | 
| 
      
 32 
     | 
    
         
            +
                    - if last_time
         
     | 
| 
      
 33 
     | 
    
         
            +
                      %td.hide-md= notification.last_time.strftime(time_format)
         
     | 
| 
      
 34 
     | 
    
         
            +
                    - if count
         
     | 
| 
      
 35 
     | 
    
         
            +
                      %td
         
     | 
| 
      
 36 
     | 
    
         
            +
                        %div.sparkline{data: {values: notification.similar_count_sparkline.to_json}}
         
     | 
| 
      
 37 
     | 
    
         
            +
                      %td= notification.similar_count
         
     | 
| 
         @@ -0,0 +1,7 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            .filter
         
     | 
| 
      
 2 
     | 
    
         
            +
              = form_tag '', remote: true, method: :get do
         
     | 
| 
      
 3 
     | 
    
         
            +
                = select_tag :status, status_options(selected: params[:status]), onchange: '$(this.form).trigger(\'submit.rails\')'
         
     | 
| 
      
 4 
     | 
    
         
            +
                = select_tag :application, application_options(selected: params[:application]), prompt: 'All', onchange: '$(this.form).trigger(\'submit.rails\')'
         
     | 
| 
      
 5 
     | 
    
         
            +
                = select_tag :env, environment_options(selected: params[:env]), onchange: '$(this.form).trigger(\'submit.rails\')'
         
     | 
| 
      
 6 
     | 
    
         
            +
            = render partial: 'exception_notification_server/notifications/notifications', object: @notifications, as: :notifications
         
     | 
| 
      
 7 
     | 
    
         
            +
            = will_paginate @notifications, remote: true
         
     | 
| 
         @@ -0,0 +1,76 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            .buttons
         
     | 
| 
      
 2 
     | 
    
         
            +
              = link_to 'Investigate', investigate_notification_path, data: {method: :put} if @notification.status.to_sym == :new
         
     | 
| 
      
 3 
     | 
    
         
            +
              = link_to 'Fix', fix_notification_path, data: {method: :put} if @notification.status.to_sym == :investigating
         
     | 
| 
      
 4 
     | 
    
         
            +
              = link_to 'Renew', renew_notification_path, data: {method: :put} if @notification.status.to_sym == :fixed
         
     | 
| 
      
 5 
     | 
    
         
            +
            .graphic
         
     | 
| 
      
 6 
     | 
    
         
            +
              %h3 Last 3 month count:
         
     | 
| 
      
 7 
     | 
    
         
            +
              .graph{data: {values: @notification.similar_count_flot.to_json}}
         
     | 
| 
      
 8 
     | 
    
         
            +
            .id
         
     | 
| 
      
 9 
     | 
    
         
            +
              %h3
         
     | 
| 
      
 10 
     | 
    
         
            +
                Id:
         
     | 
| 
      
 11 
     | 
    
         
            +
                .inline-value= @notification.id
         
     | 
| 
      
 12 
     | 
    
         
            +
            .status
         
     | 
| 
      
 13 
     | 
    
         
            +
              %h3
         
     | 
| 
      
 14 
     | 
    
         
            +
                Status:
         
     | 
| 
      
 15 
     | 
    
         
            +
                .inline-value= @notification.status
         
     | 
| 
      
 16 
     | 
    
         
            +
            .exception-hash
         
     | 
| 
      
 17 
     | 
    
         
            +
              %h3
         
     | 
| 
      
 18 
     | 
    
         
            +
                Exception hash:
         
     | 
| 
      
 19 
     | 
    
         
            +
                .inline-value= @notification.exception_hash
         
     | 
| 
      
 20 
     | 
    
         
            +
            .exception-class
         
     | 
| 
      
 21 
     | 
    
         
            +
              %h3
         
     | 
| 
      
 22 
     | 
    
         
            +
                Exception class:
         
     | 
| 
      
 23 
     | 
    
         
            +
                .inline-value= @notification.exception_class
         
     | 
| 
      
 24 
     | 
    
         
            +
            .exception-message
         
     | 
| 
      
 25 
     | 
    
         
            +
              %h3
         
     | 
| 
      
 26 
     | 
    
         
            +
                Exception message:
         
     | 
| 
      
 27 
     | 
    
         
            +
                .inline-value= @notification.exception_message
         
     | 
| 
      
 28 
     | 
    
         
            +
            - if @notification.application.present?
         
     | 
| 
      
 29 
     | 
    
         
            +
              .environment
         
     | 
| 
      
 30 
     | 
    
         
            +
                %h3
         
     | 
| 
      
 31 
     | 
    
         
            +
                  Application:
         
     | 
| 
      
 32 
     | 
    
         
            +
                  .inline-value= @notification.application
         
     | 
| 
      
 33 
     | 
    
         
            +
            - if @notification.env.present?
         
     | 
| 
      
 34 
     | 
    
         
            +
              .environment
         
     | 
| 
      
 35 
     | 
    
         
            +
                %h3
         
     | 
| 
      
 36 
     | 
    
         
            +
                  Environment:
         
     | 
| 
      
 37 
     | 
    
         
            +
                  .inline-value= @notification.env
         
     | 
| 
      
 38 
     | 
    
         
            +
            - if @notification.server.present?
         
     | 
| 
      
 39 
     | 
    
         
            +
              .server
         
     | 
| 
      
 40 
     | 
    
         
            +
                %h3
         
     | 
| 
      
 41 
     | 
    
         
            +
                  Server:
         
     | 
| 
      
 42 
     | 
    
         
            +
                  .inline-value= @notification.server
         
     | 
| 
      
 43 
     | 
    
         
            +
            - if @notification.process.present?
         
     | 
| 
      
 44 
     | 
    
         
            +
              .process
         
     | 
| 
      
 45 
     | 
    
         
            +
                %h3
         
     | 
| 
      
 46 
     | 
    
         
            +
                  Process:
         
     | 
| 
      
 47 
     | 
    
         
            +
                  .inline-value= @notification.process
         
     | 
| 
      
 48 
     | 
    
         
            +
            - if @notification.rails_root.present?
         
     | 
| 
      
 49 
     | 
    
         
            +
              .rails-root
         
     | 
| 
      
 50 
     | 
    
         
            +
                %h3
         
     | 
| 
      
 51 
     | 
    
         
            +
                  Rails root:
         
     | 
| 
      
 52 
     | 
    
         
            +
                  .inline-value= @notification.rails_root
         
     | 
| 
      
 53 
     | 
    
         
            +
            - if @notification.backtrace.present?
         
     | 
| 
      
 54 
     | 
    
         
            +
              .backtrace
         
     | 
| 
      
 55 
     | 
    
         
            +
                %h3 Backtrace
         
     | 
| 
      
 56 
     | 
    
         
            +
                = pretty_json @notification.backtrace
         
     | 
| 
      
 57 
     | 
    
         
            +
            - if @notification.data.present?
         
     | 
| 
      
 58 
     | 
    
         
            +
              .data
         
     | 
| 
      
 59 
     | 
    
         
            +
                %h3 Data
         
     | 
| 
      
 60 
     | 
    
         
            +
                = pretty_json @notification.data
         
     | 
| 
      
 61 
     | 
    
         
            +
            - if @notification.request.present?
         
     | 
| 
      
 62 
     | 
    
         
            +
              .request
         
     | 
| 
      
 63 
     | 
    
         
            +
                %h3 Request
         
     | 
| 
      
 64 
     | 
    
         
            +
                = pretty_json @notification.request
         
     | 
| 
      
 65 
     | 
    
         
            +
            - if @notification.session.present?
         
     | 
| 
      
 66 
     | 
    
         
            +
              .session
         
     | 
| 
      
 67 
     | 
    
         
            +
                %h3 Session
         
     | 
| 
      
 68 
     | 
    
         
            +
                = pretty_json @notification.session
         
     | 
| 
      
 69 
     | 
    
         
            +
            - if @notification.environment.present?
         
     | 
| 
      
 70 
     | 
    
         
            +
              .environment
         
     | 
| 
      
 71 
     | 
    
         
            +
                %h3 Environment
         
     | 
| 
      
 72 
     | 
    
         
            +
                = pretty_json @notification.environment
         
     | 
| 
      
 73 
     | 
    
         
            +
            - if @notification.similar.to_a.present?
         
     | 
| 
      
 74 
     | 
    
         
            +
              %br
         
     | 
| 
      
 75 
     | 
    
         
            +
              = render partial: 'exception_notification_server/notifications/notifications', object: @notification.similar, as: :notifications, locals: {count: false, last_time: false, env: true}
         
     | 
| 
      
 76 
     | 
    
         
            +
            %br
         
     |