diff --git a/backend/src/appenlight/static/js/appenlight.js b/backend/src/appenlight/static/js/appenlight.js index 5594949..2886332 100644 --- a/backend/src/appenlight/static/js/appenlight.js +++ b/backend/src/appenlight/static/js/appenlight.js @@ -2703,6 +2703,15 @@ angular.module('appenlight.components', [ 'appenlight.components.jiraIntegrationConfigView', 'appenlight.components.slackIntegrationConfigView', 'appenlight.components.webhooksIntegrationConfigView', + 'appenlight.components.adminView', + 'appenlight.components.adminApplicationsListView', + 'appenlight.components.adminUsersListView', + 'appenlight.components.adminUsersCreateView', + 'appenlight.components.adminGroupsListView', + 'appenlight.components.adminGroupsCreateView', + 'appenlight.components.adminConfigurationView', + 'appenlight.components.adminSystemView', + 'appenlight.components.adminPartitionsView', 'appenlight.components.settingsView' ]); angular.module('appenlight.directives', [ @@ -2988,3642 +2997,3426 @@ function kickstartAE(initialUserData) { ); - $templateCache.put('components/views/applications-integrations-view/applications-integrations-view.html', - "\n" + - "\n" + - "\n" + - "
\n" + - "
\n" + - "
\n" + + $templateCache.put('components/views/admin-applications-list-view/admin-applications-list-view.html', + "\n" + "\n" + - " \n" + - " \n" + - " Bitbucket\n" + + "
\n" + + "
\n" + "\n" + - "

Send issues and reports to Bitbucket

\n" + - "
\n" + + " Currently active applications: {{$ctrl.applications.length}}\n" + "\n" + - " \n" + - " \n" + - " Campfire\n" + + "
\n" + "\n" + - "

Receive reports and alerts in your Campfire rooms

\n" + - "
\n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + "\n" + - " \n" + - " \n" + - " Flowdock\n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + "
Application nameOwner UserOwner Group
{{resource.resource_name}}{{resource.owner_user_name}}{{resource.owner_group_name}}\n" + + " \n" + + "
\n" + + "
\n" + + "
\n" + "\n" + - "

Receive reports and alerts on your Flowdock team\n" + - " inbox

\n" + - "
\n" + + "
\n" + ); + + + $templateCache.put('components/views/admin-configuration-view/admin-configuration-view.html', + "\n" + "\n" + - " \n" + - " \n" + - " Github\n" + + "\n" + - "\n" - ); - - - $templateCache.put('components/views/applications-list-view/applications-list-view.html', - "\n" + "\n" + - "
\n" + - "
\n" + - "
\n" + + "
\n" + "\n" + - "

You have to create a new application first.

\n" + "\n" + + "
\n" + + "
\n" + + "

Plugin Configuration

\n" + + "
\n" + + "
\n" + + " \n" + + " \n" + "
\n" + - "\n" + - " 0\">\n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - "
Resource NameDomainsOptions
{{application.resource_name}}{{application.domains}}\n" + - " Update\n" + - " Integrations\n" + - "
\n" + - "\n" + "
\n" ); - $templateCache.put('components/views/applications-purge-logs-view/applications-purge-logs-view.html', - "\n" + + $templateCache.put('components/views/admin-groups-create-view/admin-groups-create-view.html', + "\n" + + "\n" + + "
\n" + "\n" + - "
\n" + "
\n" + - "
\n" + "
\n" + - "\n" + - "
\n" + - "
\n" + - " \n" + - "\n" + - "
\n" + - " \n" + + " \n" + + "
\n" + + " \n" + + " \n" + + "
\n" + + " \n" + "
\n" + "
\n" + "\n" + - "
\n" + - " \n" + - "\n" + - "
\n" + - " \n" + + "
\n" + + " \n" + + " \n" + + "
\n" + + " \n" + "
\n" + "
\n" + "\n" + - "
\n" + - " \n" + "\n" + - "
\n" + - " \n" + + "
\n" + + " \n" + + "
\n" + + " \n" + "
\n" + "
\n" + - "\n" + " \n" + "
\n" + "
\n" + - "
\n" - ); - - - $templateCache.put('components/views/applications-update-view/applications-update-view.html', - "\n" + "\n" + - "
\n" + "\n" + - "
\n" + - "
\n" + + "
\n" + + "
\n" + + "

Permissions summary

\n" + + "
\n" + "
\n" + + "

Direct application permissions

\n" + "\n" + - "
\n" + - "
\n" + + "
    \n" + + "
  • \n" + + " {{ perm.self.resource_name }}\n" + "\n" + - " \n" + - " \n" + - " \n" + - " API keys\n" + - " \n" + + "
    \n" + "\n" + - "

    PRIVATE API KEY:

    \n" + - "

    \n" + - "

    {{ $ctrl.resource.api_key }}
    \n" + - "

    \n" + - "

    PUBLIC API KEY (for javascript clients):

    \n" + - "

    \n" + - "

    {{ $ctrl.resource.public_key }}
    \n" + - "

    \n" + - "

    Your key will be used to identify to which application your data\n" + - " belongs to please keep them private at all times.

    \n" + - "\n" + - " \n" + - "\n" + - " \n" + - " \n" + - " Regenerate API keys\n" + - " \n" + - "

    Are you sure you want to regenerate API KEY for this application?

    \n" + - "

    All client application keys will need to be updated.

    \n" + - "
    \n" + - " \n" + - "
    \n" + - " \n" + - " \n" + - "
    \n" + - "
    \n" + - "
    \n" + - " \n" + - "
    \n" + - "
    \n" + - "

    How to connect your application?

    \n" + - "

    Visit our developer documentation for step-by-step integration instructions.

    \n" + - "
    \n" + - "

    \n" + - " \"Django\n" + - " \"Pyramid\n" + - " \"Flask\n" + + " {{ perm.self.owner ? 'Resource owner' : perm_name }}\n" + "\n" + - " \"Javascript\n" + - " \"Node.js\"\n" + - " \"Ruby\n" + - " \"PHP\n" + + " \n" + + " \n" + " \n" + - "\n" + - "

    \n" + - "
    \n" + - "
\n" + - "\n" + - "
\n" + - "\n" + - "
\n" + - "
\n" + - " \n" + - " \n" + - "\n" + - "
\n" + - " \n" + - "
\n" + - "\n" + - "\n" + "
\n" + + " \n" + + " \n" + "\n" + - "
\n" + - " \n" + - " \n" + - "
\n" + - " \n" + - "

Required for Javascript error tracking (one line one domain, skip http:// part)

\n" + - "
\n" + - "\n" + + "

Direct dashboard permissions

\n" + "\n" + - "
\n" + - "
\n" + - " \n" + - " \n" + - "
\n" + - " \n" + - "
\n" + + "
    \n" + + "
  • \n" + + " {{ perm.self.resource_name }}\n" + "\n" + - "
\n" + - "
\n" + - " \n" + - " \n" + - "
\n" + - " \n" + - "

Application requires to send at least this amount of error reports per minute to open alert

\n" + - "
\n" + - "
\n" + - "
\n" + - " \n" + - " \n" + + "
\n" + + " {{ perm.self.owner ? 'Resource owner' : perm_name }}\n" + "\n" + - "
\n" + - " \n" + - "

Application requires to send at least this amount of slow reports per minute to open alert

\n" + - "
\n" + - "
\n" + - "
\n" + - " \n" + - " \n" + - "
\n" + - " \n" + - "

Allow permanent storage of logs in separate DB partitions (only administrator can enable this feature)

\n" + - "
\n" + + " \n" + + " \n" + + " \n" + "
\n" + - "
\n" + - " \n" + + " \n" + + " \n" + "\n" + - "
\n" + - " \n" + - "
\n" + - "
\n" + - " \n" + "
\n" + + "\n" + "
\n" + "\n" + - "
\n" + + "\n" + + "
\n" + "
\n" + - "

Plugins

\n" + + "

User list

\n" + "
\n" + "
\n" + "\n" + - " \n" + - " \n" + + "
\n" + + "
\n" + + " \n" + + "
\n" + + "
\n" + + " \n" + + "
\n" + + "
\n" + "\n" + "
\n" + - "
\n" + "\n" + - "
\n" + - "
\n" + - "

API Testing

\n" + - "
\n" + - "
\n" + - "

Please be sure to add at least one email alert channel for your account.

\n" + - "

This will enable AppEnlight to send you notification emails about errors inside your $ctrl.

\n" + - "

After this is done you can use this CURL commands to test APIs:

\n" + - "

(Please note that the data like execution times is semi randomly generated)

\n" + - " \n" + - " \n" + - " \n" + - " Log API\n" + - " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + "\n" + - "
\n" + - "
\n" +
-    "curl -H \"Content-Type: application/json\" -k {{AeConfig.urls.baseUrl}}api/logs?protocol_version=0.5\\&api_key={{$ctrl.resource.api_key}} -d '\n" +
-    "    [\n" +
-    "      {\n" +
-    "      \"log_level\": \"WARNING\",\n" +
-    "      \"message\": \"OMG ValueError happened\",\n" +
-    "      \"namespace\": \"some.namespace.indicator\",\n" +
-    "      \"request_id\": \"SOME_UUID\",\n" +
-    "      \"permanent\": false,\n" +
-    "      \"primary_key\": \"random_key\",\n" +
-    "      \"server\": \"some.server.hostname\",\n" +
-    "      \"date\": \"{{$ctrl.momentJs.utc().milliseconds(0).toISOString()}}\",\n" +
-    "      \"tags\": [[\"tag1\",\"value\"], [\"tag2\", 5]]\n" +
-    "      },\n" +
-    "      {\n" +
-    "      \"log_level\": \"ERROR\",\n" +
-    "      \"message\": \"OMG ValueError happened2\",\n" +
-    "      \"namespace\": \"some.namespace.indicator\",\n" +
-    "      \"request_id\": \"SOME_UUID\",\n" +
-    "      \"permanent\": false,\n" +
-    "      \"server\": \"some.server.hostname\",\n" +
-    "      \"date\": \"{{$ctrl.momentJs.utc().milliseconds(0).toISOString()}}\"\n" +
-    "      }\n" +
-    "    ]'\n" +
-    "                    
\n" + - "
\n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + "
UsernameEmailStatusFirst NameLast NameLast login
{{user.user_name}}{{user.email}}{{user.first_name}}{{user.last_name}}{{user.last_login_date | isoToRelativeTime}}\n" + + " \n" + + " \n" + + " \n" + + "
    \n" + + "
  • No
  • \n" + + "
  • Yes
  • \n" + + "
\n" + + "
\n" + + "
\n" + + "
\n" + + "
\n" + "\n" + - "
\n" + + "
\n" + "\n" + - " \n" + - " \n" + - " Report API\n" + - " \n" + "\n" + - "
\n" + - "
\n" +
-    "curl -H \"Content-Type: application/json\" -k {{AeConfig.urls.baseUrl}}api/reports?protocol_version=0.5\\&api_key={{$ctrl.resource.api_key}} -d '\n" +
-    "    [{\n" +
-    "    \"client\": \"your-client-name-python\",\n" +
-    "    \"language\": \"python\",\n" +
-    "    \"view_name\": \"views/foo:bar\",\n" +
-    "    \"server\": \"SERVERNAME/INSTANCENAME\",\n" +
-    "    \"priority\": 5,\n" +
-    "    \"error\": \"OMG ValueError happened\",\n" +
-    "    \"occurences\":1,\n" +
-    "    \"http_status\": 500,\n" +
-    "    \"tags\": [[\"tag1\",\"value\"], [\"tag2\", 5]],\n" +
-    "    \"username\": \"USER\",\n" +
-    "    \"url\": \"HTTP://SOMEURL\",\n" +
-    "    \"ip\": \"127.0.0.1\",\n" +
-    "    \"start_time\": \"{{$ctrl.momentJs.utc().milliseconds(0).toISOString()}}\",\n" +
-    "    \"end_time\": \"{{$ctrl.momentJs.utc().milliseconds(0).add(2, 'seconds').toISOString()}}\",\n" +
-    "    \"user_agent\": \"BROWSER_AGENT\",\n" +
-    "    \"extra\": [[\"message\",\"CUSTOM MESSAGE\"], [\"custom_value\", \"some payload\"]],\n" +
-    "    \"request_id\": \"SOME_UUID\",\n" +
-    "    \"request\": {\"REQUEST_METHOD\": \"GET\",\n" +
-    "             \"PATH_INFO\": \"/FOO/BAR\",\n" +
-    "             \"POST\": {\"FOO\":\"BAZ\",\"XXX\":\"YYY\"}\n" +
-    "             },\n" +
-    "    \"slow_calls\":[{\n" +
-    "                   \"start\": \"{{$ctrl.momentJs.utc().milliseconds(0).toISOString()}}\",\n" +
-    "                   \"end\": \"{{$ctrl.momentJs.utc().milliseconds(0).add(1, 'seconds').toISOString()}}\",\n" +
-    "                   \"type\": \"sql\",\n" +
-    "                   \"subtype\": \"postgresql\",\n" +
-    "                   \"parameters\": [\"QPARAM1\",\"QPARAM2\",\"QPARAMX\"],\n" +
-    "                   \"statement\": \"QUERY\"\n" +
-    "                   }],\n" +
-    "    \"request_stats\": {\n" +
-    "                    \"main\": 2.50779,\n" +
-    "                    \"nosql\": 0.01008,\n" +
-    "                    \"nosql_calls\": 17.0,\n" +
-    "                    \"remote\": 0.0,\n" +
-    "                    \"remote_calls\": 0.0,\n" +
-    "                    \"sql\": 1,\n" +
-    "                    \"sql_calls\": 1.0,\n" +
-    "                    \"tmpl\": 0.0,\n" +
-    "                    \"tmpl_calls\": 0.0,\n" +
-    "                    \"custom\": 0.0,\n" +
-    "                    \"custom_calls\": 0.0\n" +
-    "                },\n" +
-    "    \"traceback\": [\n" +
-    "                {\"cline\": \"return foo_bar_baz(1,2,3)\",\n" +
-    "                \"file\": \"somedir/somefile.py\",\n" +
-    "                \"fn\": \"somefunction\",\n" +
-    "                \"line\": 454,\n" +
-    "                \"vars\": [[\"a_list\",\n" +
-    "                         [\"1\",2,\"4\",\"5\",6]],\n" +
-    "                         [\"b\", {\"1\": \"2\", \"ccc\": \"ddd\", \"1\": \"a\"}],\n" +
-    "                         [\"obj\", \"object object at 0x7f0030853dc0\"]]\n" +
-    "                        },\n" +
-    "                        {\"cline\": \"OMG ValueError happened\",\n" +
-    "                        \"file\": \"\",\n" +
-    "                        \"fn\": \"\",\n" +
-    "                        \"line\": \"\",\n" +
-    "                        \"vars\": []}\n" +
-    "                        ]\n" +
-    "                        }]'\n" +
-    "                    
\n" + - "
\n" + + "
\n" + ); + + + $templateCache.put('components/views/admin-groups-list-view/admin-groups-list-view.html', + "\n" + "\n" + - " \n" + + "
\n" + "\n" + - " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + "\n" + - " \n" + - " Metrics API\n" + - " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + "
Group nameDescriptionMember count
{{group.group_name}}{{group.description}}{{group.member_count}}\n" + + " \n" + + " \n" + + " \n" + + "
    \n" + + "
  • No
  • \n" + + "
  • Yes
  • \n" + + "
\n" + + "
\n" + + "
\n" + + "
\n" + + "
\n" + "\n" + - "
\n" + - "
\n" +
-    "curl -H \"Content-Type: application/json\" -k {{AeConfig.urls.baseUrl}}api/general_metrics?protocol_version=0.5\\&api_key={{$ctrl.resource.api_key}} -d '\n" +
-    "        [{\n" +
-    "        \"namespace\": \"some.monitor\",\n" +
-    "        \"timestamp\": \"{{$ctrl.momentJs.utc().milliseconds(0).toISOString()}}\",\n" +
-    "        \"server_name\": \"server.name\",\n" +
-    "        \"tags\": [[\"value1\", 15.7], [\"value2\", 26]]}]'\n" +
-    "                    
\n" + - "
\n" + + "
\n" + + "\n" + ); + + + $templateCache.put('components/views/admin-partitions-view/admin-partitions-view.html', + "\n" + "\n" + - " \n" + + "
\n" + "\n" + - " \n" + + "
\n" + + "
\n" + + " DELETE Daily Partitions\n" + + "
\n" + "\n" + - " \n" + - " Request Stats API\n" + - " \n" + + "
\n" + "\n" + - "
\n" + - "
\n" +
-    "curl -H \"Content-Type: application/json\" -k {{AeConfig.urls.baseUrl}}api/request_stats?protocol_version=0.5\\&api_key={{$ctrl.resource.api_key}} -d '\n" +
-    "        [{\"server\": \"some.server.hostname\",\n" +
-    "          \"timestamp\": \"{{$ctrl.momentJs.utc().milliseconds(0).toISOString()}}\",\n" +
-    "          \"metrics\": [[\"dir/module:func\",\n" +
-    "               {\"custom\": 0.0,\n" +
-    "                \"custom_calls\": 0,\n" +
-    "                \"main\": 0.01664,\n" +
-    "                \"nosql\": 0.00061,\n" +
-    "                \"nosql_calls\": 23,\n" +
-    "                \"remote\": 0.0,\n" +
-    "                \"remote_calls\": 0,\n" +
-    "                \"requests\": 1,\n" +
-    "                \"sql\": 0.00105,\n" +
-    "                \"sql_calls\": 2,\n" +
-    "                \"tmpl\": 0.0,\n" +
-    "                \"tmpl_calls\": 0}],\n" +
-    "              [\"SomeView.function\",\n" +
-    "               {\"custom\": 0.0,\n" +
-    "                \"custom_calls\": 0,\n" +
-    "                \"main\": 0.647261,\n" +
-    "                \"nosql\": 0.306554,\n" +
-    "                \"nosql_calls\": 140,\n" +
-    "                \"remote\": 0.0,\n" +
-    "                \"remote_calls\": 0,\n" +
-    "                \"requests\": 28,\n" +
-    "                \"sql\": 0.0,\n" +
-    "                \"sql_calls\": 0,\n" +
-    "                \"tmpl\": 0.0,\n" +
-    "                \"tmpl_calls\": 0}]]\n" +
-    "                }]'\n" +
-    "                    
\n" + - "
\n" + + "
\n" + "\n" + - " \n" + + " \n" + + " \n" + + " Check All\n" + "\n" + - " \n" + + "
\n" + "\n" + - "
\n" + - "
\n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + "
DateIndices
{{row[0]}}\n" + + "
    \n" + + "
  • \n" + + " ES: {{partition.name}}\n" + + "
  • \n" + + "
  • \n" + + " PG: {{partition.name}}\n" + + "
  • \n" + + "
\n" + + "
\n" + + " \n" + "\n" + - " \n" + + "
\n" + "\n" + - "
\n" + + "
\n" + "
\n" + - "

Postprocessing

\n" + + " DELETE Permanent Partitions\n" + "
\n" + - "
\n" + - "

This section allows you influence the rating of report groups - if rule is matched once its not executed anymore

\n" + - "\n" + - "

\n" + - " Add rule\n" + - "

\n" + "\n" + - " \n" + - "
\n" + - "
\n" + + "
\n" + "\n" + - "
\n" + - "
\n" + - "

Administration

\n" + - "
\n" + - "
\n" + - "

Transfer ownership

\n" + - "

Please note that by transfering ownership you WILL lose access to the application data and new owner needs to give you access permission

\n" + - "
\n" + - " \n" + - "
\n" + - " \n" + - " \n" + - "
\n" + - " \n" + - "
\n" + - "
\n" + - "
\n" + - " \n" + - " \n" + - "
\n" + - " \n" + - "
\n" + - "
\n" + - "
\n" + - " \n" + - "
\n" + - " \n" + - "
\n" + - "
\n" + - " \n" + - "
\n" + "\n" + - "
\n" + + "
\n" + "\n" + - "

Remove application

\n" + - "

This operation will wipe out all data from database - there is no undo.

\n" + + "
\n" + + " \n" + + " \n" + + " Check All\n" + + "
\n" + "\n" + - "
\n" + - "
\n" + - "
\n" + - " \n" + - " \n" + - "
\n" + - " \n" + - "
\n" + - "
\n" + - "
\n" + - "
\n" + + "\n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + "
DateIndices
{{row[0]}}\n" + + "
    \n" + + "
  • \n" + + " ES: {{partition.name}}\n" + + "
  • \n" + + "
  • \n" + + " PG: {{partition.name}}\n" + + "
  • \n" + + "
\n" + + "
\n" + + "
\n" + "\n" + - " \n" + - "
\n" + - " \n" + - "
\n" + - "
\n" + - " \n" + - "
\n" + - "
\n" + "
\n" + + "\n" + "
\n" ); - $templateCache.put('components/views/event-browser/event-browser.html', - "
\n" + - "
\n" + + $templateCache.put('components/views/admin-system-view/admin-system-view.html', + "\n" + "\n" + - "

Event history

\n" + + "
\n" + + "
\n" + + "
\n" + + "
\n" + + "
\n" + + "

\n" + + " System Info\n" + + "

\n" + + "
\n" + + "
\n" + "\n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - "
\n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - "

For {{ event.resource_name }}

\n" + + "

System Load:\n" + + " 1min: {{$ctrl.systemLoad[0]}}, 5min: {{$ctrl.systemLoad[1]}}, 15min: {{$ctrl.systemLoad[2]}}\n" + + "

\n" + + "

Awaiting tasks:\n" + + "

    \n" + + "
  • reports: {{$ctrl.queueStats.waiting_reports}}
  • \n" + + "
  • logs: {{$ctrl.queueStats.waiting_logs}}
  • \n" + + "
  • metrics: {{$ctrl.queueStats.waiting_metrics}}
  • \n" + + "
  • other: {{$ctrl.queueStats.waiting_other}}
  • \n" + + "
\n" + + "

\n" + + "

Queue stats from last minute:\n" + + "

    \n" + + "
  • Processed reports: {{$ctrl.queueStats.processed_reports}}
  • \n" + + "
  • Processed logs: {{$ctrl.queueStats.processed_logs}}
  • \n" + + "
  • Processed metrics: {{$ctrl.queueStats.processed_metrics}}
  • \n" + + "
\n" + + "

\n" + "\n" + - "

{{ event.text }}

\n" + - " created:\n" + - " \n" + - " \n" + - " | closed:\n" + - " \n" + - " \n" + - "
\n" + + "

Disks:\n" + + "

    \n" + + "
  • \n" + + " {{disk.device}} {{disk.free}}/{{disk.total}}, {{disk.percentage}}% used\n" + + "
  • \n" + + "
\n" + + "

\n" + "\n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + + "

Process stats:\n" + + "

    \n" + + "
  • FD soft limits: {{$ctrl.selfInfo.fds.soft}}
  • \n" + + "
  • FD hard limits: {{$ctrl.selfInfo.fds.hard}}
  • \n" + + "
  • Memlock soft limits: {{$ctrl.selfInfo.memlock.soft}}
  • \n" + + "
  • Memlock hard limits: {{$ctrl.selfInfo.memlock.hard}}
  • \n" + + "
\n" + + "

\n" + "\n" + - "
\n" + + "
\n" + + "
\n" + + "
\n" + "
\n" + - "
\n" - ); - - - $templateCache.put('components/views/index-dashboard/index-dashboard.html', - "\n" + + "
\n" + + "
\n" + "\n" + - "
\n" + - "
\n" + - "
\n" + + " \n" + + " \n" + + " \n" + + " Postgresql Tables\n" + + " \n" + "\n" + - "
\n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + "
Table nameSize
{{row.table_name}}{{row.size_human}}
\n" + "\n" + - "
\n" + + " \n" + "\n" + - "
\n" + + " \n" + + " \n" + + " Elasticsearch Indices\n" + + " \n" + "\n" + - "
\n" + - "
\n" + - "
\n" + - "
\n" + - "
\n" + - " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + "
Index nameSize
{{row.name}}{{row.size_human}}
\n" + "\n" + - " \n" + + " \n" + "\n" + + " \n" + + " \n" + + " Processes\n" + + " \n" + "\n" + - "
\n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - "
\n" + - " \n" + - "
\n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + "
OwnerPIDCPUMEMName
{{row.owner}}{{row.pid}}{{row.cpu}}{{row.mem_usage}} ({{row.mem_percentage}}%){{row.name}}
{{row.command}}
\n" + "\n" + - "

\n" + - " \n" + - "

\n" + + "
\n" + "\n" + - "
\n" + - "
\n" + - " \n" + - " \n" + - "
\n" + + " \n" + + " \n" + + " Python packages\n" + + " \n" + "\n" + - "
\n" + - " \n" + - " \n" + - "
\n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + "
{{package.name}}{{package.version}}
\n" + + "

\n" + "\n" + - "
\n" + - " \n" + - " \n" + - "
\n" + - "
\n" + - " \n" + - " \n" + - "
\n" + + "
\n" + "\n" + - "
\n" + - " \n" + - " \n" + - "
\n" + - "\n" + - "

\n" + - " Average requests per second from all servers\n" + - "

\n" + + " \n" + + "
\n" + + "
\n" + + "
\n" + + "
\n" + + "
\n" + ); + + + $templateCache.put('components/views/admin-users-create-view/admin-users-create-view.html', + "\n" + "\n" + - "

\n" + - " Average response time from all servers\n" + - "

\n" + + "
\n" + "\n" + - "

\n" + - " Aggregated average time spent per request - broken to layers\n" + - "

\n" + + "
\n" + + "
\n" + "\n" + - "

\n" + - " Aggregated reports sent by your application\n" + - "

\n" + + " \n" + + " Re-login to user\n" + + "
    \n" + + "
  • No
  • \n" + + "
  • Yes
  • \n" + + "
\n" + + "
\n" + "\n" + - "

\n" + - " Aggregated slow reports sent by your application\n" + - "

\n" + - "
\n" + - "
\n" + + "
\n" + + "
\n" + + " \n" + + " \n" + + "
\n" + + " \n" + "
\n" + "
\n" + "\n" + + "
\n" + + " \n" + + " \n" + + "
\n" + + " \n" + "\n" + - "
\n" + - "\n" + - "
\n" + - "\n" + - " \n" + + "
\n" + + " \n" + + " \n" + + "
\n" + + " \n" + + "
\n" + + "
\n" + "\n" + - "
\n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - "
ServerApdex\n" + - " \n" + - " rpmavg. response
\n" + - " {{ server.name }}\n" + - " \n" + - " {{ server.apdex }} %\n" + - " \n" + - " {{ server.rpm }}rpm\n" + - " \n" + - " {{ server.avg_response_time }}s\n" + - "
\n" + + "
\n" + + " \n" + + " \n" + + "
\n" + + " \n" + + "
\n" + + "
\n" + + "
\n" + + " \n" + + " \n" + + "
\n" + + " \n" + + "
\n" + + "
\n" + "\n" + - "
\n" + + "
\n" + + " \n" + + " \n" + + "
\n" + + " \n" + "
\n" + + "
\n" + "\n" + + "
\n" + + " \n" + + "
\n" + + " \n" + + "
\n" + "
\n" + + " \n" + + "
\n" + + "
\n" + "\n" + "\n" + - "
\n" + + "
\n" + + "
\n" + + "

Permission Summary

\n" + + "
\n" + + "
\n" + + "

Direct application permissions

\n" + "\n" + - "
\n" + - "
\n" + + "
    \n" + + "
  • \n" + + " {{ perm.self.resource_name }}\n" + + "
    \n" + "\n" + - "
    \n" + - "
    \n" + - "

    Newest errors (real-time)\n" + - "

    \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + + " {{ perm.self.owner ? 'Resource owner' : perm_name }}\n" + "\n" + + " \n" + + " \n" + + " \n" + + "
    \n" + + "
  • \n" + + "
\n" + "\n" + - "
\n" + - "
\n" + + "

Direct dashboard permissions

\n" + "\n" + - "

No new reports

\n" + + "
    \n" + + "
  • \n" + + " {{ perm.self.resource_name }}\n" + + "
    \n" + "\n" + - "
    \n" + - "
    \n" + - "
\n" + - "
\n" + + " {{ perm.self.owner ? 'Resource owner' : perm_name }}\n" + "\n" + - "
\n" + + " \n" + + " \n" + + " \n" + + "
\n" + + " \n" + + " \n" + "\n" + - "
\n" + - "
\n" + - "

Request breakdown over {{ $ctrl.timeSpan.label }}

\n" + - "
\n" + - "
\n" + - "

\n" + - " \n" + - "

\n" + + "
\n" + "\n" + - "
\n" + - "
\n" + - "
\n" + - "
\n" + - "
\n" + - "
\n" + - "
\n" + - " \n" + - " {{view.view_name}}\n" + - " {{view.view_name}}\n" + + "
\n" + "\n" + - "
\n" + - " \n" + - " avg. response {{view.avg_response}}s in\n" + - " {{view.requests|numberToThousands}} requests\n" + "\n" + - " \n" + - "    Latest reports:\n" + - " {{$index+1}}\n" + - " \n" + - " \n" + - "
\n" + + "
\n" + ); + + + $templateCache.put('components/views/admin-users-list-view/admin-users-list-view.html', + "\n" + "\n" + - "
\n" + + "
\n" + "\n" + - "
\n" + - "
\n" + + "
\n" + "\n" + + "
\n" + + " {{$ctrl.activeUsers}} active out of {{$ctrl.users.length}} users\n" + + "
\n" + "\n" + - "
\n" + - "
\n" + - "\n" + - "
\n" + - "\n" + - "
\n" + - "\n" + - "
\n" + - "
\n" + - "\n" + - "
\n" + - "
\n" + - "

\n" + - " Report groups trending over {{ $ctrl.timeSpan.label }}\n" + - "

\n" + - "
\n" + - "
\n" + - "

\n" + - " \n" + - "

\n" + - "\n" + - "

\n" + - " No reports found\n" + - "

\n" + - "\n" + - "
\n" + - "
\n" + - "
\n" + - "\n" + - "
\n" + - "\n" + - "
\n" + - "\n" + - "\n" + - "
\n" + - "
\n" + - "

\n" + - " Most common slow calls over {{ $ctrl.timeSpan.label }}\n" + - "

\n" + - "
\n" + - "
\n" + - "\n" + - "
\n" + - " \n" + - "
\n" + - "\n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - "
\n" + - " {{call.occurences|numberToThousands}}\n" + - " \n" + - " {{call.statement}}\n" + - "
\n" + - " {{call.statement_type}}\n" + - " {{call.statement_subtype}}\n" + - " {{call.total_duration/call.occurences|round:2}}s\n" + - " \n" + - " Latest reports:\n" + - " {{$index+1}} \n" + - " \n" + - "
\n" + "\n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + "\n" + - " \n" + - " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + "
UsernameEmailStatusFirst NameLast NameLast login
{{user.user_name}}{{user.email}}{{user.first_name}}{{user.last_name}}{{user.last_login_date | isoToRelativeTime}}\n" + + " \n" + + " \n" + + " \n" + + "
    \n" + + "
  • No
  • \n" + + "
  • Yes
  • \n" + + "
\n" + + "
\n" + + "
\n" + + "
\n" + + "
\n" + "\n" + "\n" + - "
\n" + + "
\n" + + "
\n" + ); + + + $templateCache.put('components/views/admin-view/admin-view.html', + "
\n" + + "
\n" + + "
\n" + + "
Users and groups
\n" + + " \n" + + "
\n" + + "
\n" + + "
Resources
\n" + + " \n" + + "
\n" + "\n" + - "
\n" + + "
\n" + + "
System
\n" + + " \n" + "
\n" + "
\n" + + "\n" + + "
\n" + "
\n" ); - $templateCache.put('components/views/integrations/bitbucket-integration-config-view/bitbucket-integration-config-view.html', - "\n" + + $templateCache.put('components/views/applications-integrations-view/applications-integrations-view.html', + "\n" + "\n" + - "
\n" + - "
\n" + - "
\n" + + "\n" + + "
\n" + + "
\n" + + "
\n" + "\n" + - "

Bitbucket Integration

\n" + + " \n" + + " \n" + + " Bitbucket\n" + "\n" + - "
\n" + - " \n" + - "
\n" + + " \n" + + " \n" + + " Github\n" + "\n" + - " \n" + + "

Send issues and reports to Github

\n" + + "
\n" + "\n" + - "
\n" + - " \n" + - " \n" + - " Remove Integration\n" + - "
    \n" + - "
  • No
  • \n" + - "
  • Yes
  • \n" + - "
\n" + - "
\n" + - "
\n" + - "
\n" + - "
\n" + + " \n" + + " \n" + + " HipChat\n" + "\n" + - "

Remember you first need to\n" + - " \n" + - " authorize your user account\n" + - " with Bitbucket before we can send issues on your behalf.

\n" + + "

Receive reports and alerts in your Hipchat chanels

\n" + + " \n" + "\n" + - "

Every user will have to authorize AppEnlight to access Bitbucket to be able to post issues.

\n" + + " \n" + + " \n" + + " Jira\n" + + "\n" + + "

Send issues and reports to Jira

\n" + + "
\n" + + "\n" + + " \n" + + " \n" + + " Slack\n" + + "\n" + + "

Receive reports and alerts in your Slack chanels

\n" + + "
\n" + + "\n" + + " \n" + + " \n" + + " Webhooks\n" + "\n" + + "

Notify third party API's of your reports and alerts

\n" + + "
\n" + + "
\n" + "
\n" + - "
\n" + "\n" ); - $templateCache.put('components/views/integrations/campfire-integration-config-view/campfire-integration-config-view.html', - "\n" + + $templateCache.put('components/views/applications-list-view/applications-list-view.html', + "\n" + "\n" + - "
\n" + + "
\n" + "
\n" + - "
\n" + - "

Campfire Integration

\n" + - "\n" + - "
\n" + + "
\n" + "\n" + - "
\n" + + "

You have to create a new application first.

\n" + "\n" + - " \n" + - "
\n" + - " \n" + + "
\n" + "\n" + - "
\n" + - "
http://
\n" + - " \n" + - "
.campfirenow.com
\n" + - "
\n" + - "
\n" + - "
\n" + - "\n" + - "
\n" + - " \n" + - "
\n" + - " \n" + - " \n" + - "
\n" + - "
\n" + - "\n" + - "
\n" + - " \n" + - "
\n" + - " \n" + - " \n" + - "

\n" + - " Room ID list separated by comma\n" + - "

\n" + - "
\n" + - "
\n" + - "
\n" + - " \n" + - "\n" + - " \n" + - " Remove Integration\n" + - "
    \n" + - "
  • No
  • \n" + - "
  • Yes
  • \n" + - "
\n" + - "
\n" + - "\n" + - "
\n" + - " \n" + - " \n" + - "
\n" + - "\n" + - "
\n" + - "\n" + - "
\n" + + " 0\">\n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + "
Resource NameDomainsOptions
{{application.resource_name}}{{application.domains}}\n" + + " Update\n" + + " Integrations\n" + + "
\n" + "\n" + - "
\n" + "
\n" ); - $templateCache.put('components/views/integrations/flowdock-integration-config-view/flowdock-integration-config-view.html', - "\n" + - "\n" + - "
\n" + - "
\n" + - "
\n" + - "\n" + - "

Flowdock Integration

\n" + - "\n" + - "
\n" + + $templateCache.put('components/views/applications-purge-logs-view/applications-purge-logs-view.html', + "\n" + "\n" + - "
\n" + + "
\n" + + "
\n" + + "
\n" + + "
\n" + "\n" + - " \n" + + " \n" + + "
\n" + + " \n" + "\n" + - "
\n" + - " \n" + - " \n" + + "
\n" + + " \n" + + "
\n" + "
\n" + "\n" + + "
\n" + + " \n" + "\n" + - "
\n" + - "\n" + - "
\n" + - "\n" + - " \n" + - "\n" + - "
\n" + - "\n" + - " \n" + - "\n" + - " \n" + - " Remove Integration\n" + - "
    \n" + - "
  • No
  • \n" + - "
  • Yes
  • \n" + - "
\n" + - "
\n" + - "
\n" + - " \n" + - " \n" + + "
\n" + + " \n" + "
\n" + "
\n" + - "
\n" + "\n" + + "
\n" + + " \n" + "\n" + - " \n" + + "
\n" + + " \n" + + "
\n" + + "
\n" + "\n" + + " \n" + + "
\n" + "
\n" + "
\n" ); - $templateCache.put('components/views/integrations/github-integration-config-view/github-integration-config-view.html', - "\n" + - "\n" + - "
\n" + - "
\n" + - "
\n" + + $templateCache.put('components/views/applications-update-view/applications-update-view.html', + "\n" + "\n" + - "

Github Integration

\n" + + "
\n" + "\n" + - "
\n" + + "
\n" + + "
\n" + + "
\n" + "\n" + + "
\n" + + "
\n" + "\n" + - "
\n" + + " \n" + + " \n" + + " \n" + + " API keys\n" + + " \n" + "\n" + - " \n" + + "

PRIVATE API KEY:

\n" + + "

\n" + + "

{{ $ctrl.resource.api_key }}
\n" + + "

\n" + + "

PUBLIC API KEY (for javascript clients):

\n" + + "

\n" + + "

{{ $ctrl.resource.public_key }}
\n" + + "

\n" + + "

Your key will be used to identify to which application your data\n" + + " belongs to please keep them private at all times.

\n" + "\n" + - "
\n" + + " \n" + "\n" + - " \n" + - " \n" + + " \n" + + " \n" + + " Regenerate API keys\n" + + " \n" + + "

Are you sure you want to regenerate API KEY for this application?

\n" + + "

All client application keys will need to be updated.

\n" + + " \n" + + " \n" + + "
\n" + + " \n" + + " \n" + + "
\n" + + " \n" + + "
\n" + + " \n" + + "
\n" + + "
\n" + + "

How to connect your application?

\n" + + "

Visit our developer documentation for step-by-step integration instructions.

\n" + + "
\n" + + "

\n" + + " \"Django\n" + + " \"Pyramid\n" + + " \"Flask\n" + "\n" + - "

\n" + - "
https://api.github.com/
\n" + - " \n" + - "
/
\n" + - " \n" + - "
\n" + + " \"Javascript\n" + + " \"Node.js\"\n" + + " \"Ruby\n" + + " \"PHP\n" + + " \n" + "\n" + + "

\n" + "
\n" + "
\n" + "\n" + - "
\n" + + "
\n" + "\n" + - " \n" + + "
\n" + + "
\n" + + " \n" + + " \n" + "\n" + - " \n" + + "
\n" + + " \n" + + "
\n" + "\n" + - " \n" + - " Remove Integration\n" + - "
    \n" + - "
  • No
  • \n" + - "
  • Yes
  • \n" + - "
\n" + - "
\n" + "\n" + - "
\n" + - "
\n" + + "
\n" + "\n" + - "

Remember you first need to\n" + - " \n" + - " authorize your user account\n" + - " with Github before we can send issues on your behalf.

\n" + + "
\n" + + " \n" + + " \n" + + "
\n" + + " \n" + + "

Required for Javascript error tracking (one line one domain, skip http:// part)

\n" + + "
\n" + "\n" + - "

Every user will have to authorize AppEnlight to access Github to be able to post issues.

\n" + "\n" + - "
\n" + - "
Private repository access
\n" + - "
\n" + - "

If you need access to private repositories profile page allows you to require token including private repository permissions.

\n" + + "
\n" + + "
\n" + + " \n" + + " \n" + + "
\n" + + " \n" + + "
\n" + "\n" + - "

Registration page OAuth does NOT give you token with private repository access permissions.

\n" + - "
\n" + - "
\n" + + "
\n" + + "
\n" + + " \n" + + " \n" + + "
\n" + + " \n" + + "

Application requires to send at least this amount of error reports per minute to open alert

\n" + + "
\n" + + "
\n" + + "
\n" + + " \n" + + " \n" + "\n" + - "
\n" + - "
\n" - ); - - - $templateCache.put('components/views/integrations/hipchat-integration-config-view/hipchat-integration-config-view.html', - "\n" + + "
\n" + + " \n" + + "

Application requires to send at least this amount of slow reports per minute to open alert

\n" + + "
\n" + + "
\n" + + "
\n" + + " \n" + + " \n" + + "
\n" + + " \n" + + "

Allow permanent storage of logs in separate DB partitions (only administrator can enable this feature)

\n" + + "
\n" + + "
\n" + + "
\n" + + "
\n" + "\n" + - "
\n" + + "
\n" + + "
\n" + + "

Plugins

\n" + + "
\n" + + "
\n" + "\n" + - "
\n" + - " \n" + + " \n" + + " \n" + "\n" + - "
\n" + - " \n" + - " \n" + - "
\n" + - "
\n" + + "
\n" + + "
\n" + "\n" + - "
\n" + + "
\n" + + "
\n" + + "

API Testing

\n" + + "
\n" + + "
\n" + + "

Please be sure to add at least one email alert channel for your account.

\n" + + "

This will enable AppEnlight to send you notification emails about errors inside your $ctrl.

\n" + + "

After this is done you can use this CURL commands to test APIs:

\n" + + "

(Please note that the data like execution times is semi randomly generated)

\n" + + " \n" + + " \n" + + " \n" + + " Log API\n" + + " \n" + "\n" + - " \n" + + "
\n" + + "
\n" +
+    "curl -H \"Content-Type: application/json\" -k {{AeConfig.urls.baseUrl}}api/logs?protocol_version=0.5\\&api_key={{$ctrl.resource.api_key}} -d '\n" +
+    "    [\n" +
+    "      {\n" +
+    "      \"log_level\": \"WARNING\",\n" +
+    "      \"message\": \"OMG ValueError happened\",\n" +
+    "      \"namespace\": \"some.namespace.indicator\",\n" +
+    "      \"request_id\": \"SOME_UUID\",\n" +
+    "      \"permanent\": false,\n" +
+    "      \"primary_key\": \"random_key\",\n" +
+    "      \"server\": \"some.server.hostname\",\n" +
+    "      \"date\": \"{{$ctrl.momentJs.utc().milliseconds(0).toISOString()}}\",\n" +
+    "      \"tags\": [[\"tag1\",\"value\"], [\"tag2\", 5]]\n" +
+    "      },\n" +
+    "      {\n" +
+    "      \"log_level\": \"ERROR\",\n" +
+    "      \"message\": \"OMG ValueError happened2\",\n" +
+    "      \"namespace\": \"some.namespace.indicator\",\n" +
+    "      \"request_id\": \"SOME_UUID\",\n" +
+    "      \"permanent\": false,\n" +
+    "      \"server\": \"some.server.hostname\",\n" +
+    "      \"date\": \"{{$ctrl.momentJs.utc().milliseconds(0).toISOString()}}\"\n" +
+    "      }\n" +
+    "    ]'\n" +
+    "                    
\n" + + "
\n" + "\n" + - "
\n" + - " \n" + - " \n" + + " \n" + "\n" + - "

\n" + - " Room ID list separated by comma\n" + - "

\n" + - "
\n" + + " \n" + + " \n" + + " Report API\n" + + " \n" + "\n" + - "
\n" + + "
\n" + + "
\n" +
+    "curl -H \"Content-Type: application/json\" -k {{AeConfig.urls.baseUrl}}api/reports?protocol_version=0.5\\&api_key={{$ctrl.resource.api_key}} -d '\n" +
+    "    [{\n" +
+    "    \"client\": \"your-client-name-python\",\n" +
+    "    \"language\": \"python\",\n" +
+    "    \"view_name\": \"views/foo:bar\",\n" +
+    "    \"server\": \"SERVERNAME/INSTANCENAME\",\n" +
+    "    \"priority\": 5,\n" +
+    "    \"error\": \"OMG ValueError happened\",\n" +
+    "    \"occurences\":1,\n" +
+    "    \"http_status\": 500,\n" +
+    "    \"tags\": [[\"tag1\",\"value\"], [\"tag2\", 5]],\n" +
+    "    \"username\": \"USER\",\n" +
+    "    \"url\": \"HTTP://SOMEURL\",\n" +
+    "    \"ip\": \"127.0.0.1\",\n" +
+    "    \"start_time\": \"{{$ctrl.momentJs.utc().milliseconds(0).toISOString()}}\",\n" +
+    "    \"end_time\": \"{{$ctrl.momentJs.utc().milliseconds(0).add(2, 'seconds').toISOString()}}\",\n" +
+    "    \"user_agent\": \"BROWSER_AGENT\",\n" +
+    "    \"extra\": [[\"message\",\"CUSTOM MESSAGE\"], [\"custom_value\", \"some payload\"]],\n" +
+    "    \"request_id\": \"SOME_UUID\",\n" +
+    "    \"request\": {\"REQUEST_METHOD\": \"GET\",\n" +
+    "             \"PATH_INFO\": \"/FOO/BAR\",\n" +
+    "             \"POST\": {\"FOO\":\"BAZ\",\"XXX\":\"YYY\"}\n" +
+    "             },\n" +
+    "    \"slow_calls\":[{\n" +
+    "                   \"start\": \"{{$ctrl.momentJs.utc().milliseconds(0).toISOString()}}\",\n" +
+    "                   \"end\": \"{{$ctrl.momentJs.utc().milliseconds(0).add(1, 'seconds').toISOString()}}\",\n" +
+    "                   \"type\": \"sql\",\n" +
+    "                   \"subtype\": \"postgresql\",\n" +
+    "                   \"parameters\": [\"QPARAM1\",\"QPARAM2\",\"QPARAMX\"],\n" +
+    "                   \"statement\": \"QUERY\"\n" +
+    "                   }],\n" +
+    "    \"request_stats\": {\n" +
+    "                    \"main\": 2.50779,\n" +
+    "                    \"nosql\": 0.01008,\n" +
+    "                    \"nosql_calls\": 17.0,\n" +
+    "                    \"remote\": 0.0,\n" +
+    "                    \"remote_calls\": 0.0,\n" +
+    "                    \"sql\": 1,\n" +
+    "                    \"sql_calls\": 1.0,\n" +
+    "                    \"tmpl\": 0.0,\n" +
+    "                    \"tmpl_calls\": 0.0,\n" +
+    "                    \"custom\": 0.0,\n" +
+    "                    \"custom_calls\": 0.0\n" +
+    "                },\n" +
+    "    \"traceback\": [\n" +
+    "                {\"cline\": \"return foo_bar_baz(1,2,3)\",\n" +
+    "                \"file\": \"somedir/somefile.py\",\n" +
+    "                \"fn\": \"somefunction\",\n" +
+    "                \"line\": 454,\n" +
+    "                \"vars\": [[\"a_list\",\n" +
+    "                         [\"1\",2,\"4\",\"5\",6]],\n" +
+    "                         [\"b\", {\"1\": \"2\", \"ccc\": \"ddd\", \"1\": \"a\"}],\n" +
+    "                         [\"obj\", \"object object at 0x7f0030853dc0\"]]\n" +
+    "                        },\n" +
+    "                        {\"cline\": \"OMG ValueError happened\",\n" +
+    "                        \"file\": \"\",\n" +
+    "                        \"fn\": \"\",\n" +
+    "                        \"line\": \"\",\n" +
+    "                        \"vars\": []}\n" +
+    "                        ]\n" +
+    "                        }]'\n" +
+    "                    
\n" + + "
\n" + "\n" + - "
\n" + - " \n" + - "
\n" + - " \n" + - " \n" + - " Remove Integration\n" + - "
    \n" + - "
  • No
  • \n" + - "
  • Yes
  • \n" + - "
\n" + - "
\n" + + " \n" + "\n" + - "
\n" + - " \n" + - " \n" + - "
\n" + + " \n" + + "\n" + + " \n" + + " Metrics API\n" + + " \n" + "\n" + + "
\n" + + "
\n" +
+    "curl -H \"Content-Type: application/json\" -k {{AeConfig.urls.baseUrl}}api/general_metrics?protocol_version=0.5\\&api_key={{$ctrl.resource.api_key}} -d '\n" +
+    "        [{\n" +
+    "        \"namespace\": \"some.monitor\",\n" +
+    "        \"timestamp\": \"{{$ctrl.momentJs.utc().milliseconds(0).toISOString()}}\",\n" +
+    "        \"server_name\": \"server.name\",\n" +
+    "        \"tags\": [[\"value1\", 15.7], [\"value2\", 26]]}]'\n" +
+    "                    
\n" + "
\n" + - "
\n" + "\n" + - " \n" + + " \n" + "\n" + - "
\n" + - "
\n" - ); - - - $templateCache.put('components/views/integrations/jira-integration-config-view/jira-integration-config-view.html', - "\n" + - "\n" + - "
\n" + - "
\n" + - "
\n" + + " \n" + "\n" + - "

Jira Integration

\n" + + " \n" + + " Request Stats API\n" + + " \n" + "\n" + - "
\n" + + "
\n" + + "
\n" +
+    "curl -H \"Content-Type: application/json\" -k {{AeConfig.urls.baseUrl}}api/request_stats?protocol_version=0.5\\&api_key={{$ctrl.resource.api_key}} -d '\n" +
+    "        [{\"server\": \"some.server.hostname\",\n" +
+    "          \"timestamp\": \"{{$ctrl.momentJs.utc().milliseconds(0).toISOString()}}\",\n" +
+    "          \"metrics\": [[\"dir/module:func\",\n" +
+    "               {\"custom\": 0.0,\n" +
+    "                \"custom_calls\": 0,\n" +
+    "                \"main\": 0.01664,\n" +
+    "                \"nosql\": 0.00061,\n" +
+    "                \"nosql_calls\": 23,\n" +
+    "                \"remote\": 0.0,\n" +
+    "                \"remote_calls\": 0,\n" +
+    "                \"requests\": 1,\n" +
+    "                \"sql\": 0.00105,\n" +
+    "                \"sql_calls\": 2,\n" +
+    "                \"tmpl\": 0.0,\n" +
+    "                \"tmpl_calls\": 0}],\n" +
+    "              [\"SomeView.function\",\n" +
+    "               {\"custom\": 0.0,\n" +
+    "                \"custom_calls\": 0,\n" +
+    "                \"main\": 0.647261,\n" +
+    "                \"nosql\": 0.306554,\n" +
+    "                \"nosql_calls\": 140,\n" +
+    "                \"remote\": 0.0,\n" +
+    "                \"remote_calls\": 0,\n" +
+    "                \"requests\": 28,\n" +
+    "                \"sql\": 0.0,\n" +
+    "                \"sql_calls\": 0,\n" +
+    "                \"tmpl\": 0.0,\n" +
+    "                \"tmpl_calls\": 0}]]\n" +
+    "                }]'\n" +
+    "                    
\n" + + "
\n" + "\n" + - "
\n" + + " \n" + "\n" + - " \n" + - "
\n" + - " \n" + - " \n" + + " \n" + "\n" + - "

\n" + - " https://servername.atlassian.net\n" + - "

\n" + + "
\n" + + "
\n" + "\n" + - "
\n" + - "
\n" + - "
\n" + + " \n" + "\n" + - " \n" + - "
\n" + + "
\n" + + "
\n" + + "

Postprocessing

\n" + + "
\n" + + "
\n" + + "

This section allows you influence the rating of report groups - if rule is matched once its not executed anymore

\n" + "\n" + - " \n" + - " \n" + + "

\n" + + " Add rule\n" + + "

\n" + "\n" + - "

\n" + - " user@email.com\n" + - "

\n" + + " \n" + + "
\n" + + "
\n" + "\n" + - "
\n" + + "
\n" + + "
\n" + + "

Administration

\n" + + "
\n" + + "
\n" + + "

Transfer ownership

\n" + + "

Please note that by transfering ownership you WILL lose access to the application data and new owner needs to give you access permission

\n" + + "
\n" + + " \n" + + "
\n" + + " \n" + + " \n" + + "
\n" + + " \n" + + "
\n" + + "
\n" + + "
\n" + + " \n" + + " \n" + + "
\n" + + " \n" + + "
\n" + + "
\n" + + "
\n" + + " \n" + + "
\n" + + " \n" + + "
\n" + + "
\n" + + " \n" + "
\n" + - "
\n" + "\n" + - " \n" + - "
\n" + - " \n" + - " \n" + - "
\n" + - "
\n" + - "
\n" + + "
\n" + "\n" + - " \n" + - "
\n" + - " \n" + - " \n" + - "
\n" + - "
\n" + - "
\n" + - " \n" + - "
\n" + - " \n" + + "

Remove application

\n" + + "

This operation will wipe out all data from database - there is no undo.

\n" + "\n" + - " \n" + - " Remove Integration\n" + - "
    \n" + - "
  • No
  • \n" + - "
  • Yes
  • \n" + - "
\n" + - "
\n" + - "
\n" + + "
\n" + + "
\n" + + "
\n" + + " \n" + + " \n" + + "
\n" + + " \n" + + "
\n" + + "
\n" + + "
\n" + + " \n" + + "
\n" + + " \n" + + "
\n" + + "
\n" + + "
\n" + "
\n" + + "
\n" + + "
\n" + + "
\n" + ); + + + $templateCache.put('components/views/event-browser/event-browser.html', + "
\n" + + "
\n" + "\n" + - " \n" + + "

Event history

\n" + + "\n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + "
\n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + "

For {{ event.resource_name }}

\n" + + "\n" + + "

{{ event.text }}

\n" + + " created:\n" + + " \n" + + " \n" + + " | closed:\n" + + " \n" + + " \n" + + "
\n" + "\n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + "\n" + + "
\n" + "
\n" + "
\n" ); - $templateCache.put('components/views/integrations/slack-integration-config-view/slack-integration-config-view.html', - "\n" + + $templateCache.put('components/views/index-dashboard/index-dashboard.html', + "\n" + "\n" + - "

Slack Integration

\n" + + "
\n" + + "
\n" + + "
\n" + "\n" + - "
\n" + + "
\n" + "\n" + - "
\n" + + "
\n" + "\n" + - " \n" + - "
\n" + - " \n" + - " \n" + - "
\n" + - "
\n" + + "
\n" + "\n" + - "
\n" + + "
\n" + + "
\n" + + "
\n" + + "
\n" + + " \n" + + " \n" + "\n" + - " \n" + - "
\n" + - " \n" + + " \n" + "\n" + - " \n" + - " Remove Integration\n" + - "
    \n" + - "
  • No
  • \n" + - "
  • Yes
  • \n" + - "
\n" + - "
\n" + "\n" + - "
\n" + - " \n" + - " \n" + - "
\n" + - "
\n" + - "
\n" + - " \n" + + "
\n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + "
\n" + + " \n" + + "
\n" + "\n" + - "
\n" + - "
\n" - ); - - - $templateCache.put('components/views/integrations/webhooks-integration-config-view/webhooks-integration-config-view.html', - "\n" + + "

\n" + + " \n" + + "

\n" + "\n" + - "
\n" + - "
\n" + - "
\n" + + "
\n" + + "
\n" + + " \n" + + " \n" + + "
\n" + "\n" + - "

Webhooks Integration

\n" + + "
\n" + + " \n" + + " \n" + + "
\n" + "\n" + - "
\n" + - "
\n" + + "
\n" + + " \n" + + " \n" + + "
\n" + + "
\n" + + " \n" + + " \n" + + "
\n" + "\n" + - " \n" + - "
\n" + - " \n" + - " \n" + - "
\n" + - "
\n" + - "
\n" + + "
\n" + + " \n" + + " \n" + + "
\n" + "\n" + - " \n" + - "
\n" + - " \n" + - " \n" + - "
\n" + + "

\n" + + " Average requests per second from all servers\n" + + "

\n" + "\n" + + "

\n" + + " Average response time from all servers\n" + + "

\n" + "\n" + - "
\n" + - "
\n" + + "

\n" + + " Aggregated average time spent per request - broken to layers\n" + + "

\n" + "\n" + - " \n" + - "
\n" + - " \n" + - " \n" + - " Remove Integration\n" + - "
    \n" + - "
  • No
  • \n" + - "
  • Yes
  • \n" + - "
\n" + - "
\n" + + "

\n" + + " Aggregated reports sent by your application\n" + + "

\n" + + "\n" + + "

\n" + + " Aggregated slow reports sent by your application\n" + + "

\n" + + "
\n" + + "
\n" + + "
\n" + "
\n" + - "
\n" + - " \n" + - "
\n" + - "
\n" - ); - - - $templateCache.put('components/views/logs-browser/logs-browser.html', - "\n" + "\n" + - "
\n" + "\n" + - "

\n" + - " Search params:\n" + - " \n" + - " {{tag.type}}\n" + - " {{ tag.type == 'resource' ? $ctrl.applications[tag.value].resource_name : tag.value }}\n" + + "

\n" + "\n" + - " \n" + - " \n" + - "

\n" + + "
\n" + "\n" + - "

\n" + + "

\n" + "\n" + - " \n" + + " -->\n" + + " Frustrating req.\n" + + "
\n" + + " {{$ctrl.frustratingRequests|numberToThousands}}\n" + + " \n" + + "
\n" + + " Tolerated req.\n" + + "
\n" + + " {{$ctrl.toleratedRequests|numberToThousands}}\n" + + " \n" + + "
\n" + + " Satisfying req.\n" + + "
\n" + + " {{$ctrl.satisfyingRequests|numberToThousands}}\n" + + "
\n" + + " Uptime\n" + + "
\n" + + " {{$ctrl.uptimeStats}}%\n" + + " \n" + + "
\n" + "\n" + - "

\n" + + "
\n" + + "
\n" + "\n" + - "
\n" + + "
\n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + "
ServerApdex\n" + + " \n" + + " rpmavg. response
\n" + + " {{ server.name }}\n" + + " \n" + + " {{ server.apdex }} %\n" + + " \n" + + " {{ server.rpm }}rpm\n" + + " \n" + + " {{ server.avg_response_time }}s\n" + + "
\n" + "\n" + - "
\n" + - " \n" + - " \n" + - "
\n" + - "
\n" + + "
\n" + + "
\n" + "\n" + + "
\n" + "\n" + - "
\n" + - " \n" + - "
\n" + "\n" + - "
\n" + + "
\n" + "\n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + + "
\n" + + "
\n" + "\n" + - "
\n" + - "
Logs
ApplicationMessageWhen
\n" + - " \n" + - " {{log.resource_name}}\n" + - " \n" + - " \n" + - " level: {{log.log_level}}\n" + - " \n" + - " namespace: {{log.namespace}}\n" + - " \n" + - " {{tag}}: {{value}}\n" + - "
{{log.message}}
\n" + - "
\n" + - " \n" + - " \n" + - " \n" + - "
\n" + + "
\n" + + "
\n" + + "

Newest errors (real-time)\n" + + "

\n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + "\n" + - "
\n" + "\n" + - "
\n" + - " \n" + - "
\n" + + "
\n" + + "
\n" + "\n" + - "
\n" - ); - - - $templateCache.put('components/views/report-view/report-view.html', - "\n" + + "
\n" + + "
\n" + + "
\n" + + "
\n" + + "
\n" + + "
\n" + + "
\n" + + " \n" + + " {{view.view_name}}\n" + + " {{view.view_name}}\n" + "\n" + - "\n" + "\n" + - "\n" + + "
\n" + + "
\n" + "\n" + - "
\n" + - " OOPS something went wrong :(\n" + - "
\n" + + "
\n" + + "
\n" + + "

\n" + + " Report groups trending over {{ $ctrl.timeSpan.label }}\n" + + "

\n" + + "
\n" + + "
\n" + + "

\n" + + " \n" + + "

\n" + "\n" + - "
\n" + + "

\n" + + " No reports found\n" + + "

\n" + "\n" + - "
\n" + - "
\n" + - " 2\">\n" + - " Go back\n" + - " Assign report\n" + - " to user\n" + + "
\n" + + "
\n" + + "
\n" + "\n" + - " \n" + - " Mark fixed\n" + + "
\n" + "\n" + - " \n" + - " \n" + - " Integrations\n" + - " \n" + - " \n" + - " \n" + + "
\n" + "\n" + - " Make {{$ctrl.group.public ? 'private' : 'public'}}\n" + "\n" + - "\n" + - " Delete\n" + - "
    \n" + - "
  • No
  • \n" + - "
  • Yes
  • \n" + - "
\n" + - "
\n" + - "
\n" + - "
\n" + + "
\n" + + "
\n" + + "

\n" + + " Most common slow calls over {{ $ctrl.timeSpan.label }}\n" + + "

\n" + + "
\n" + + "
\n" + "\n" + - "
\n" + - "
\n" + + "
\n" + + " \n" + + "
\n" + "\n" + - "
\n" + - "
\n" + - "\n" + - "

Report Information

\n" + - "\n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - "\n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " 0\">\n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - "
Occurences{{$ctrl.report.group.occurences}}
HTTP status{{$ctrl.report.http_status}}
Priority{{$ctrl.report.group.priority}}
Public URL\n" + - "
\n" + - " \n" + - "
\n" + - "
URL{{$ctrl.report.url}}
Remote IP{{$ctrl.report.ip}}
User Agent{{$ctrl.report.user_agent}}
Message{{$ctrl.report.message}}
Duration\n" + - " {{$ctrl.report.duration}}s\n" + - "
First occured\n" + - " \n" + - "
Last occured\n" + - " \n" + - "
\n" + - "\n" + - "
\n" + - "

Performance stats

\n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + "
\n" + + " {{call.occurences|numberToThousands}}\n" + + " \n" + + " {{call.statement}}\n" + + "
\n" + + " {{call.statement_type}}\n" + + " {{call.statement_subtype}}\n" + + " {{call.total_duration/call.occurences|round:2}}s\n" + + " \n" + + " Latest reports:\n" + + " {{$index+1}} \n" + + " \n" + + "
\n" + "\n" + - "
\n" + - " 0 || stat.value > 0\">\n" + - " {{stat.calls}}\n" + - " {{stat.name}} calls\n" + - " \n" + - " Other\n" + - " \n" + - " \n" + "\n" + - "
\n" + - "
\n" + - "
\n" + - "
\n" + - " 0s\n" + - "
\n" + - "
\n" + - " {{$ctrl.report.duration.toFixed(3)}}s\n" + - "
\n" + - "
\n" + - "
\n" + "
\n" + "
\n" + "\n" + - "

Tags

\n" + - "\n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - "
Username/UIDView NameServer Name{{ tag }}\n" + - " {{ value }}
\n" + "\n" + "
\n" + + "\n" + "
\n" + + "
\n" + + "
\n" + + "
\n" + ); + + + $templateCache.put('components/views/integrations/bitbucket-integration-config-view/bitbucket-integration-config-view.html', + "\n" + "\n" + + "
\n" + + "
\n" + + "
\n" + "\n" + - "
\n" + - "
\n" + - "
\n" + - "

Report history

\n" + + "

Bitbucket Integration

\n" + "\n" + - "
\n" + - "
\n" + - " \n" + - " \n" + - "
\n" + - "
\n" + + "
\n" + + "
\n" + "\n" + - "
\n" + - "
\n" + - " \n" + - " \n" + - " Prev. detail\n" + + " \n" + "\n" + + "
\n" + + "\n" + + " \n" + + " \n" + + "\n" + + "
\n" + + "
https://bitbucket.org/
\n" + + " \n" + + "
/
\n" + + " \n" + "
\n" + - "
\n" + - " \n" + - " \n" + - " {{$ctrl.report.start_time.replace('T', ' ')}} UTC\n" + - " ID: {{$ctrl.report.request_id}}\n" + - " \n" + - "
\n" + - "
\n" + - " \n" + - " Next detail \n" + - "
\n" + + "\n" + "
\n" + + "
\n" + + "
\n" + "\n" + - "

{{$ctrl.report.error}}

\n" + + " \n" + "\n" + - "
\n" + + "
\n" + + " \n" + + " \n" + + " Remove Integration\n" + + "
    \n" + + "
  • No
  • \n" + + "
  • Yes
  • \n" + + "
\n" + + "
\n" + + "
\n" + + "
\n" + + " \n" + "\n" + - "

Traceback

\n" + + "

Remember you first need to\n" + + " \n" + + " authorize your user account\n" + + " with Bitbucket before we can send issues on your behalf.

\n" + "\n" + - " \n" + + "
\n" + + "
\n" + ); + + + $templateCache.put('components/views/integrations/campfire-integration-config-view/campfire-integration-config-view.html', + "\n" + "\n" + - "
\n" + - "
{{$ctrl.rawTraceback}}
\n" + - "
\n" + - "
\n" + + "
\n" + + "
\n" + + "
\n" + + "

Campfire Integration

\n" + "\n" + - "
= $ctrl.traceback.length-10 || $ctrl.traceback.length <= 10 || $ctrl.showLong\">\n" + - "
\n" + - " \n" + - " \n" + - " \n" + + "
\n" + "\n" + - " \n" + + "
\n" + "\n" + - " \n" + - " File {{frame.file || 'Unknown file'}},\n" + - " \n" + - " \n" + - " Module {{frame.module || 'Unknown module'}},\n" + - " \n" + - " line {{frame.line || 'Unknown line'}}\n" + + " \n" + + "
\n" + + " \n" + "\n" + - " in {{frame.fn || 'Unknown function'}}\n" + + "
\n" + + "
http://
\n" + + " \n" + + "
.campfirenow.com
\n" + + "
\n" + + "
\n" + + "
\n" + "\n" + - "
\n" + - "
{{frame.cline || 'Unknown context'}}
\n" + - "\n" + - "
\n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - "
{{ fvar[0] }}\n" + - " \n" + - "
\n" + + "
\n" + + " \n" + + "
\n" + + " \n" + + " \n" + + "
\n" + + "
\n" + "\n" + - "
\n" + - "
\n" + - "
\n" + + "
\n" + + " \n" + + "
\n" + + " \n" + + " \n" + + "

\n" + + " Room ID list separated by comma\n" + + "

\n" + + "
\n" + + "
\n" + + "
\n" + + " \n" + "\n" + + " \n" + + " Remove Integration\n" + + "
    \n" + + "
  • No
  • \n" + + "
  • Yes
  • \n" + + "
\n" + + "
\n" + "\n" + + "
\n" + + " \n" + + " \n" + "
\n" + "\n" + + "
\n" + "\n" + - " \n" + - " \n" + - " \n" + - " Slow Calls\n" + - " \n" + + " \n" + "\n" + - "

Slow Calls

\n" + + "
\n" + + "
\n" + ); + + + $templateCache.put('components/views/integrations/flowdock-integration-config-view/flowdock-integration-config-view.html', + "\n" + "\n" + - "
0\">\n" + - "
\n" + - "
\n" + + "
\n" + + "
\n" + + "
\n" + "\n" + - "
\n" + - " No slow calls reported\n" + - "
\n" + + "

Flowdock Integration

\n" + "\n" + - " \n" + + "
\n" + "\n" + + "
\n" + "\n" + - " \n" + - " \n" + - " Request details\n" + - " \n" + + " \n" + "\n" + - "

Extra

\n" + - "
\n" + - "

Request details

\n" + - "
\n" + + "
\n" + + " \n" + + " \n" + + "
\n" + "\n" + - "
\n" + "\n" + - " \n" + - " \n" + - " Logs\n" + - " \n" + + "
\n" + "\n" + - "
\n" + - " \n" + - "
\n" + - "

No logs found

\n" + + "
\n" + "\n" + - " 0\">\n" + + " \n" + "\n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + + "
\n" + "\n" + - "
\n" + - "
Logs
MessageWhen
\n" + - " \n" + - " level: {{log.log_level}}\n" + - " \n" + - " namespace: {{log.namespace}}\n" + - " \n" + - " {{tag}}: {{value}}\n" + - "
\n" + - " {{log.message}}\n" + - "
\n" + - "
\n" + - " \n" + - " \n" + - " \n" + - "
\n" + + " \n" + "\n" + - " \n" + + " \n" + + " Remove Integration\n" + + "
    \n" + + "
  • No
  • \n" + + "
  • Yes
  • \n" + + "
\n" + + "
\n" + + "
\n" + + " \n" + + " \n" + + "
\n" + + "
\n" + + "
\n" + "\n" + "\n" + - " \n" + - " \n" + - " Comments\n" + - " {{$ctrl.report.comments.length}}\n" + + " \n" + "\n" + - " \n" + + "
\n" + + "
\n" + ); + + + $templateCache.put('components/views/integrations/github-integration-config-view/github-integration-config-view.html', + "\n" + "\n" + - "

Comments

\n" + + "
\n" + + "
\n" + + "
\n" + "\n" + - "

No comments yet - be first to add one!

\n" + + "

Github Integration

\n" + "\n" + - "
\n" + - "

\n" + - " {{comment.user_name}}\n" + - " \n" + - "

\n" + - "

{{comment.body}}

\n" + - "
\n" + + "
\n" + "\n" + - " \n" + - "
\n" + - " \n" + "\n" + - "
\n" + - "
\n" + - " \n" + - "
\n" + - "
\n" + + "
\n" + "\n" + - "
\n" + - "
\n" + + " \n" + "\n" + - " \n" + + "
\n" + "\n" + - " \n" + - " \n" + - " Affected users\n" + - " {{$ctrl.report.affected_users_count}}\n" + + " \n" + + " \n" + "\n" + - " \n" + + "
\n" + + "
https://api.github.com/
\n" + + " \n" + + "
/
\n" + + " \n" + + "
\n" + "\n" + - "

50 most affected users ID's by this issue:

\n" + - "
    \n" + - "
  • \n" + - " {{user.username}} {{user.count}}\n" + - "
  • \n" + - "
\n" + + "
\n" + + "
\n" + "\n" + - " \n" + + "
\n" + "\n" + - " \n" + + " \n" + + "\n" + + " \n" + "\n" + + " \n" + + " Remove Integration\n" + + "
    \n" + + "
  • No
  • \n" + + "
  • Yes
  • \n" + + "
\n" + + "
\n" + "\n" + "
\n" + + " \n" + + "\n" + + "

Remember you first need to\n" + + " \n" + + " authorize your user account\n" + + " with Github before we can send issues on your behalf.

\n" + + "\n" + + "

Every user will have to authorize AppEnlight to access Github to be able to post issues.

\n" + "\n" + + "
\n" + + "
Private repository access
\n" + + "
\n" + + "

If you need access to private repositories profile page allows you to require token including private repository permissions.

\n" + + "\n" + + "

Registration page OAuth does NOT give you token with private repository access permissions.

\n" + + "
\n" + "
\n" + + "\n" + "
\n" + "
\n" ); - $templateCache.put('components/views/reports-browser-view/reports-browser-view.html', - "\n" + + $templateCache.put('components/views/integrations/hipchat-integration-config-view/hipchat-integration-config-view.html', + "\n" + "\n" + - "
\n" + + "
\n" + + "
\n" + + "
\n" + "\n" + - "

\n" + - " Search params:\n" + - " \n" + - " {{tag.type}}\n" + - " {{ tag.type == 'resource' ? $ctrl.applications[tag.value].resource_name : tag.value }}\n" + + "

Hipchat Integration

\n" + "\n" + - " \n" + - " \n" + - "

\n" + + "
\n" + "\n" + - " \n" + - "
\n" + - " \n" + - "
\n" + - "
\n" + + "
\n" + + " \n" + "\n" + + "
\n" + + " \n" + + " \n" + + "
\n" + + "
\n" + "\n" + - "
\n" + - " \n" + - "
\n" + + "
\n" + "\n" + - "

\n" + + " \n" + "\n" + + "
\n" + + " \n" + + " \n" + "\n" + - "
\n" + - " \n" + - "
\n" + + "

\n" + + " Room ID list separated by comma\n" + + "

\n" + + "
\n" + "\n" + - "
\n" + - " \n" + + "
\n" + "\n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + + "
\n" + + " \n" + + "
\n" + + " \n" + + " \n" + + " Remove Integration\n" + + "
    \n" + + "
  • No
  • \n" + + "
  • Yes
  • \n" + + "
\n" + + "
\n" + "\n" + - "
\n" + - "
Reports
#ApplicationWhen Error
\n" + - " {{report.group.priority}}\n" + - " \n" + - " {{report.group.occurences|numberToThousands}}\n" + - " \n" + - " \n" + - "
{{report.resource_name}}
\n" + - " @{{report.tags.server_name}}
\n" + - " \n" + - " \n" + - " {{report.group.last_timestamp.replace('T', ' ').slice(0,16)}}\n" + - " {{report.error || 'Unknown Exception'}}
\n" + - " {{ report.tags.view_name || report.url_path}}
\n" + - "
\n" + + "
\n" + + " \n" + + " \n" + + "
\n" + "\n" + + "
\n" + + "
\n" + "\n" + - "
\n" + - " \n" + - "
\n" + + " \n" + "\n" + + "
\n" + "
\n" ); - $templateCache.put('components/views/reports-slow-browser-view/reports-slow-browser-view.html', - "\n" + + $templateCache.put('components/views/integrations/jira-integration-config-view/jira-integration-config-view.html', + "\n" + "\n" + - "
\n" + + "
\n" + + "
\n" + + "
\n" + "\n" + - "

\n" + - " Search params:\n" + - " \n" + - " {{tag.type}}\n" + - " {{ tag.type == 'resource' ? $ctrl.applications[tag.value].resource_name : tag.value }}\n" + + "

Jira Integration

\n" + "\n" + - " \n" + - " \n" + - "

\n" + + "
\n" + "\n" + - "

\n" + + "

\n" + "\n" + - " \n" + - "
\n" + - " \n" + - "
\n" + - " \n" + + " \n" + + "
\n" + + " \n" + + " \n" + "\n" + + "

\n" + + " https://servername.atlassian.net\n" + + "

\n" + "\n" + - "
\n" + - " \n" + - "
\n" + + "
\n" + + "
\n" + + "
\n" + "\n" + - "

\n" + + " \n" + + "
\n" + "\n" + + " \n" + + " \n" + "\n" + - "
\n" + - " \n" + - "
\n" + + "

\n" + + " user@email.com\n" + + "

\n" + "\n" + + "
\n" + + "
\n" + + "
\n" + "\n" + - "
\n" + - " \n" + + " \n" + + "
\n" + + " \n" + + " \n" + + "
\n" + + "
\n" + + "
\n" + "\n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + + " \n" + + "
\n" + + " \n" + + " \n" + + "
\n" + + " \n" + + "
\n" + + " \n" + + "
\n" + + " \n" + "\n" + - "
\n" + - "
Slow Request Reports
#Avg. durationApplicationWhen Location
\n" + - " {{report.group.priority}}\n" + - " \n" + - " {{report.group.occurences|numberToThousands}}\n" + - " \n" + - " {{report.group.average_duration.toFixed(3)}}s\n" + - "
{{report.resource_name}}
\n" + - " @{{report.tags.server_name}}
\n" + - " \n" + - " \n" + - " {{report.group.last_timestamp.replace('T', ' ').slice(0,16)}}\n" + - " \n" + - " {{ report.tags.view_name || report.url_path}}
\n" + + " \n" + + " Remove Integration\n" + + "
    \n" + + "
  • No
  • \n" + + "
  • Yes
  • \n" + + "
\n" + + "
\n" + + "
\n" + + "
\n" + "\n" + - "
\n" + + " \n" + "\n" + - "
\n" + - " \n" + - "
\n" + "\n" + + "
\n" + "
\n" ); - $templateCache.put('components/views/settings-view/settings-view.html', - "
\n" + - "
\n" + - "
\n" + - "
Applications
\n" + - " \n" + - "
\n" + - "\n" + + $templateCache.put('components/views/integrations/slack-integration-config-view/slack-integration-config-view.html', + "\n" + "\n" + - "
\n" + - "
Settings
\n" + - " \n" + - "
\n" + + "
\n" + + "
\n" + + "
\n" + "\n" + - "
\n" + - "
Notifications
\n" + - " \n" + - "
\n" + - "
\n" + + "

Slack Integration

\n" + "\n" + - "
\n" + - "
\n" - ); - - - $templateCache.put('components/views/user-alert-channel-email-new-view/user-alert-channel-email-new-view.html', - "\n" + + "
\n" + "\n" + - "
\n" + + "
\n" + "\n" + - "
\n" + - "
\n" + - "
\n" + - "

Adding email alert channel - after you authorize your email in the system we can send alerts directly to this mailbox.

\n" + - " \n" + - "
\n" + - " \n" + - " \n" + - "
\n" + - " \n" + - "
\n" + + " \n" + + "
\n" + + " \n" + + " \n" + "
\n" + - "
\n" + - " \n" + - "
\n" + - " \n" + + "
\n" + + "\n" + + "
\n" + + "\n" + + " \n" + + "
\n" + + " \n" + + "\n" + + " \n" + + " Remove Integration\n" + + "
    \n" + + "
  • No
  • \n" + + "
  • Yes
  • \n" + + "
\n" + + "
\n" + + "\n" + + "
\n" + + " \n" + + " \n" + "
\n" + "
\n" + - " \n" + - "
\n" + + "
\n" + + " \n" + + "\n" + "
\n" + "
\n" ); - $templateCache.put('components/views/user-alert-channels-list-view/user-alert-channels-list-view.html', - "\n" + - "\n" + - "
\n" + - "\n" + - "
\n" + - "
\n" + - "
\n" + - "

Report alert rules

\n" + - "

\n" + - " Add top-level rule\n" + - "

\n" + + $templateCache.put('components/views/integrations/webhooks-integration-config-view/webhooks-integration-config-view.html', + "\n" + "\n" + - " \n" + + "
\n" + + "
\n" + + "
\n" + "\n" + - "
\n" + - "
\n" + + "

Webhooks Integration

\n" + "\n" + - "
\n" + - "
\n" + - "

Alert channels

\n" + + "
\n" + + "
\n" + "\n" + - "

Here you can configure your alert channels.

\n" + + " \n" + + "
\n" + + " \n" + + " \n" + + "
\n" + + "
\n" + + "
\n" + "\n" + - "

An alert channel serves as means of delivery of notifications about important events that happen in your applications.

\n" + + " \n" + + "
\n" + + " \n" + + " \n" + + "
\n" + "\n" + - "
You can add more integrations that support different alert channels via application management panel.
\n" + "\n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - "
{{ channel.channel_visible_value }}\n" + - " \n" + - " \n" + - " \n" + - " \n" + - " Alerts\n" + - " \n" + - " \n" + - " Daily digests\n" + - " \n" + + " \n" + + "
\n" + "\n" + + " \n" + + "
\n" + + " \n" + " \n" + - " Remove\n" + + " Remove Integration\n" + "
    \n" + "
  • No
  • \n" + - "
  • Yes
  • \n" + + "
  • Yes
  • \n" + "
\n" + "
\n" + - "\n" + - "
\n" + - "\n" + - "
\n" + + "
\n" + + "
\n" + + " \n" + "
\n" + - "\n" + "
\n" ); - $templateCache.put('components/views/user-auth-tokens-view/user-auth-tokens-view.html', - "\n" + + $templateCache.put('components/views/logs-browser/logs-browser.html', + "\n" + "\n" + - "
\n" + + "
\n" + "\n" + - "
\n" + - "
\n" + + "

\n" + + " Search params:\n" + + " \n" + + " {{tag.type}}\n" + + " {{ tag.type == 'resource' ? $ctrl.applications[tag.value].resource_name : tag.value }}\n" + "\n" + - "

\n" + + " \n" + + " \n" + + "

\n" + "\n" + - "
You can use those tokens to authenticate yourself when performing various API calls
\n" + + "

\n" + "\n" + - "


\n" + + " \n" + "\n" + + "
\n" + + "
\n" + + " \n" + "
\n" + + "
\n" + + "\n" + + "
\n" + + " \n" + + "
\n" + + "\n" + + "

\n" + "\n" + + "
\n" + "\n" + + "
\n" + + " \n" + + " \n" + + "
\n" + "
\n" + "\n" + - "
\n" + - " \n" + - " \n" + + "\n" + + "
\n" + + " \n" + + "
\n" + + "\n" + + "
\n" + + "\n" + + "
Your current tokens
\n" + + " \n" + " \n" + " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + + " \n" + + " \n" + + " \n" + " \n" + " \n" + " \n" + - "\n" + - " \n" + - " \n" + + " \n" + - " \n" + - " \n" + - " \n" + + " \n" + " \n" + + "\n" + " \n" + "
Logs
DescriptionCreatedExpires
ApplicationMessageWhen

{{token.description}}

\n" + - "
{{token.token| limitTo:token.limit}}...
\n" + + "
\n" + + " \n" + + " {{log.resource_name}}\n" + " {{token.creation_date | isoToRelativeTime}}{{token.expires | isoToRelativeTime}}\n" + - " Never\n" + - " \n" + - " \n" + - "
    \n" + - "
  • No
  • \n" + - "
  • Yes
  • \n" + - "
\n" + - "
\n" + + "
\n" + + " \n" + + " level: {{log.log_level}}\n" + + " \n" + + " namespace: {{log.namespace}}\n" + + " \n" + + " {{tag}}: {{value}}\n" + + "
{{log.message}}
\n" + + "
\n" + + " \n" + + " \n" + + " \n" + "
\n" + + "\n" + + "
\n" + + "\n" + + "
\n" + + " \n" + "
\n" + "\n" + "
\n" ); - $templateCache.put('components/views/user-identities-view/user-identities-view.html', - "\n" + + $templateCache.put('components/views/report-view/report-view.html', + "\n" + "\n" + - "
\n" + - "
\n" + - "
\n" + + "\n" + "\n" + - "
\n" + - "
\n" + - "
\n" + - "
\n" + - "
\n" + - "
\n" + - " \n" + - " \n" + - "
\n" + - " \n" + - "
\n" + - "
\n" + + "\n" + "\n" + - "
\n" + - " \n" + - " \n" + - "
\n" + - " \n" + - "
\n" + - "
\n" + - "
\n" + - " \n" + - " \n" + - "
\n" + - " \n" + - "
\n" + - "
\n" + - "
\n" + - " \n" + - " \n" + - "
\n" + - " \n" + - "
\n" + - "
\n" + - "
\n" + - " \n" + - " \n" + - "
\n" + - " \n" + - "
\n" + - "
\n" + - "
\n" + - " \n" + - " \n" + - "
\n" + - " \n" + - "
\n" + - "
\n" + - "
\n" + - " \n" + - " \n" + - "
\n" + - " \n" + - "
\n" + - "
\n" + - "
\n" + - " \n" + - " \n" + - "
\n" + - " \n" + - "
\n" + - "
\n" + - "
\n" + - " \n" + - "
\n" + - " \n" + - "
\n" + - "
\n" + - "
\n" + - "
\n" + - "
\n" + - "
\n" - ); - - - $templateCache.put('directives/permissions/permissions.html', - "
\n" + - "
\n" + - "

Permissions

\n" + - "
\n" + - "
\n" + - "

Here you can set permissions for others to access your app data.

\n" + - "\n" + - "

For example you can let other staff member view or alter error reports.

\n" + + "
\n" + + " OOPS something went wrong :(\n" + + "
\n" + "\n" + - "
0\">\n" + - "

Group permissions

\n" + + "
\n" + "\n" + - "
    \n" + - "
  • \n" + - " {{ perm.self.group_name }}\n" + - "
    \n" + - " Resource owner\n" + - " \n" + - " {{ perm_name }}\n" + - "
      \n" + - "
    • No
    • \n" + - "
    • Yes
    • \n" + - "
    \n" + - "
    \n" + - "
    \n" + - "
  • \n" + - "
\n" + + "
\n" + + "
\n" + + " 2\">\n" + + " Go back\n" + + " Assign report\n" + + " to user\n" + "\n" + - "
\n" + - "
\n" + - " \n" + - "
\n" + - "
\n" + - " \n" + - " {{ permission }}\n" + - " \n" + - "
\n" + - "
\n" + - " \n" + - "
\n" + - "
\n" + + " \n" + + " Mark fixed\n" + "\n" + - "
\n" + + " \n" + + " \n" + + " Integrations\n" + + " \n" + + " \n" + + " \n" + "\n" + - "

User permissions

\n" + - "
\n" + - "
    \n" + - "
  • \n" + - " {{ perm.self.user_name }}\n" + - "
    \n" + - " Resource owner\n" + - " \n" + - " {{ perm_name }}\n" + - "
      \n" + - "
    • No
    • \n" + - "
    • Yes
    • \n" + - "
    \n" + - "
    \n" + - "
    \n" + - "
  • \n" + - "
\n" + - "
\n" + - "
\n" + - "

First enter username or full email of person you want to give access to (the person needs to be already registered in AppEnlight)

\n" + + " Make {{$ctrl.group.public ? 'private' : 'public'}}\n" + "\n" + - "
\n" + - "
\n" + - " \n" + - "
\n" + - "
\n" + - " \n" + - " {{ permission }}\n" + - " \n" + - "
\n" + - "
\n" + - " \n" + - "
\n" + - "
\n" + - "
\n" + + "\n" + + " Delete\n" + + "
    \n" + + "
  • No
  • \n" + + "
  • Yes
  • \n" + + "
\n" + + "
\n" + + "
\n" + "
\n" + - "
\n" - ); - - - $templateCache.put('directives/plugin_config/plugin_config.html', - "
\n" + - "
Plugin: {{tmpl.name}}
\n" + - " \n" + - "
\n" + - "
\n" - ); - - - $templateCache.put('directives/postprocess_action/postprocess_action.html', - "
\n" + - "
\n" + - "
\n" + - " \n" + - " \n" + - "
    \n" + - "
  • No
  • \n" + - "
  • Yes
  • \n" + - "
\n" + - "
\n" + - "
\n" + "\n" + - "
\n" + - " \n" + - "\n" + - "
\n" + - " \n" + - "
\n" + - "\n" + - "  Save changes\n" + - "\n" + - "
\n" + - "
\n" + - "

Meeting following criteria:

\n" + - " \n" + - " {{ctrl.rule}}\n" + - " \n" + - "
\n" + - "
\n" - ); - - - $templateCache.put('directives/report_alert_action/report_alert_action.html', - "
\n" + - "
\n" + - "
\n" + - " \n" + - " \n" + - "
    \n" + - "
  • No
  • \n" + - "
  • Yes
  • \n" + - "
\n" + - "
\n" + - "
\n" + + "
\n" + + "
\n" + "\n" + - "
\n" + - " \n" + - " \n" + - "
\n" + - "
\n" + - " \n" + - " \n" + + "
\n" + + "
\n" + "\n" + - "  Save changes\n" + + "

Report Information

\n" + "\n" + - "
\n" + - "
\n" + - "

Channels:

\n" + - "
    \n" + - "
  • \n" + - " {{channel.channel_visible_value}}\n" + - "
    \n" + - " \n" + - " \n" + - "
      \n" + - "
    • No
    • \n" + - "
    • Yes
    • \n" + - "
    \n" + - "
    \n" + - "
    \n" + - "
  • \n" + - "
\n" + - "
\n" + - " \n" + - " Add Channel\n" + - "
\n" + - "
\n" + - " You need to create an alert channel before you can assign it to your rule.\n" + - "
\n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + "\n" + - " \n" + - "
\n" + - "

Meeting following criteria:

\n" + - " \n" + - " \n" + - " \n" + - "\n" - ); - - - $templateCache.put('directives/rule_read_only/rule_read_only.html', - "
\n" + + "
\n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " 0\">\n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + "
Occurences{{$ctrl.report.group.occurences}}
HTTP status{{$ctrl.report.http_status}}
Priority{{$ctrl.report.group.priority}}
Public URL\n" + + "
\n" + + " \n" + + "
\n" + + "
URL{{$ctrl.report.url}}
Remote IP{{$ctrl.report.ip}}
User Agent{{$ctrl.report.user_agent}}
Message{{$ctrl.report.message}}
Duration\n" + + " {{$ctrl.report.duration}}s\n" + + "
First occured\n" + + " \n" + + "
Last occured\n" + + " \n" + + "
\n" + "\n" + - " \n" + - " {{rule_ctrlr.readOnlyPossibleFields[rule_ctrlr.rule.field]}}\n" + - " \n" + + "
\n" + + "

Performance stats

\n" + "\n" + - " \n" + - " is {{rule_ctrlr.ruleDefinitions.allOps[rule_ctrlr.rule.op]}} {{rule_ctrlr.rule.value}}\n" + - " \n" + + "
\n" + + " 0 || stat.value > 0\">\n" + + " {{stat.calls}}\n" + + " {{stat.name}} calls\n" + + " \n" + + " Other\n" + + " \n" + + " \n" + "\n" + - " \n" + - "

Subrules

\n" + - "
\n" + + "
\n" + + "
\n" + + "
\n" + + "
\n" + + " 0s\n" + + "
\n" + + "
\n" + + " {{$ctrl.report.duration.toFixed(3)}}s\n" + + "
\n" + + "
\n" + + "
\n" + + "
\n" + + "
\n" + + "\n" + + "

Tags

\n" + + "\n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + "
Username/UIDView NameServer Name{{ tag }}\n" + + " {{ value }}
\n" + "\n" + - "
\n" + - "
\n" + - " \n" + - " \n" + - " \n" + "
\n" + "
\n" + - "
\n" + "\n" + - " \n" + - "
\n" - ); - - - $templateCache.put('directives/rule/rule.html', - "
\n" + "\n" + - "
\n" + - " \n" + - "
\n" + + "
\n" + + "
\n" + + "
\n" + + "

Report history

\n" + "\n" + - "
\n" + + "
\n" + + "
\n" + + " \n" + + " \n" + + "
\n" + + "
\n" + "\n" + - " \n" + + "
\n" + + "
\n" + + " \n" + + " \n" + + " Prev. detail\n" + "\n" + - " \n" + + "
\n" + + "
\n" + + " \n" + + " \n" + + " {{$ctrl.report.start_time.replace('T', ' ')}} UTC\n" + + " ID: {{$ctrl.report.request_id}}\n" + + " \n" + + "
\n" + + "
\n" + + " \n" + + " Next detail \n" + + "
\n" + + "
\n" + "\n" + - "
\n" + + "

{{$ctrl.report.error}}

\n" + "\n" + - " \n" + - "

Subrules

\n" + - "
\n" + - "
\n" + - "
\n" + - " \n" + - " \n" + - " \n" + - "
\n" + - "
\n" + - "
\n" + + "
\n" + "\n" + - " Add rule\n" + + "

Traceback

\n" + "\n" + - " \n" + - "
\n" + - " \n" + - " \n" + - "
    \n" + - "
  • No
  • \n" + - "
  • Yes
  • \n" + - "
\n" + - "
\n" + - "
\n" + - "
\n" - ); - - - $templateCache.put('templates/admin/applications/applications_list.html', - "\n" + + "
\n" + + " 0 \" ng-click=\"$ctrl.showLong = !$ctrl.showLong\"\n" + + " class=\"btn btn-default {{$ctrl.showLong ? 'active' : ''}}\">\n" + + " \n" + + " Show {{$ctrl.traceback.length-10}} remaining frames\n" + + " \n" + "\n" + - "
\n" + - " \n" + "\n" + - " Currently active applications: {{applications.applications.length}}\n" + + "
\n" + + "
{{$ctrl.rawTraceback}}
\n" + + "
\n" + + "
\n" + "\n" + - "
\n" + + "
= $ctrl.traceback.length-10 || $ctrl.traceback.length <= 10 || $ctrl.showLong\">\n" + + "
\n" + + " \n" + + " \n" + + " \n" + "\n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - "\n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - "
Application nameOwner UserOwner Group
{{resource.resource_name}}{{resource.owner_user_name}}{{resource.owner_group_name}}\n" + - " \n" + - "
\n" + - "
\n" + - "
\n" + + " \n" + "\n" + - "
\n" - ); - - - $templateCache.put('templates/admin/configs/edit.html', - "\n" + + " \n" + + " File {{frame.file || 'Unknown file'}},\n" + + " \n" + + " \n" + + " Module {{frame.module || 'Unknown module'}},\n" + + " \n" + + " line {{frame.line || 'Unknown line'}}\n" + "\n" + - "
\n" + - "
\n" + - "

Basic Configuration

\n" + - "
\n" + - "
\n" + - "

Visual

\n" + - "
\n" + - "
\n" + - " \n" + - "
\n" + - " \n" + - "
\n" + - "
\n" + - "
\n" + + " in {{frame.fn || 'Unknown function'}}\n" + "\n" + - "

Functional

\n" + + "
\n" + + "
{{frame.cline || 'Unknown context'}}
\n" + "\n" + - "
\n" + - "
\n" + - " \n" + - "
\n" + - " \n" + - "
\n" + - "
\n" + - "
\n" + + "
\n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + "
{{ fvar[0] }}\n" + + " \n" + + "
\n" + "\n" + - "

Global Rate Limiting

\n" + + "
\n" + + "
\n" + + "
\n" + "\n" + - "
\n" + - "
\n" + - " \n" + - "
\n" + - " \n" + - "
\n" + - "
\n" + "\n" + - "
\n" + - " \n" + - "
\n" + - " \n" + "
\n" + - "
\n" + "\n" + - "
\n" + - " \n" + - "
\n" + - " \n" + - "
\n" + - "
\n" + "\n" + - "
\n" + + " \n" + + " \n" + + " \n" + + " Slow Calls\n" + + " \n" + "\n" + - "
\n" + + "

Slow Calls

\n" + "\n" + - " Save configuration\n" + - "
\n" + + "
0\">\n" + + "
\n" + + "
\n" + "\n" + - "
\n" + + "
\n" + + " No slow calls reported\n" + + "
\n" + "\n" + + " \n" + "\n" + - "
\n" + - "
\n" + - "

Plugin Configuration

\n" + - "
\n" + - "
\n" + - " \n" + - " \n" + - "
\n" + - "
\n" - ); - - - $templateCache.put('templates/admin/configs/parent_view.html', - "
" - ); - - - $templateCache.put('templates/admin/groups/groups_create.html', - "\n" + "\n" + - "
\n" + + " \n" + + " \n" + + " Request details\n" + + " \n" + "\n" + - "
\n" + - "
\n" + - "
\n" + - "
\n" + - " \n" + - " \n" + - "
\n" + - " \n" + - "
\n" + - "
\n" + + "

Extra

\n" + + "
\n" + + "

Request details

\n" + + "
\n" + "\n" + - "
\n" + - " \n" + - " \n" + - "
\n" + - " \n" + - "
\n" + - "
\n" + + " \n" + "\n" + + " \n" + + " \n" + + " Logs\n" + + " \n" + "\n" + - "
\n" + - " \n" + - "
\n" + - " \n" + - "
\n" + - "
\n" + - " \n" + - "
\n" + - "
\n" + + "
\n" + + " \n" + + "
\n" + + "

No logs found

\n" + "\n" + + " 0\">\n" + "\n" + - "
\n" + - "
\n" + - "

Permissions summary

\n" + - "
\n" + - "
\n" + - "

Direct application permissions

\n" + + "
\n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + "\n" + - "
    \n" + - "
  • \n" + - " {{ perm.self.resource_name }}\n" + + "
\n" + + "
Logs
MessageWhen
\n" + + " \n" + + " level: {{log.log_level}}\n" + + " \n" + + " namespace: {{log.namespace}}\n" + + " \n" + + " {{tag}}: {{value}}\n" + + "
\n" + + " {{log.message}}\n" + + "
\n" + + "
\n" + + " \n" + + " \n" + + " \n" + + "
\n" + "\n" + - "
\n" + + " \n" + "\n" + - " {{ perm.self.owner ? 'Resource owner' : perm_name }}\n" + "\n" + - " \n" + - " \n" + - " \n" + - "
\n" + - " \n" + - " \n" + + " \n" + + " \n" + + " Comments\n" + + " {{$ctrl.report.comments.length}}\n" + "\n" + - "

Direct dashboard permissions

\n" + + "
\n" + "\n" + - "
    \n" + - "
  • \n" + - " {{ perm.self.resource_name }}\n" + + "

    Comments

    \n" + "\n" + - "
    \n" + - " {{ perm.self.owner ? 'Resource owner' : perm_name }}\n" + + "

    No comments yet - be first to add one!

    \n" + "\n" + - " \n" + - " \n" + - " \n" + - "
    \n" + - "
  • \n" + - "
\n" + + "
\n" + + "

\n" + + " {{comment.user_name}}\n" + + " \n" + + "

\n" + + "

{{comment.body}}

\n" + + "
\n" + "\n" + - "
\n" + + "
\n" + + "
\n" + + " \n" + "\n" + - "
\n" + + "
\n" + + "
\n" + + " \n" + + "
\n" + + " \n" + + "\n" + + "
\n" + + "
\n" + "\n" + + " \n" + + "\n" + + " \n" + + " \n" + + " Affected users\n" + + " {{$ctrl.report.affected_users_count}}\n" + + "\n" + + " \n" + + "\n" + + "

50 most affected users ID's by this issue:

\n" + + "
    \n" + + "
  • \n" + + " {{user.username}} {{user.count}}\n" + + "
  • \n" + + "
\n" + + "\n" + + "
\n" + + "\n" + + " \n" + + "\n" + + "\n" + + "
\n" + "\n" + - "
\n" + - "
\n" + - "

User list

\n" + "
\n" + - "
\n" + + "
\n" + + "
\n" + ); + + + $templateCache.put('components/views/reports-browser-view/reports-browser-view.html', + "\n" + "\n" + - "
\n" + - "
\n" + - " \n" + - "
\n" + - "
\n" + - " \n" + - "
\n" + - "
\n" + + "
\n" + + "\n" + + "

\n" + + " Search params:\n" + + " \n" + + " {{tag.type}}\n" + + " {{ tag.type == 'resource' ? $ctrl.applications[tag.value].resource_name : tag.value }}\n" + + "\n" + + " \n" + + " \n" + + "

\n" + "\n" + + "
\n" + + "
\n" + + " \n" + "
\n" + + "
\n" + + "\n" + + "\n" + + "
\n" + + " \n" + + "
\n" + + "\n" + + "

\n" + + "\n" + + "\n" + + "
\n" + + " \n" + + "
\n" + + "\n" + + "
\n" + + " \n" + "\n" + - " \n" + + "
\n" + + " \n" + " \n" + " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + + " \n" + + " \n" + + " \n" + + " \n" + " \n" + " \n" + " \n" + - "\n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + + " \n" + + " \n" + + " \n" + + " \n" + " \n" + - " \n" + + "\n" + " \n" + "
Reports
UsernameEmailStatusFirst NameLast NameLast login
#ApplicationWhen Error
{{user.user_name}}{{user.email}}{{user.first_name}}{{user.last_name}}{{user.last_login_date | isoToRelativeTime}}\n" + - " \n" + - " \n" + - " \n" + - "
    \n" + - "
  • No
  • \n" + - "
  • Yes
  • \n" + - "
\n" + - "
\n" + - "
\n" + - "
\n" + + "
\n" + + " {{report.group.priority}}\n" + + " \n" + + " {{report.group.occurences|numberToThousands}}\n" + + " \n" + + " \n" + + "
{{report.resource_name}}
\n" + + " @{{report.tags.server_name}}
\n" + + " \n" + + " \n" + + " {{report.group.last_timestamp.replace('T', ' ').slice(0,16)}}\n" + " {{report.error || 'Unknown Exception'}}
\n" + + " {{ report.tags.view_name || report.url_path}}
\n" + - "\n" + "
\n" + "\n" + "\n" + + "
\n" + + " \n" + + "
\n" + + "\n" + "
\n" ); - $templateCache.put('templates/admin/groups/groups_list.html', - "\n" + - "\n" + - "
\n" + + $templateCache.put('components/views/reports-slow-browser-view/reports-slow-browser-view.html', + "\n" + "\n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + + "
\n" + "\n" + - "
\n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - "
Group nameDescriptionMember count
{{group.group_name}}{{group.description}}{{group.member_count}}\n" + - " \n" + - " \n" + - " \n" + - "
    \n" + - "
  • No
  • \n" + - "
  • Yes
  • \n" + - "
\n" + - "
\n" + - "
\n" + - "
\n" + - "
\n" + + "

\n" + + " Search params:\n" + + " \n" + + " {{tag.type}}\n" + + " {{ tag.type == 'resource' ? $ctrl.applications[tag.value].resource_name : tag.value }}\n" + "\n" + - "

\n" + - "\n" - ); - - - $templateCache.put('templates/admin/groups/parent_view.html', - "
" - ); - - - $templateCache.put('templates/admin/parent_view.html', - "
\n" + - "
\n" + - "
Users and groups
\n" + - " \n" + - "
\n" + - "
\n" + - "
Resources
\n" + - " \n" + - "
\n" + + " \n" + + " \n" + + "

\n" + "\n" + - "
\n" + - "
System
\n" + - " \n" + - "
\n" + - "
\n" + + "

\n" + "\n" + + "

\n" + + "
\n" + + " \n" + + "
\n" + + "
\n" + "\n" + - "
\n" - ); - - - $templateCache.put('templates/admin/partitions.html', - "\n" + "\n" + - "
\n" + + "
\n" + + " \n" + + "
\n" + "\n" + - "
\n" + - "
\n" + - " DELETE Daily Partitions\n" + - "
\n" + + "

\n" + "\n" + - "
\n" + "\n" + - "
\n" + + "
\n" + + " \n" + + "
\n" + "\n" + - " \n" + - " \n" + - " Check All\n" + "\n" + - "
\n" + + "
\n" + + " \n" + "\n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - "
DateIndices
{{row[0]}}\n" + - "
    \n" + - "
  • \n" + - " ES: {{partition.name}}\n" + - "
  • \n" + - "
  • \n" + - " PG: {{partition.name}}\n" + - "
  • \n" + - "
\n" + - "
\n" + - " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + "\n" + + " \n" + + "
Slow Request Reports
#Avg. durationApplicationWhen Location
\n" + + " {{report.group.priority}}\n" + + " \n" + + " {{report.group.occurences|numberToThousands}}\n" + + " \n" + + " {{report.group.average_duration.toFixed(3)}}s\n" + + "
{{report.resource_name}}
\n" + + " @{{report.tags.server_name}}
\n" + + " \n" + + " \n" + + " {{report.group.last_timestamp.replace('T', ' ').slice(0,16)}}\n" + + " \n" + + " {{ report.tags.view_name || report.url_path}}
\n" + "\n" + "
\n" + "\n" + - "
\n" + - "
\n" + - " DELETE Permanent Partitions\n" + + "
\n" + + " \n" + + "
\n" + + "\n" + + "
\n" + ); + + + $templateCache.put('components/views/settings-view/settings-view.html', + "
\n" + + "
\n" + + "
\n" + + "
Applications
\n" + + " \n" + "
\n" + "\n" + - "
\n" + "\n" + + "
\n" + + "
Settings
\n" + + " \n" + + "
\n" + "\n" + - "
\n" + + "
\n" + + "
Notifications
\n" + + " \n" + + "
\n" + + "
\n" + + "\n" + + "
\n" + + "
\n" + ); + + + $templateCache.put('components/views/user-alert-channel-email-new-view/user-alert-channel-email-new-view.html', + "\n" + + "\n" + + "
\n" + "\n" + + "
\n" + + "
\n" + + "
\n" + + "

Adding email alert channel - after you authorize your email in the system we can send alerts directly to this mailbox.

\n" + + " \n" + + "
\n" + + " \n" + + " \n" + + "
\n" + + " \n" + + "
\n" + + "
\n" + "
\n" + - " \n" + - " \n" + - " Check All\n" + + " \n" + + "
\n" + + " \n" + + "
\n" + "
\n" + + " \n" + + "
\n" + + "
\n" + + "
\n" + ); + + + $templateCache.put('components/views/user-alert-channels-list-view/user-alert-channels-list-view.html', + "\n" + "\n" + - "
\n" + + "
\n" + + "\n" + + "
\n" + + "
\n" + + "
\n" + + "

Report alert rules

\n" + + "

\n" + + " Add top-level rule\n" + + "

\n" + + "\n" + + " \n" + + "\n" + + "
\n" + + "
\n" + + "\n" + + "
\n" + + "
\n" + + "

Alert channels

\n" + + "\n" + + "

Here you can configure your alert channels.

\n" + + "\n" + + "

An alert channel serves as means of delivery of notifications about important events that happen in your applications.

\n" + + "\n" + + "
You can add more integrations that support different alert channels via application management panel.
\n" + "\n" + " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + + " \n" + + " \n" + " \n" + "
DateIndices
{{row[0]}}\n" + - "
    \n" + - "
  • \n" + - " ES: {{partition.name}}\n" + - "
  • \n" + - "
  • \n" + - " PG: {{partition.name}}\n" + - "
  • \n" + - "
\n" + + "
{{ channel.channel_visible_value }}\n" + + " \n" + + " \n" + + " \n" + + " \n" + + " Alerts\n" + + " \n" + + " \n" + + " Daily digests\n" + + " \n" + + "\n" + + " \n" + + " Remove\n" + + "
    \n" + + "
  • No
  • \n" + + "
  • Yes
  • \n" + + "
\n" + + "
\n" + + "\n" + "
\n" + - " \n" + "\n" + + "
\n" + "
\n" + "\n" + "
\n" ); - $templateCache.put('templates/admin/system.html', - "\n" + - "\n" + - "
\n" + - "
\n" + - "
\n" + - "
\n" + - "
\n" + - "

\n" + - " System Info\n" + - "

\n" + - "
\n" + - "
\n" + + $templateCache.put('components/views/user-auth-tokens-view/user-auth-tokens-view.html', + "\n" + "\n" + - "

System Load:\n" + - " 1min: {{system.systemLoad[0]}}, 5min: {{system.systemLoad[1]}}, 15min: {{system.systemLoad[2]}}\n" + - "

\n" + - "

Awaiting tasks:\n" + - "

    \n" + - "
  • reports: {{system.queueStats.waiting_reports}}
  • \n" + - "
  • logs: {{system.queueStats.waiting_logs}}
  • \n" + - "
  • metrics: {{system.queueStats.waiting_metrics}}
  • \n" + - "
  • other: {{system.queueStats.waiting_other}}
  • \n" + - "
\n" + - "

\n" + - "

Queue stats from last minute:\n" + - "

    \n" + - "
  • Processed reports: {{system.queueStats.processed_reports}}
  • \n" + - "
  • Processed logs: {{system.queueStats.processed_logs}}
  • \n" + - "
  • Processed metrics: {{system.queueStats.processed_metrics}}
  • \n" + - "
\n" + - "

\n" + + "
\n" + "\n" + - "

Disks:\n" + - "

    \n" + - "
  • \n" + - " {{disk.device}} {{disk.free}}/{{disk.total}}, {{disk.percentage}}% used\n" + - "
  • \n" + - "
\n" + - "

\n" + + "
\n" + + "
\n" + "\n" + - "

Process stats:\n" + - "

    \n" + - "
  • FD soft limits: {{system.selfInfo.fds.soft}}
  • \n" + - "
  • FD hard limits: {{system.selfInfo.fds.hard}}
  • \n" + - "
  • Memlock soft limits: {{system.selfInfo.memlock.soft}}
  • \n" + - "
  • Memlock hard limits: {{system.selfInfo.memlock.hard}}
  • \n" + - "
\n" + - "

\n" + + "
\n" + "\n" + - "
\n" + - "
\n" + - "
\n" + - "
\n" + - "
\n" + - "
\n" + + "
You can use those tokens to authenticate yourself when performing various API calls
\n" + "\n" + - "
\n" + - "
\n" + + "
\n" + "\n" + - " \n" + - " \n" + - " \n" + - " Postgresql Tables\n" + - " \n" + - "\n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - "
Table nameSize
{{row.table_name}}{{row.size_human}}
\n" + - "\n" + - "
\n" + - "\n" + - " \n" + - " \n" + - " Elasticsearch Indices\n" + - " \n" + + "
\n" + + " \n" + + " \n" + + "
\n" + + " \n" + + " \n" + + "
\n" + + "
\n" + + " \n" + + " \n" + + "
\n" + + "
\n" + + " \n" + + " \n" + + "
\n" + + "
\n" + "\n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - "
Index nameSize
{{row.name}}{{row.size_human}}
\n" + + "
\n" + "\n" + - " \n" + "\n" + - " \n" + - " \n" + - " Processes\n" + - " \n" + + "
\n" + "\n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - "
OwnerPIDCPUMEMName
{{row.owner}}{{row.pid}}{{row.cpu}}{{row.mem_usage}} ({{row.mem_percentage}}%){{row.name}}
{{row.command}}
\n" + + "
\n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + "\n" + - " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + "
Your current tokens
DescriptionCreatedExpires

{{token.description}}

\n" + + "
{{token.token| limitTo:token.limit}}...
\n" + + "
{{token.creation_date | isoToRelativeTime}}{{token.expires | isoToRelativeTime}}\n" + + " Never\n" + + " \n" + + " \n" + + "
    \n" + + "
  • No
  • \n" + + "
  • Yes
  • \n" + + "
\n" + + "
\n" + + "
\n" + + "
\n" + "\n" + - " \n" + - " \n" + - " Python packages\n" + - " \n" + + "
\n" + ); + + + $templateCache.put('components/views/user-identities-view/user-identities-view.html', + "\n" + "\n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - "
{{package.name}}{{package.version}}
\n" + - "

\n" + + "
\n" + "\n" + - " \n" + + "
\n" + + "
\n" + + "
\n" + "\n" + - " \n" + - "
\n" + + "
\n" + + "

No external providers linked yet

\n" + + "
    \n" + + "
  • \n" + + "
    \n" + + " \n" + + " \n" + + "
      \n" + + "
    • No
    • \n" + + "
    • Yes
    • \n" + + "
    \n" + + "
    \n" + + "
    \n" + + " @{{ provider.provider }}: {{ provider.id }}\n" + + "
  • \n" + + "
\n" + + "
\n" + + "
\n" + + " \n" + "
\n" + "
\n" + "
\n" + @@ -6631,240 +6424,442 @@ function kickstartAE(initialUserData) { ); - $templateCache.put('templates/admin/users/parent_view.html', - "
" - ); - - - $templateCache.put('templates/admin/users/users_create.html', - "\n" + + $templateCache.put('components/views/user-password-view/user-password-view.html', + "\n" + "\n" + - "
\n" + + "
\n" + "\n" + "
\n" + + "
\n" + "
\n" + "\n" + - " \n" + - " Re-login to user\n" + - "
    \n" + - "
  • No
  • \n" + - "
  • Yes
  • \n" + - "
\n" + - "
\n" + - "\n" + - "
\n" + - "
\n" + - " \n" + - "
\n" + + "
\n" + ); + + + $templateCache.put('components/views/user-profile-view/user-profile-view.html', + "\n" + "\n" + + "
\n" + + "
\n" + + "
\n" + + "
\n" + + "
\n" + "
\n" + - " \n" + + " \n" + " \n" + "
\n" + - " \n" + + " \n" + "
\n" + "
\n" + "\n" + "
\n" + - " \n" + + " \n" + " \n" + "
\n" + - " \n" + + " \n" + "
\n" + "
\n" + "
\n" + - " \n" + + " \n" + " \n" + "
\n" + - " \n" + + " \n" + "
\n" + "
\n" + - "\n" + - "
\n" + - " \n" + - "
\n" + "
\n" + + "
\n" + ); + + + $templateCache.put('directives/permissions/permissions.html', + "
\n" + + "
\n" + + "

Permissions

\n" + + "
\n" + + "
\n" + + "

Here you can set permissions for others to access your app data.

\n" + "\n" + + "

For example you can let other staff member view or alter error reports.

\n" + "\n" + - "
\n" + - "
\n" + - "

Permission Summary

\n" + - "
\n" + - "
\n" + - "

Direct application permissions

\n" + + "
0\">\n" + + "

Group permissions

\n" + "\n" + "
    \n" + - "
  • \n" + - " {{ perm.self.resource_name }}\n" + - "
    \n" + - "\n" + - " {{ perm.self.owner ? 'Resource owner' : perm_name }}\n" + - "\n" + - " \n" + - " \n" + - " \n" + + "
  • \n" + + " {{ perm.self.group_name }}\n" + + "
    \n" + + " Resource owner\n" + + " \n" + + " {{ perm_name }}\n" + + "
      \n" + + "
    • No
    • \n" + + "
    • Yes
    • \n" + + "
    \n" + + "
    \n" + "
    \n" + "
  • \n" + "
\n" + "\n" + - "

Direct dashboard permissions

\n" + - "\n" + - "
    \n" + - "
  • \n" + - " {{ perm.self.resource_name }}\n" + - "
    \n" + + "
    \n" + + "
    \n" + + " \n" + + "
    \n" + + "
    \n" + + " \n" + + " {{ permission }}\n" + + " \n" + + "
    \n" + + "
    \n" + + " \n" + + "
    \n" + + "
    \n" + "\n" + - " {{ perm.self.owner ? 'Resource owner' : perm_name }}\n" + + "
    \n" + "\n" + - " \n" + - " \n" + - " \n" + + "

    User permissions

    \n" + + "
    \n" + + "
      \n" + + "
    • \n" + + " {{ perm.self.user_name }}\n" + + "
      \n" + + " Resource owner\n" + + " \n" + + " {{ perm_name }}\n" + + "
        \n" + + "
      • No
      • \n" + + "
      • Yes
      • \n" + + "
      \n" + + "
      \n" + "
      \n" + "
    • \n" + "
    \n" + - "\n" + "
    \n" + + "
    \n" + + "

    First enter username or full email of person you want to give access to (the person needs to be already registered in AppEnlight)

    \n" + "\n" + + "
    \n" + + "
    \n" + + " \n" + + "
    \n" + + "
    \n" + + " \n" + + " {{ permission }}\n" + + " \n" + + "
    \n" + + "
    \n" + + " \n" + + "
    \n" + + "
    \n" + + "
    \n" + "
\n" + - "\n" + - "\n" + "
\n" ); - $templateCache.put('templates/admin/users/users_list.html', - "\n" + - "\n" + - "
\n" + - "\n" + - "
\n" + - "\n" + - "
\n" + - " {{users.activeUsers}} active out of {{users.users.length}} users\n" + + $templateCache.put('directives/plugin_config/plugin_config.html', + "
\n" + + "
Plugin: {{tmpl.name}}
\n" + + " \n" + + "
\n" + + "
\n" + ); + + + $templateCache.put('directives/postprocess_action/postprocess_action.html', + "
\n" + + "
\n" + + "
\n" + + " \n" + + " \n" + + "
    \n" + + "
  • No
  • \n" + + "
  • Yes
  • \n" + + "
\n" + + "
\n" + "
\n" + "\n" + + "
\n" + + " \n" + "\n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - "\n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - "
UsernameEmailStatusFirst NameLast NameLast login
{{user.user_name}}{{user.email}}{{user.first_name}}{{user.last_name}}{{user.last_login_date | isoToRelativeTime}}\n" + - " \n" + - " \n" + - " \n" + - "
    \n" + - "
  • No
  • \n" + - "
  • Yes
  • \n" + - "
\n" + - "
\n" + - "
\n" + - "
\n" + - "
\n" + + "
\n" + + " \n" + + "
\n" + "\n" + + "  Save changes\n" + "\n" + + "
\n" + + "
\n" + + "

Meeting following criteria:

\n" + + " \n" + + " {{ctrl.rule}}\n" + + " \n" + "
\n" + "
\n" ); - $templateCache.put('templates/directives/search_type_ahead.html', - "\n" + - " {{match.model.tag}}\n" + - " {{match.label}}\n" + - " - {{match.model.example}}\n" + - "
{{match.model.description}}
\n" + + $templateCache.put('directives/report_alert_action/report_alert_action.html', + "
\n" + + "
\n" + + "
\n" + + " \n" + + " \n" + + "
    \n" + + "
  • No
  • \n" + + "
  • Yes
  • \n" + + "
\n" + + " \n" + + "
\n" + "\n" + - "\n" - ); - - - $templateCache.put('templates/directives/user_search_type_ahead.html', - "\n" + - " {{match.label}} -\n" + - " {{match.model.name}}\n" + - "\n" - ); - + "
\n" + + " \n" + + " \n" + + "
\n" + + "
\n" + + " \n" + + " \n" + + "\n" + + "  Save changes\n" + + "\n" + + "
\n" + + "
\n" + + "

Channels:

\n" + + "
    \n" + + "
  • \n" + + " {{channel.channel_visible_value}}\n" + + "
    \n" + + " \n" + + " \n" + + "
      \n" + + "
    • No
    • \n" + + "
    • Yes
    • \n" + + "
    \n" + + "
    \n" + + "
    \n" + + "
  • \n" + + "
\n" + + "
\n" + + " \n" + + " Add Channel\n" + + "
\n" + + "
\n" + + " You need to create an alert channel before you can assign it to your rule.\n" + + "
\n" + + "\n" + + "
\n" + + "
\n" + + "

Meeting following criteria:

\n" + + " \n" + + " \n" + + "
\n" + + "
\n" + ); + + + $templateCache.put('directives/rule_read_only/rule_read_only.html', + "
\n" + + "\n" + + " \n" + + " {{rule_ctrlr.readOnlyPossibleFields[rule_ctrlr.rule.field]}}\n" + + " \n" + + "\n" + + " \n" + + " is {{rule_ctrlr.ruleDefinitions.allOps[rule_ctrlr.rule.op]}} {{rule_ctrlr.rule.value}}\n" + + " \n" + + "\n" + + " \n" + + "

Subrules

\n" + + "
\n" + + "\n" + + "
\n" + + "
\n" + + " \n" + + " \n" + + " \n" + + "
\n" + + "
\n" + + "
\n" + + "\n" + + "
\n" + + "
\n" + ); + + + $templateCache.put('directives/rule/rule.html', + "
\n" + + "\n" + + "
\n" + + " \n" + + "
\n" + + "\n" + + "
\n" + + "\n" + + " \n" + + "\n" + + " \n" + + "\n" + + "
\n" + + "\n" + + " \n" + + "

Subrules

\n" + + "
\n" + + "
\n" + + "
\n" + + " \n" + + " \n" + + " \n" + + "
\n" + + "
\n" + + "
\n" + + "\n" + + " Add rule\n" + + "\n" + + "
\n" + + "
\n" + + " \n" + + " \n" + + "
    \n" + + "
  • No
  • \n" + + "
  • Yes
  • \n" + + "
\n" + + "
\n" + + "
\n" + + "
\n" + ); + + + $templateCache.put('templates/directives/search_type_ahead.html', + "\n" + + " {{match.model.tag}}\n" + + " {{match.label}}\n" + + " - {{match.model.example}}\n" + + "
{{match.model.description}}
\n" + + "\n" + + "
\n" + ); + + + $templateCache.put('templates/directives/user_search_type_ahead.html', + "\n" + + " {{match.label}} -\n" + + " {{match.model.name}}\n" + + "\n" + ); + $templateCache.put('templates/integrations/bitbucket.html', "
\n" + @@ -7323,23 +7318,26 @@ function ChannelstreamController($rootScope, stateHolder, userSelfPropertyResour // # services, and proprietary license terms, please see // # https://rhodecode.com/licenses/ -angular.module('appenlight.components.integrationsListView', []) - .component('integrationsListView', { - templateUrl: 'components/views/applications-integrations-view/applications-integrations-view.html', - controller: IntegrationsListViewController +angular.module('appenlight.components.adminApplicationsListView', []) + .component('adminApplicationsListView', { + templateUrl: 'components/views/admin-applications-list-view/admin-applications-list-view.html', + controller: AdminApplicationsListController }); -IntegrationsListViewController.$inject = ['$state', 'applicationsResource']; +AdminApplicationsListController.$inject = ['applicationsResource']; -function IntegrationsListViewController($state, applicationsResource) { +function AdminApplicationsListController(applicationsResource) { var vm = this; - vm.loading = {application: true}; - vm.resource = applicationsResource.get({resourceId: $state.params.resourceId}, function (data) { - vm.loading.application = false; - $state.current.data.resource = vm.resource; + vm.loading = {applications: true}; + + vm.applications = applicationsResource.query({ + root_list: true, + resource_type: 'application' + }, function (data) { + vm.loading = {applications: false}; }); -} +}; ;// # Copyright (C) 2010-2016 RhodeCode GmbH // # @@ -7360,23 +7358,48 @@ function IntegrationsListViewController($state, applicationsResource) { // # services, and proprietary license terms, please see // # https://rhodecode.com/licenses/ -angular.module('appenlight.components.applicationsListView', []) - .component('applicationsListView', { - templateUrl: 'components/views/applications-list-view/applications-list-view.html', - controller: ApplicationsListViewController +angular.module('appenlight.components.adminConfigurationView', []) + .component('adminConfigurationView', { + templateUrl: 'components/views/admin-configuration-view/admin-configuration-view.html', + controller: AdminConfigurationViewController }); -ApplicationsListViewController.$inject = ['$state', 'applicationsResource']; +AdminConfigurationViewController.$inject = ['configsResource', 'configsNoIdResource']; -function ApplicationsListViewController($state, applicationsResource) { - +function AdminConfigurationViewController(configsResource, configsNoIdResource) { var vm = this; - vm.$state = $state; - vm.loading = {applications: true}; - vm.applications = applicationsResource.query(null, function(){ - vm.loading.applications = false; - }); -} + vm.loading = {config: true}; + + var filters = [ + 'template_footer_html:global', + 'list_groups_to_non_admins:global', + 'per_application_reports_rate_limit:global', + 'per_application_logs_rate_limit:global', + 'per_application_metrics_rate_limit:global', + ]; + + vm.configs = {}; + + vm.configList = configsResource.query({filter: filters}, + function (data) { + vm.loading = {config: false}; + _.each(data, function (item) { + if (vm.configs[item.section] === undefined) { + vm.configs[item.section] = {}; + } + vm.configs[item.section][item.key] = item; + }); + }); + + vm.save = function () { + vm.loading.config = true; + _.each(vm.configList, function (item) { + item.$save(); + }); + vm.loading.config = false; + }; + +}; ;// # Copyright (C) 2010-2016 RhodeCode GmbH // # @@ -7397,51 +7420,133 @@ function ApplicationsListViewController($state, applicationsResource) { // # services, and proprietary license terms, please see // # https://rhodecode.com/licenses/ -angular.module('appenlight.components.applicationsPurgeLogsView', []) - .component('applicationsPurgeLogsView', { - templateUrl: 'components/views/applications-purge-logs-view/applications-purge-logs-view.html', - controller: applicationsPurgeLogsViewController +angular.module('appenlight.components.adminGroupsCreateView', []) + .component('adminGroupsCreateView', { + templateUrl: 'components/views/admin-groups-create-view/admin-groups-create-view.html', + controller: AdminGroupsCreateViewController }); -applicationsPurgeLogsViewController.$inject = ['$state' ,'applicationsResource', 'sectionViewResource', 'logsNoIdResource']; +AdminGroupsCreateViewController.$inject = ['$state', 'groupsResource', 'groupsPropertyResource', 'sectionViewResource']; -function applicationsPurgeLogsViewController($state, applicationsResource, sectionViewResource, logsNoIdResource) { +function AdminGroupsCreateViewController($state, groupsResource, groupsPropertyResource, sectionViewResource) { var vm = this; vm.$state = $state; - vm.loading = {applications: true}; + vm.loading = { + group: false, + resource_permissions: false, + users: false + }; - vm.namespace = null; - vm.selectedResource = null; - vm.commonNamespaces = []; + vm.form = { + autocompleteUser: '', + } - vm.applications = applicationsResource.query({'type':'update_reports'}, function () { - vm.loading.applications = false; - vm.selectedResource = vm.applications[0].resource_id; - vm.getCommonKeys(); - }); - /** - * Fetches most commonly used tags in logs - */ - vm.getCommonKeys = function () { - sectionViewResource.get({ - section: 'logs_section', - view: 'common_tags', - resource: vm.selectedResource - }, function (data) { - vm.commonNamespaces = data['namespaces'] + if (typeof $state.params.groupId !== 'undefined') { + vm.loading.group = true; + var groupId = $state.params.groupId; + vm.group = groupsResource.get({groupId: groupId}, function (data) { + vm.loading.group = false; }); - }; - vm.purgeLogs = function () { - vm.loading.applications = true; - logsNoIdResource.delete({resource:vm.selectedResource, - namespace: vm.namespace}, function(){ - vm.loading.applications = false; - }); - } -} + vm.resource_permissions = groupsPropertyResource.query( + {groupId: groupId, key: 'resource_permissions'}, function (data) { + vm.loading.resource_permissions = false; + var tmpObj = { + 'group': { + 'application': {}, + 'dashboard': {} + } + }; + _.each(data, function (item) { + + var section = tmpObj[item.type][item.resource_type]; + if (typeof section[item.resource_id] == 'undefined') { + section[item.resource_id] = { + self: item, + permissions: [] + } + } + section[item.resource_id].permissions.push(item.perm_name); + + }); + vm.resourcePermissions = tmpObj; + }); + + vm.users = groupsPropertyResource.query( + {groupId: groupId, key: 'users'}, function (data) { + vm.loading.users = false; + }, function () { + vm.loading.users = false; + }); + + } + else { + var groupId = null; + } + + var formResponse = function (response) { + if (response.status === 422) { + setServerValidation(vm.groupForm, response.data); + } + vm.loading.group = false; + }; + + vm.createGroup = function () { + vm.loading.group = true; + if (groupId) { + groupsResource.update({groupId: vm.group.id}, vm.group, function (data) { + setServerValidation(vm.groupForm); + vm.loading.group = false; + }, formResponse); + } + else { + groupsResource.save(vm.group, function (data) { + $state.go('admin.group.update', {groupId: data.id}); + }, formResponse); + } + }; + + vm.removeUser = function (user) { + groupsPropertyResource.delete( + {groupId: groupId, key: 'users', user_name: user.user_name}, + function (data) { + vm.loading.users = false; + vm.users = _.filter(vm.users, function (item) { + return item != user; + }); + }, function () { + vm.loading.users = false; + }); + }; + + vm.addUser = function () { + groupsPropertyResource.save( + {groupId: groupId, key: 'users'}, + {user_name: vm.form.autocompleteUser}, + function (data) { + vm.loading.users = false; + vm.users.push(data); + vm.form.autocompleteUser = ''; + }, function () { + vm.loading.users = false; + }); + } + + vm.searchUsers = function (searchPhrase) { + + return sectionViewResource.query({ + section: 'users_section', + view: 'search_users', + 'user_name': searchPhrase + }).$promise.then(function (data) { + return _.map(data, function (item) { + return item.user; + }); + }); + } +}; ;// # Copyright (C) 2010-2016 RhodeCode GmbH // # @@ -7462,156 +7567,45 @@ function applicationsPurgeLogsViewController($state, applicationsResource, secti // # services, and proprietary license terms, please see // # https://rhodecode.com/licenses/ -angular.module('appenlight.components.applicationsUpdateView', []) - .component('applicationsUpdateView', { - templateUrl: 'components/views/applications-update-view/applications-update-view.html', - controller: applicationsUpdateViewController +angular.module('appenlight.components.adminGroupsListView', []) + .component('adminGroupsListView', { + templateUrl: 'components/views/admin-groups-list-view/admin-groups-list-view.html', + controller: AdminGroupsListViewController }); -applicationsUpdateViewController.$inject = ['$state', 'applicationsNoIdResource', 'applicationsResource', 'applicationsPropertyResource', 'stateHolder']; +AdminGroupsListViewController.$inject = ['$state', 'groupsResource']; -function applicationsUpdateViewController($state, applicationsNoIdResource, applicationsResource, applicationsPropertyResource, stateHolder) { - 'use strict'; +function AdminGroupsListViewController($state, groupsResource) { var vm = this; vm.$state = $state; - vm.loading = {application: false}; - - vm.groupingOptions = [ - ['url_type', 'Error Type + location'], - ['url_traceback', 'Traceback + location'], - ['traceback_server', 'Traceback + Server'], - ]; - var resourceId = $state.params.resourceId; - var options = {}; - vm.momentJs = moment; - vm.formTransferModel = {password:''}; - - // set initial data - - if (resourceId === 'new') { - vm.resource = { - resource_id: null, - slow_report_threshold: 10, - error_report_threshold: 10, - allow_permanent_storage: true, - default_grouping: vm.groupingOptions[1][0] - }; - } - else { - vm.loading.application = true; - vm.resource = applicationsResource.get({ - 'resourceId': resourceId - }, function (data) { - vm.loading.application = false; - }); - } - - - vm.updateBasicForm = function () { - vm.loading.application = true; - if (vm.resource.resource_id === null) { - applicationsNoIdResource.save(null, vm.resource, function (data) { - stateHolder.AeUser.addApplication(data); - $state.go('applications.update', {resourceId: data.resource_id}); - setServerValidation(vm.BasicForm); - }, function (response) { - if (response.status == 422) { - setServerValidation(vm.BasicForm, response.data); - } - vm.loading.application = false; - - }); - } - else { - applicationsResource.update({resourceId: vm.resource.resource_id}, - vm.resource, function (data) { - vm.resource = data; - vm.loading.application = false; - setServerValidation(vm.BasicForm); - }, function (response) { - if (response.status == 422) { - setServerValidation(vm.BasicForm, response.data); - } - vm.loading.application = false; - }); - } - }; - - vm.addRule = function () { - - applicationsPropertyResource.save({ - resourceId: vm.resource.resource_id, - key: 'postprocessing_rules' - }, null, - function (data) { - vm.resource.postprocessing_rules.push(data); - } - ); - }; + vm.loading = {groups: true}; - vm.regenerateAPIKeys = function(){ - vm.loading.application = true; - applicationsPropertyResource.save({ - resourceId: vm.resource.resource_id, - key: 'api_key' - }, {password: vm.regenerateAPIKeysPassword}, - function (data) { - vm.resource = data; - vm.loading.application = false; - vm.regenerateAPIKeysPassword = ''; - setServerValidation(vm.regenerateAPIKeysForm); - }, - function (response) { - if (response.status == 422) { - setServerValidation(vm.regenerateAPIKeysForm, response.data); - - } - vm.loading.application = false; + vm.groups = groupsResource.query({}, function (data) { + vm.loading = {groups: false}; + vm.activeUsers = _.reduce(vm.groups, function(memo, val){ + if (val.status == 1){ + return memo + 1; } - ) - }; + return memo; + }, 0); + + }); - vm.deleteApplication = function(){ - vm.loading.application = true; - applicationsPropertyResource.update({ - resourceId: vm.resource.resource_id, - key: 'delete_resource' - }, vm.formDeleteModel, - function (data) { - stateHolder.AeUser.removeApplicationById(vm.resource.resource_id); - $state.go('applications.list'); - }, - function (response) { - if (response.status == 422) { - setServerValidation(vm.formDelete, response.data); - - } - vm.loading.application = false; - } - ); - }; - vm.transferApplication = function(){ - vm.loading.application = true; - applicationsPropertyResource.update({ - resourceId: vm.resource.resource_id, - key: 'owner' - }, vm.formTransferModel, - function (data) { - $state.go('applications.list'); - }, - function (response) { - if (response.status == 422) { - setServerValidation(vm.formTransfer, response.data); - + vm.removeGroup = function (group) { + groupsResource.remove({groupId: group.id}, function (data, responseHeaders) { + + if (data) { + var index = vm.groups.indexOf(group); + if (index !== -1) { + vm.groups.splice(index, 1); + vm.activeGroups -= 1; } - vm.loading.application = false; } - ) + }); } - -} +}; ;// # Copyright (C) 2010-2016 RhodeCode GmbH // # @@ -7632,32 +7626,112 @@ function applicationsUpdateViewController($state, applicationsNoIdResource, appl // # services, and proprietary license terms, please see // # https://rhodecode.com/licenses/ -angular.module('appenlight.components.eventBrowserView', []) - .component('eventBrowserView', { - templateUrl: 'components/views/event-browser/event-browser.html', - controller: EventBrowserController +angular.module('appenlight.components.adminPartitionsView', []) + .component('adminPartitionsView', { + templateUrl: 'components/views/admin-partitions-view/admin-partitions-view.html', + controller: AdminPartitionsViewController }); -EventBrowserController.$inject = ['eventsNoIdResource', 'eventsResource']; +AdminPartitionsViewController.$inject = ['sectionViewResource']; -function EventBrowserController(eventsNoIdResource, eventsResource) { - console.info('EventBrowserController'); +function AdminPartitionsViewController(sectionViewResource) { var vm = this; + vm.permanentPartitions = []; + vm.dailyPartitions = []; + vm.loading = {partitions: true}; + vm.dailyChecked = false; + vm.permChecked = false; + vm.dailyConfirm = ''; + vm.permConfirm = ''; - vm.loading = {events: true}; - vm.events = eventsNoIdResource.query( - {key: 'events'}, - function (data) { - vm.loading.events = false; - }); + vm.loadPartitions = function (data) { + var permanentPartitions = vm.transformPartitionList( + data.permanent_partitions); + var dailyPartitions = vm.transformPartitionList( + data.daily_partitions); + vm.permanentPartitions = permanentPartitions; + vm.dailyPartitions = dailyPartitions; + vm.loading = {partitions: false}; + }; + vm.setCheckedList = function (scope) { + var toTest = null; + if (scope === 'dailyPartitions'){ + toTest = 'dailyChecked'; + } + else{ + toTest = 'permChecked'; + } - vm.closeEvent = function (event) { + if (vm[toTest]) { + var val = true; + } + else { + var val = false; + } - eventsResource.update({eventId: event.id}, {status: 0}, function (data) { - event.status = 0; + _.each(vm[scope], function (item) { + _.each(item[1].pg, function (index) { + index.checked = val; + }); + _.each(item[1].elasticsearch, function (index) { + index.checked = val; + }); + }); + } + + + vm.transformPartitionList = function (inputList) { + var outputList = []; + + _.each(inputList, function (item) { + var time = [item[0], { + elasticsearch: [], + pg: [] + }] + _.each(item[1].pg, function (index) { + time[1].pg.push({name: index, checked: false}) + }); + _.each(item[1].elasticsearch, function (index) { + time[1].elasticsearch.push({ + name: index, + checked: false + }) + }); + outputList.push(time); + }); + return outputList; + }; + + sectionViewResource.get({section:'admin_section', view: 'partitions'}, + vm.loadPartitions); + + vm.partitionsDelete = function (partitionType) { + var es_indices = []; + var pg_indices = []; + _.each(vm[partitionType], function (item) { + _.each(item[1].pg, function (index) { + if (index.checked) { + pg_indices.push(index.name) + } + }); + _.each(item[1].elasticsearch, function (index) { + if (index.checked) { + es_indices.push(index.name) + } + }); }); + + + vm.loading = {partitions: true}; + sectionViewResource.save({section:'admin_section', + view: 'partitions_remove'}, { + es_indices: es_indices, + pg_indices: pg_indices, + confirm: 'CONFIRM' + }, vm.loadPartitions); + } } @@ -7681,652 +7755,324 @@ function EventBrowserController(eventsNoIdResource, eventsResource) { // # services, and proprietary license terms, please see // # https://rhodecode.com/licenses/ -angular.module('appenlight.components.indexDashboardView', []) - .component('indexDashboardView', { - templateUrl: 'components/views/index-dashboard/index-dashboard.html', - controller: IndexDashboardController +angular.module('appenlight.components.adminSystemView', []) + .component('adminSystemView', { + templateUrl: 'components/views/admin-system-view/admin-system-view.html', + controller: AdminSystemViewController }); -IndexDashboardController.$inject = ['$rootScope', '$scope', '$location','$cookies', '$interval', 'stateHolder', 'applicationsPropertyResource', 'AeConfig']; +AdminSystemViewController.$inject = ['sectionViewResource']; -function IndexDashboardController($rootScope, $scope, $location, $cookies, $interval, stateHolder, applicationsPropertyResource, AeConfig) { +function AdminSystemViewController(sectionViewResource) { var vm = this; - stateHolder.section = 'dashboard'; - vm.timeOptions = {}; - var allowed = ['1h', '4h', '12h', '24h', '1w', '2w', '1M']; - _.each(allowed, function (key) { - if (allowed.indexOf(key) !== -1) { - vm.timeOptions[key] = AeConfig.timeOptions[key]; - } + vm.tables = []; + vm.loading = {system: true}; + sectionViewResource.get({ + section: 'admin_section', + view: 'system' + }, null, function (data) { + vm.DBtables = data.db_tables; + vm.ESIndices = data.es_indices; + vm.queueStats = data.queue_stats; + vm.systemLoad = data.system_load; + vm.packages = data.packages; + vm.processInfo = data.process_info; + vm.disks = data.disks; + vm.memory = data.memory; + vm.selfInfo = data.self_info; + + vm.loading.system = false; }); - vm.stateHolder = stateHolder; - vm.urls = AeConfig.urls; - vm.applications = stateHolder.AeUser.applications_map; - vm.show_dashboard = false; - vm.resource = null; - vm.graphType = {selected: null}; - vm.timeSpan = vm.timeOptions['1h']; - vm.trendingReports = []; - vm.exceptions = 0; - vm.satisfyingRequests = 0; - vm.toleratedRequests = 0; - vm.frustratingRequests = 0; - vm.uptimeStats = 0; - vm.apdexStats = []; - vm.seriesRequestsData = []; - vm.seriesMetricsData = []; - vm.seriesSlowData = []; - vm.slowCalls = []; - vm.slowURIS = []; +}; - vm.reportChartConfig = { - data: { - json: [], - xFormat: '%Y-%m-%dT%H:%M:%S' - }, - color: { - pattern: ['#6baed6', '#e6550d', '#74c476', '#fdd0a2', '#8c564b'] - }, - axis: { - x: { - type: 'timeseries', - tick: { - culling: { - max: 6 // the number of tick texts will be adjusted to less than this value - }, - format: '%Y-%m-%d %H:%M' - } - }, - y: { - tick: { - count: 5, - format: d3.format('.2s') - } - } - }, - subchart: { - show: true, - size: { - height: 20 - } - }, - size: { - height: 250 - }, - zoom: { - rescale: true - }, - grid: { - x: { - show: true - }, - y: { - show: true - } - }, - tooltip: { - format: { - title: function (d) { - return '' + d; - }, - value: function (v) { - return v - } +;// # Copyright (C) 2010-2016 RhodeCode GmbH +// # +// # This program is free software: you can redistribute it and/or modify +// # it under the terms of the GNU Affero General Public License, version 3 +// # (only), as published by the Free Software Foundation. +// # +// # This program is distributed in the hope that it will be useful, +// # but WITHOUT ANY WARRANTY; without even the implied warranty of +// # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// # GNU General Public License for more details. +// # +// # You should have received a copy of the GNU Affero General Public License +// # along with this program. If not, see . +// # +// # This program is dual-licensed. If you wish to learn more about the +// # AppEnlight Enterprise Edition, including its added features, Support +// # services, and proprietary license terms, please see +// # https://rhodecode.com/licenses/ + +angular.module('appenlight.components.adminUsersCreateView', []) + .component('adminUsersCreateView', { + templateUrl: 'components/views/admin-users-create-view/admin-users-create-view.html', + controller: AdminUsersCreateViewController + }); + +AdminUsersCreateViewController.$inject = ['$state', 'usersResource', 'usersPropertyResource', 'sectionViewResource', 'AeConfig']; + +function AdminUsersCreateViewController($state, usersResource, usersPropertyResource, sectionViewResource, AeConfig) { + + var vm = this; + vm.$state = $state; + vm.loading = {user: false}; + + + if (typeof $state.params.userId !== 'undefined') { + vm.loading.user = true; + var userId = $state.params.userId; + vm.user = usersResource.get({userId: userId}, function (data) { + vm.loading.user = false; + // cast to true for angular checkbox + if (vm.user.status === 1) { + vm.user.status = true; } - } - }; - vm.reportChartData = {}; + }); - vm.reportSlowChartConfig = { - data: { - json: [], - xFormat: '%Y-%m-%dT%H:%M:%S' - }, - color: { - pattern: ['#6baed6', '#e6550d', '#74c476', '#fdd0a2', '#8c564b'] - }, - axis: { - x: { - type: 'timeseries', - tick: { - culling: { - max: 6 // the number of tick texts will be adjusted to less than this value + vm.resource_permissions = usersPropertyResource.query( + {userId: userId, key: 'resource_permissions'}, function (data) { + vm.loading.resource_permissions = false; + var tmpObj = { + 'user': { + 'application': {}, + 'dashboard': {} }, - format: '%Y-%m-%d %H:%M' - } - }, - y: { - tick: { - count: 5, - format: d3.format('.2s') - } - } - }, - subchart: { - show: true, - size: { - height: 20 - } - }, - size: { - height: 250 - }, - zoom: { - rescale: true - }, - grid: { - x: { - show: true - }, - y: { - show: true - } - }, - tooltip: { - format: { - title: function (d) { - return '' + d; - }, - value: function (v) { - return v - } - } + 'group': { + 'application': {}, + 'dashboard': {} + } + }; + _.each(data, function (item) { + + var section = tmpObj[item.type][item.resource_type]; + if (typeof section[item.resource_id] == 'undefined'){ + section[item.resource_id] = { + self:item, + permissions: [] + } + } + section[item.resource_id].permissions.push(item.perm_name); + + }); + vm.resourcePermissions = tmpObj; + }); + + } + else { + var userId = null; + vm.user = { + status: true } - }; - vm.reportSlowChartData = {}; + } - vm.metricsChartConfig = { - data: { - json: [], - xFormat: '%Y-%m-%dT%H:%M:%S', - keys: { - x: 'x', - value: ["main", "sql", "nosql", "tmpl", "remote", "custom"] - }, - names: { - main: 'View/Application logic', - sql: 'Relational database queries', - nosql: 'NoSql datastore calls', - tmpl: 'Template rendering', - custom: 'Custom timed calls', - remote: 'Requests to remote resources' - }, - type: 'area', - groups: [["main", "sql", "nosql", "remote", "custom", "tmpl"]], - order: null - }, - color: { - pattern: ['#6baed6', '#c7e9c0', '#fd8d3c', '#d6616b', '#ffcc00', '#c6dbef'] - }, - axis: { - x: { - type: 'timeseries', - tick: { - culling: { - max: 6 // the number of tick texts will be adjusted to less than this value - }, - format: '%Y-%m-%d %H:%M' - } - }, - y: { - tick: { - count: 5, - format: d3.format('.2f') - } - } - }, - point: { - show: false - }, - subchart: { - show: true, - size: { - height: 20 - } - }, - size: { - height: 350 - }, - zoom: { - rescale: true - }, - grid: { - x: { - show: true - }, - y: { - show: true - } - }, - tooltip: { - format: { - title: function (d) { - return '' + d; - }, - value: function (v) { - return v - } - } + var formResponse = function (response) { + if (response.status == 422) { + setServerValidation(vm.profileForm, response.data); } - }; - vm.metricsChartData = {}; + vm.loading.user = false; + } - vm.responseChartConfig = { - data: { - json: [], - xFormat: '%Y-%m-%dT%H:%M:%S' - }, - color: { - pattern: ['#d6616b', '#6baed6', '#fd8d3c'] - }, - axis: { - x: { - type: 'timeseries', - tick: { - culling: { - max: 6 // the number of tick texts will be adjusted to less than this value - }, - format: '%Y-%m-%d %H:%M' - } - }, - y: { - tick: { - count: 5, - format: d3.format('.2f') - } - } - }, - point: { - show: false - }, - subchart: { - show: true, - size: { - height: 20 - } - }, - size: { - height: 350 - }, - zoom: { - rescale: true - }, - grid: { - x: { - show: true - }, - y: { - show: true - } - }, - tooltip: { - format: { - title: function (d) { - return '' + d; - }, - value: function (v) { - return v - } - } + vm.createUser = function () { + vm.loading.user = true; + + if (userId) { + usersResource.update({userId: vm.user.id}, vm.user, function (data) { + setServerValidation(vm.profileForm); + vm.loading.user = false; + }, formResponse); } - }; - vm.responseChartData = {}; + else { + usersResource.save(vm.user, function (data) { + $state.go('admin.user.update', {userId: data.id}); + }, formResponse); + } + } - vm.requestsChartConfig = { - data: { - json: [], - xFormat: '%Y-%m-%dT%H:%M:%S' - }, - color: { - pattern: ['#d6616b', '#6baed6', '#fd8d3c'] - }, - axis: { - x: { - type: 'timeseries', - tick: { - culling: { - max: 6 // the number of tick texts will be adjusted to less than this value - }, - format: '%Y-%m-%d %H:%M' - } - }, - y: { - tick: { - count: 5, - format: d3.format('.2f') - } - } - }, - point: { - show: false - }, - subchart: { - show: true, - size: { - height: 20 - } - }, - size: { - height: 350 - }, - zoom: { - rescale: true - }, - grid: { - x: { - show: true - }, - y: { - show: true - } - }, - tooltip: { - format: { - title: function (d) { - return '' + d; - }, - value: function (v) { - return v - } - } + vm.generatePassword = function () { + var length = 8; + var charset = "abcdefghijklnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; + vm.gen_pass = ""; + for (var i = 0, n = charset.length; i < length; ++i) { + vm.gen_pass += charset.charAt(Math.floor(Math.random() * n)); } - }; - vm.requestsChartData = {}; - - vm.loading = { - 'apdex': true, - 'reports': true, - 'graphs': true, - 'slowCalls': true, - 'slowURIS': true, - 'requestsBreakdown': true, - 'series': true - }; - vm.stream = {paused: false, filtered: false, messages: [], reports: []}; + vm.user.user_password = '' + vm.gen_pass; + + } - $rootScope.$on('channelstream-message.front_dashboard.new_topic', function(event, message){ - var ws_report = message.message.report; - if (ws_report.http_status != 500) { - return - } - if (vm.stream.paused == true) { - return - } - if (vm.stream.filtered && ws_report.resource_id != vm.resource) { - return - } - var should_insert = true; - _.each(vm.stream.reports, function (report) { - if (report.report_id == ws_report.report_id) { - report.occurences = ws_report.occurences; - should_insert = false; - } + vm.reloginUser = function () { + sectionViewResource.get({ + section: 'admin_section', view: 'relogin_user', + user_id: vm.user.id + }, function () { + window.location = AeConfig.urls.baseUrl; }); - if (should_insert) { - if (vm.stream.reports.length > 7) { - vm.stream.reports.pop(); - } - vm.stream.reports.unshift(ws_report); - } + + } +}; + +;// # Copyright (C) 2010-2016 RhodeCode GmbH +// # +// # This program is free software: you can redistribute it and/or modify +// # it under the terms of the GNU Affero General Public License, version 3 +// # (only), as published by the Free Software Foundation. +// # +// # This program is distributed in the hope that it will be useful, +// # but WITHOUT ANY WARRANTY; without even the implied warranty of +// # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// # GNU General Public License for more details. +// # +// # You should have received a copy of the GNU Affero General Public License +// # along with this program. If not, see . +// # +// # This program is dual-licensed. If you wish to learn more about the +// # AppEnlight Enterprise Edition, including its added features, Support +// # services, and proprietary license terms, please see +// # https://rhodecode.com/licenses/ + +angular.module('appenlight.components.adminUsersListView', []) + .component('adminUsersListView', { + templateUrl: 'components/views/admin-users-list-view/admin-users-list-view.html', + controller: AdminUserListViewController }); - vm.determineStartState = function () { - if (stateHolder.AeUser.applications.length) { - vm.resource = Number($location.search().resource); +AdminUserListViewController.$inject = ['usersResource']; - if (!vm.resource){ - var cookieResource = $cookies.getObject('resource'); - +function AdminUserListViewController(usersResource) { + + var vm = this; + vm.loading = {users: true}; - if (cookieResource) { - vm.resource = cookieResource; - } - else{ - vm.resource = stateHolder.AeUser.applications[0].resource_id; - } + vm.users = usersResource.query({}, function (data) { + vm.loading = {users: false}; + vm.activeUsers = _.reduce(vm.users, function(memo, val){ + if (val.status == 1){ + return memo + 1; } - } + return memo; + }, 0); + + }); - var timespan = $location.search().timespan; - if(_.has(vm.timeOptions, timespan)){ - vm.timeSpan = vm.timeOptions[timespan]; - } - else{ - vm.timeSpan = vm.timeOptions['1h']; - } + vm.removeUser = function (user) { + usersResource.remove({userId: user.id}, function (data, responseHeaders) { + + if (data) { + var index = vm.users.indexOf(user); + if (index !== -1) { + vm.users.splice(index, 1); + vm.activeUsers -= 1; + } + } + }); + } +}; - var graphType = $location.search().graphtype; - if(!graphType){ - vm.graphType = {selected: 'metrics_graphs'}; - } - else{ - vm.graphType = {selected: graphType}; - } - vm.updateSearchParams(); - }; +;// # Copyright (C) 2010-2016 RhodeCode GmbH +// # +// # This program is free software: you can redistribute it and/or modify +// # it under the terms of the GNU Affero General Public License, version 3 +// # (only), as published by the Free Software Foundation. +// # +// # This program is distributed in the hope that it will be useful, +// # but WITHOUT ANY WARRANTY; without even the implied warranty of +// # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// # GNU General Public License for more details. +// # +// # You should have received a copy of the GNU Affero General Public License +// # along with this program. If not, see . +// # +// # This program is dual-licensed. If you wish to learn more about the +// # AppEnlight Enterprise Edition, including its added features, Support +// # services, and proprietary license terms, please see +// # https://rhodecode.com/licenses/ - vm.updateSearchParams = function () { - $location.search('resource', vm.resource); - $location.search('timespan', vm.timeSpan.key); - $location.search('graphtype', vm.graphType.selected); - stateHolder.resource = vm.resource; +angular.module('appenlight.components.adminView', []) + .component('adminView', { + templateUrl: 'components/views/admin-view/admin-view.html', + controller: AdminViewController + }); - if (vm.resource){ - $cookies.putObject('resource', vm.resource, - {expires:new Date(3000, 1, 1)}); - } - vm.refreshData(); - }; +AdminViewController.$inject = ['$state']; - vm.refreshData = function () { - vm.fetchApdexStats(); - vm.fetchTrendingReports(); - vm.fetchMetrics(); - vm.fetchRequestsBreakdown(); - vm.fetchSlowCalls(); - }; +function AdminViewController($state) { + this.$state = $state; + console.info('AdminViewController'); +} - vm.changedTimeSpan = function(){ - vm.startDateFilter = timeSpanToStartDate(vm.timeSpan.key); - vm.refreshData(); - }; +;// # Copyright (C) 2010-2016 RhodeCode GmbH +// # +// # This program is free software: you can redistribute it and/or modify +// # it under the terms of the GNU Affero General Public License, version 3 +// # (only), as published by the Free Software Foundation. +// # +// # This program is distributed in the hope that it will be useful, +// # but WITHOUT ANY WARRANTY; without even the implied warranty of +// # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// # GNU General Public License for more details. +// # +// # You should have received a copy of the GNU Affero General Public License +// # along with this program. If not, see . +// # +// # This program is dual-licensed. If you wish to learn more about the +// # AppEnlight Enterprise Edition, including its added features, Support +// # services, and proprietary license terms, please see +// # https://rhodecode.com/licenses/ - vm.intervalId = $interval(function () { - if (_.contains(['30m', "1h"], vm.timeSpan.key)) { - // don't do anything if window is unfocused - if(document.hidden === true){ - return ; - } - vm.refreshData(); - } - }, 60000); +angular.module('appenlight.components.integrationsListView', []) + .component('integrationsListView', { + templateUrl: 'components/views/applications-integrations-view/applications-integrations-view.html', + controller: IntegrationsListViewController + }); - vm.fetchApdexStats = function () { - vm.loading.apdex = true; - vm.apdexStats = applicationsPropertyResource.query({ - 'key': 'apdex_stats', - 'resourceId': vm.resource, - "start_date": timeSpanToStartDate(vm.timeSpan.key) - }, - function (data) { - vm.loading.apdex = false; +IntegrationsListViewController.$inject = ['$state', 'applicationsResource']; - vm.exceptions = _.reduce(data, function (memo, row) { - return memo + row.errors; - }, 0); - vm.satisfyingRequests = _.reduce(data, function (memo, row) { - return memo + row.satisfying_requests; - }, 0); - vm.toleratedRequests = _.reduce(data, function (memo, row) { - return memo + row.tolerated_requests; - }, 0); - vm.frustratingRequests = _.reduce(data, function (memo, row) { - return memo + row.frustrating_requests; - }, 0); - if (data.length) { - vm.uptimeStats = data[0].uptime; - } - - }, - function () { - vm.loading.apdex = false; - } - ); - } - - vm.fetchMetrics = function () { - vm.loading.series = true; - applicationsPropertyResource.query({ - 'resourceId': vm.resource, - 'key': vm.graphType.selected, - "start_date": timeSpanToStartDate(vm.timeSpan.key) - }, function (data) { - if (vm.graphType.selected == 'metrics_graphs') { - vm.metricsChartData = { - json: data, - xFormat: '%Y-%m-%dT%H:%M:%S', - keys: { - x: 'x', - value: ["main", "sql", "nosql", "tmpl", "remote", "custom"] - }, - names: { - main: 'View/Application logic', - sql: 'Relational database queries', - nosql: 'NoSql datastore calls', - tmpl: 'Template rendering', - custom: 'Custom timed calls', - remote: 'Requests to remote resources' - }, - type: 'area', - groups: [["main", "sql", "nosql", "remote", "custom", "tmpl"]], - order: null - }; - } - else if (vm.graphType.selected == 'report_graphs') { - vm.reportChartData = { - json: data, - xFormat: '%Y-%m-%dT%H:%M:%S', - keys: { - x: 'x', - value: ["not_found", "report"] - }, - names: { - report: 'Errors', - not_found: '404\'s requests' - }, - type: 'bar' - }; - } - else if (vm.graphType.selected == 'slow_report_graphs') { - vm.reportSlowChartData = { - json: data, - xFormat: '%Y-%m-%dT%H:%M:%S', - keys: { - x: 'x', - value: ["slow_report"] - }, - names: { - slow_report: 'Slow reports' - }, - type: 'bar' - }; - } - else if (vm.graphType.selected == 'response_graphs') { - vm.responseChartData = { - json: data, - xFormat: '%Y-%m-%dT%H:%M:%S', - keys: { - x: 'x', - value: ["today", "days_ago_2", "days_ago_7"] - }, - names: { - today: 'Today', - "days_ago_2": '2 days ago', - "days_ago_7": '7 days ago' - } - }; - } - else if (vm.graphType.selected == 'requests_graphs') { - vm.requestsChartData = { - json: data, - xFormat: '%Y-%m-%dT%H:%M:%S', - keys: { - x: 'x', - value: ["requests"] - }, - names: { - requests: 'Requests/s' - } - }; - } - vm.loading.series = false; - }, function(){ - vm.loading.series = false; - }); - } - - vm.fetchSlowCalls = function () { - vm.loading.slowCalls = true; - applicationsPropertyResource.query({ - 'resourceId': vm.resource, - "start_date": timeSpanToStartDate(vm.timeSpan.key), - 'key': 'slow_calls' - }, function (data) { - vm.slowCalls = data; - vm.loading.slowCalls = false; - }, function () { - vm.loading.slowCalls = false; - }); - } - - vm.fetchRequestsBreakdown = function () { - vm.loading.requestsBreakdown = true; - applicationsPropertyResource.query({ - 'resourceId': vm.resource, - "start_date": timeSpanToStartDate(vm.timeSpan.key), - 'key': 'requests_breakdown' - }, function (data) { - vm.requestsBreakdown = data; - vm.loading.requestsBreakdown = false; - }, function () { - vm.loading.requestsBreakdown = false; - }); - } +function IntegrationsListViewController($state, applicationsResource) { + + var vm = this; + vm.loading = {application: true}; + vm.resource = applicationsResource.get({resourceId: $state.params.resourceId}, function (data) { + vm.loading.application = false; + $state.current.data.resource = vm.resource; + }); +} - vm.fetchTrendingReports = function () { +;// # Copyright (C) 2010-2016 RhodeCode GmbH +// # +// # This program is free software: you can redistribute it and/or modify +// # it under the terms of the GNU Affero General Public License, version 3 +// # (only), as published by the Free Software Foundation. +// # +// # This program is distributed in the hope that it will be useful, +// # but WITHOUT ANY WARRANTY; without even the implied warranty of +// # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// # GNU General Public License for more details. +// # +// # You should have received a copy of the GNU Affero General Public License +// # along with this program. If not, see . +// # +// # This program is dual-licensed. If you wish to learn more about the +// # AppEnlight Enterprise Edition, including its added features, Support +// # services, and proprietary license terms, please see +// # https://rhodecode.com/licenses/ - if (vm.graphType.selected == 'slow_report_graphs') { - var report_type = 'slow'; - } - else { - var report_type = 'error'; - } +angular.module('appenlight.components.applicationsListView', []) + .component('applicationsListView', { + templateUrl: 'components/views/applications-list-view/applications-list-view.html', + controller: ApplicationsListViewController + }); - vm.loading.reports = true; - vm.trendingReports = applicationsPropertyResource.query({ - 'key': 'trending_reports', - 'resourceId': vm.resource, - "start_date": timeSpanToStartDate(vm.timeSpan.key), - "report_type": report_type - }, - function () { - vm.loading.reports = false; - }, - function () { - vm.loading.reports = false; - } - ); - }; +ApplicationsListViewController.$inject = ['$state', 'applicationsResource']; - $scope.$on('$destroy',function(){ - $interval.cancel(vm.intervalId); +function ApplicationsListViewController($state, applicationsResource) { + + var vm = this; + vm.$state = $state; + vm.loading = {applications: true}; + vm.applications = applicationsResource.query(null, function(){ + vm.loading.applications = false; }); - - if (stateHolder.AeUser.applications.length){ - vm.show_dashboard = true; - vm.determineStartState(); - } } ;// # Copyright (C) 2010-2016 RhodeCode GmbH @@ -8348,121 +8094,221 @@ function IndexDashboardController($rootScope, $scope, $location, $cookies, $inte // # services, and proprietary license terms, please see // # https://rhodecode.com/licenses/ +angular.module('appenlight.components.applicationsPurgeLogsView', []) + .component('applicationsPurgeLogsView', { + templateUrl: 'components/views/applications-purge-logs-view/applications-purge-logs-view.html', + controller: applicationsPurgeLogsViewController + }); -ApplicationsIntegrationsEditViewController.$inject = ['$state', 'integrationResource']; +applicationsPurgeLogsViewController.$inject = ['$state' ,'applicationsResource', 'sectionViewResource', 'logsNoIdResource']; -function ApplicationsIntegrationsEditViewController($state, integrationResource) { +function applicationsPurgeLogsViewController($state, applicationsResource, sectionViewResource, logsNoIdResource) { var vm = this; vm.$state = $state; - vm.loading = {integration: true}; - vm.config = integrationResource.get( - { - integration: $state.params.integration, - action: 'setup', - resourceId: $state.params.resourceId + vm.loading = {applications: true}; + + vm.namespace = null; + vm.selectedResource = null; + vm.commonNamespaces = []; + + vm.applications = applicationsResource.query({'type':'update_reports'}, function () { + vm.loading.applications = false; + vm.selectedResource = vm.applications[0].resource_id; + vm.getCommonKeys(); + }); + + /** + * Fetches most commonly used tags in logs + */ + vm.getCommonKeys = function () { + sectionViewResource.get({ + section: 'logs_section', + view: 'common_tags', + resource: vm.selectedResource }, function (data) { - vm.loading.integration = false; + vm.commonNamespaces = data['namespaces'] }); - - vm.configureIntegration = function () { - console.info('configureIntegration'); - vm.loading.integration = true; - integrationResource.save( - { - integration: $state.params.integration, - action: 'setup', - resourceId: $state.params.resourceId - }, vm.config, function (data) { - vm.loading.integration = false; - setServerValidation(vm.integrationForm); - }, function (response) { - if (response.status == 422) { - setServerValidation(vm.integrationForm, response.data); - } - vm.loading.integration = false; - }); }; - vm.removeIntegration = function () { - console.info('removeIntegration'); - integrationResource.remove({ - integration: $state.params.integration, - resourceId: $state.params.resourceId, - action: 'delete' - }, - function () { - $state.go('applications.integrations', - {resourceId: $state.params.resourceId}); - } - ); + vm.purgeLogs = function () { + vm.loading.applications = true; + logsNoIdResource.delete({resource:vm.selectedResource, + namespace: vm.namespace}, function(){ + vm.loading.applications = false; + }); } +} - vm.testIntegration = function (to_test) { - console.info('testIntegration', to_test); - vm.loading.integration = true; - integrationResource.save( - { - integration: $state.params.integration, - action: 'test_' + to_test, - resourceId: $state.params.resourceId - }, vm.config, function (data) { - vm.loading.integration = false; - }, function (response) { - vm.loading.integration = false; - }); - } +;// # Copyright (C) 2010-2016 RhodeCode GmbH +// # +// # This program is free software: you can redistribute it and/or modify +// # it under the terms of the GNU Affero General Public License, version 3 +// # (only), as published by the Free Software Foundation. +// # +// # This program is distributed in the hope that it will be useful, +// # but WITHOUT ANY WARRANTY; without even the implied warranty of +// # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// # GNU General Public License for more details. +// # +// # You should have received a copy of the GNU Affero General Public License +// # along with this program. If not, see . +// # +// # This program is dual-licensed. If you wish to learn more about the +// # AppEnlight Enterprise Edition, including its added features, Support +// # services, and proprietary license terms, please see +// # https://rhodecode.com/licenses/ + +angular.module('appenlight.components.applicationsUpdateView', []) + .component('applicationsUpdateView', { + templateUrl: 'components/views/applications-update-view/applications-update-view.html', + controller: applicationsUpdateViewController + }); + +applicationsUpdateViewController.$inject = ['$state', 'applicationsNoIdResource', 'applicationsResource', 'applicationsPropertyResource', 'stateHolder']; +function applicationsUpdateViewController($state, applicationsNoIdResource, applicationsResource, applicationsPropertyResource, stateHolder) { + 'use strict'; -} + var vm = this; + vm.$state = $state; + vm.loading = {application: false}; -;angular.module('appenlight.components.bitbucketIntegrationConfigView', []) - .component('bitbucketIntegrationConfigView', { - templateUrl: 'components/views/integrations/bitbucket-integration-config-view/bitbucket-integration-config-view.html', - controller: ApplicationsIntegrationsEditViewController - }); + vm.groupingOptions = [ + ['url_type', 'Error Type + location'], + ['url_traceback', 'Traceback + location'], + ['traceback_server', 'Traceback + Server'], + ]; + var resourceId = $state.params.resourceId; + var options = {}; + vm.momentJs = moment; + vm.formTransferModel = {password:''}; -;angular.module('appenlight.components.campfireIntegrationConfigView', []) - .component('campfireIntegrationConfigView', { - templateUrl: 'components/views/integrations/campfire-integration-config-view/campfire-integration-config-view.html', - controller: ApplicationsIntegrationsEditViewController - }); + // set initial data -;angular.module('appenlight.components.flowdockIntegrationConfigView', []) - .component('flowdockIntegrationConfigView', { - templateUrl: 'components/views/integrations/flowdock-integration-config-view/flowdock-integration-config-view.html', - controller: ApplicationsIntegrationsEditViewController - }); + if (resourceId === 'new') { + vm.resource = { + resource_id: null, + slow_report_threshold: 10, + error_report_threshold: 10, + allow_permanent_storage: true, + default_grouping: vm.groupingOptions[1][0] + }; + } + else { + vm.loading.application = true; + vm.resource = applicationsResource.get({ + 'resourceId': resourceId + }, function (data) { + vm.loading.application = false; + }); + } -;angular.module('appenlight.components.githubIntegrationConfigView', []) - .component('githubIntegrationConfigView', { - templateUrl: 'components/views/integrations/github-integration-config-view/github-integration-config-view.html', - controller: ApplicationsIntegrationsEditViewController - }); -;angular.module('appenlight.components.hipchatIntegrationConfigView', []) - .component('hipchatIntegrationConfigView', { - templateUrl: 'components/views/integrations/hipchat-integration-config-view/hipchat-integration-config-view.html', - controller: ApplicationsIntegrationsEditViewController - }); + vm.updateBasicForm = function () { + vm.loading.application = true; + if (vm.resource.resource_id === null) { + applicationsNoIdResource.save(null, vm.resource, function (data) { + stateHolder.AeUser.addApplication(data); + $state.go('applications.update', {resourceId: data.resource_id}); + setServerValidation(vm.BasicForm); + }, function (response) { + if (response.status == 422) { + setServerValidation(vm.BasicForm, response.data); + } + vm.loading.application = false; + + }); + } + else { + applicationsResource.update({resourceId: vm.resource.resource_id}, + vm.resource, function (data) { + vm.resource = data; + vm.loading.application = false; + setServerValidation(vm.BasicForm); + }, function (response) { + if (response.status == 422) { + setServerValidation(vm.BasicForm, response.data); + } + vm.loading.application = false; + }); + } + }; -;angular.module('appenlight.components.jiraIntegrationConfigView', []) - .component('jiraIntegrationConfigView', { - templateUrl: 'components/views/integrations/jira-integration-config-view/jira-integration-config-view.html', - controller: ApplicationsIntegrationsEditViewController - }); + vm.addRule = function () { + + applicationsPropertyResource.save({ + resourceId: vm.resource.resource_id, + key: 'postprocessing_rules' + }, null, + function (data) { + vm.resource.postprocessing_rules.push(data); + } + ); + }; -;angular.module('appenlight.components.slackIntegrationConfigView', []) - .component('slackIntegrationConfigView', { - templateUrl: 'components/views/integrations/slack-integration-config-view/slack-integration-config-view.html', - controller: ApplicationsIntegrationsEditViewController - }); + vm.regenerateAPIKeys = function(){ + vm.loading.application = true; + applicationsPropertyResource.save({ + resourceId: vm.resource.resource_id, + key: 'api_key' + }, {password: vm.regenerateAPIKeysPassword}, + function (data) { + vm.resource = data; + vm.loading.application = false; + vm.regenerateAPIKeysPassword = ''; + setServerValidation(vm.regenerateAPIKeysForm); + }, + function (response) { + if (response.status == 422) { + setServerValidation(vm.regenerateAPIKeysForm, response.data); + + } + vm.loading.application = false; + } + ) + }; -;angular.module('appenlight.components.webhooksIntegrationConfigView', []) - .component('webhooksIntegrationConfigView', { - templateUrl: 'components/views/integrations/webhooks-integration-config-view/webhooks-integration-config-view.html', - controller: ApplicationsIntegrationsEditViewController - }); + vm.deleteApplication = function(){ + vm.loading.application = true; + applicationsPropertyResource.update({ + resourceId: vm.resource.resource_id, + key: 'delete_resource' + }, vm.formDeleteModel, + function (data) { + stateHolder.AeUser.removeApplicationById(vm.resource.resource_id); + $state.go('applications.list'); + }, + function (response) { + if (response.status == 422) { + setServerValidation(vm.formDelete, response.data); + + } + vm.loading.application = false; + } + ); + }; + + vm.transferApplication = function(){ + vm.loading.application = true; + applicationsPropertyResource.update({ + resourceId: vm.resource.resource_id, + key: 'owner' + }, vm.formTransferModel, + function (data) { + $state.go('applications.list'); + }, + function (response) { + if (response.status == 422) { + setServerValidation(vm.formTransfer, response.data); + + } + vm.loading.application = false; + } + ) + } + +} ;// # Copyright (C) 2010-2016 RhodeCode GmbH // # @@ -8483,29 +8329,109 @@ function ApplicationsIntegrationsEditViewController($state, integrationResource) // # services, and proprietary license terms, please see // # https://rhodecode.com/licenses/ -angular.module('appenlight.components.logsBrowserView', []) - .component('logsBrowserView', { - templateUrl: 'components/views/logs-browser/logs-browser.html', - controller: LogsBrowserController +angular.module('appenlight.components.eventBrowserView', []) + .component('eventBrowserView', { + templateUrl: 'components/views/event-browser/event-browser.html', + controller: EventBrowserController }); -LogsBrowserController.$inject = ['$location', 'stateHolder', 'typeAheadTagHelper', 'logsNoIdResource', 'sectionViewResource']; +EventBrowserController.$inject = ['eventsNoIdResource', 'eventsResource']; -function LogsBrowserController($location, stateHolder, typeAheadTagHelper, logsNoIdResource, sectionViewResource) { +function EventBrowserController(eventsNoIdResource, eventsResource) { + console.info('EventBrowserController'); var vm = this; - vm.logEventsChartConfig = { - data: { - json: [], - xFormat: '%Y-%m-%dT%H:%M:%S' - }, - color: { - pattern: ['#6baed6', '#e6550d', '#74c476', '#fdd0a2', '#8c564b'] - }, - axis: { - x: { - type: 'timeseries', - tick: { - format: '%Y-%m-%d' + + vm.loading = {events: true}; + + vm.events = eventsNoIdResource.query( + {key: 'events'}, + function (data) { + vm.loading.events = false; + }); + + + vm.closeEvent = function (event) { + + eventsResource.update({eventId: event.id}, {status: 0}, function (data) { + event.status = 0; + }); + } + +} + +;// # Copyright (C) 2010-2016 RhodeCode GmbH +// # +// # This program is free software: you can redistribute it and/or modify +// # it under the terms of the GNU Affero General Public License, version 3 +// # (only), as published by the Free Software Foundation. +// # +// # This program is distributed in the hope that it will be useful, +// # but WITHOUT ANY WARRANTY; without even the implied warranty of +// # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// # GNU General Public License for more details. +// # +// # You should have received a copy of the GNU Affero General Public License +// # along with this program. If not, see . +// # +// # This program is dual-licensed. If you wish to learn more about the +// # AppEnlight Enterprise Edition, including its added features, Support +// # services, and proprietary license terms, please see +// # https://rhodecode.com/licenses/ + +angular.module('appenlight.components.indexDashboardView', []) + .component('indexDashboardView', { + templateUrl: 'components/views/index-dashboard/index-dashboard.html', + controller: IndexDashboardController + }); + +IndexDashboardController.$inject = ['$rootScope', '$scope', '$location','$cookies', '$interval', 'stateHolder', 'applicationsPropertyResource', 'AeConfig']; + +function IndexDashboardController($rootScope, $scope, $location, $cookies, $interval, stateHolder, applicationsPropertyResource, AeConfig) { + var vm = this; + stateHolder.section = 'dashboard'; + vm.timeOptions = {}; + var allowed = ['1h', '4h', '12h', '24h', '1w', '2w', '1M']; + _.each(allowed, function (key) { + if (allowed.indexOf(key) !== -1) { + vm.timeOptions[key] = AeConfig.timeOptions[key]; + } + }); + vm.stateHolder = stateHolder; + vm.urls = AeConfig.urls; + vm.applications = stateHolder.AeUser.applications_map; + vm.show_dashboard = false; + vm.resource = null; + vm.graphType = {selected: null}; + vm.timeSpan = vm.timeOptions['1h']; + vm.trendingReports = []; + vm.exceptions = 0; + vm.satisfyingRequests = 0; + vm.toleratedRequests = 0; + vm.frustratingRequests = 0; + vm.uptimeStats = 0; + vm.apdexStats = []; + vm.seriesRequestsData = []; + vm.seriesMetricsData = []; + vm.seriesSlowData = []; + vm.slowCalls = []; + vm.slowURIS = []; + + vm.reportChartConfig = { + data: { + json: [], + xFormat: '%Y-%m-%dT%H:%M:%S' + }, + color: { + pattern: ['#6baed6', '#e6550d', '#74c476', '#fdd0a2', '#8c564b'] + }, + axis: { + x: { + type: 'timeseries', + tick: { + culling: { + max: 6 // the number of tick texts will be adjusted to less than this value + }, + format: '%Y-%m-%d %H:%M' } }, y: { @@ -8546,279 +8472,170 @@ function LogsBrowserController($location, stateHolder, typeAheadTagHelper, logsN } } }; - vm.logEventsChartData = {}; - stateHolder.section = 'logs'; - vm.today = function () { - vm.pickerDate = new Date(); - }; - vm.today(); + vm.reportChartData = {}; - vm.applications = stateHolder.AeUser.applications_map; - vm.logsPage = []; - vm.itemCount = 0; - vm.itemsPerPage = 250; - vm.page = 1; - vm.$location = $location; - vm.isLoading = { - logs: true, - series: true - }; - vm.filterTypeAheadOptions = [ - { - type: 'message', - text: 'message:', - 'description': 'Full-text search in your logs', - tag: 'Message', - example: 'message:text-im-looking-for' - }, - { - type: 'namespace', - text: 'namespace:', - 'description': 'Query logs from specific namespace', - tag: 'Namespace', - example: "namespace:module.foo" + vm.reportSlowChartConfig = { + data: { + json: [], + xFormat: '%Y-%m-%dT%H:%M:%S' }, - { - type: 'resource', - text: 'resource:', - 'description': 'Restrict resultset to application', - tag: 'Application', - example: "resource:ID" + color: { + pattern: ['#6baed6', '#e6550d', '#74c476', '#fdd0a2', '#8c564b'] }, - { - type: 'request_id', - text: 'request_id:', - 'description': 'Show logs with specific request id', - example: "request_id:883143dc572e4c38aceae92af0ea5ae0", - tag: 'Request ID' + axis: { + x: { + type: 'timeseries', + tick: { + culling: { + max: 6 // the number of tick texts will be adjusted to less than this value + }, + format: '%Y-%m-%d %H:%M' + } + }, + y: { + tick: { + count: 5, + format: d3.format('.2s') + } + } }, - { - type: 'level', - text: 'level:', - 'description': 'Show entries with specific log level', - example: 'level:warning', - tag: 'Level' + subchart: { + show: true, + size: { + height: 20 + } }, - { - type: 'server_name', - text: 'server_name:', - 'description': 'Show entries tagged with this key/value pair', - example: 'server_name:hostname', - tag: 'Tag' + size: { + height: 250 }, - { - type: 'start_date', - text: 'start_date:', - 'description': 'Show results newer than this date (press TAB for dropdown)', - example: 'start_date:2014-08-15T13:00', - tag: 'Start Date' + zoom: { + rescale: true }, - { - type: 'end_date', - text: 'end_date:', - 'description': 'Show results older than this date (press TAB for dropdown)', - example: 'start_date:2014-08-15T23:59', - tag: 'End Date' + grid: { + x: { + show: true + }, + y: { + show: true + } }, - {type: 'level', value: 'debug', text: 'level:debug'}, - {type: 'level', value: 'info', text: 'level:info'}, - {type: 'level', value: 'warning', text: 'level:warning'}, - {type: 'level', value: 'critical', text: 'level:critical'} - ]; - vm.filterTypeAhead = null; - vm.showDatePicker = false; - vm.manualOpen = false; - vm.aheadFilter = typeAheadTagHelper.aheadFilter; - vm.removeSearchTag = function (tag) { - $location.search(tag.type, null); - vm.refresh(); - }; - vm.addSearchTag = function (tag) { - $location.search(tag.type, tag.value); - vm.refresh(); - }; - - vm.paginationChange = function(){ - $location.search('page', vm.page); - vm.refresh(); + tooltip: { + format: { + title: function (d) { + return '' + d; + }, + value: function (v) { + return v + } + } + } }; + vm.reportSlowChartData = {}; - - _.each(vm.applications, function (item) { - vm.filterTypeAheadOptions.push({ - type: 'resource', - text: 'resource:' + item.resource_id + ':' + item.resource_name, - example: 'resource:' + item.resource_id, - 'tag': item.resource_name, - 'description': 'Restrict resultset to this application' - }); - }); - - vm.typeAheadTag = function (event) { - var text = vm.filterTypeAhead; - if (_.isObject(vm.filterTypeAhead)) { - text = vm.filterTypeAhead.text; - }; - if (!vm.filterTypeAhead) { - return - } - var parsed = text.split(':'); - var tag = {'type': null, 'value': null}; - // app tags have : twice - if (parsed.length > 2 && parsed[0] == 'resource') { - tag.type = 'resource'; - tag.value = parsed[1]; - } - // normal tag:value - else if (parsed.length > 1) { - tag.type = parsed[0]; - tag.value = parsed.slice(1).join(':'); - } - else { - tag.type = 'message'; - tag.value = parsed.join(':'); - } - - // set datepicker hour based on type of field - if ('start_date:' == text) { - vm.showDatePicker = true; - vm.filterTypeAhead = 'start_date:' + moment(vm.pickerDate).utc().format(); - } - else if ('end_date:' == text) { - vm.showDatePicker = true; - vm.filterTypeAhead = 'end_date:' + moment(vm.pickerDate).utc().hour(23).minute(59).format(); - } - - if (event.keyCode != 13 || !tag.type || !tag.value) { - return - } - vm.showDatePicker = false; - // aka we selected one of main options - vm.addSearchTag({type: tag.type, value: tag.value}); - // clear typeahead - vm.filterTypeAhead = undefined; - }; - - - vm.pickerDateChanged = function(){ - if (vm.filterTypeAhead.indexOf('start_date:') == '0') { - vm.filterTypeAhead = 'start_date:' + moment(vm.pickerDate).utc().format(); - } - else if (vm.filterTypeAhead.indexOf('end_date:') == '0') { - vm.filterTypeAhead = 'end_date:' + moment(vm.pickerDate).utc().hour(23).minute(59).format(); - } - vm.showDatePicker = false; - }; - - vm.fetchLogs = function (searchParams) { - vm.isLoading.logs = true; - logsNoIdResource.query(searchParams, function (data, getResponseHeaders) { - vm.isLoading.logs = false; - var headers = getResponseHeaders(); - vm.logsPage = data; - vm.itemCount = headers['x-total-count']; - vm.itemsPerPage = headers['x-items-per-page']; - }, function () { - vm.isLoading.logs = false; - }); - }; - - vm.fetchSeriesData = function (searchParams) { - searchParams['section'] = 'logs_section'; - searchParams['view'] = 'fetch_series'; - vm.isLoading.series = true; - sectionViewResource.query(searchParams, function (data) { - - vm.logEventsChartData = { - json: data, - xFormat: '%Y-%m-%dT%H:%M:%S', - keys: { - x: 'x', - value: ["logs"] - }, - names: { - logs: 'Log events' + vm.metricsChartConfig = { + data: { + json: [], + xFormat: '%Y-%m-%dT%H:%M:%S', + keys: { + x: 'x', + value: ["main", "sql", "nosql", "tmpl", "remote", "custom"] + }, + names: { + main: 'View/Application logic', + sql: 'Relational database queries', + nosql: 'NoSql datastore calls', + tmpl: 'Template rendering', + custom: 'Custom timed calls', + remote: 'Requests to remote resources' + }, + type: 'area', + groups: [["main", "sql", "nosql", "remote", "custom", "tmpl"]], + order: null + }, + color: { + pattern: ['#6baed6', '#c7e9c0', '#fd8d3c', '#d6616b', '#ffcc00', '#c6dbef'] + }, + axis: { + x: { + type: 'timeseries', + tick: { + culling: { + max: 6 // the number of tick texts will be adjusted to less than this value + }, + format: '%Y-%m-%d %H:%M' + } + }, + y: { + tick: { + count: 5, + format: d3.format('.2f') + } + } + }, + point: { + show: false + }, + subchart: { + show: true, + size: { + height: 20 + } + }, + size: { + height: 350 + }, + zoom: { + rescale: true + }, + grid: { + x: { + show: true + }, + y: { + show: true + } + }, + tooltip: { + format: { + title: function (d) { + return '' + d; }, - type: 'bar' - }; - vm.isLoading.series = false; - }, function () { - vm.isLoading.series = false; - }); - }; - - vm.filterId = function (log) { - $location.search('request_id', log.request_id); - vm.refresh(); - }; - - vm.refresh = function(){ - vm.searchParams = parseSearchToTags($location.search()); - vm.page = Number(vm.searchParams.page) || 1; - var params = parseTagsToSearch(vm.searchParams); - vm.fetchLogs(params); - vm.fetchSeriesData(params); + value: function (v) { + return v + } + } + } }; - console.info('page load'); - vm.refresh(); -} - -;// # Copyright (C) 2010-2016 RhodeCode GmbH -// # -// # This program is free software: you can redistribute it and/or modify -// # it under the terms of the GNU Affero General Public License, version 3 -// # (only), as published by the Free Software Foundation. -// # -// # This program is distributed in the hope that it will be useful, -// # but WITHOUT ANY WARRANTY; without even the implied warranty of -// # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// # GNU General Public License for more details. -// # -// # You should have received a copy of the GNU Affero General Public License -// # along with this program. If not, see . -// # -// # This program is dual-licensed. If you wish to learn more about the -// # AppEnlight Enterprise Edition, including its added features, Support -// # services, and proprietary license terms, please see -// # https://rhodecode.com/licenses/ - -angular.module('appenlight.components.reportView', []) - .component('reportView', { - templateUrl: 'components/views/report-view/report-view.html', - controller: ReportViewController - }); - -ReportViewController.$inject = ['$window', '$location', '$state', '$uibModal', - '$cookies', 'reportGroupPropertyResource', 'reportGroupResource', - 'logsNoIdResource', 'stateHolder']; + vm.metricsChartData = {}; -function ReportViewController($window, $location, $state, $uibModal, $cookies, reportGroupPropertyResource, reportGroupResource, logsNoIdResource, stateHolder) { - var vm = this; - vm.window = $window; - vm.stateHolder = stateHolder; - vm.$state = $state; - vm.reportHistoryConfig = { + vm.responseChartConfig = { data: { json: [], xFormat: '%Y-%m-%dT%H:%M:%S' }, color: { - pattern: ['#6baed6', '#e6550d', '#74c476', '#fdd0a2', '#8c564b'] + pattern: ['#d6616b', '#6baed6', '#fd8d3c'] }, axis: { x: { type: 'timeseries', tick: { - format: '%Y-%m-%d' + culling: { + max: 6 // the number of tick texts will be adjusted to less than this value + }, + format: '%Y-%m-%d %H:%M' } }, y: { tick: { count: 5, - format: d3.format('.2s') + format: d3.format('.2f') } } }, + point: { + show: false + }, subchart: { show: true, size: { @@ -8826,7 +8643,7 @@ function ReportViewController($window, $location, $state, $uibModal, $cookies, r } }, size: { - height: 250 + height: 350 }, zoom: { rescale: true @@ -8850,599 +8667,499 @@ function ReportViewController($window, $location, $state, $uibModal, $cookies, r } } }; - vm.mentionedPeople = []; - vm.reportHistoryData = {}; - vm.textTraceback = true; - vm.rawTraceback = ''; - vm.traceback = ''; - vm.reportType = 'report'; - vm.report = null; - vm.showLong = false; - vm.reportLogs = null; - vm.requestStats = null; - vm.comment = null; - vm.is_loading = { - report: true, - logs: true, - history: true - }; - - vm.searchMentionedPeople = function(term){ - //vm.mentionedPeople = []; - var term = term.toLowerCase(); - reportGroupPropertyResource.get({ - groupId: vm.report.group_id, - key: 'assigned_users' - }, null, - function (data) { - var users = []; - _.each(data.assigned, function(u){ - users.push({label: u.user_name}); - }); - _.each(data.unassigned, function(u){ - users.push({label: u.user_name}); - }); - - var result = _.filter(users, function(u){ - return u.label.toLowerCase().indexOf(term) !== -1; - }); - vm.mentionedPeople = result; - }); - }; + vm.responseChartData = {}; - vm.searchTag = function (tag, value) { - - if (vm.report.report_type === 3) { - $location.url($state.href('report.list_slow')); - } - else { - $location.url($state.href('report.list')); + vm.requestsChartConfig = { + data: { + json: [], + xFormat: '%Y-%m-%dT%H:%M:%S' + }, + color: { + pattern: ['#d6616b', '#6baed6', '#fd8d3c'] + }, + axis: { + x: { + type: 'timeseries', + tick: { + culling: { + max: 6 // the number of tick texts will be adjusted to less than this value + }, + format: '%Y-%m-%d %H:%M' + } + }, + y: { + tick: { + count: 5, + format: d3.format('.2f') + } + } + }, + point: { + show: false + }, + subchart: { + show: true, + size: { + height: 20 + } + }, + size: { + height: 350 + }, + zoom: { + rescale: true + }, + grid: { + x: { + show: true + }, + y: { + show: true + } + }, + tooltip: { + format: { + title: function (d) { + return '' + d; + }, + value: function (v) { + return v + } + } } - $location.search(tag, value); }; + vm.requestsChartData = {}; - vm.tabs = { - slow_calls:false, - request_details:false, - logs:false, - comments:false, - affected_users:false + vm.loading = { + 'apdex': true, + 'reports': true, + 'graphs': true, + 'slowCalls': true, + 'slowURIS': true, + 'requestsBreakdown': true, + 'series': true }; - if ($cookies.selectedReportTab) { - vm.tabs[$cookies.selectedReportTab] = true; - } - else{ - $cookies.selectedReportTab = 'request_details'; - vm.tabs.request_details = true; - } + vm.stream = {paused: false, filtered: false, messages: [], reports: []}; - vm.fetchLogs = function () { - if (!vm.report.request_id){ + $rootScope.$on('channelstream-message.front_dashboard.new_topic', function(event, message){ + var ws_report = message.message.report; + if (ws_report.http_status != 500) { return } - vm.is_loading.logs = true; - logsNoIdResource.query({request_id: vm.report.request_id}, - function (data) { - vm.is_loading.logs = false; - vm.reportLogs = data; - }, function () { - vm.is_loading.logs = false; + if (vm.stream.paused == true) { + return + } + if (vm.stream.filtered && ws_report.resource_id != vm.resource) { + return + } + var should_insert = true; + _.each(vm.stream.reports, function (report) { + if (report.report_id == ws_report.report_id) { + report.occurences = ws_report.occurences; + should_insert = false; + } }); - }; - vm.addComment = function () { - reportGroupPropertyResource.save({ - groupId: vm.report.group_id, - key: 'comments' - }, {body: vm.comment}, - function (data) { - vm.report.comments.push(data); - }); - vm.comment = ''; - }; + if (should_insert) { + if (vm.stream.reports.length > 7) { + vm.stream.reports.pop(); + } + vm.stream.reports.unshift(ws_report); + } + }); - vm.fetchReport = function () { - vm.is_loading.report = true; - reportGroupResource.get($state.params, function (data) { - vm.is_loading.report = false; - if (data.request) { - try { - var to_sort = _.pairs(data.request); - data.request = _.object(_.sortBy(to_sort, function (i) { - return i[0] - })); + vm.determineStartState = function () { + if (stateHolder.AeUser.applications.length) { + vm.resource = Number($location.search().resource); + + if (!vm.resource){ + var cookieResource = $cookies.getObject('resource'); + + + if (cookieResource) { + vm.resource = cookieResource; } - catch (err) { + else{ + vm.resource = stateHolder.AeUser.applications[0].resource_id; } } - vm.report = data; - if (vm.report.req_stats) { - vm.requestStats = []; - _.each(_.pairs(vm.report.req_stats['percentages']), function (p) { - vm.requestStats.push({ - name: p[0], - value: vm.report.req_stats[p[0]].toFixed(3), - percent: p[1], - calls: vm.report.req_stats[p[0] + '_calls'] - }) - }); - } - vm.traceback = data.traceback; - _.each(vm.traceback, function (frame) { - if (frame.line) { - vm.rawTraceback += 'File ' + frame.file + ' line ' + frame.line + ' in ' + frame.fn + ": \r\n"; - } - vm.rawTraceback += ' ' + frame.cline + "\r\n"; - }); + } - if (stateHolder.AeUser.id){ - vm.fetchHistory(); - } + var timespan = $location.search().timespan; - vm.selectedTab($cookies.selectedReportTab); + if(_.has(vm.timeOptions, timespan)){ + vm.timeSpan = vm.timeOptions[timespan]; + } + else{ + vm.timeSpan = vm.timeOptions['1h']; + } - }, function (response) { - - if (response.status == 403) { - var uid = response.headers('x-appenlight-uid'); - if (!uid) { - window.location = '/register?came_from=' + encodeURIComponent(window.location); - } - } - vm.is_loading.report = false; - }); + var graphType = $location.search().graphtype; + if(!graphType){ + vm.graphType = {selected: 'metrics_graphs'}; + } + else{ + vm.graphType = {selected: graphType}; + } + vm.updateSearchParams(); }; - vm.selectedTab = function(tab_name){ - $cookies.selectedReportTab = tab_name; - if (tab_name == 'logs' && vm.reportLogs === null) { - vm.fetchLogs(); + vm.updateSearchParams = function () { + $location.search('resource', vm.resource); + $location.search('timespan', vm.timeSpan.key); + $location.search('graphtype', vm.graphType.selected); + stateHolder.resource = vm.resource; + + if (vm.resource){ + $cookies.putObject('resource', vm.resource, + {expires:new Date(3000, 1, 1)}); } + vm.refreshData(); }; - vm.markFixed = function () { - reportGroupResource.update({ - groupId: vm.report.group_id - }, {fixed: !vm.report.group.fixed}, - function (data) { - vm.report.group.fixed = data.fixed; - }); + vm.refreshData = function () { + vm.fetchApdexStats(); + vm.fetchTrendingReports(); + vm.fetchMetrics(); + vm.fetchRequestsBreakdown(); + vm.fetchSlowCalls(); }; - vm.markPublic = function () { - reportGroupResource.update({ - groupId: vm.report.group_id - }, {public: !vm.report.group.public}, - function (data) { - vm.report.group.public = data.public; - }); + vm.changedTimeSpan = function(){ + vm.startDateFilter = timeSpanToStartDate(vm.timeSpan.key); + vm.refreshData(); }; - vm.delete = function () { - reportGroupResource.delete({'groupId': vm.report.group_id}, - function (data) { - $state.go('report.list'); - }) - }; + vm.intervalId = $interval(function () { + if (_.contains(['30m', "1h"], vm.timeSpan.key)) { + // don't do anything if window is unfocused + if(document.hidden === true){ + return ; + } + vm.refreshData(); + } + }, 60000); - vm.assignUsersModal = function (index) { - vm.opts = { - backdrop: 'static', - templateUrl: 'AssignReportCtrl.html', - controller: 'AssignReportCtrl as ctrl', - resolve: { - report: function () { - return vm.report; - } - } - }; - var modalInstance = $uibModal.open(vm.opts); - modalInstance.result.then(function (report) { + vm.fetchApdexStats = function () { + vm.loading.apdex = true; + vm.apdexStats = applicationsPropertyResource.query({ + 'key': 'apdex_stats', + 'resourceId': vm.resource, + "start_date": timeSpanToStartDate(vm.timeSpan.key) + }, + function (data) { + vm.loading.apdex = false; - }, function () { - console.info('Modal dismissed at: ' + new Date()); - }); + vm.exceptions = _.reduce(data, function (memo, row) { + return memo + row.errors; + }, 0); + vm.satisfyingRequests = _.reduce(data, function (memo, row) { + return memo + row.satisfying_requests; + }, 0); + vm.toleratedRequests = _.reduce(data, function (memo, row) { + return memo + row.tolerated_requests; + }, 0); + vm.frustratingRequests = _.reduce(data, function (memo, row) { + return memo + row.frustrating_requests; + }, 0); + if (data.length) { + vm.uptimeStats = data[0].uptime; + } - }; + }, + function () { + vm.loading.apdex = false; + } + ); + } - vm.fetchHistory = function () { - reportGroupPropertyResource.query({ - groupId: vm.report.group_id, - key: 'history' + vm.fetchMetrics = function () { + vm.loading.series = true; + applicationsPropertyResource.query({ + 'resourceId': vm.resource, + 'key': vm.graphType.selected, + "start_date": timeSpanToStartDate(vm.timeSpan.key) }, function (data) { - vm.reportHistoryData = { - json: data, - keys: { - x: 'x', - value: ["reports"] - }, - names: { - reports: 'Reports history' - }, - type: 'bar' - }; - vm.is_loading.history = false; - }); - }; - - vm.nextDetail = function () { - $state.go('report.view_detail', { - groupId: vm.report.group_id, - reportId: vm.report.group.next_report - }); - }; - vm.previousDetail = function () { - $state.go('report.view_detail', { - groupId: vm.report.group_id, - reportId: vm.report.group.previous_report - }); - }; - - vm.runIntegration = function (integration_name) { - - if (integration_name == 'bitbucket') { - var controller = 'BitbucketIntegrationCtrl as ctrl'; - var template_url = 'templates/integrations/bitbucket.html'; - } - else if (integration_name == 'github') { - var controller = 'GithubIntegrationCtrl as ctrl'; - var template_url = 'templates/integrations/github.html'; - } - else if (integration_name == 'jira') { - var controller = 'JiraIntegrationCtrl as ctrl'; - var template_url = 'templates/integrations/jira.html'; - } - else { - return false; - } - - vm.opts = { - backdrop: 'static', - templateUrl: template_url, - controller: controller, - resolve: { - integrationName: function () { - return integration_name - }, - report: function () { - return vm.report; - } + if (vm.graphType.selected == 'metrics_graphs') { + vm.metricsChartData = { + json: data, + xFormat: '%Y-%m-%dT%H:%M:%S', + keys: { + x: 'x', + value: ["main", "sql", "nosql", "tmpl", "remote", "custom"] + }, + names: { + main: 'View/Application logic', + sql: 'Relational database queries', + nosql: 'NoSql datastore calls', + tmpl: 'Template rendering', + custom: 'Custom timed calls', + remote: 'Requests to remote resources' + }, + type: 'area', + groups: [["main", "sql", "nosql", "remote", "custom", "tmpl"]], + order: null + }; } - }; - var modalInstance = $uibModal.open(vm.opts); - modalInstance.result.then(function (report) { - - }, function () { - console.info('Modal dismissed at: ' + new Date()); - }); - - }; - - // load report - vm.fetchReport(); - - -} - -;// # Copyright (C) 2010-2016 RhodeCode GmbH -// # -// # This program is free software: you can redistribute it and/or modify -// # it under the terms of the GNU Affero General Public License, version 3 -// # (only), as published by the Free Software Foundation. -// # -// # This program is distributed in the hope that it will be useful, -// # but WITHOUT ANY WARRANTY; without even the implied warranty of -// # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// # GNU General Public License for more details. -// # -// # You should have received a copy of the GNU Affero General Public License -// # along with this program. If not, see . -// # -// # This program is dual-licensed. If you wish to learn more about the -// # AppEnlight Enterprise Edition, including its added features, Support -// # services, and proprietary license terms, please see -// # https://rhodecode.com/licenses/ - -angular.module('appenlight.components.reportsBrowserView', []) - .component('reportsBrowserView', { - templateUrl: 'components/views/reports-browser-view/reports-browser-view.html', - controller: reportsBrowserViewController - }); - -reportsBrowserViewController.$inject = ['$location', '$cookies', - 'stateHolder', 'typeAheadTagHelper', 'reportsResource']; - -function reportsBrowserViewController($location, $cookies, stateHolder, - typeAheadTagHelper, reportsResource) { - var vm = this; - vm.applications = stateHolder.AeUser.applications_map; - stateHolder.section = 'reports'; - vm.today = function () { - vm.pickerDate = new Date(); - }; - vm.today(); - vm.reportsPage = []; - vm.page = 1; - vm.itemCount = 0; - vm.itemsPerPage = 250; - typeAheadTagHelper.tags = []; - vm.searchParams = {tags: [], page: 1, type: 'report'}; - vm.is_loading = false; - vm.filterTypeAheadOptions = [ - { - type: 'error', - text: 'error:', - 'description': 'Full-text search in your reports', - example: 'error:text-im-looking-for', - tag: 'Error' - }, - { - type: 'view_name', - text: 'view_name:', - 'description': 'Query reports occured in specific views', - example: "view_name:module.foo", - tag: 'View Name' - }, - { - type: 'resource', - text: 'resource:', - 'description': 'Restrict resultset to application', - example: "resource:ID", - tag: 'Application' - }, - { - type: 'priority', - text: 'priority:', - 'description': 'Show reports with specific priority', - example: 'priority:8', - tag: 'Priority' - }, - { - type: 'min_occurences', - text: 'min_occurences:', - 'description': 'Show reports from groups with at least X occurences', - example: 'min_occurences:25', - tag: 'Occurences' - }, - { - type: 'url_path', - text: 'url_path:', - 'description': 'Show reports from specific URL paths', - example: 'url_path:/foo/bar/baz', - tag: 'Url Path' - }, - { - type: 'url_domain', - text: 'url_domain:', - 'description': 'Show reports from specific domain', - example: 'url_domain:domain.com', - tag: 'Domain' - }, - { - type: 'report_status', - text: 'report_status:', - 'description': 'Show reports from groups with specific status', - example: 'report_status:never_reviewed', - tag: 'Status' - }, - { - type: 'request_id', - text: 'request_id:', - 'description': 'Show reports with specific request id', - example: "request_id:883143dc572e4c38aceae92af0ea5ae0", - tag: 'Request ID' - }, - { - type: 'server_name', - text: 'server_name:', - 'description': 'Show reports tagged with this key/value pair', - example: 'server_name:hostname', - tag: 'Tag' - }, - { - type: 'http_status', - text: 'http_status:', - 'description': 'Show reports with specific HTTP status code', - example: "http_status:", - tag: 'HTTP Status' - }, - { - type: 'http_status', - text: 'http_status:500', - 'description': 'Show reports with specific HTTP status code', - example: "http_status:500", - tag: 'HTTP Status' - }, - { - type: 'http_status', - text: 'http_status:404', - 'description': 'Include 404 reports in your search', - example: "http_status:404", - tag: 'HTTP Status' - }, - { - type: 'start_date', - text: 'start_date:', - 'description': 'Show reports newer than this date (press TAB for dropdown)', - example: 'start_date:2014-08-15T13:00', - tag: 'Start Date' - }, - { - type: 'end_date', - text: 'end_date:', - 'description': 'Show reports older than this date (press TAB for dropdown)', - example: 'start_date:2014-08-15T23:59', - tag: 'End Date' - } - ]; - - vm.filterTypeAhead = undefined; - vm.showDatePicker = false; - vm.manualOpen = false; - vm.aheadFilter = typeAheadTagHelper.aheadFilter; - vm.removeSearchTag = function (tag) { - $location.search(tag.type, null); - vm.refresh(); - }; - vm.addSearchTag = function (tag) { - $location.search(tag.type, tag.value); - vm.refresh(); - }; - vm.notRelativeTime = false; - if ($cookies.notRelativeTime) { - vm.notRelativeTime = JSON.parse($cookies.notRelativeTime); + else if (vm.graphType.selected == 'report_graphs') { + vm.reportChartData = { + json: data, + xFormat: '%Y-%m-%dT%H:%M:%S', + keys: { + x: 'x', + value: ["not_found", "report"] + }, + names: { + report: 'Errors', + not_found: '404\'s requests' + }, + type: 'bar' + }; + } + else if (vm.graphType.selected == 'slow_report_graphs') { + vm.reportSlowChartData = { + json: data, + xFormat: '%Y-%m-%dT%H:%M:%S', + keys: { + x: 'x', + value: ["slow_report"] + }, + names: { + slow_report: 'Slow reports' + }, + type: 'bar' + }; + } + else if (vm.graphType.selected == 'response_graphs') { + vm.responseChartData = { + json: data, + xFormat: '%Y-%m-%dT%H:%M:%S', + keys: { + x: 'x', + value: ["today", "days_ago_2", "days_ago_7"] + }, + names: { + today: 'Today', + "days_ago_2": '2 days ago', + "days_ago_7": '7 days ago' + } + }; + } + else if (vm.graphType.selected == 'requests_graphs') { + vm.requestsChartData = { + json: data, + xFormat: '%Y-%m-%dT%H:%M:%S', + keys: { + x: 'x', + value: ["requests"] + }, + names: { + requests: 'Requests/s' + } + }; + } + vm.loading.series = false; + }, function(){ + vm.loading.series = false; + }); } - vm.changeRelativeTime = function () { - $cookies.notRelativeTime = JSON.stringify(vm.notRelativeTime); - }; - - _.each(_.range(1, 11), function (priority) { - vm.filterTypeAheadOptions.push({ - type: 'priority', - text: 'priority:' + priority.toString(), - description: 'Show entries with specific priority', - example: 'priority:' + priority, - tag: 'Priority' - }); - }); - _.each(['never_reviewed', 'reviewed', 'fixed', 'public'], function (status) { - vm.filterTypeAheadOptions.push({ - type: 'report_status', - text: 'report_status:' + status, - 'description': 'Show only reports with this status', - example: 'report_status:' + status, - tag: 'Status ' + status.toUpperCase() + vm.fetchSlowCalls = function () { + vm.loading.slowCalls = true; + applicationsPropertyResource.query({ + 'resourceId': vm.resource, + "start_date": timeSpanToStartDate(vm.timeSpan.key), + 'key': 'slow_calls' + }, function (data) { + vm.slowCalls = data; + vm.loading.slowCalls = false; + }, function () { + vm.loading.slowCalls = false; }); - }); - _.each(stateHolder.AeUser.applications, function (item) { - vm.filterTypeAheadOptions.push({ - type: 'resource', - text: 'resource:' + item.resource_id + ':' + item.resource_name, - example: 'resource:' + item.resource_id, - 'tag': item.resource_name, - 'description': 'Restrict resultset to this application' + } + + vm.fetchRequestsBreakdown = function () { + vm.loading.requestsBreakdown = true; + applicationsPropertyResource.query({ + 'resourceId': vm.resource, + "start_date": timeSpanToStartDate(vm.timeSpan.key), + 'key': 'requests_breakdown' + }, function (data) { + vm.requestsBreakdown = data; + vm.loading.requestsBreakdown = false; + }, function () { + vm.loading.requestsBreakdown = false; }); - }); + } - vm.paginationChange = function(){ - $location.search('page', vm.page); - vm.refresh(); - }; + vm.fetchTrendingReports = function () { - vm.typeAheadTag = function (event) { - var text = vm.filterTypeAhead; - if (_.isObject(vm.filterTypeAhead)) { - text = vm.filterTypeAhead.text; + if (vm.graphType.selected == 'slow_report_graphs') { + var report_type = 'slow'; } - if (!vm.filterTypeAhead) { - return + else { + var report_type = 'error'; } - var parsed = text.split(':'); - var tag = {'type': null, 'value': null}; - // app tags have : twice - if (parsed.length > 2 && parsed[0] == 'resource') { - tag.type = 'resource'; - tag.value = parsed[1]; - } - // normal tag:value - else if (parsed.length > 1) { - tag.type = parsed[0]; - var tagValue = parsed.slice(1); - if (tagValue) { - tag.value = tagValue.join(':'); + vm.loading.reports = true; + vm.trendingReports = applicationsPropertyResource.query({ + 'key': 'trending_reports', + 'resourceId': vm.resource, + "start_date": timeSpanToStartDate(vm.timeSpan.key), + "report_type": report_type + }, + function () { + vm.loading.reports = false; + }, + function () { + vm.loading.reports = false; } - } - else { - tag.type = 'error'; - tag.value = parsed.join(':'); - } + ); + }; - // set datepicker hour based on type of field - if ('start_date:' == text) { - vm.showDatePicker = true; - vm.filterTypeAhead = 'start_date:' + moment(vm.pickerDate).utc().format(); - } - else if ('end_date:' == text) { - vm.showDatePicker = true; - vm.filterTypeAhead = 'end_date:' + moment(vm.pickerDate).utc().hour(23).minute(59).format(); - } + $scope.$on('$destroy',function(){ + $interval.cancel(vm.intervalId); + }); - if (event.keyCode != 13 || !tag.type || !tag.value) { - return - } - vm.showDatePicker = false; - // aka we selected one of main options - vm.addSearchTag({type: tag.type, value: tag.value}); - // clear typeahead - vm.filterTypeAhead = undefined; - }; + if (stateHolder.AeUser.applications.length){ + vm.show_dashboard = true; + vm.determineStartState(); + } +} - vm.pickerDateChanged = function(){ - if (vm.filterTypeAhead.indexOf('start_date:') == '0') { - vm.filterTypeAhead = 'start_date:' + moment(vm.pickerDate).utc().format(); - } - else if (vm.filterTypeAhead.indexOf('end_date:') == '0') { - vm.filterTypeAhead = 'end_date:' + moment(vm.pickerDate).utc().hour(23).minute(59).format(); - } - vm.showDatePicker = false; +;// # Copyright (C) 2010-2016 RhodeCode GmbH +// # +// # This program is free software: you can redistribute it and/or modify +// # it under the terms of the GNU Affero General Public License, version 3 +// # (only), as published by the Free Software Foundation. +// # +// # This program is distributed in the hope that it will be useful, +// # but WITHOUT ANY WARRANTY; without even the implied warranty of +// # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// # GNU General Public License for more details. +// # +// # You should have received a copy of the GNU Affero General Public License +// # along with this program. If not, see . +// # +// # This program is dual-licensed. If you wish to learn more about the +// # AppEnlight Enterprise Edition, including its added features, Support +// # services, and proprietary license terms, please see +// # https://rhodecode.com/licenses/ + + +ApplicationsIntegrationsEditViewController.$inject = ['$state', 'integrationResource']; + +function ApplicationsIntegrationsEditViewController($state, integrationResource) { + + var vm = this; + vm.$state = $state; + vm.loading = {integration: true}; + vm.config = integrationResource.get( + { + integration: $state.params.integration, + action: 'setup', + resourceId: $state.params.resourceId + }, function (data) { + vm.loading.integration = false; + }); + + vm.configureIntegration = function () { + console.info('configureIntegration'); + vm.loading.integration = true; + integrationResource.save( + { + integration: $state.params.integration, + action: 'setup', + resourceId: $state.params.resourceId + }, vm.config, function (data) { + vm.loading.integration = false; + setServerValidation(vm.integrationForm); + }, function (response) { + if (response.status == 422) { + setServerValidation(vm.integrationForm, response.data); + } + vm.loading.integration = false; + }); }; - var reportPresentation = function (report) { - report.presentation = {}; - if (report.group.public) { - report.presentation.className = 'public'; - report.presentation.tooltip = 'Public'; - } - else if (report.group.fixed) { - report.presentation.className = 'fixed'; - report.presentation.tooltip = 'Fixed'; - } - else if (report.group.read) { - report.presentation.className = 'reviewed'; - report.presentation.tooltip = 'Reviewed'; - } - else { - report.presentation.className = 'new'; - report.presentation.tooltip = 'New'; - } - return report; - }; + vm.removeIntegration = function () { + console.info('removeIntegration'); + integrationResource.remove({ + integration: $state.params.integration, + resourceId: $state.params.resourceId, + action: 'delete' + }, + function () { + $state.go('applications.integrations', + {resourceId: $state.params.resourceId}); + } + ); + } + + vm.testIntegration = function (to_test) { + console.info('testIntegration', to_test); + vm.loading.integration = true; + integrationResource.save( + { + integration: $state.params.integration, + action: 'test_' + to_test, + resourceId: $state.params.resourceId + }, vm.config, function (data) { + vm.loading.integration = false; + }, function (response) { + vm.loading.integration = false; + }); + } + + +} + +;angular.module('appenlight.components.bitbucketIntegrationConfigView', []) + .component('bitbucketIntegrationConfigView', { + templateUrl: 'components/views/integrations/bitbucket-integration-config-view/bitbucket-integration-config-view.html', + controller: ApplicationsIntegrationsEditViewController + }); + +;angular.module('appenlight.components.campfireIntegrationConfigView', []) + .component('campfireIntegrationConfigView', { + templateUrl: 'components/views/integrations/campfire-integration-config-view/campfire-integration-config-view.html', + controller: ApplicationsIntegrationsEditViewController + }); + +;angular.module('appenlight.components.flowdockIntegrationConfigView', []) + .component('flowdockIntegrationConfigView', { + templateUrl: 'components/views/integrations/flowdock-integration-config-view/flowdock-integration-config-view.html', + controller: ApplicationsIntegrationsEditViewController + }); + +;angular.module('appenlight.components.githubIntegrationConfigView', []) + .component('githubIntegrationConfigView', { + templateUrl: 'components/views/integrations/github-integration-config-view/github-integration-config-view.html', + controller: ApplicationsIntegrationsEditViewController + }); - vm.fetchReports = function (searchParams) { - vm.is_loading = true; - reportsResource.query(searchParams, function (data, getResponseHeaders) { - var headers = getResponseHeaders(); - - vm.is_loading = false; - vm.reportsPage = _.map(data, function (item) { - return reportPresentation(item); - }); - vm.itemCount = headers['x-total-count']; - vm.itemsPerPage = headers['x-items-per-page']; - }, function () { - vm.is_loading = false; - }); - }; +;angular.module('appenlight.components.hipchatIntegrationConfigView', []) + .component('hipchatIntegrationConfigView', { + templateUrl: 'components/views/integrations/hipchat-integration-config-view/hipchat-integration-config-view.html', + controller: ApplicationsIntegrationsEditViewController + }); - vm.filterId = function (log) { - vm.searchParams.tags.push({ - type: "request_id", - value: log.request_id - }); - vm.refresh(); - }; +;angular.module('appenlight.components.jiraIntegrationConfigView', []) + .component('jiraIntegrationConfigView', { + templateUrl: 'components/views/integrations/jira-integration-config-view/jira-integration-config-view.html', + controller: ApplicationsIntegrationsEditViewController + }); - vm.refresh = function(){ - vm.searchParams = parseSearchToTags($location.search()); - vm.page = Number(vm.searchParams.page) || 1; - var params = parseTagsToSearch(vm.searchParams); - - vm.fetchReports(params); - }; - // initial load - vm.refresh(); -} +;angular.module('appenlight.components.slackIntegrationConfigView', []) + .component('slackIntegrationConfigView', { + templateUrl: 'components/views/integrations/slack-integration-config-view/slack-integration-config-view.html', + controller: ApplicationsIntegrationsEditViewController + }); + +;angular.module('appenlight.components.webhooksIntegrationConfigView', []) + .component('webhooksIntegrationConfigView', { + templateUrl: 'components/views/integrations/webhooks-integration-config-view/webhooks-integration-config-view.html', + controller: ApplicationsIntegrationsEditViewController + }); ;// # Copyright (C) 2010-2016 RhodeCode GmbH // # @@ -9463,41 +9180,100 @@ function reportsBrowserViewController($location, $cookies, stateHolder, // # services, and proprietary license terms, please see // # https://rhodecode.com/licenses/ -'use strict'; - -/* Controllers */ - -angular.module('appenlight.components.reportsSlowBrowserView', []) - .component('reportsSlowBrowserView', { - templateUrl: 'components/views/reports-slow-browser-view/reports-slow-browser-view.html', - controller: ReportsSlowBrowserViewController +angular.module('appenlight.components.logsBrowserView', []) + .component('logsBrowserView', { + templateUrl: 'components/views/logs-browser/logs-browser.html', + controller: LogsBrowserController }); -ReportsSlowBrowserViewController.$inject = ['$location', '$cookies', - 'stateHolder', 'typeAheadTagHelper', 'slowReportsResource'] +LogsBrowserController.$inject = ['$location', 'stateHolder', 'typeAheadTagHelper', 'logsNoIdResource', 'sectionViewResource']; -function ReportsSlowBrowserViewController($location, $cookies, stateHolder, typeAheadTagHelper, slowReportsResource) { +function LogsBrowserController($location, stateHolder, typeAheadTagHelper, logsNoIdResource, sectionViewResource) { var vm = this; - vm.applications = stateHolder.AeUser.applications_map; - stateHolder.section = 'slow_reports'; + vm.logEventsChartConfig = { + data: { + json: [], + xFormat: '%Y-%m-%dT%H:%M:%S' + }, + color: { + pattern: ['#6baed6', '#e6550d', '#74c476', '#fdd0a2', '#8c564b'] + }, + axis: { + x: { + type: 'timeseries', + tick: { + format: '%Y-%m-%d' + } + }, + y: { + tick: { + count: 5, + format: d3.format('.2s') + } + } + }, + subchart: { + show: true, + size: { + height: 20 + } + }, + size: { + height: 250 + }, + zoom: { + rescale: true + }, + grid: { + x: { + show: true + }, + y: { + show: true + } + }, + tooltip: { + format: { + title: function (d) { + return '' + d; + }, + value: function (v) { + return v + } + } + } + }; + vm.logEventsChartData = {}; + stateHolder.section = 'logs'; vm.today = function () { vm.pickerDate = new Date(); }; vm.today(); - vm.reportsPage = []; - vm.page = 1; + + vm.applications = stateHolder.AeUser.applications_map; + vm.logsPage = []; vm.itemCount = 0; vm.itemsPerPage = 250; - typeAheadTagHelper.tags = []; - vm.searchParams = {tags: [], page: 1, type: 'slow_report'}; - vm.is_loading = false; + vm.page = 1; + vm.$location = $location; + vm.isLoading = { + logs: true, + series: true + }; vm.filterTypeAheadOptions = [ { - type: 'view_name', - text: 'view_name:', - 'description': 'Query reports occured in specific views', - tag: 'View Name', - example: "view_name:module.foo" + type: 'message', + text: 'message:', + 'description': 'Full-text search in your logs', + tag: 'Message', + example: 'message:text-im-looking-for' + }, + { + type: 'namespace', + text: 'namespace:', + 'description': 'Query logs from specific namespace', + tag: 'Namespace', + example: "namespace:module.foo" }, { type: 'resource', @@ -9507,79 +9283,48 @@ function ReportsSlowBrowserViewController($location, $cookies, stateHolder, type example: "resource:ID" }, { - type: 'priority', - text: 'priority:', - 'description': 'Show reports with specific priority', - example: 'priority:8', - tag: 'Priority' - }, - { - type: 'min_occurences', - text: 'min_occurences:', - 'description': 'Show reports from groups with at least X occurences', - example: 'min_occurences:25', - tag: 'Min. occurences' - }, - { - type: 'min_duration', - text: 'min_duration:', - 'description': 'Show reports from groups with average duration >= Xs', - example: 'min_duration:4.5', - tag: 'Min. duration' - }, - { - type: 'url_path', - text: 'url_path:', - 'description': 'Show reports from specific URL paths', - example: 'url_path:/foo/bar/baz', - tag: 'Url Path' - }, - { - type: 'url_domain', - text: 'url_domain:', - 'description': 'Show reports from specific domain', - example: 'url_domain:domain.com', - tag: 'Domain' - }, - { type: 'request_id', text: 'request_id:', - 'description': 'Show reports with specific request id', + 'description': 'Show logs with specific request id', example: "request_id:883143dc572e4c38aceae92af0ea5ae0", tag: 'Request ID' }, { - type: 'report_status', - text: 'report_status:', - 'description': 'Show reports from groups with specific status', - example: 'report_status:never_reviewed', - tag: 'Status' + type: 'level', + text: 'level:', + 'description': 'Show entries with specific log level', + example: 'level:warning', + tag: 'Level' }, { type: 'server_name', text: 'server_name:', - 'description': 'Show reports tagged with this key/value pair', + 'description': 'Show entries tagged with this key/value pair', example: 'server_name:hostname', tag: 'Tag' }, { type: 'start_date', text: 'start_date:', - 'description': 'Show reports newer than this date (press TAB for dropdown)', + 'description': 'Show results newer than this date (press TAB for dropdown)', example: 'start_date:2014-08-15T13:00', tag: 'Start Date' }, { type: 'end_date', text: 'end_date:', - 'description': 'Show reports older than this date (press TAB for dropdown)', + 'description': 'Show results older than this date (press TAB for dropdown)', example: 'start_date:2014-08-15T23:59', tag: 'End Date' - } + }, + {type: 'level', value: 'debug', text: 'level:debug'}, + {type: 'level', value: 'info', text: 'level:info'}, + {type: 'level', value: 'warning', text: 'level:warning'}, + {type: 'level', value: 'critical', text: 'level:critical'} ]; - - vm.filterTypeAhead = undefined; + vm.filterTypeAhead = null; vm.showDatePicker = false; + vm.manualOpen = false; vm.aheadFilter = typeAheadTagHelper.aheadFilter; vm.removeSearchTag = function (tag) { $location.search(tag.type, null); @@ -9589,36 +9334,14 @@ function ReportsSlowBrowserViewController($location, $cookies, stateHolder, type $location.search(tag.type, tag.value); vm.refresh(); }; - vm.manualOpen = false; - vm.notRelativeTime = false; - if ($cookies.notRelativeTime) { - vm.notRelativeTime = JSON.parse($cookies.notRelativeTime); - } - - vm.changeRelativeTime = function () { - $cookies.notRelativeTime = JSON.stringify(vm.notRelativeTime); + vm.paginationChange = function(){ + $location.search('page', vm.page); + vm.refresh(); }; - _.each(_.range(1, 11), function (priority) { - vm.filterTypeAheadOptions.push({ - type: 'priority', - text: 'priority:' + priority.toString(), - description: 'Show entries with specific priority', - example: 'priority:' + priority, - tag: 'Priority' - }); - }); - _.each(['never_reviewed', 'reviewed', 'fixed', 'public'], function (status) { - vm.filterTypeAheadOptions.push({ - type: 'report_status', - text: 'report_status:' + status, - 'description': 'Show only reports with this status', - example: 'report_status:' + status, - tag: 'Status ' + status.toUpperCase() - }); - }); - _.each(stateHolder.AeUser.applications, function (item) { + + _.each(vm.applications, function (item) { vm.filterTypeAheadOptions.push({ type: 'resource', text: 'resource:' + item.resource_id + ':' + item.resource_name, @@ -9646,10 +9369,11 @@ function ReportsSlowBrowserViewController($location, $cookies, stateHolder, type // normal tag:value else if (parsed.length > 1) { tag.type = parsed[0]; - var tagValue = parsed.slice(1); - if (tagValue) { - tag.value = tagValue.join(':'); - } + tag.value = parsed.slice(1).join(':'); + } + else { + tag.type = 'message'; + tag.value = parsed.join(':'); } // set datepicker hour based on type of field @@ -9672,10 +9396,6 @@ function ReportsSlowBrowserViewController($location, $cookies, stateHolder, type vm.filterTypeAhead = undefined; }; - vm.paginationChange = function(){ - $location.search('page', vm.page); - vm.refresh(); - }; vm.pickerDateChanged = function(){ if (vm.filterTypeAhead.indexOf('start_date:') == '0') { @@ -9687,58 +9407,56 @@ function ReportsSlowBrowserViewController($location, $cookies, stateHolder, type vm.showDatePicker = false; }; - var reportPresentation = function (report) { - report.presentation = {}; - if (report.group.public) { - report.presentation.className = 'public'; - report.presentation.tooltip = 'Public'; - } - else if (report.group.fixed) { - report.presentation.className = 'fixed'; - report.presentation.tooltip = 'Fixed'; - } - else if (report.group.read) { - report.presentation.className = 'reviewed'; - report.presentation.tooltip = 'Reviewed'; - } - else { - report.presentation.className = 'new'; - report.presentation.tooltip = 'New'; - } - return report; - }; - - vm.fetchReports = function (searchParams) { - vm.is_loading = true; - slowReportsResource.query(searchParams, function (data, getResponseHeaders) { + vm.fetchLogs = function (searchParams) { + vm.isLoading.logs = true; + logsNoIdResource.query(searchParams, function (data, getResponseHeaders) { + vm.isLoading.logs = false; var headers = getResponseHeaders(); - - vm.is_loading = false; - vm.reportsPage = _.map(data, function (item) { - return reportPresentation(item); - }); + vm.logsPage = data; vm.itemCount = headers['x-total-count']; vm.itemsPerPage = headers['x-items-per-page']; }, function () { - vm.is_loading = false; + vm.isLoading.logs = false; }); }; - vm.filterId = function (log) { - vm.searchParams.tags.push({ - type: "request_id", - value: log.request_id + vm.fetchSeriesData = function (searchParams) { + searchParams['section'] = 'logs_section'; + searchParams['view'] = 'fetch_series'; + vm.isLoading.series = true; + sectionViewResource.query(searchParams, function (data) { + + vm.logEventsChartData = { + json: data, + xFormat: '%Y-%m-%dT%H:%M:%S', + keys: { + x: 'x', + value: ["logs"] + }, + names: { + logs: 'Log events' + }, + type: 'bar' + }; + vm.isLoading.series = false; + }, function () { + vm.isLoading.series = false; }); + }; + + vm.filterId = function (log) { + $location.search('request_id', log.request_id); vm.refresh(); }; + vm.refresh = function(){ vm.searchParams = parseSearchToTags($location.search()); vm.page = Number(vm.searchParams.page) || 1; var params = parseTagsToSearch(vm.searchParams); - vm.fetchReports(params); + vm.fetchLogs(params); + vm.fetchSeriesData(params); }; - - //initial load + console.info('page load'); vm.refresh(); } @@ -9761,275 +9479,345 @@ function ReportsSlowBrowserViewController($location, $cookies, stateHolder, type // # services, and proprietary license terms, please see // # https://rhodecode.com/licenses/ -angular.module('appenlight.components.settingsView', []) - .component('settingsView', { - templateUrl: 'components/views/settings-view/settings-view.html', - controller: SettingsViewController - }); - -SettingsViewController.$inject = ['$state']; - -function SettingsViewController($state) { - this.$state = $state; - console.info('SettingsViewController'); -} - -;// # Copyright (C) 2010-2016 RhodeCode GmbH -// # -// # This program is free software: you can redistribute it and/or modify -// # it under the terms of the GNU Affero General Public License, version 3 -// # (only), as published by the Free Software Foundation. -// # -// # This program is distributed in the hope that it will be useful, -// # but WITHOUT ANY WARRANTY; without even the implied warranty of -// # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// # GNU General Public License for more details. -// # -// # You should have received a copy of the GNU Affero General Public License -// # along with this program. If not, see . -// # -// # This program is dual-licensed. If you wish to learn more about the -// # AppEnlight Enterprise Edition, including its added features, Support -// # services, and proprietary license terms, please see -// # https://rhodecode.com/licenses/ - -angular.module('appenlight.components.userAlertChannelsEmailNewView', []) - .component('userAlertChannelsEmailNewView', { - templateUrl: 'components/views/user-alert-channel-email-new-view/user-alert-channel-email-new-view.html', - controller: AlertChannelsEmailController +angular.module('appenlight.components.reportView', []) + .component('reportView', { + templateUrl: 'components/views/report-view/report-view.html', + controller: ReportViewController }); -AlertChannelsEmailController.$inject = ['$state','userSelfPropertyResource']; +ReportViewController.$inject = ['$window', '$location', '$state', '$uibModal', + '$cookies', 'reportGroupPropertyResource', 'reportGroupResource', + 'logsNoIdResource', 'stateHolder']; -function AlertChannelsEmailController($state, userSelfPropertyResource) { - +function ReportViewController($window, $location, $state, $uibModal, $cookies, reportGroupPropertyResource, reportGroupResource, logsNoIdResource, stateHolder) { var vm = this; + vm.window = $window; + vm.stateHolder = stateHolder; vm.$state = $state; - vm.loading = {email: false}; - vm.form = {}; - - vm.createChannel = function () { - vm.loading.email = true; - - userSelfPropertyResource.save({key: 'alert_channels'}, vm.form, function () { - //vm.loading.email = false; - //setServerValidation(vm.channelForm); - //vm.form = {}; - $state.go('user.alert_channels.list'); - }, function (response) { - if (response.status == 422) { - setServerValidation(vm.channelForm, response.data); + vm.reportHistoryConfig = { + data: { + json: [], + xFormat: '%Y-%m-%dT%H:%M:%S' + }, + color: { + pattern: ['#6baed6', '#e6550d', '#74c476', '#fdd0a2', '#8c564b'] + }, + axis: { + x: { + type: 'timeseries', + tick: { + format: '%Y-%m-%d' + } + }, + y: { + tick: { + count: 5, + format: d3.format('.2s') + } } - vm.loading.email = false; - }); - } -} - -;// # Copyright (C) 2010-2016 RhodeCode GmbH -// # -// # This program is free software: you can redistribute it and/or modify -// # it under the terms of the GNU Affero General Public License, version 3 -// # (only), as published by the Free Software Foundation. -// # -// # This program is distributed in the hope that it will be useful, -// # but WITHOUT ANY WARRANTY; without even the implied warranty of -// # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// # GNU General Public License for more details. -// # -// # You should have received a copy of the GNU Affero General Public License -// # along with this program. If not, see . -// # -// # This program is dual-licensed. If you wish to learn more about the -// # AppEnlight Enterprise Edition, including its added features, Support -// # services, and proprietary license terms, please see -// # https://rhodecode.com/licenses/ + }, + subchart: { + show: true, + size: { + height: 20 + } + }, + size: { + height: 250 + }, + zoom: { + rescale: true + }, + grid: { + x: { + show: true + }, + y: { + show: true + } + }, + tooltip: { + format: { + title: function (d) { + return '' + d; + }, + value: function (v) { + return v + } + } + } + }; + vm.mentionedPeople = []; + vm.reportHistoryData = {}; + vm.textTraceback = true; + vm.rawTraceback = ''; + vm.traceback = ''; + vm.reportType = 'report'; + vm.report = null; + vm.showLong = false; + vm.reportLogs = null; + vm.requestStats = null; + vm.comment = null; + vm.is_loading = { + report: true, + logs: true, + history: true + }; -angular.module('appenlight.components.userAlertChannelsListView', []) - .component('userAlertChannelsListView', { - templateUrl: 'components/views/user-alert-channels-list-view/user-alert-channels-list-view.html', - controller: userAlertChannelsListViewController - }); + vm.searchMentionedPeople = function(term){ + //vm.mentionedPeople = []; + var term = term.toLowerCase(); + reportGroupPropertyResource.get({ + groupId: vm.report.group_id, + key: 'assigned_users' + }, null, + function (data) { + var users = []; + _.each(data.assigned, function(u){ + users.push({label: u.user_name}); + }); + _.each(data.unassigned, function(u){ + users.push({label: u.user_name}); + }); -userAlertChannelsListViewController.$inject = ['$state','userSelfPropertyResource', 'applicationsNoIdResource']; + var result = _.filter(users, function(u){ + return u.label.toLowerCase().indexOf(term) !== -1; + }); + vm.mentionedPeople = result; + }); + }; -function userAlertChannelsListViewController($state, userSelfPropertyResource, applicationsNoIdResource) { - - var vm = this; - vm.$state = $state; - vm.loading = {channels: true, applications: true, actions:true}; + vm.searchTag = function (tag, value) { + + if (vm.report.report_type === 3) { + $location.url($state.href('report.list_slow')); + } + else { + $location.url($state.href('report.list')); + } + $location.search(tag, value); + }; - vm.alertChannels = userSelfPropertyResource.query({key: 'alert_channels'}, - function (data) { - vm.loading.channels = false; - }); + vm.tabs = { + slow_calls:false, + request_details:false, + logs:false, + comments:false, + affected_users:false + }; + if ($cookies.selectedReportTab) { + vm.tabs[$cookies.selectedReportTab] = true; + } + else{ + $cookies.selectedReportTab = 'request_details'; + vm.tabs.request_details = true; + } - vm.alertActions = userSelfPropertyResource.query({key: 'alert_actions'}, - function (data) { - vm.loading.actions = false; + vm.fetchLogs = function () { + if (!vm.report.request_id){ + return + } + vm.is_loading.logs = true; + logsNoIdResource.query({request_id: vm.report.request_id}, + function (data) { + vm.is_loading.logs = false; + vm.reportLogs = data; + }, function () { + vm.is_loading.logs = false; }); + }; + vm.addComment = function () { + reportGroupPropertyResource.save({ + groupId: vm.report.group_id, + key: 'comments' + }, {body: vm.comment}, + function (data) { + vm.report.comments.push(data); + }); + vm.comment = ''; + }; - vm.applications = applicationsNoIdResource.query({permission: 'view'}, - function (data) { - vm.loading.applications = false; + vm.fetchReport = function () { + vm.is_loading.report = true; + reportGroupResource.get($state.params, function (data) { + vm.is_loading.report = false; + if (data.request) { + try { + var to_sort = _.pairs(data.request); + data.request = _.object(_.sortBy(to_sort, function (i) { + return i[0] + })); + } + catch (err) { + } + } + vm.report = data; + if (vm.report.req_stats) { + vm.requestStats = []; + _.each(_.pairs(vm.report.req_stats['percentages']), function (p) { + vm.requestStats.push({ + name: p[0], + value: vm.report.req_stats[p[0]].toFixed(3), + percent: p[1], + calls: vm.report.req_stats[p[0] + '_calls'] + }) + }); + } + vm.traceback = data.traceback; + _.each(vm.traceback, function (frame) { + if (frame.line) { + vm.rawTraceback += 'File ' + frame.file + ' line ' + frame.line + ' in ' + frame.fn + ": \r\n"; + } + vm.rawTraceback += ' ' + frame.cline + "\r\n"; + }); + + if (stateHolder.AeUser.id){ + vm.fetchHistory(); + } + + vm.selectedTab($cookies.selectedReportTab); + + }, function (response) { + + if (response.status == 403) { + var uid = response.headers('x-appenlight-uid'); + if (!uid) { + window.location = '/register?came_from=' + encodeURIComponent(window.location); + } + } + vm.is_loading.report = false; }); + }; - var allOps = { - 'eq': 'Equal', - 'ne': 'Not equal', - 'ge': 'Greater or equal', - 'gt': 'Greater than', - 'le': 'Lesser or equal', - 'lt': 'Lesser than', - 'startswith': 'Starts with', - 'endswith': 'Ends with', - 'contains': 'Contains' + vm.selectedTab = function(tab_name){ + $cookies.selectedReportTab = tab_name; + if (tab_name == 'logs' && vm.reportLogs === null) { + vm.fetchLogs(); + } }; - var fieldOps = {}; - fieldOps['http_status'] = ['eq', 'ne', 'ge', 'le']; - fieldOps['group:priority'] = ['eq', 'ne', 'ge', 'le']; - fieldOps['duration'] = ['ge', 'le']; - fieldOps['url_domain'] = ['eq', 'ne', 'startswith', 'endswith', - 'contains']; - fieldOps['url_path'] = ['eq', 'ne', 'startswith', 'endswith', - 'contains']; - fieldOps['error'] = ['eq', 'ne', 'startswith', 'endswith', - 'contains']; - fieldOps['tags:server_name'] = ['eq', 'ne', 'startswith', 'endswith', - 'contains']; - fieldOps['group:occurences'] = ['eq', 'ne', 'ge', 'le']; + vm.markFixed = function () { + reportGroupResource.update({ + groupId: vm.report.group_id + }, {fixed: !vm.report.group.fixed}, + function (data) { + vm.report.group.fixed = data.fixed; + }); + }; - var possibleFields = { - '__AND__': 'All met (composite rule)', - '__OR__': 'One met (composite rule)', - '__NOT__': 'Not met (composite rule)', - 'http_status': 'HTTP Status', - 'duration': 'Request duration', - 'group:priority': 'Group -> Priority', - 'url_domain': 'Domain', - 'url_path': 'URL Path', - 'error': 'Error', - 'tags:server_name': 'Tag -> Server name', - 'group:occurences': 'Group -> Occurences' + vm.markPublic = function () { + reportGroupResource.update({ + groupId: vm.report.group_id + }, {public: !vm.report.group.public}, + function (data) { + vm.report.group.public = data.public; + }); }; - vm.ruleDefinitions = { - fieldOps: fieldOps, - allOps: allOps, - possibleFields: possibleFields + vm.delete = function () { + reportGroupResource.delete({'groupId': vm.report.group_id}, + function (data) { + $state.go('report.list'); + }) }; - vm.addAction = function (channel) { - - userSelfPropertyResource.save({key: 'alert_channels_rules'}, {}, function (data) { - vm.alertActions.push(data); - }, function (response) { - if (response.status == 422) { - + vm.assignUsersModal = function (index) { + vm.opts = { + backdrop: 'static', + templateUrl: 'AssignReportCtrl.html', + controller: 'AssignReportCtrl as ctrl', + resolve: { + report: function () { + return vm.report; + } } + }; + var modalInstance = $uibModal.open(vm.opts); + modalInstance.result.then(function (report) { + + }, function () { + console.info('Modal dismissed at: ' + new Date()); }); + }; - vm.updateChannel = function (channel, subKey) { - var params = { - key: 'alert_channels', - channel_name: channel['channel_name'], - channel_value: channel['channel_value'] - }; - var toUpdate = {}; - if (['daily_digest', 'send_alerts'].indexOf(subKey) !== -1) { - toUpdate[subKey] = !channel[subKey]; - } - userSelfPropertyResource.update(params, toUpdate, function (data) { - _.extend(channel, data); + vm.fetchHistory = function () { + reportGroupPropertyResource.query({ + groupId: vm.report.group_id, + key: 'history' + }, function (data) { + vm.reportHistoryData = { + json: data, + keys: { + x: 'x', + value: ["reports"] + }, + names: { + reports: 'Reports history' + }, + type: 'bar' + }; + vm.is_loading.history = false; }); }; - vm.removeChannel = function (channel) { - - userSelfPropertyResource.delete({ - key: 'alert_channels', - channel_name: channel.channel_name, - channel_value: channel.channel_value - }, function () { - vm.alertChannels = _.filter(vm.alertChannels, function(item){ - return item != channel; - }); + vm.nextDetail = function () { + $state.go('report.view_detail', { + groupId: vm.report.group_id, + reportId: vm.report.group.next_report }); + }; + vm.previousDetail = function () { + $state.go('report.view_detail', { + groupId: vm.report.group_id, + reportId: vm.report.group.previous_report + }); + }; - } - -} - -;// # Copyright (C) 2010-2016 RhodeCode GmbH -// # -// # This program is free software: you can redistribute it and/or modify -// # it under the terms of the GNU Affero General Public License, version 3 -// # (only), as published by the Free Software Foundation. -// # -// # This program is distributed in the hope that it will be useful, -// # but WITHOUT ANY WARRANTY; without even the implied warranty of -// # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// # GNU General Public License for more details. -// # -// # You should have received a copy of the GNU Affero General Public License -// # along with this program. If not, see . -// # -// # This program is dual-licensed. If you wish to learn more about the -// # AppEnlight Enterprise Edition, including its added features, Support -// # services, and proprietary license terms, please see -// # https://rhodecode.com/licenses/ - -angular.module('appenlight.components.userAuthTokensView', []) - .component('userAuthTokensView', { - templateUrl: 'components/views/user-auth-tokens-view/user-auth-tokens-view.html', - controller: userAuthTokensViewController - }); - -userAuthTokensViewController.$inject = ['$state', 'userSelfPropertyResource', 'AeConfig']; - -function userAuthTokensViewController($state, userSelfPropertyResource, AeConfig) { - - var vm = this; - vm.$state = $state; - vm.loading = {tokens: true}; + vm.runIntegration = function (integration_name) { + + if (integration_name == 'bitbucket') { + var controller = 'BitbucketIntegrationCtrl as ctrl'; + var template_url = 'templates/integrations/bitbucket.html'; + } + else if (integration_name == 'github') { + var controller = 'GithubIntegrationCtrl as ctrl'; + var template_url = 'templates/integrations/github.html'; + } + else if (integration_name == 'jira') { + var controller = 'JiraIntegrationCtrl as ctrl'; + var template_url = 'templates/integrations/jira.html'; + } + else { + return false; + } - vm.expireOptions = AeConfig.timeOptions; + vm.opts = { + backdrop: 'static', + templateUrl: template_url, + controller: controller, + resolve: { + integrationName: function () { + return integration_name + }, + report: function () { + return vm.report; + } + } + }; + var modalInstance = $uibModal.open(vm.opts); + modalInstance.result.then(function (report) { - vm.tokens = userSelfPropertyResource.query({key: 'auth_tokens'}, - function (data) { - vm.loading.tokens = false; + }, function () { + console.info('Modal dismissed at: ' + new Date()); }); - vm.addToken = function () { - vm.loading.tokens = true; - userSelfPropertyResource.save({key: 'auth_tokens'}, - vm.form, - function (data) { - vm.loading.tokens = false; - setServerValidation(vm.TokenForm); - vm.form = {}; - vm.tokens.push(data); - }, function (response) { - vm.loading.tokens = false; - if (response.status == 422) { - setServerValidation(vm.TokenForm, response.data); - } - }) }; - vm.removeToken = function (token) { - userSelfPropertyResource.delete({ - key: 'auth_tokens', - token: token.token - }, - function () { - var index = vm.tokens.indexOf(token); - if (index !== -1) { - vm.tokens.splice(index, 1); - } - }) - } + // load report + vm.fetchReport(); + + } ;// # Copyright (C) 2010-2016 RhodeCode GmbH @@ -10051,151 +9839,306 @@ function userAuthTokensViewController($state, userSelfPropertyResource, AeConfig // # services, and proprietary license terms, please see // # https://rhodecode.com/licenses/ -angular.module('appenlight.components.userIdentitiesView', []) - .component('userIdentitiesView', { - templateUrl: 'components/views/user-identities-view/user-identities-view.html', - controller: UserIdentitiesController +angular.module('appenlight.components.reportsBrowserView', []) + .component('reportsBrowserView', { + templateUrl: 'components/views/reports-browser-view/reports-browser-view.html', + controller: reportsBrowserViewController }); -UserIdentitiesController.$inject = ['$state', 'userSelfPropertyResource', 'AeConfig']; +reportsBrowserViewController.$inject = ['$location', '$cookies', + 'stateHolder', 'typeAheadTagHelper', 'reportsResource']; -function UserIdentitiesController($state, userSelfPropertyResource, AeConfig) { - +function reportsBrowserViewController($location, $cookies, stateHolder, + typeAheadTagHelper, reportsResource) { var vm = this; - vm.$state = $state; - vm.AeConfig = AeConfig; - vm.loading = {identities: true}; - - vm.identities = userSelfPropertyResource.query( - {key: 'external_identities'}, - function (data) { - vm.loading.identities = false; - - }); - - vm.removeProvider = function (provider) { - - userSelfPropertyResource.delete( - { - key: 'external_identities', - provider: provider.provider, - id: provider.id - }, - function (status) { - if (status){ - vm.identities = _.filter(vm.identities, function (item) { - return item != provider - }); - } + vm.applications = stateHolder.AeUser.applications_map; + stateHolder.section = 'reports'; + vm.today = function () { + vm.pickerDate = new Date(); + }; + vm.today(); + vm.reportsPage = []; + vm.page = 1; + vm.itemCount = 0; + vm.itemsPerPage = 250; + typeAheadTagHelper.tags = []; + vm.searchParams = {tags: [], page: 1, type: 'report'}; + vm.is_loading = false; + vm.filterTypeAheadOptions = [ + { + type: 'error', + text: 'error:', + 'description': 'Full-text search in your reports', + example: 'error:text-im-looking-for', + tag: 'Error' + }, + { + type: 'view_name', + text: 'view_name:', + 'description': 'Query reports occured in specific views', + example: "view_name:module.foo", + tag: 'View Name' + }, + { + type: 'resource', + text: 'resource:', + 'description': 'Restrict resultset to application', + example: "resource:ID", + tag: 'Application' + }, + { + type: 'priority', + text: 'priority:', + 'description': 'Show reports with specific priority', + example: 'priority:8', + tag: 'Priority' + }, + { + type: 'min_occurences', + text: 'min_occurences:', + 'description': 'Show reports from groups with at least X occurences', + example: 'min_occurences:25', + tag: 'Occurences' + }, + { + type: 'url_path', + text: 'url_path:', + 'description': 'Show reports from specific URL paths', + example: 'url_path:/foo/bar/baz', + tag: 'Url Path' + }, + { + type: 'url_domain', + text: 'url_domain:', + 'description': 'Show reports from specific domain', + example: 'url_domain:domain.com', + tag: 'Domain' + }, + { + type: 'report_status', + text: 'report_status:', + 'description': 'Show reports from groups with specific status', + example: 'report_status:never_reviewed', + tag: 'Status' + }, + { + type: 'request_id', + text: 'request_id:', + 'description': 'Show reports with specific request id', + example: "request_id:883143dc572e4c38aceae92af0ea5ae0", + tag: 'Request ID' + }, + { + type: 'server_name', + text: 'server_name:', + 'description': 'Show reports tagged with this key/value pair', + example: 'server_name:hostname', + tag: 'Tag' + }, + { + type: 'http_status', + text: 'http_status:', + 'description': 'Show reports with specific HTTP status code', + example: "http_status:", + tag: 'HTTP Status' + }, + { + type: 'http_status', + text: 'http_status:500', + 'description': 'Show reports with specific HTTP status code', + example: "http_status:500", + tag: 'HTTP Status' + }, + { + type: 'http_status', + text: 'http_status:404', + 'description': 'Include 404 reports in your search', + example: "http_status:404", + tag: 'HTTP Status' + }, + { + type: 'start_date', + text: 'start_date:', + 'description': 'Show reports newer than this date (press TAB for dropdown)', + example: 'start_date:2014-08-15T13:00', + tag: 'Start Date' + }, + { + type: 'end_date', + text: 'end_date:', + 'description': 'Show reports older than this date (press TAB for dropdown)', + example: 'start_date:2014-08-15T23:59', + tag: 'End Date' + } + ]; - }); + vm.filterTypeAhead = undefined; + vm.showDatePicker = false; + vm.manualOpen = false; + vm.aheadFilter = typeAheadTagHelper.aheadFilter; + vm.removeSearchTag = function (tag) { + $location.search(tag.type, null); + vm.refresh(); + }; + vm.addSearchTag = function (tag) { + $location.search(tag.type, tag.value); + vm.refresh(); + }; + vm.notRelativeTime = false; + if ($cookies.notRelativeTime) { + vm.notRelativeTime = JSON.parse($cookies.notRelativeTime); } -} -;// # Copyright (C) 2010-2016 RhodeCode GmbH -// # -// # This program is free software: you can redistribute it and/or modify -// # it under the terms of the GNU Affero General Public License, version 3 -// # (only), as published by the Free Software Foundation. -// # -// # This program is distributed in the hope that it will be useful, -// # but WITHOUT ANY WARRANTY; without even the implied warranty of -// # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// # GNU General Public License for more details. -// # -// # You should have received a copy of the GNU Affero General Public License -// # along with this program. If not, see . -// # -// # This program is dual-licensed. If you wish to learn more about the -// # AppEnlight Enterprise Edition, including its added features, Support -// # services, and proprietary license terms, please see -// # https://rhodecode.com/licenses/ + vm.changeRelativeTime = function () { + $cookies.notRelativeTime = JSON.stringify(vm.notRelativeTime); + }; -angular.module('appenlight.components.userPasswordView', []) - .component('userPasswordView', { - templateUrl: 'components/views/user-password-view/user-password-view.html', - controller: UserPasswordViewController + _.each(_.range(1, 11), function (priority) { + vm.filterTypeAheadOptions.push({ + type: 'priority', + text: 'priority:' + priority.toString(), + description: 'Show entries with specific priority', + example: 'priority:' + priority, + tag: 'Priority' + }); + }); + _.each(['never_reviewed', 'reviewed', 'fixed', 'public'], function (status) { + vm.filterTypeAheadOptions.push({ + type: 'report_status', + text: 'report_status:' + status, + 'description': 'Show only reports with this status', + example: 'report_status:' + status, + tag: 'Status ' + status.toUpperCase() + }); + }); + _.each(stateHolder.AeUser.applications, function (item) { + vm.filterTypeAheadOptions.push({ + type: 'resource', + text: 'resource:' + item.resource_id + ':' + item.resource_name, + example: 'resource:' + item.resource_id, + 'tag': item.resource_name, + 'description': 'Restrict resultset to this application' + }); }); -UserPasswordViewController.$inject = ['$state', 'userSelfPropertyResource']; + vm.paginationChange = function(){ + $location.search('page', vm.page); + vm.refresh(); + }; -function UserPasswordViewController($state, userSelfPropertyResource) { - - var vm = this; - vm.$state = $state; - vm.loading = {password: false}; - vm.form = {}; + vm.typeAheadTag = function (event) { + var text = vm.filterTypeAhead; + if (_.isObject(vm.filterTypeAhead)) { + text = vm.filterTypeAhead.text; + } + if (!vm.filterTypeAhead) { + return + } - vm.updatePassword = function () { - vm.loading.password = true; - - userSelfPropertyResource.update({key: 'password'}, vm.form, function () { - vm.loading.password = false; - vm.form = {}; - setServerValidation(vm.passwordForm); - }, function (response) { - if (response.status == 422) { - - setServerValidation(vm.passwordForm, response.data); - + var parsed = text.split(':'); + var tag = {'type': null, 'value': null}; + // app tags have : twice + if (parsed.length > 2 && parsed[0] == 'resource') { + tag.type = 'resource'; + tag.value = parsed[1]; + } + // normal tag:value + else if (parsed.length > 1) { + tag.type = parsed[0]; + var tagValue = parsed.slice(1); + if (tagValue) { + tag.value = tagValue.join(':'); } - vm.loading.password = false; - }); - } -} + } + else { + tag.type = 'error'; + tag.value = parsed.join(':'); + } -;// # Copyright (C) 2010-2016 RhodeCode GmbH -// # -// # This program is free software: you can redistribute it and/or modify -// # it under the terms of the GNU Affero General Public License, version 3 -// # (only), as published by the Free Software Foundation. -// # -// # This program is distributed in the hope that it will be useful, -// # but WITHOUT ANY WARRANTY; without even the implied warranty of -// # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// # GNU General Public License for more details. -// # -// # You should have received a copy of the GNU Affero General Public License -// # along with this program. If not, see . -// # -// # This program is dual-licensed. If you wish to learn more about the -// # AppEnlight Enterprise Edition, including its added features, Support -// # services, and proprietary license terms, please see -// # https://rhodecode.com/licenses/ + // set datepicker hour based on type of field + if ('start_date:' == text) { + vm.showDatePicker = true; + vm.filterTypeAhead = 'start_date:' + moment(vm.pickerDate).utc().format(); + } + else if ('end_date:' == text) { + vm.showDatePicker = true; + vm.filterTypeAhead = 'end_date:' + moment(vm.pickerDate).utc().hour(23).minute(59).format(); + } -angular.module('appenlight.components.userProfileView', []) - .component('userProfileView', { - templateUrl: 'components/views/user-profile-view/user-profile-view.html', - controller: UserProfileViewController - }); + if (event.keyCode != 13 || !tag.type || !tag.value) { + return + } + vm.showDatePicker = false; + // aka we selected one of main options + vm.addSearchTag({type: tag.type, value: tag.value}); + // clear typeahead + vm.filterTypeAhead = undefined; + }; -UserProfileViewController.$inject = ['$state', 'userSelfResource']; + vm.pickerDateChanged = function(){ + if (vm.filterTypeAhead.indexOf('start_date:') == '0') { + vm.filterTypeAhead = 'start_date:' + moment(vm.pickerDate).utc().format(); + } + else if (vm.filterTypeAhead.indexOf('end_date:') == '0') { + vm.filterTypeAhead = 'end_date:' + moment(vm.pickerDate).utc().hour(23).minute(59).format(); + } + vm.showDatePicker = false; + }; -function UserProfileViewController($state, userSelfResource) { - - var vm = this; - vm.$state = $state; - vm.loading = {profile: true}; + var reportPresentation = function (report) { + report.presentation = {}; + if (report.group.public) { + report.presentation.className = 'public'; + report.presentation.tooltip = 'Public'; + } + else if (report.group.fixed) { + report.presentation.className = 'fixed'; + report.presentation.tooltip = 'Fixed'; + } + else if (report.group.read) { + report.presentation.className = 'reviewed'; + report.presentation.tooltip = 'Reviewed'; + } + else { + report.presentation.className = 'new'; + report.presentation.tooltip = 'New'; + } + return report; + }; - vm.user = userSelfResource.get(null, function (data) { - vm.loading.profile = false; - - }); + vm.fetchReports = function (searchParams) { + vm.is_loading = true; + reportsResource.query(searchParams, function (data, getResponseHeaders) { + var headers = getResponseHeaders(); + + vm.is_loading = false; + vm.reportsPage = _.map(data, function (item) { + return reportPresentation(item); + }); + vm.itemCount = headers['x-total-count']; + vm.itemsPerPage = headers['x-items-per-page']; + }, function () { + vm.is_loading = false; + }); + }; - vm.updateProfile = function () { - vm.loading.profile = true; + vm.filterId = function (log) { + vm.searchParams.tags.push({ + type: "request_id", + value: log.request_id + }); + vm.refresh(); + }; + vm.refresh = function(){ + vm.searchParams = parseSearchToTags($location.search()); + vm.page = Number(vm.searchParams.page) || 1; + var params = parseTagsToSearch(vm.searchParams); - vm.user.$update(null, function () { - vm.loading.profile = false; - setServerValidation(vm.profileForm); - }, function (response) { - if (response.status == 422) { - setServerValidation(vm.profileForm, response.data); - } - vm.loading.profile = false; - }); - } + vm.fetchReports(params); + }; + // initial load + vm.refresh(); } ;// # Copyright (C) 2010-2016 RhodeCode GmbH @@ -10217,58 +10160,284 @@ function UserProfileViewController($state, userSelfResource) { // # services, and proprietary license terms, please see // # https://rhodecode.com/licenses/ -var aeconfig = angular.module('appenlight.config', []); -aeconfig.factory('AeConfig', function () { - var obj = {}; - obj.flashMessages = decodeEncodedJSON(window.AE.flash_messages); - obj.timeOptions = decodeEncodedJSON(window.AE.timeOptions); - obj.plugins = decodeEncodedJSON(window.AE.plugins); - obj.topNav = decodeEncodedJSON(window.AE.topNav); - obj.ws_url = window.AE.ws_url; - obj.urls = window.AE.urls; - // set keys on values because we wont be able to retrieve them everywhere - for (var key in obj.timeOptions) { - obj.timeOptions[key]['key'] = key; +'use strict'; + +/* Controllers */ + +angular.module('appenlight.components.reportsSlowBrowserView', []) + .component('reportsSlowBrowserView', { + templateUrl: 'components/views/reports-slow-browser-view/reports-slow-browser-view.html', + controller: ReportsSlowBrowserViewController + }); + +ReportsSlowBrowserViewController.$inject = ['$location', '$cookies', + 'stateHolder', 'typeAheadTagHelper', 'slowReportsResource'] + +function ReportsSlowBrowserViewController($location, $cookies, stateHolder, typeAheadTagHelper, slowReportsResource) { + var vm = this; + vm.applications = stateHolder.AeUser.applications_map; + stateHolder.section = 'slow_reports'; + vm.today = function () { + vm.pickerDate = new Date(); + }; + vm.today(); + vm.reportsPage = []; + vm.page = 1; + vm.itemCount = 0; + vm.itemsPerPage = 250; + typeAheadTagHelper.tags = []; + vm.searchParams = {tags: [], page: 1, type: 'slow_report'}; + vm.is_loading = false; + vm.filterTypeAheadOptions = [ + { + type: 'view_name', + text: 'view_name:', + 'description': 'Query reports occured in specific views', + tag: 'View Name', + example: "view_name:module.foo" + }, + { + type: 'resource', + text: 'resource:', + 'description': 'Restrict resultset to application', + tag: 'Application', + example: "resource:ID" + }, + { + type: 'priority', + text: 'priority:', + 'description': 'Show reports with specific priority', + example: 'priority:8', + tag: 'Priority' + }, + { + type: 'min_occurences', + text: 'min_occurences:', + 'description': 'Show reports from groups with at least X occurences', + example: 'min_occurences:25', + tag: 'Min. occurences' + }, + { + type: 'min_duration', + text: 'min_duration:', + 'description': 'Show reports from groups with average duration >= Xs', + example: 'min_duration:4.5', + tag: 'Min. duration' + }, + { + type: 'url_path', + text: 'url_path:', + 'description': 'Show reports from specific URL paths', + example: 'url_path:/foo/bar/baz', + tag: 'Url Path' + }, + { + type: 'url_domain', + text: 'url_domain:', + 'description': 'Show reports from specific domain', + example: 'url_domain:domain.com', + tag: 'Domain' + }, + { + type: 'request_id', + text: 'request_id:', + 'description': 'Show reports with specific request id', + example: "request_id:883143dc572e4c38aceae92af0ea5ae0", + tag: 'Request ID' + }, + { + type: 'report_status', + text: 'report_status:', + 'description': 'Show reports from groups with specific status', + example: 'report_status:never_reviewed', + tag: 'Status' + }, + { + type: 'server_name', + text: 'server_name:', + 'description': 'Show reports tagged with this key/value pair', + example: 'server_name:hostname', + tag: 'Tag' + }, + { + type: 'start_date', + text: 'start_date:', + 'description': 'Show reports newer than this date (press TAB for dropdown)', + example: 'start_date:2014-08-15T13:00', + tag: 'Start Date' + }, + { + type: 'end_date', + text: 'end_date:', + 'description': 'Show reports older than this date (press TAB for dropdown)', + example: 'start_date:2014-08-15T23:59', + tag: 'End Date' + } + ]; + + vm.filterTypeAhead = undefined; + vm.showDatePicker = false; + vm.aheadFilter = typeAheadTagHelper.aheadFilter; + vm.removeSearchTag = function (tag) { + $location.search(tag.type, null); + vm.refresh(); + }; + vm.addSearchTag = function (tag) { + $location.search(tag.type, tag.value); + vm.refresh(); + }; + vm.manualOpen = false; + vm.notRelativeTime = false; + if ($cookies.notRelativeTime) { + vm.notRelativeTime = JSON.parse($cookies.notRelativeTime); } - console.info('config', obj); - return obj; -}); -;// # Copyright (C) 2010-2016 RhodeCode GmbH -// # -// # This program is free software: you can redistribute it and/or modify -// # it under the terms of the GNU Affero General Public License, version 3 -// # (only), as published by the Free Software Foundation. -// # -// # This program is distributed in the hope that it will be useful, -// # but WITHOUT ANY WARRANTY; without even the implied warranty of -// # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// # GNU General Public License for more details. -// # -// # You should have received a copy of the GNU Affero General Public License -// # along with this program. If not, see . -// # -// # This program is dual-licensed. If you wish to learn more about the -// # AppEnlight Enterprise Edition, including its added features, Support -// # services, and proprietary license terms, please see -// # https://rhodecode.com/licenses/ -angular.module('appenlight.controllers').controller('AdminApplicationsListController', AdminApplicationsListController); + vm.changeRelativeTime = function () { + $cookies.notRelativeTime = JSON.stringify(vm.notRelativeTime); + }; + + _.each(_.range(1, 11), function (priority) { + vm.filterTypeAheadOptions.push({ + type: 'priority', + text: 'priority:' + priority.toString(), + description: 'Show entries with specific priority', + example: 'priority:' + priority, + tag: 'Priority' + }); + }); + _.each(['never_reviewed', 'reviewed', 'fixed', 'public'], function (status) { + vm.filterTypeAheadOptions.push({ + type: 'report_status', + text: 'report_status:' + status, + 'description': 'Show only reports with this status', + example: 'report_status:' + status, + tag: 'Status ' + status.toUpperCase() + }); + }); + _.each(stateHolder.AeUser.applications, function (item) { + vm.filterTypeAheadOptions.push({ + type: 'resource', + text: 'resource:' + item.resource_id + ':' + item.resource_name, + example: 'resource:' + item.resource_id, + 'tag': item.resource_name, + 'description': 'Restrict resultset to this application' + }); + }); + + vm.typeAheadTag = function (event) { + var text = vm.filterTypeAhead; + if (_.isObject(vm.filterTypeAhead)) { + text = vm.filterTypeAhead.text; + }; + if (!vm.filterTypeAhead) { + return + } + var parsed = text.split(':'); + var tag = {'type': null, 'value': null}; + // app tags have : twice + if (parsed.length > 2 && parsed[0] == 'resource') { + tag.type = 'resource'; + tag.value = parsed[1]; + } + // normal tag:value + else if (parsed.length > 1) { + tag.type = parsed[0]; + var tagValue = parsed.slice(1); + if (tagValue) { + tag.value = tagValue.join(':'); + } + } + + // set datepicker hour based on type of field + if ('start_date:' == text) { + vm.showDatePicker = true; + vm.filterTypeAhead = 'start_date:' + moment(vm.pickerDate).utc().format(); + } + else if ('end_date:' == text) { + vm.showDatePicker = true; + vm.filterTypeAhead = 'end_date:' + moment(vm.pickerDate).utc().hour(23).minute(59).format(); + } + + if (event.keyCode != 13 || !tag.type || !tag.value) { + return + } + vm.showDatePicker = false; + // aka we selected one of main options + vm.addSearchTag({type: tag.type, value: tag.value}); + // clear typeahead + vm.filterTypeAhead = undefined; + }; + + vm.paginationChange = function(){ + $location.search('page', vm.page); + vm.refresh(); + }; -AdminApplicationsListController.$inject = ['applicationsResource']; + vm.pickerDateChanged = function(){ + if (vm.filterTypeAhead.indexOf('start_date:') == '0') { + vm.filterTypeAhead = 'start_date:' + moment(vm.pickerDate).utc().format(); + } + else if (vm.filterTypeAhead.indexOf('end_date:') == '0') { + vm.filterTypeAhead = 'end_date:' + moment(vm.pickerDate).utc().hour(23).minute(59).format(); + } + vm.showDatePicker = false; + }; -function AdminApplicationsListController(applicationsResource) { - - var vm = this; - vm.loading = {applications: true}; + var reportPresentation = function (report) { + report.presentation = {}; + if (report.group.public) { + report.presentation.className = 'public'; + report.presentation.tooltip = 'Public'; + } + else if (report.group.fixed) { + report.presentation.className = 'fixed'; + report.presentation.tooltip = 'Fixed'; + } + else if (report.group.read) { + report.presentation.className = 'reviewed'; + report.presentation.tooltip = 'Reviewed'; + } + else { + report.presentation.className = 'new'; + report.presentation.tooltip = 'New'; + } + return report; + }; - vm.applications = applicationsResource.query({ - root_list: true, - resource_type: 'application' - }, function (data) { - vm.loading = {applications: false}; - }); -}; + vm.fetchReports = function (searchParams) { + vm.is_loading = true; + slowReportsResource.query(searchParams, function (data, getResponseHeaders) { + var headers = getResponseHeaders(); + + vm.is_loading = false; + vm.reportsPage = _.map(data, function (item) { + return reportPresentation(item); + }); + vm.itemCount = headers['x-total-count']; + vm.itemsPerPage = headers['x-items-per-page']; + }, function () { + vm.is_loading = false; + }); + }; + + vm.filterId = function (log) { + vm.searchParams.tags.push({ + type: "request_id", + value: log.request_id + }); + vm.refresh(); + }; + vm.refresh = function(){ + vm.searchParams = parseSearchToTags($location.search()); + vm.page = Number(vm.searchParams.page) || 1; + var params = parseTagsToSearch(vm.searchParams); + vm.fetchReports(params); + }; + + //initial load + vm.refresh(); +} ;// # Copyright (C) 2010-2016 RhodeCode GmbH // # @@ -10289,44 +10458,18 @@ function AdminApplicationsListController(applicationsResource) { // # services, and proprietary license terms, please see // # https://rhodecode.com/licenses/ -angular.module('appenlight.controllers').controller('ConfigsListController', ConfigsListController); - -ConfigsListController.$inject = ['configsResource', 'configsNoIdResource']; - -function ConfigsListController(configsResource, configsNoIdResource) { - var vm = this; - vm.loading = {config: true}; - - var filters = [ - 'template_footer_html:global', - 'list_groups_to_non_admins:global', - 'per_application_reports_rate_limit:global', - 'per_application_logs_rate_limit:global', - 'per_application_metrics_rate_limit:global', - ]; - - vm.configs = {}; - - vm.configList = configsResource.query({filter: filters}, - function (data) { - vm.loading = {config: false}; - _.each(data, function (item) { - if (vm.configs[item.section] === undefined) { - vm.configs[item.section] = {}; - } - vm.configs[item.section][item.key] = item; - }); - }); +angular.module('appenlight.components.settingsView', []) + .component('settingsView', { + templateUrl: 'components/views/settings-view/settings-view.html', + controller: SettingsViewController + }); - vm.save = function () { - vm.loading.config = true; - _.each(vm.configList, function (item) { - item.$save(); - }); - vm.loading.config = false; - }; +SettingsViewController.$inject = ['$state']; -}; +function SettingsViewController($state) { + this.$state = $state; + console.info('SettingsViewController'); +} ;// # Copyright (C) 2010-2016 RhodeCode GmbH // # @@ -10347,128 +10490,37 @@ function ConfigsListController(configsResource, configsNoIdResource) { // # services, and proprietary license terms, please see // # https://rhodecode.com/licenses/ -angular.module('appenlight.controllers').controller('AdminGroupsCreateController', AdminGroupsCreateController); +angular.module('appenlight.components.userAlertChannelsEmailNewView', []) + .component('userAlertChannelsEmailNewView', { + templateUrl: 'components/views/user-alert-channel-email-new-view/user-alert-channel-email-new-view.html', + controller: AlertChannelsEmailController + }); -AdminGroupsCreateController.$inject = ['$state', 'groupsResource', 'groupsPropertyResource', 'sectionViewResource', 'AeConfig']; +AlertChannelsEmailController.$inject = ['$state','userSelfPropertyResource']; -function AdminGroupsCreateController($state, groupsResource, groupsPropertyResource, sectionViewResource, AeConfig) { +function AlertChannelsEmailController($state, userSelfPropertyResource) { var vm = this; - vm.loading = { - group: false, - resource_permissions: false, - users: false - }; - - vm.form = { - autocompleteUser: '', - } - - - if (typeof $state.params.groupId !== 'undefined') { - vm.loading.group = true; - var groupId = $state.params.groupId; - vm.group = groupsResource.get({groupId: groupId}, function (data) { - vm.loading.group = false; - }); - - vm.resource_permissions = groupsPropertyResource.query( - {groupId: groupId, key: 'resource_permissions'}, function (data) { - vm.loading.resource_permissions = false; - var tmpObj = { - 'group': { - 'application': {}, - 'dashboard': {} - } - }; - _.each(data, function (item) { - - var section = tmpObj[item.type][item.resource_type]; - if (typeof section[item.resource_id] == 'undefined') { - section[item.resource_id] = { - self: item, - permissions: [] - } - } - section[item.resource_id].permissions.push(item.perm_name); - - }); - vm.resourcePermissions = tmpObj; - }); - - vm.users = groupsPropertyResource.query( - {groupId: groupId, key: 'users'}, function (data) { - vm.loading.users = false; - }, function () { - vm.loading.users = false; - }); - - } - else { - var groupId = null; - } - - var formResponse = function (response) { - if (response.status === 422) { - setServerValidation(vm.groupForm, response.data); - } - vm.loading.group = false; - }; - - vm.createGroup = function () { - vm.loading.group = true; - if (groupId) { - groupsResource.update({groupId: vm.group.id}, vm.group, function (data) { - setServerValidation(vm.groupForm); - vm.loading.group = false; - }, formResponse); - } - else { - groupsResource.save(vm.group, function (data) { - $state.go('admin.group.update', {groupId: data.id}); - }, formResponse); - } - }; - - vm.removeUser = function (user) { - groupsPropertyResource.delete( - {groupId: groupId, key: 'users', user_name: user.user_name}, - function (data) { - vm.loading.users = false; - vm.users = _.filter(vm.users, function (item) { - return item != user; - }); - }, function () { - vm.loading.users = false; - }); - }; - - vm.addUser = function () { - groupsPropertyResource.save( - {groupId: groupId, key: 'users'}, - {user_name: vm.form.autocompleteUser}, - function (data) { - vm.loading.users = false; - vm.users.push(data); - vm.form.autocompleteUser = ''; - }, function () { - vm.loading.users = false; - }); - } + vm.$state = $state; + vm.loading = {email: false}; + vm.form = {}; - vm.searchUsers = function (searchPhrase) { + vm.createChannel = function () { + vm.loading.email = true; - return sectionViewResource.query({ - section: 'users_section', - view: 'search_users', - 'user_name': searchPhrase - }).$promise.then(function (data) { - return _.map(data, function (item) { - return item.user; - }); - }); + userSelfPropertyResource.save({key: 'alert_channels'}, vm.form, function () { + //vm.loading.email = false; + //setServerValidation(vm.channelForm); + //vm.form = {}; + $state.go('user.alert_channels.list'); + }, function (response) { + if (response.status == 422) { + setServerValidation(vm.channelForm, response.data); + } + vm.loading.email = false; + }); } -}; +} ;// # Copyright (C) 2010-2016 RhodeCode GmbH // # @@ -10489,40 +10541,122 @@ function AdminGroupsCreateController($state, groupsResource, groupsPropertyResou // # services, and proprietary license terms, please see // # https://rhodecode.com/licenses/ -angular.module('appenlight.controllers').controller('AdminGroupsController', AdminGroupsController); +angular.module('appenlight.components.userAlertChannelsListView', []) + .component('userAlertChannelsListView', { + templateUrl: 'components/views/user-alert-channels-list-view/user-alert-channels-list-view.html', + controller: userAlertChannelsListViewController + }); -AdminGroupsController.$inject = ['groupsResource']; +userAlertChannelsListViewController.$inject = ['$state','userSelfPropertyResource', 'applicationsNoIdResource']; -function AdminGroupsController(groupsResource) { +function userAlertChannelsListViewController($state, userSelfPropertyResource, applicationsNoIdResource) { var vm = this; - vm.loading = {groups: true}; + vm.$state = $state; + vm.loading = {channels: true, applications: true, actions:true}; - vm.groups = groupsResource.query({}, function (data) { - vm.loading = {groups: false}; - vm.activeUsers = _.reduce(vm.groups, function(memo, val){ - if (val.status == 1){ - return memo + 1; - } - return memo; - }, 0); - - }); + vm.alertChannels = userSelfPropertyResource.query({key: 'alert_channels'}, + function (data) { + vm.loading.channels = false; + }); + + vm.alertActions = userSelfPropertyResource.query({key: 'alert_actions'}, + function (data) { + vm.loading.actions = false; + }); + vm.applications = applicationsNoIdResource.query({permission: 'view'}, + function (data) { + vm.loading.applications = false; + }); - vm.removeGroup = function (group) { - groupsResource.remove({groupId: group.id}, function (data, responseHeaders) { - - if (data) { - var index = vm.groups.indexOf(group); - if (index !== -1) { - vm.groups.splice(index, 1); - vm.activeGroups -= 1; - } + var allOps = { + 'eq': 'Equal', + 'ne': 'Not equal', + 'ge': 'Greater or equal', + 'gt': 'Greater than', + 'le': 'Lesser or equal', + 'lt': 'Lesser than', + 'startswith': 'Starts with', + 'endswith': 'Ends with', + 'contains': 'Contains' + }; + + var fieldOps = {}; + fieldOps['http_status'] = ['eq', 'ne', 'ge', 'le']; + fieldOps['group:priority'] = ['eq', 'ne', 'ge', 'le']; + fieldOps['duration'] = ['ge', 'le']; + fieldOps['url_domain'] = ['eq', 'ne', 'startswith', 'endswith', + 'contains']; + fieldOps['url_path'] = ['eq', 'ne', 'startswith', 'endswith', + 'contains']; + fieldOps['error'] = ['eq', 'ne', 'startswith', 'endswith', + 'contains']; + fieldOps['tags:server_name'] = ['eq', 'ne', 'startswith', 'endswith', + 'contains']; + fieldOps['group:occurences'] = ['eq', 'ne', 'ge', 'le']; + + var possibleFields = { + '__AND__': 'All met (composite rule)', + '__OR__': 'One met (composite rule)', + '__NOT__': 'Not met (composite rule)', + 'http_status': 'HTTP Status', + 'duration': 'Request duration', + 'group:priority': 'Group -> Priority', + 'url_domain': 'Domain', + 'url_path': 'URL Path', + 'error': 'Error', + 'tags:server_name': 'Tag -> Server name', + 'group:occurences': 'Group -> Occurences' + }; + + vm.ruleDefinitions = { + fieldOps: fieldOps, + allOps: allOps, + possibleFields: possibleFields + }; + + vm.addAction = function (channel) { + + userSelfPropertyResource.save({key: 'alert_channels_rules'}, {}, function (data) { + vm.alertActions.push(data); + }, function (response) { + if (response.status == 422) { + } }); + }; + + vm.updateChannel = function (channel, subKey) { + var params = { + key: 'alert_channels', + channel_name: channel['channel_name'], + channel_value: channel['channel_value'] + }; + var toUpdate = {}; + if (['daily_digest', 'send_alerts'].indexOf(subKey) !== -1) { + toUpdate[subKey] = !channel[subKey]; + } + userSelfPropertyResource.update(params, toUpdate, function (data) { + _.extend(channel, data); + }); + }; + + vm.removeChannel = function (channel) { + + userSelfPropertyResource.delete({ + key: 'alert_channels', + channel_name: channel.channel_name, + channel_value: channel.channel_value + }, function () { + vm.alertChannels = _.filter(vm.alertChannels, function(item){ + return item != channel; + }); + }); + } -}; + +} ;// # Copyright (C) 2010-2016 RhodeCode GmbH // # @@ -10543,110 +10677,56 @@ function AdminGroupsController(groupsResource) { // # services, and proprietary license terms, please see // # https://rhodecode.com/licenses/ -angular.module('appenlight.controllers').controller('AdminPartitionsController', AdminPartitionsController); +angular.module('appenlight.components.userAuthTokensView', []) + .component('userAuthTokensView', { + templateUrl: 'components/views/user-auth-tokens-view/user-auth-tokens-view.html', + controller: userAuthTokensViewController + }); -AdminPartitionsController.$inject = ['sectionViewResource']; +userAuthTokensViewController.$inject = ['$state', 'userSelfPropertyResource', 'AeConfig']; -function AdminPartitionsController(sectionViewResource) { +function userAuthTokensViewController($state, userSelfPropertyResource, AeConfig) { + var vm = this; - vm.permanentPartitions = []; - vm.dailyPartitions = []; - vm.loading = {partitions: true}; - vm.dailyChecked = false; - vm.permChecked = false; - vm.dailyConfirm = ''; - vm.permConfirm = ''; - - - vm.loadPartitions = function (data) { - var permanentPartitions = vm.transformPartitionList( - data.permanent_partitions); - var dailyPartitions = vm.transformPartitionList( - data.daily_partitions); - vm.permanentPartitions = permanentPartitions; - vm.dailyPartitions = dailyPartitions; - vm.loading = {partitions: false}; - }; - - vm.setCheckedList = function (scope) { - var toTest = null; - if (scope === 'dailyPartitions'){ - toTest = 'dailyChecked'; - } - else{ - toTest = 'permChecked'; - } - - if (vm[toTest]) { - var val = true; - } - else { - var val = false; - } - - _.each(vm[scope], function (item) { - _.each(item[1].pg, function (index) { - index.checked = val; - }); - _.each(item[1].elasticsearch, function (index) { - index.checked = val; - }); - }); - } - + vm.$state = $state; + vm.loading = {tokens: true}; - vm.transformPartitionList = function (inputList) { - var outputList = []; + vm.expireOptions = AeConfig.timeOptions; - _.each(inputList, function (item) { - var time = [item[0], { - elasticsearch: [], - pg: [] - }] - _.each(item[1].pg, function (index) { - time[1].pg.push({name: index, checked: false}) - }); - _.each(item[1].elasticsearch, function (index) { - time[1].elasticsearch.push({ - name: index, - checked: false - }) - }); - outputList.push(time); + vm.tokens = userSelfPropertyResource.query({key: 'auth_tokens'}, + function (data) { + vm.loading.tokens = false; }); - return outputList; - }; - - sectionViewResource.get({section:'admin_section', view: 'partitions'}, - vm.loadPartitions); - vm.partitionsDelete = function (partitionType) { - var es_indices = []; - var pg_indices = []; - _.each(vm[partitionType], function (item) { - _.each(item[1].pg, function (index) { - if (index.checked) { - pg_indices.push(index.name) - } - }); - _.each(item[1].elasticsearch, function (index) { - if (index.checked) { - es_indices.push(index.name) + vm.addToken = function () { + vm.loading.tokens = true; + userSelfPropertyResource.save({key: 'auth_tokens'}, + vm.form, + function (data) { + vm.loading.tokens = false; + setServerValidation(vm.TokenForm); + vm.form = {}; + vm.tokens.push(data); + }, function (response) { + vm.loading.tokens = false; + if (response.status == 422) { + setServerValidation(vm.TokenForm, response.data); } - }); - }); - - - vm.loading = {partitions: true}; - sectionViewResource.save({section:'admin_section', - view: 'partitions_remove'}, { - es_indices: es_indices, - pg_indices: pg_indices, - confirm: 'CONFIRM' - }, vm.loadPartitions); + }) + }; + vm.removeToken = function (token) { + userSelfPropertyResource.delete({ + key: 'auth_tokens', + token: token.token + }, + function () { + var index = vm.tokens.indexOf(token); + if (index !== -1) { + vm.tokens.splice(index, 1); + } + }) } - } ;// # Copyright (C) 2010-2016 RhodeCode GmbH @@ -10668,31 +10748,46 @@ function AdminPartitionsController(sectionViewResource) { // # services, and proprietary license terms, please see // # https://rhodecode.com/licenses/ -angular.module('appenlight.controllers').controller('AdminSystemController', AdminSystemController); +angular.module('appenlight.components.userIdentitiesView', []) + .component('userIdentitiesView', { + templateUrl: 'components/views/user-identities-view/user-identities-view.html', + controller: UserIdentitiesController + }); -AdminSystemController.$inject = ['sectionViewResource']; +UserIdentitiesController.$inject = ['$state', 'userSelfPropertyResource', 'AeConfig']; -function AdminSystemController(sectionViewResource) { +function UserIdentitiesController($state, userSelfPropertyResource, AeConfig) { + var vm = this; - vm.tables = []; - vm.loading = {system: true}; - sectionViewResource.get({ - section: 'admin_section', - view: 'system' - }, null, function (data) { - vm.DBtables = data.db_tables; - vm.ESIndices = data.es_indices; - vm.queueStats = data.queue_stats; - vm.systemLoad = data.system_load; - vm.packages = data.packages; - vm.processInfo = data.process_info; - vm.disks = data.disks; - vm.memory = data.memory; - vm.selfInfo = data.self_info; + vm.$state = $state; + vm.AeConfig = AeConfig; + vm.loading = {identities: true}; - vm.loading.system = false; - }); -}; + vm.identities = userSelfPropertyResource.query( + {key: 'external_identities'}, + function (data) { + vm.loading.identities = false; + + }); + + vm.removeProvider = function (provider) { + + userSelfPropertyResource.delete( + { + key: 'external_identities', + provider: provider.provider, + id: provider.id + }, + function (status) { + if (status){ + vm.identities = _.filter(vm.identities, function (item) { + return item != provider + }); + } + + }); + } +} ;// # Copyright (C) 2010-2016 RhodeCode GmbH // # @@ -10713,107 +10808,38 @@ function AdminSystemController(sectionViewResource) { // # services, and proprietary license terms, please see // # https://rhodecode.com/licenses/ -angular.module('appenlight.controllers').controller('AdminUsersCreateController', AdminUsersCreateController); +angular.module('appenlight.components.userPasswordView', []) + .component('userPasswordView', { + templateUrl: 'components/views/user-password-view/user-password-view.html', + controller: UserPasswordViewController + }); -AdminUsersCreateController.$inject = ['$state', 'usersResource', 'usersPropertyResource', 'sectionViewResource', 'AeConfig']; +UserPasswordViewController.$inject = ['$state', 'userSelfPropertyResource']; -function AdminUsersCreateController($state, usersResource, usersPropertyResource, sectionViewResource, AeConfig) { +function UserPasswordViewController($state, userSelfPropertyResource) { var vm = this; - vm.loading = {user: false}; - - - if (typeof $state.params.userId !== 'undefined') { - vm.loading.user = true; - var userId = $state.params.userId; - vm.user = usersResource.get({userId: userId}, function (data) { - vm.loading.user = false; - // cast to true for angular checkbox - if (vm.user.status === 1) { - vm.user.status = true; - } - }); - - vm.resource_permissions = usersPropertyResource.query( - {userId: userId, key: 'resource_permissions'}, function (data) { - vm.loading.resource_permissions = false; - var tmpObj = { - 'user': { - 'application': {}, - 'dashboard': {} - }, - 'group': { - 'application': {}, - 'dashboard': {} - } - }; - _.each(data, function (item) { - - var section = tmpObj[item.type][item.resource_type]; - if (typeof section[item.resource_id] == 'undefined'){ - section[item.resource_id] = { - self:item, - permissions: [] - } - } - section[item.resource_id].permissions.push(item.perm_name); - - }); - vm.resourcePermissions = tmpObj; - }); - - } - else { - var userId = null; - vm.user = { - status: true - } - } - - var formResponse = function (response) { - if (response.status == 422) { - setServerValidation(vm.profileForm, response.data); - } - vm.loading.user = false; - } - - vm.createUser = function () { - vm.loading.user = true; - - if (userId) { - usersResource.update({userId: vm.user.id}, vm.user, function (data) { - setServerValidation(vm.profileForm); - vm.loading.user = false; - }, formResponse); - } - else { - usersResource.save(vm.user, function (data) { - $state.go('admin.user.update', {userId: data.id}); - }, formResponse); - } - } + vm.$state = $state; + vm.loading = {password: false}; + vm.form = {}; - vm.generatePassword = function () { - var length = 8; - var charset = "abcdefghijklnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; - vm.gen_pass = ""; - for (var i = 0, n = charset.length; i < length; ++i) { - vm.gen_pass += charset.charAt(Math.floor(Math.random() * n)); - } - vm.user.user_password = '' + vm.gen_pass; + vm.updatePassword = function () { + vm.loading.password = true; - } - - vm.reloginUser = function () { - sectionViewResource.get({ - section: 'admin_section', view: 'relogin_user', - user_id: vm.user.id - }, function () { - window.location = AeConfig.urls.baseUrl; + userSelfPropertyResource.update({key: 'password'}, vm.form, function () { + vm.loading.password = false; + vm.form = {}; + setServerValidation(vm.passwordForm); + }, function (response) { + if (response.status == 422) { + + setServerValidation(vm.passwordForm, response.data); + + } + vm.loading.password = false; }); - } -}; +} ;// # Copyright (C) 2010-2016 RhodeCode GmbH // # @@ -10834,40 +10860,76 @@ function AdminUsersCreateController($state, usersResource, usersPropertyResource // # services, and proprietary license terms, please see // # https://rhodecode.com/licenses/ -angular.module('appenlight.controllers').controller('AdminUsersController', AdminUsersController); +angular.module('appenlight.components.userProfileView', []) + .component('userProfileView', { + templateUrl: 'components/views/user-profile-view/user-profile-view.html', + controller: UserProfileViewController + }); -AdminUsersController.$inject = ['usersResource']; +UserProfileViewController.$inject = ['$state', 'userSelfResource']; -function AdminUsersController(usersResource) { +function UserProfileViewController($state, userSelfResource) { var vm = this; - vm.loading = {users: true}; + vm.$state = $state; + vm.loading = {profile: true}; - vm.users = usersResource.query({}, function (data) { - vm.loading = {users: false}; - vm.activeUsers = _.reduce(vm.users, function(memo, val){ - if (val.status == 1){ - return memo + 1; - } - return memo; - }, 0); + vm.user = userSelfResource.get(null, function (data) { + vm.loading.profile = false; }); + vm.updateProfile = function () { + vm.loading.profile = true; - vm.removeUser = function (user) { - usersResource.remove({userId: user.id}, function (data, responseHeaders) { - - if (data) { - var index = vm.users.indexOf(user); - if (index !== -1) { - vm.users.splice(index, 1); - vm.activeUsers -= 1; - } + + vm.user.$update(null, function () { + vm.loading.profile = false; + setServerValidation(vm.profileForm); + }, function (response) { + if (response.status == 422) { + setServerValidation(vm.profileForm, response.data); } + vm.loading.profile = false; }); } -}; +} + +;// # Copyright (C) 2010-2016 RhodeCode GmbH +// # +// # This program is free software: you can redistribute it and/or modify +// # it under the terms of the GNU Affero General Public License, version 3 +// # (only), as published by the Free Software Foundation. +// # +// # This program is distributed in the hope that it will be useful, +// # but WITHOUT ANY WARRANTY; without even the implied warranty of +// # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// # GNU General Public License for more details. +// # +// # You should have received a copy of the GNU Affero General Public License +// # along with this program. If not, see . +// # +// # This program is dual-licensed. If you wish to learn more about the +// # AppEnlight Enterprise Edition, including its added features, Support +// # services, and proprietary license terms, please see +// # https://rhodecode.com/licenses/ + +var aeconfig = angular.module('appenlight.config', []); +aeconfig.factory('AeConfig', function () { + var obj = {}; + obj.flashMessages = decodeEncodedJSON(window.AE.flash_messages); + obj.timeOptions = decodeEncodedJSON(window.AE.timeOptions); + obj.plugins = decodeEncodedJSON(window.AE.plugins); + obj.topNav = decodeEncodedJSON(window.AE.topNav); + obj.ws_url = window.AE.ws_url; + obj.urls = window.AE.urls; + // set keys on values because we wont be able to retrieve them everywhere + for (var key in obj.timeOptions) { + obj.timeOptions[key]['key'] = key; + } + console.info('config', obj); + return obj; +}); ;// # Copyright (C) 2010-2016 RhodeCode GmbH // # @@ -12438,84 +12500,74 @@ angular.module('appenlight').config(['$stateProvider', '$urlRouterProvider', fun }); $stateProvider.state('admin', { url: '/ui/admin', - templateUrl: 'templates/admin/parent_view.html' + component: 'adminView' }); $stateProvider.state('admin.user', { abstract: true, url: '/user', - templateUrl: 'templates/admin/users/parent_view.html' + template: '' }); $stateProvider.state('admin.user.list', { url: '/list', - templateUrl: 'templates/admin/users/users_list.html', - controller: 'AdminUsersController as users' + component: 'adminUsersListView' }); $stateProvider.state('admin.user.create', { url: '/create', - templateUrl: 'templates/admin/users/users_create.html', - controller: 'AdminUsersCreateController as user' + component: 'adminUsersCreateView' }); $stateProvider.state('admin.user.update', { url: '/{userId}/update', - templateUrl: 'templates/admin/users/users_create.html', - controller: 'AdminUsersCreateController as user' + component: 'adminUsersCreateView' }); $stateProvider.state('admin.group', { abstract: true, url: '/group', - templateUrl: 'templates/admin/groups/parent_view.html' + template: '' }); $stateProvider.state('admin.group.list', { url: '/list', - templateUrl: 'templates/admin/groups/groups_list.html', - controller: 'AdminGroupsController as groups' + component: 'adminGroupsListView' }); $stateProvider.state('admin.group.create', { url: '/create', - templateUrl: 'templates/admin/groups/groups_create.html', - controller: 'AdminGroupsCreateController as group' + component: 'adminGroupsCreateView' }); $stateProvider.state('admin.group.update', { url: '/{groupId}/update', - templateUrl: 'templates/admin/groups/groups_create.html', - controller: 'AdminGroupsCreateController as group' + component: 'adminGroupsCreateView' }); $stateProvider.state('admin.application', { abstract: true, url: '/application', - templateUrl: 'templates/admin/users/parent_view.html' + template: '' }); $stateProvider.state('admin.application.list', { url: '/list', - templateUrl: 'templates/admin/applications/applications_list.html', - controller: 'AdminApplicationsListController as applications' + component: 'adminApplicationsListView' }); $stateProvider.state('admin.partitions', { url: '/partitions', - templateUrl: 'templates/admin/partitions.html', - controller: 'AdminPartitionsController as partitions' + component: 'adminPartitionsView' }); $stateProvider.state('admin.system', { url: '/system', - templateUrl: 'templates/admin/system.html', - controller: 'AdminSystemController as system' + component: 'adminSystemView' }); $stateProvider.state('admin.configs', { abstract: true, url: '/configs', - templateUrl: 'templates/admin/configs/parent_view.html' + template: '' }); $stateProvider.state('admin.configs.list', { url: '/list', - templateUrl: 'templates/admin/configs/edit.html', - controller: 'ConfigsListController as configs' + component: 'adminConfigurationView' }); $stateProvider.state('user', { diff --git a/frontend/src/app.js b/frontend/src/app.js index bb2839e..9a641de 100644 --- a/frontend/src/app.js +++ b/frontend/src/app.js @@ -67,6 +67,15 @@ angular.module('appenlight.components', [ 'appenlight.components.jiraIntegrationConfigView', 'appenlight.components.slackIntegrationConfigView', 'appenlight.components.webhooksIntegrationConfigView', + 'appenlight.components.adminView', + 'appenlight.components.adminApplicationsListView', + 'appenlight.components.adminUsersListView', + 'appenlight.components.adminUsersCreateView', + 'appenlight.components.adminGroupsListView', + 'appenlight.components.adminGroupsCreateView', + 'appenlight.components.adminConfigurationView', + 'appenlight.components.adminSystemView', + 'appenlight.components.adminPartitionsView', 'appenlight.components.settingsView' ]); angular.module('appenlight.directives', [ diff --git a/frontend/src/templates/admin/applications/applications_list.html b/frontend/src/components/views/admin-applications-list-view/admin-applications-list-view.html similarity index 86% rename from frontend/src/templates/admin/applications/applications_list.html rename to frontend/src/components/views/admin-applications-list-view/admin-applications-list-view.html index 87f0a8a..281211a 100644 --- a/frontend/src/templates/admin/applications/applications_list.html +++ b/frontend/src/components/views/admin-applications-list-view/admin-applications-list-view.html @@ -1,13 +1,13 @@ - + -
+
- Currently active applications: {{applications.applications.length}} + Currently active applications: {{$ctrl.applications.length}}
- +
diff --git a/frontend/src/controllers/admin/applications/applications_list.js b/frontend/src/components/views/admin-applications-list-view/admin-applications-list-view.js similarity index 88% rename from frontend/src/controllers/admin/applications/applications_list.js rename to frontend/src/components/views/admin-applications-list-view/admin-applications-list-view.js index 7617c65..34c5d21 100644 --- a/frontend/src/controllers/admin/applications/applications_list.js +++ b/frontend/src/components/views/admin-applications-list-view/admin-applications-list-view.js @@ -17,7 +17,11 @@ // # services, and proprietary license terms, please see // # https://rhodecode.com/licenses/ -angular.module('appenlight.controllers').controller('AdminApplicationsListController', AdminApplicationsListController); +angular.module('appenlight.components.adminApplicationsListView', []) + .component('adminApplicationsListView', { + templateUrl: 'components/views/admin-applications-list-view/admin-applications-list-view.html', + controller: AdminApplicationsListController + }); AdminApplicationsListController.$inject = ['applicationsResource']; diff --git a/frontend/src/templates/admin/configs/edit.html b/frontend/src/components/views/admin-configuration-view/admin-configuration-view.html similarity index 81% rename from frontend/src/templates/admin/configs/edit.html rename to frontend/src/components/views/admin-configuration-view/admin-configuration-view.html index 4e17380..77f3308 100644 --- a/frontend/src/templates/admin/configs/edit.html +++ b/frontend/src/components/views/admin-configuration-view/admin-configuration-view.html @@ -1,6 +1,6 @@ - + -
+

Basic Configuration

@@ -12,7 +12,7 @@ Footer HTML
- +
@@ -25,7 +25,7 @@ Show user groups to non-admin users
-
@@ -40,7 +40,7 @@ Ignore reports per minute/per application
- +
@@ -49,7 +49,7 @@ Ignore logs per minute/per application
- +
@@ -58,7 +58,7 @@ Ignore metrics per minute/per application
- +
@@ -66,7 +66,7 @@
- Save configuration + Save configuration diff --git a/frontend/src/controllers/admin/config.js b/frontend/src/components/views/admin-configuration-view/admin-configuration-view.js similarity index 86% rename from frontend/src/controllers/admin/config.js rename to frontend/src/components/views/admin-configuration-view/admin-configuration-view.js index 3edc5ad..2a96765 100644 --- a/frontend/src/controllers/admin/config.js +++ b/frontend/src/components/views/admin-configuration-view/admin-configuration-view.js @@ -17,11 +17,15 @@ // # services, and proprietary license terms, please see // # https://rhodecode.com/licenses/ -angular.module('appenlight.controllers').controller('ConfigsListController', ConfigsListController); +angular.module('appenlight.components.adminConfigurationView', []) + .component('adminConfigurationView', { + templateUrl: 'components/views/admin-configuration-view/admin-configuration-view.html', + controller: AdminConfigurationViewController + }); -ConfigsListController.$inject = ['configsResource', 'configsNoIdResource']; +AdminConfigurationViewController.$inject = ['configsResource', 'configsNoIdResource']; -function ConfigsListController(configsResource, configsNoIdResource) { +function AdminConfigurationViewController(configsResource, configsNoIdResource) { var vm = this; vm.loading = {config: true}; diff --git a/frontend/src/templates/admin/groups/groups_create.html b/frontend/src/components/views/admin-groups-create-view/admin-groups-create-view.html similarity index 87% rename from frontend/src/templates/admin/groups/groups_create.html rename to frontend/src/components/views/admin-groups-create-view/admin-groups-create-view.html index a917660..08d23df 100644 --- a/frontend/src/templates/admin/groups/groups_create.html +++ b/frontend/src/components/views/admin-groups-create-view/admin-groups-create-view.html @@ -1,29 +1,29 @@ - + -
+
-
+
- +
- +
- +
- +
@@ -32,7 +32,7 @@
- +
@@ -40,7 +40,7 @@
-
+

Permissions summary

@@ -48,7 +48,7 @@

Direct application permissions

    -
  • +
  • {{ perm.self.resource_name }}
    @@ -65,7 +65,7 @@

    Direct dashboard permissions

      -
    • +
    • {{ perm.self.resource_name }}
      @@ -83,24 +83,24 @@
      -
      +

      User list

      -
      +
      - +
      - +
      -
Application name
+
@@ -136,7 +136,7 @@ diff --git a/frontend/src/controllers/admin/groups/groups_create.js b/frontend/src/components/views/admin-groups-create-view/admin-groups-create-view.js similarity index 90% rename from frontend/src/controllers/admin/groups/groups_create.js rename to frontend/src/components/views/admin-groups-create-view/admin-groups-create-view.js index 994f060..aa8c087 100644 --- a/frontend/src/controllers/admin/groups/groups_create.js +++ b/frontend/src/components/views/admin-groups-create-view/admin-groups-create-view.js @@ -17,13 +17,18 @@ // # services, and proprietary license terms, please see // # https://rhodecode.com/licenses/ -angular.module('appenlight.controllers').controller('AdminGroupsCreateController', AdminGroupsCreateController); +angular.module('appenlight.components.adminGroupsCreateView', []) + .component('adminGroupsCreateView', { + templateUrl: 'components/views/admin-groups-create-view/admin-groups-create-view.html', + controller: AdminGroupsCreateViewController + }); -AdminGroupsCreateController.$inject = ['$state', 'groupsResource', 'groupsPropertyResource', 'sectionViewResource', 'AeConfig']; +AdminGroupsCreateViewController.$inject = ['$state', 'groupsResource', 'groupsPropertyResource', 'sectionViewResource']; -function AdminGroupsCreateController($state, groupsResource, groupsPropertyResource, sectionViewResource, AeConfig) { +function AdminGroupsCreateViewController($state, groupsResource, groupsPropertyResource, sectionViewResource) { console.debug('AdminGroupsCreateController'); var vm = this; + vm.$state = $state; vm.loading = { group: false, resource_permissions: false, diff --git a/frontend/src/templates/admin/groups/groups_list.html b/frontend/src/components/views/admin-groups-list-view/admin-groups-list-view.html similarity index 87% rename from frontend/src/templates/admin/groups/groups_list.html rename to frontend/src/components/views/admin-groups-list-view/admin-groups-list-view.html index 9d51d25..74134fd 100644 --- a/frontend/src/templates/admin/groups/groups_list.html +++ b/frontend/src/components/views/admin-groups-list-view/admin-groups-list-view.html @@ -1,8 +1,8 @@ - + -
+
-
Username
+
@@ -29,7 +29,7 @@ diff --git a/frontend/src/controllers/admin/groups/groups_list.js b/frontend/src/components/views/admin-groups-list-view/admin-groups-list-view.js similarity index 85% rename from frontend/src/controllers/admin/groups/groups_list.js rename to frontend/src/components/views/admin-groups-list-view/admin-groups-list-view.js index f60274e..6225e4a 100644 --- a/frontend/src/controllers/admin/groups/groups_list.js +++ b/frontend/src/components/views/admin-groups-list-view/admin-groups-list-view.js @@ -17,13 +17,18 @@ // # services, and proprietary license terms, please see // # https://rhodecode.com/licenses/ -angular.module('appenlight.controllers').controller('AdminGroupsController', AdminGroupsController); +angular.module('appenlight.components.adminGroupsListView', []) + .component('adminGroupsListView', { + templateUrl: 'components/views/admin-groups-list-view/admin-groups-list-view.html', + controller: AdminGroupsListViewController + }); -AdminGroupsController.$inject = ['groupsResource']; +AdminGroupsListViewController.$inject = ['$state', 'groupsResource']; -function AdminGroupsController(groupsResource) { - console.debug('AdminGroupsController'); +function AdminGroupsListViewController($state, groupsResource) { + console.debug('AdminGroupsListViewController'); var vm = this; + vm.$state = $state; vm.loading = {groups: true}; vm.groups = groupsResource.query({}, function (data) { diff --git a/frontend/src/templates/admin/partitions.html b/frontend/src/components/views/admin-partitions-view/admin-partitions-view.html similarity index 75% rename from frontend/src/templates/admin/partitions.html rename to frontend/src/components/views/admin-partitions-view/admin-partitions-view.html index 2c7c6ae..b5f0f05 100644 --- a/frontend/src/templates/admin/partitions.html +++ b/frontend/src/components/views/admin-partitions-view/admin-partitions-view.html @@ -1,23 +1,23 @@ - + -
+
DELETE Daily Partitions
-
+ ng-class="{'has-error':$ctrl.dailyPartitionsForm.$invalid}">
- - Check All + placeholder="Enter CONFIRM to proceed" class="form-control input-autosize" confirm-validate required ng-model="$ctrl.dailyConfirm"> + + Check All
@@ -26,7 +26,7 @@
- + - + - + @@ -93,7 +93,7 @@ - + @@ -118,7 +118,7 @@ - + @@ -139,7 +139,7 @@
Group name
Date Indices
{{row[0]}}
    @@ -49,19 +49,19 @@ DELETE Permanent Partitions - + ng-class="{'has-error':$ctrl.permanentPartitionsForm.$invalid}">
    - - Check All + placeholder="Enter CONFIRM to proceed" class="form-control" confirm-validate required ng-model="$ctrl.permConfirm"> + + Check All
    @@ -71,7 +71,7 @@
Date Indices
{{row[0]}}
    diff --git a/frontend/src/controllers/admin/partitions.js b/frontend/src/components/views/admin-partitions-view/admin-partitions-view.js similarity index 94% rename from frontend/src/controllers/admin/partitions.js rename to frontend/src/components/views/admin-partitions-view/admin-partitions-view.js index dfff57c..cdada5e 100644 --- a/frontend/src/controllers/admin/partitions.js +++ b/frontend/src/components/views/admin-partitions-view/admin-partitions-view.js @@ -17,11 +17,15 @@ // # services, and proprietary license terms, please see // # https://rhodecode.com/licenses/ -angular.module('appenlight.controllers').controller('AdminPartitionsController', AdminPartitionsController); +angular.module('appenlight.components.adminPartitionsView', []) + .component('adminPartitionsView', { + templateUrl: 'components/views/admin-partitions-view/admin-partitions-view.html', + controller: AdminPartitionsViewController + }); -AdminPartitionsController.$inject = ['sectionViewResource']; +AdminPartitionsViewController.$inject = ['sectionViewResource']; -function AdminPartitionsController(sectionViewResource) { +function AdminPartitionsViewController(sectionViewResource) { var vm = this; vm.permanentPartitions = []; vm.dailyPartitions = []; diff --git a/frontend/src/templates/admin/system.html b/frontend/src/components/views/admin-system-view/admin-system-view.html similarity index 84% rename from frontend/src/templates/admin/system.html rename to frontend/src/components/views/admin-system-view/admin-system-view.html index 399d162..01097b4 100644 --- a/frontend/src/templates/admin/system.html +++ b/frontend/src/components/views/admin-system-view/admin-system-view.html @@ -1,6 +1,6 @@ - + -
    +
    @@ -12,27 +12,27 @@

    System Load: - 1min: {{system.systemLoad[0]}}, 5min: {{system.systemLoad[1]}}, 15min: {{system.systemLoad[2]}} + 1min: {{$ctrl.systemLoad[0]}}, 5min: {{$ctrl.systemLoad[1]}}, 15min: {{$ctrl.systemLoad[2]}}

    Awaiting tasks:

      -
    • reports: {{system.queueStats.waiting_reports}}
    • -
    • logs: {{system.queueStats.waiting_logs}}
    • -
    • metrics: {{system.queueStats.waiting_metrics}}
    • -
    • other: {{system.queueStats.waiting_other}}
    • +
    • reports: {{$ctrl.queueStats.waiting_reports}}
    • +
    • logs: {{$ctrl.queueStats.waiting_logs}}
    • +
    • metrics: {{$ctrl.queueStats.waiting_metrics}}
    • +
    • other: {{$ctrl.queueStats.waiting_other}}

    Queue stats from last minute:

      -
    • Processed reports: {{system.queueStats.processed_reports}}
    • -
    • Processed logs: {{system.queueStats.processed_logs}}
    • -
    • Processed metrics: {{system.queueStats.processed_metrics}}
    • +
    • Processed reports: {{$ctrl.queueStats.processed_reports}}
    • +
    • Processed logs: {{$ctrl.queueStats.processed_logs}}
    • +
    • Processed metrics: {{$ctrl.queueStats.processed_metrics}}

    Disks:

      -
    • +
    • {{disk.device}} {{disk.free}}/{{disk.total}}, {{disk.percentage}}% used
    @@ -40,10 +40,10 @@

    Process stats:

      -
    • FD soft limits: {{system.selfInfo.fds.soft}}
    • -
    • FD hard limits: {{system.selfInfo.fds.hard}}
    • -
    • Memlock soft limits: {{system.selfInfo.memlock.soft}}
    • -
    • Memlock hard limits: {{system.selfInfo.memlock.hard}}
    • +
    • FD soft limits: {{$ctrl.selfInfo.fds.soft}}
    • +
    • FD hard limits: {{$ctrl.selfInfo.fds.hard}}
    • +
    • Memlock soft limits: {{$ctrl.selfInfo.memlock.soft}}
    • +
    • Memlock hard limits: {{$ctrl.selfInfo.memlock.hard}}

    @@ -71,7 +71,7 @@
{{row.table_name}} {{row.size_human}}
{{row.name}} {{row.size_human}}
{{row.owner}} {{row.pid}} {{row.cpu}}
- + diff --git a/frontend/src/controllers/admin/system.js b/frontend/src/components/views/admin-system-view/admin-system-view.js similarity index 87% rename from frontend/src/controllers/admin/system.js rename to frontend/src/components/views/admin-system-view/admin-system-view.js index 5a91ee1..d9a7278 100644 --- a/frontend/src/controllers/admin/system.js +++ b/frontend/src/components/views/admin-system-view/admin-system-view.js @@ -17,11 +17,15 @@ // # services, and proprietary license terms, please see // # https://rhodecode.com/licenses/ -angular.module('appenlight.controllers').controller('AdminSystemController', AdminSystemController); +angular.module('appenlight.components.adminSystemView', []) + .component('adminSystemView', { + templateUrl: 'components/views/admin-system-view/admin-system-view.html', + controller: AdminSystemViewController + }); -AdminSystemController.$inject = ['sectionViewResource']; +AdminSystemViewController.$inject = ['sectionViewResource']; -function AdminSystemController(sectionViewResource) { +function AdminSystemViewController(sectionViewResource) { var vm = this; vm.tables = []; vm.loading = {system: true}; diff --git a/frontend/src/templates/admin/users/users_create.html b/frontend/src/components/views/admin-users-create-view/admin-users-create-view.html similarity index 72% rename from frontend/src/templates/admin/users/users_create.html rename to frontend/src/components/views/admin-users-create-view/admin-users-create-view.html index aab3e27..dfda12c 100644 --- a/frontend/src/templates/admin/users/users_create.html +++ b/frontend/src/components/views/admin-users-create-view/admin-users-create-view.html @@ -1,41 +1,41 @@ - + -
+
- + Re-login to user - +
- +
- +
- +
- + -

Generate password - (generated password: {{user.gen_pass}}) +

Generate password + (generated password: {{$ctrl.gen_pass}})

@@ -43,42 +43,42 @@
- +
- +
- +
- +
- +
- +
- +
- +
@@ -86,7 +86,7 @@
- +
@@ -94,7 +94,7 @@
-
+

Permission Summary

@@ -102,7 +102,7 @@

Direct application permissions

    -
  • +
  • {{ perm.self.resource_name }}
    @@ -118,7 +118,7 @@

    Direct dashboard permissions

      -
    • +
    • {{ perm.self.resource_name }}
      diff --git a/frontend/src/controllers/admin/users/users_create.js b/frontend/src/components/views/admin-users-create-view/admin-users-create-view.js similarity index 91% rename from frontend/src/controllers/admin/users/users_create.js rename to frontend/src/components/views/admin-users-create-view/admin-users-create-view.js index c80bb88..ddbe7b2 100644 --- a/frontend/src/controllers/admin/users/users_create.js +++ b/frontend/src/components/views/admin-users-create-view/admin-users-create-view.js @@ -17,13 +17,18 @@ // # services, and proprietary license terms, please see // # https://rhodecode.com/licenses/ -angular.module('appenlight.controllers').controller('AdminUsersCreateController', AdminUsersCreateController); +angular.module('appenlight.components.adminUsersCreateView', []) + .component('adminUsersCreateView', { + templateUrl: 'components/views/admin-users-create-view/admin-users-create-view.html', + controller: AdminUsersCreateViewController + }); -AdminUsersCreateController.$inject = ['$state', 'usersResource', 'usersPropertyResource', 'sectionViewResource', 'AeConfig']; +AdminUsersCreateViewController.$inject = ['$state', 'usersResource', 'usersPropertyResource', 'sectionViewResource', 'AeConfig']; -function AdminUsersCreateController($state, usersResource, usersPropertyResource, sectionViewResource, AeConfig) { - console.debug('AdminUsersCreateController'); +function AdminUsersCreateViewController($state, usersResource, usersPropertyResource, sectionViewResource, AeConfig) { + console.debug('AdminUsersCreateViewController'); var vm = this; + vm.$state = $state; vm.loading = {user: false}; diff --git a/frontend/src/templates/admin/users/users_list.html b/frontend/src/components/views/admin-users-list-view/admin-users-list-view.html similarity index 92% rename from frontend/src/templates/admin/users/users_list.html rename to frontend/src/components/views/admin-users-list-view/admin-users-list-view.html index af1a596..cb1bff3 100644 --- a/frontend/src/templates/admin/users/users_list.html +++ b/frontend/src/components/views/admin-users-list-view/admin-users-list-view.html @@ -1,15 +1,15 @@ - + -
      +
      - {{users.activeUsers}} active out of {{users.users.length}} users + {{$ctrl.activeUsers}} active out of {{$ctrl.users.length}} users
      -
{{package.name}} {{package.version}}
+
@@ -45,7 +45,7 @@ diff --git a/frontend/src/controllers/admin/users/users_list.js b/frontend/src/components/views/admin-users-list-view/admin-users-list-view.js similarity index 88% rename from frontend/src/controllers/admin/users/users_list.js rename to frontend/src/components/views/admin-users-list-view/admin-users-list-view.js index c18c9ef..1d8b69f 100644 --- a/frontend/src/controllers/admin/users/users_list.js +++ b/frontend/src/components/views/admin-users-list-view/admin-users-list-view.js @@ -17,11 +17,15 @@ // # services, and proprietary license terms, please see // # https://rhodecode.com/licenses/ -angular.module('appenlight.controllers').controller('AdminUsersController', AdminUsersController); +angular.module('appenlight.components.adminUsersListView', []) + .component('adminUsersListView', { + templateUrl: 'components/views/admin-users-list-view/admin-users-list-view.html', + controller: AdminUserListViewController + }); -AdminUsersController.$inject = ['usersResource']; +AdminUserListViewController.$inject = ['usersResource']; -function AdminUsersController(usersResource) { +function AdminUserListViewController(usersResource) { console.debug('AdminUsersController'); var vm = this; vm.loading = {users: true}; diff --git a/frontend/src/templates/admin/parent_view.html b/frontend/src/components/views/admin-view/admin-view.html similarity index 97% rename from frontend/src/templates/admin/parent_view.html rename to frontend/src/components/views/admin-view/admin-view.html index fcd4b1d..bcf4df0 100644 --- a/frontend/src/templates/admin/parent_view.html +++ b/frontend/src/components/views/admin-view/admin-view.html @@ -1,29 +1,30 @@ -
Username