diff --git a/backend/src/appenlight/models/alert_channel.py b/backend/src/appenlight/models/alert_channel.py index d9310d3..fd910e7 100644 --- a/backend/src/appenlight/models/alert_channel.py +++ b/backend/src/appenlight/models/alert_channel.py @@ -210,7 +210,7 @@ class AlertChannel(Base, BaseModel): tmpl_vars["confirmed_total"] = len(reports) tmpl_vars["report_type"] = "error reports" - tmpl_vars["url_report_type"] = 'report' + tmpl_vars["url_report_type"] = 'report/list' alert_type = tmpl_vars.get('alert_type', '') if 'slow_report' in alert_type: diff --git a/backend/src/appenlight/static/js/appenlight.js b/backend/src/appenlight/static/js/appenlight.js index c9ab9da..5594949 100644 --- a/backend/src/appenlight/static/js/appenlight.js +++ b/backend/src/appenlight/static/js/appenlight.js @@ -2681,6 +2681,9 @@ angular.module('appenlight.components', [ 'appenlight.components.appenlightHeader', 'appenlight.components.indexDashboardView', 'appenlight.components.logsBrowserView', + 'appenlight.components.reportView', + 'appenlight.components.reportsBrowserView', + 'appenlight.components.reportsSlowBrowserView', 'appenlight.components.eventBrowserView', 'appenlight.components.userProfileView', 'appenlight.components.userIdentitiesView', @@ -4609,1459 +4612,1574 @@ function kickstartAE(initialUserData) { ); - $templateCache.put('components/views/settings-view/settings-view.html', - "
\n" + - "
\n" + - "
\n" + - "
Applications
\n" + - " \n" + - "
\n" + + $templateCache.put('components/views/report-view/report-view.html', + "\n" + "\n" + - "
\n" + + "\n" + "\n" + - "
\n" + - "
\n" + - "

Alert channels

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

Here you can configure your alert channels.

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

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

\n" + + "
\n" + "\n" + - "
You can add more integrations that support different alert channels via application management panel.
\n" + + "
\n" + + "
\n" + + " 2\">\n" + + " Go back\n" + + " Assign report\n" + + " to user\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" + + " Mark fixed\n" + "\n" + - " \n" + - " Remove\n" + - "
    \n" + - "
  • No
  • \n" + - "
  • Yes
  • \n" + - "
\n" + - "
\n" + + " \n" + + " \n" + + " Integrations\n" + + " \n" + + " \n" + + " \n" + "\n" + - "
\n" + + " Make {{$ctrl.group.public ? 'private' : 'public'}}\n" + "\n" + - "
\n" + + "\n" + + " Delete\n" + + "
    \n" + + "
  • No
  • \n" + + "
  • Yes
  • \n" + + "
\n" + + "
\n" + + "
\n" + "
\n" + "\n" + - "
\n" - ); - - - $templateCache.put('components/views/user-auth-tokens-view/user-auth-tokens-view.html', - "\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" + - "
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" + + " 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" + + "
\n" + + "

Performance stats

\n" + "\n" + - "
\n" + - " \n" + - " \n" + - "
\n" + - " \n" + - " \n" + - "
\n" + - "
\n" + - " \n" + - " \n" + - "
\n" + - "
\n" + - " \n" + - " \n" + - "
\n" + - "
\n" + - "\n" + - "
\n" + - "\n" + - "\n" + - "
\n" + - "\n" + - "
\n" + - " \n" + - " \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" + + " 0 || stat.value > 0\">\n" + + " {{stat.calls}}\n" + + " {{stat.name}} calls\n" + + " \n" + + " Other\n" + + " \n" + + " \n" + "\n" + - "
\n" - ); - - - $templateCache.put('components/views/user-identities-view/user-identities-view.html', - "\n" + + "
\n" + + "
\n" + + "
\n" + + "
\n" + + " 0s\n" + + "
\n" + + "
\n" + + " {{$ctrl.report.duration.toFixed(3)}}s\n" + + "
\n" + + "
\n" + + "
\n" + + "
\n" + + "
\n" + "\n" + - "
\n" + + "

Tags

\n" + "\n" + - "
\n" + - "
\n" + - "
\n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + "
Username/UIDView NameServer Name{{ tag }}\n" + + " {{ value }}
\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" + - "
\n" + - "
\n" - ); - - - $templateCache.put('components/views/user-password-view/user-password-view.html', - "\n" + "\n" + - "
\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" + - " \n" + - " \n" + - "
\n" + - " \n" + + "\n" + + "
\n" + + "
\n" + + " \n" + + " \n" + + " Prev. detail\n" + + "\n" + "
\n" + - "
\n" + - "
\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" + - " \n" + - "
\n" + - " \n" + + "
\n" + + " \n" + + " Next detail \n" + "
\n" + "
\n" + - " \n" + "\n" + - "
\n" + - "
\n" + - "
\n" - ); - - - $templateCache.put('components/views/user-profile-view/user-profile-view.html', - "\n" + + "

{{$ctrl.report.error}}

\n" + "\n" + - "
\n" + - "
\n" + - "
\n" + - "
\n" + - "
\n" + - "
\n" + - " \n" + - " \n" + - "
\n" + - " \n" + - "
\n" + - "
\n" + + "
\n" + "\n" + - "
\n" + - " \n" + - " \n" + - " \n" + - "
\n" + - " \n" + - " \n" + - "
\n" + - " \n" + + "\n" + + "
\n" + + "
{{$ctrl.rawTraceback}}
\n" + "
\n" + - "
\n" + - "
\n" + - " \n" + - " \n" + - "
\n" + - " \n" + - "
\n" + - "
\n" + - "
\n" + - " \n" + - " \n" + - "
\n" + - " \n" + - "
\n" + - "
\n" + - "
\n" + - " \n" + - " \n" + - "
\n" + - " \n" + - "
\n" + - "
\n" + - "
\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" + "\n" + - "

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

\n" + + "
= $ctrl.traceback.length-10 || $ctrl.traceback.length <= 10 || $ctrl.showLong\">\n" + + "
\n" + + " \n" + + " \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" + + " 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" + - "
\n" + - "
\n" + - " \n" + - " {{ permission }}\n" + - " \n" + - "
\n" + - "
\n" + - " \n" + - "
\n" + - "
\n" + + " in {{frame.fn || 'Unknown function'}}\n" + "\n" + - "
\n" + + "
\n" + + "
{{frame.cline || 'Unknown context'}}
\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" + + "
    {{ fvar[0] }}\n" + + " \n" + + "
    \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" - ); - - - $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" + + " Slow Calls\n" + + " \n" + "\n" + - "  Save changes\n" + + "

Slow Calls

\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" + + "
0\">\n" + + "
\n" + + "
\n" + "\n" + - "
\n" + - " \n" + - " \n" + - "
\n" + - "
\n" + - " \n" + - " \n" + + "
\n" + + " No slow calls reported\n" + + "
\n" + + "\n" + + " \n" + + "\n" + + "\n" + + " \n" + + " \n" + + " Request details\n" + + " \n" + + "\n" + + "

Extra

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

Request details

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

No logs found

\n" + + "\n" + + " 0\">\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" + + " \n" + + " \n" + + " Comments\n" + + " {{$ctrl.report.comments.length}}\n" + + "\n" + + " \n" + + "\n" + + "

Comments

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

No comments yet - be first to add one!

\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" + + " 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" + - "  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" + + $templateCache.put('components/views/reports-browser-view/reports-browser-view.html', + "\n" + "\n" + - " \n" + - " {{rule_ctrlr.readOnlyPossibleFields[rule_ctrlr.rule.field]}}\n" + - " \n" + + "
\n" + "\n" + - " \n" + - " is {{rule_ctrlr.ruleDefinitions.allOps[rule_ctrlr.rule.op]}} {{rule_ctrlr.rule.value}}\n" + - " \n" + + "

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

Subrules

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

\n" + "\n" + - "
\n" + - "
\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" + + "
\n" + + " \n" + "
\n" + "\n" + - " \n" + - "

Subrules

\n" + - "
\n" + - "
\n" + - "
\n" + - " \n" + - " \n" + - " \n" + - "
\n" + - "
\n" + - "
\n" + + "
\n" + + " \n" + "\n" + - " Add 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" + - "
  • No
  • \n" + - "
  • Yes
  • \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" ); - $templateCache.put('templates/admin/applications/applications_list.html', - "\n" + + $templateCache.put('components/views/reports-slow-browser-view/reports-slow-browser-view.html', + "\n" + "\n" + - "
\n" + - "
\n" + + "
\n" + "\n" + - " Currently active applications: {{applications.applications.length}}\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" + - "
Application nameOwner UserOwner Group
{{resource.resource_name}}{{resource.owner_user_name}}{{resource.owner_group_name}}\n" + - " \n" + - "
\n" + - "
\n" + - "
\n" + + "
\n" + + "
\n" + + " \n" + + "
\n" + + "
\n" + "\n" + - "
\n" - ); - - - $templateCache.put('templates/admin/configs/edit.html', - "\n" + "\n" + - "
\n" + - "
\n" + - "

Basic Configuration

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

Visual

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

Functional

\n" + "\n" + - "
\n" + - "
\n" + - " \n" + - "
\n" + - " \n" + - "
\n" + - "
\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" + + " \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" + - " Save configuration\n" + "
\n" + "\n" + - "
\n" + - "\n" + - "\n" + - "
\n" + - "
\n" + - "

Plugin Configuration

\n" + - "
\n" + - "
\n" + - " \n" + - " \n" + + "
\n" + + " \n" + "
\n" + + "\n" + "
\n" ); - $templateCache.put('templates/admin/configs/parent_view.html', - "
" + $templateCache.put('components/views/settings-view/settings-view.html', + "
\n" + + "
\n" + + "
\n" + + "
Applications
\n" + + " \n" + + "
\n" + + "\n" + + "\n" + + "
\n" + + "
Settings
\n" + + " \n" + + "
\n" + + "\n" + + "
\n" + + "
Notifications
\n" + + " \n" + + "
\n" + + "
\n" + + "\n" + + "
\n" + + "
\n" ); - $templateCache.put('templates/admin/groups/groups_create.html', - "\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" + - "
\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" + - "

Permissions summary

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

Direct application permissions

\n" + + "

Report alert rules

\n" + + "

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

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

Alert channels

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

Here you can configure your alert channels.

\n" + "\n" + - "

Direct dashboard permissions

\n" + + "

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

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

User list

\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" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + + " \n" + + " \n" + + " \n" + + " \n" + " \n" + " \n" + - " \n" + - " \n" + + " \n" + + " \n" + " \n" + - " \n" + - " \n" + - " \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
UsernameEmailStatusFirst NameLast NameLast loginDescriptionCreatedExpires
{{user.user_name}}{{user.email}}{{user.first_name}}{{user.last_name}}{{user.last_login_date | isoToRelativeTime}}

{{token.description}}

\n" + + "
{{token.token| limitTo:token.limit}}...
\n" + + "
{{token.creation_date | isoToRelativeTime}}{{token.expires | isoToRelativeTime}}\n" + + " Never\n" + - " \n" + " \n" + - " \n" + + " \n" + "
    \n" + "
  • No
  • \n" + - "
  • Yes
  • \n" + + "
  • Yes
  • \n" + "
\n" + "
\n" + - "
\n" + - "
\n" + "
\n" + - "\n" + "
\n" + "\n" + - "\n" + "
\n" ); - $templateCache.put('templates/admin/groups/groups_list.html', - "\n" + - "\n" + - "
\n" + + "
\n" ); - $templateCache.put('templates/admin/parent_view.html', - "
\n" + - "
\n" + - "
Users and groups
\n" + - " \n" + - "
\n" + - "
\n" + - "
Resources
\n" + - " \n" + - "
\n" + + $templateCache.put('components/views/user-password-view/user-password-view.html', + "\n" + "\n" + - "
\n" + - "
System
\n" + - " \n" + - "
\n" + - "
\n" + + "
\n" + "\n" + + "
\n" + + "
\n" + + "
\n" + "\n" + - "
\n" + "
\n" + + "
\n" + + " \n" + + " \n" + + "
\n" + + " \n" + + "
\n" + + "
\n" + + "
\n" + + " \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('templates/admin/partitions.html', - "\n" + - "\n" + - "
\n" + + $templateCache.put('components/views/user-profile-view/user-profile-view.html', + "\n" + "\n" + + "
\n" + "
\n" + - "
\n" + - " DELETE Daily Partitions\n" + - "
\n" + - "\n" + - "
\n" + + "
\n" + + "
\n" + + " \n" + + "
\n" + + " \n" + + " \n" + + "
\n" + + " \n" + + "
\n" + + "
\n" + "\n" + - "
\n" + + "
\n" + + " \n" + + " \n" + + "
\n" + + " \n" + + "
\n" + + "
\n" + + "
\n" + + " \n" + + " \n" + + "
\n" + + " \n" + + "
\n" + + "
\n" + + "
\n" + + " \n" + + " \n" + + "
\n" + + " \n" + + "
\n" + + "
\n" + + "
\n" + + " \n" + + " \n" + + "
\n" + + " \n" + + "
\n" + + "
\n" + + "
\n" + + " \n" + + " \n" + + "
\n" + + " \n" + + "
\n" + + "
\n" + + "
\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" + - " \n" + - " \n" + - " Check All\n" + + "

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

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

Group permissions

\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" + + " {{ 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" + + "
\n" + + "
\n" + + " \n" + + "
\n" + + "
\n" + + " \n" + + " {{ permission }}\n" + + " \n" + + "
\n" + + "
\n" + + " \n" + + "
\n" + + "
\n" + "\n" + - "
\n" + - "
\n" + - " DELETE Permanent Partitions\n" + "
\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" + + "

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" + - " 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" + + " {{ permission }}\n" + + " \n" + + "
\n" + + "
\n" + + " \n" + + "
\n" + + " \n" + + "
\n" + "
\n" + - "\n" + "
\n" ); - $templateCache.put('templates/admin/system.html', - "\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" + - " System Info\n" + - "

\n" + - "
\n" + - "
\n" + + "
\n" + + " \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" + + "
\n" + "\n" + - "

Disks:\n" + - "

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

\n" + + "  Save changes\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" + + "

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" + + "  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" + - "
\n" + + "
\n" + ); + + + $templateCache.put('directives/rule_read_only/rule_read_only.html', + "
\n" + "\n" + - "
\n" + - "
\n" + + " \n" + + " {{rule_ctrlr.readOnlyPossibleFields[rule_ctrlr.rule.field]}}\n" + + " \n" + "\n" + - " \n" + - " \n" + - " \n" + - " Postgresql Tables\n" + - " \n" + + " \n" + + " is {{rule_ctrlr.ruleDefinitions.allOps[rule_ctrlr.rule.op]}} {{rule_ctrlr.rule.value}}\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" + + "

Subrules

\n" + + "
\n" + "\n" + - " \n" + + "
\n" + + "
\n" + + " \n" + + " \n" + + " \n" + + "
\n" + + "
\n" + + "
\n" + "\n" + - " \n" + - " \n" + - " Elasticsearch Indices\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" + - "
Index nameSize
{{row.name}}{{row.size_human}}
\n" + + "
\n" + + " \n" + + "
\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" + - " Python packages\n" + - " \n" + + " \n" + + "

Subrules

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

\n" + + " Add rule\n" + "\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" + - " \n" + + "
\n" + + "
\n" + + "\n" + + " Currently active applications: {{applications.applications.length}}\n" + + "\n" + + "
\n" + + "\n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \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" + ); + + + $templateCache.put('templates/admin/configs/edit.html', + "\n" + + "\n" + + "
\n" + + "
\n" + + "

Basic Configuration

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

Visual

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

Functional

\n" + + "\n" + + "
\n" + + "
\n" + + " \n" + + "
\n" + + " \n" + + "
\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" + + " Save configuration\n" + + "
\n" + + "\n" + + "
\n" + + "\n" + + "\n" + + "
\n" + + "
\n" + + "

Plugin Configuration

\n" + + "
\n" + + "
\n" + + " \n" + + " \n" + "
\n" + "
\n" ); - $templateCache.put('templates/admin/users/parent_view.html', + $templateCache.put('templates/admin/configs/parent_view.html', "
" ); - $templateCache.put('templates/admin/users/users_create.html', - "\n" + + $templateCache.put('templates/admin/groups/groups_create.html', + "\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" + "\n" + - "\n" + - "
\n" + + "
\n" + "
\n" + - "

Permission Summary

\n" + + "

Permissions summary

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

Direct application permissions

\n" + "\n" + "
    \n" + - "
  • \n" + + "
  • \n" + " {{ perm.self.resource_name }}\n" + + "\n" + "
    \n" + "\n" + " {{ perm.self.owner ? 'Resource owner' : perm_name }}\n" + @@ -6076,10 +6194,10 @@ function kickstartAE(initialUserData) { "

    Direct dashboard permissions

    \n" + "\n" + "
      \n" + - "
    • \n" + + "
    • \n" + " {{ perm.self.resource_name }}\n" + - "
      \n" + "\n" + + "
      \n" + " {{ perm.self.owner ? 'Resource owner' : perm_name }}\n" + "\n" + " \n" + @@ -6094,32 +6212,33 @@ function kickstartAE(initialUserData) { "
      \n" + "\n" + "\n" + - "
      \n" - ); - - - $templateCache.put('templates/admin/users/users_list.html', - "\n" + - "\n" + - "
      \n" + - "\n" + - "
      \n" + - "\n" + + "
      \n" + "
      \n" + - " {{users.activeUsers}} active out of {{users.users.length}} users\n" + + "

      User list

      \n" + "
      \n" + + "
      \n" + + "\n" + + "
      \n" + + "
      \n" + + " \n" + + "
      \n" + + "
      \n" + + " \n" + + "
      \n" + + "
      \n" + "\n" + + "
      \n" + "\n" + - " \n" + + "
      \n" + " \n" + " \n" + - " \n" + - " \n" + - " \n" + + " \n" + + " \n" + + " \n" + " \n" + " \n" + " \n" + - " \n" + + " \n" + " \n" + " \n" + " \n" + @@ -6133,959 +6252,838 @@ function kickstartAE(initialUserData) { " \n" + " \n" + "\n" + - " \n" + + " \n" + " \n" + - " \n" + + " \n" + " \n" + - " \n" + - " \n" + - " \n" + + " \n" + + " \n" + + " \n" + " \n" + " \n" + " \n" + - " \n" + " \n" + " \n" + " \n" + "
      UsernameEmailStatusUsernameEmailStatusFirst NameLast NameLast login
      {{user.user_name}}{{user.email}}{{user.email}}{{user.first_name}}{{user.last_name}}{{user.last_login_date | isoToRelativeTime}}{{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" + + "
      • No
      • \n" + + "
      • Yes
      • \n" + + "
      \n" + + "
      \n" + "
      \n" + - "
      \n" + + "
      \n" + + "
      \n" + "
      \n" + "\n" + - "\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" + + $templateCache.put('templates/admin/groups/groups_list.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" + + "
      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" ); - $templateCache.put('templates/directives/user_search_type_ahead.html', - "\n" + - " {{match.label}} -\n" + - " {{match.model.name}}\n" + - "\n" + $templateCache.put('templates/admin/groups/parent_view.html', + "
      " ); - $templateCache.put('templates/integrations/bitbucket.html', - "
      \n" + - "

      Add issue to Bitbucket

      \n" + - "
      \n" + - "
      \n" + - "
      {{msg}}
      \n" + - "
      \n" + - " \n" + - "
      \n" + + $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" + - "
      \n" + - "
      \n" + - "
      \n" + - " \n" + - " \n" + - "
      \n" + + "
      \n" + + "
      System
      \n" + + " \n" + + "
      \n" + + "
      \n" + "\n" + - "
      \n" + - " \n" + - " \n" + - "
      \n" + - "
      \n" + - "
      \n" + - " \n" + - " \n" + - "
      \n" + - " \n" + "\n" + - "
      \n" + - "
      \n" + - " \n" + - " \n" + - "
      \n" + "
      \n" ); - $templateCache.put('templates/integrations/github.html', - "
      \n" + - "

      Add issue to Github

      \n" + - "
      \n" + - "
      \n" + - "
      {{msg}}
      \n" + + $templateCache.put('templates/admin/partitions.html', + "\n" + "\n" + - "
      \n" + - " \n" + + "
      \n" + + "\n" + + "
      \n" + + "
      \n" + + " DELETE Daily Partitions\n" + "
      \n" + "\n" + - "
      \n" + - "
      \n" + - " \n" + - " \n" + - "
      \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('templates/integrations/jira.html', - "
      \n" + - "

      Add issue to Jira

      \n" + - "
      \n" + - "
      \n" + - "
      {{msg}}
      \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" + - " \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" - ); - - - $templateCache.put('templates/loader.html', - "
      \n" + - " \n" + - "
      \n" - ); - - - $templateCache.put('templates/quickstart.html', - "

      AppEnlight quickstart

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

      \n" + - " 1\n" + - " For AppEnlight to operate, you need to\n" + - " create an app profile that allows\n" + - " you to\n" + - " obtain an API key that one of the clients can use.\n" + - "

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

      \n" + - " 2\n" + - " It is a good idea to configure an\n" + - " \n" + - " email alert channel that you can use to receive\n" + - " notifications about events that happen in your application.\n" + - "

      \n" + "\n" + - "

      \n" + - " It can be the same email account you used to register withing AppEnlight -\n" + - " although we often recommend using a separate errors@... account\n" + - " designated for alert notifications.\n" + - "

      \n" + + "
      \n" + "\n" + - "
      \n" + - "
      \n" + + "
      \n" + + " \n" + + " \n" + + " Check All\n" + + "
      \n" + "\n" + - "

      \n" + - " 3\n" + - " In order for your application to stream meaningful information, you will need to\n" + - " integrate a compatible client for your language of choice.\n" + - "

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

      Head over to the \n" + - " developers section for information on currently available\n" + - " clients that you can plug into your software

      \n" - ); - - - $templateCache.put('templates/register.html', - "" + " \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" ); - $templateCache.put('templates/reports/list_slow.html', - "\n" + + $templateCache.put('templates/admin/system.html', + "\n" + "\n" + - "
      \n" + + "
      \n" + + "
      \n" + + "
      \n" + + "
      \n" + + "
      \n" + + "

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

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

      \n" + - " Search params:\n" + - " \n" + - " {{tag.type}}\n" + - " {{ tag.type == 'resource' ? reports_list.applications[tag.value].resource_name : tag.value }}\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" + - " \n" + - "

      \n" + + "

      Disks:\n" + + "

        \n" + + "
      • \n" + + " {{disk.device}} {{disk.free}}/{{disk.total}}, {{disk.percentage}}% used\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" + - "\n" + - "\n" + - "
      \n" + - " \n" + - "
      \n" + - "\n" + - "

      \n" + - "\n" + - "\n" + - "
      \n" + - " \n" + "
      \n" + + "
      \n" + + "
      \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" + - " \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" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + "
      Table nameSize
      {{row.table_name}}{{row.size_human}}
      \n" + "\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" + + "
      Index nameSize
      {{row.name}}{{row.size_human}}
      \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" + + "
      OwnerPIDCPUMEMName
      {{row.owner}}{{row.pid}}{{row.cpu}}{{row.mem_usage}} ({{row.mem_percentage}}%){{row.name}}
      {{row.command}}
      \n" + + "\n" + + "
      \n" + + "\n" + + " \n" + + " \n" + + " Python packages\n" + + " \n" + + "\n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + "
      {{package.name}}{{package.version}}
      \n" + + "

      \n" + + "\n" + + "
      \n" + "\n" + + " \n" + + "
      \n" + + "
      \n" + + "
      \n" + + "
      \n" + "
      \n" ); - $templateCache.put('templates/reports/list.html', - "\n" + + $templateCache.put('templates/admin/users/parent_view.html', + "
      " + ); + + + $templateCache.put('templates/admin/users/users_create.html', + "\n" + "\n" + - "
      \n" + + "
      \n" + "\n" + - "

      \n" + - " Search params:\n" + - " \n" + - " {{tag.type}}\n" + - " {{ tag.type == 'resource' ? reports_list.applications[tag.value].resource_name : tag.value }}\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" + + "
      \n" + + "
      \n" + + " \n" + + " \n" + + "
      \n" + + " \n" + + "
      \n" + + "
      \n" + "\n" + + "
      \n" + + " \n" + + " \n" + + "
      \n" + + " \n" + "\n" + - "
      \n" + - " \n" + - "
      \n" + + "

      Generate password\n" + + " 0\">(generated password: {{user.gen_pass}})\n" + + "

      \n" + "\n" + - "

      \n" + + "
      \n" + + "
      \n" + "\n" + "\n" + - "
      \n" + - " \n" + - "
      \n" + + "
      \n" + + " \n" + + " \n" + + "
      \n" + + " \n" + + "
      \n" + + "
      \n" + "\n" + - "
      \n" + - " \n" + + "
      \n" + + " \n" + + " \n" + + "
      \n" + + " \n" + + "
      \n" + + "
      \n" + + "
      \n" + + " \n" + + " \n" + + "
      \n" + + " \n" + + "
      \n" + + "
      \n" + "\n" + - " \n" + - " \n" + - " \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
      #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('templates/reports/parent_view.html', - "
      " - ); - - - $templateCache.put('templates/reports/small_report_group_list.html', - "\n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - "
      {{ report_group.occurences|numberToThousands }}\n" + - " \n" + - " {{ report_group.error || \"Slow Report\"}}\n" + - "
      \n" + - " {{report_group.summed_duration/report_group.occurences|round:2}}s\n" + - " {{ report_group.view_name || report_group.url_path}}\n" + - "
      \n" + - " @{{applications[report_group.resource_id].resource_name}}
      \n" + - " {{report_group.last_timestamp | isoToRelativeTime}}\n" + - "
      \n" - ); - - - $templateCache.put('templates/reports/small_report_list.html', - "\n" + - " 0\" class=\"animate-repeat\">\n" + - " \n" + - " \n" + - " \n" + - " \n" + - "
      {{ report.group.occurences|numberToThousands }}\n" + - " \n" + - " {{ report.error || \"Slow Report\"}}\n" + - "
      \n" + - " {{report.group.summed_duration/report.group.occurences|round:2}}s\n" + - " {{ report.view_name || report.url_path}}\n" + - "
      \n" + - " @{{applications[report.resource_id].resource_name}}
      \n" + - " {{report.last_timestamp | isoToRelativeTime}}\n" + - "
      \n" - ); - - - $templateCache.put('templates/reports/view.html', - "\n" + + "
      \n" + + "
      \n" + + " \n" + + " \n" + + "
      \n" + ); + + + $templateCache.put('templates/integrations/jira.html', + "
      \n" + + "

      Add issue to Jira

      \n" + + "
      \n" + + "
      \n" + + "
      {{msg}}
      \n" + + "
      \n" + + " \n" + + "
      \n" + "\n" + + "
      \n" + + "
      \n" + + " \n" + + " \n" + + "
      \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" + + " \n" + + "
      \n" + + "
      \n" + + "
      \n" + + " \n" + + " \n" + + "
      \n" + + " \n" + "\n" + - "
      \n" + - " \n" + + "
      \n" + + " \n" + + " \n" + + "
      \n" + ); + + + $templateCache.put('templates/loader.html', + "
      \n" + + " \n" + + "
      \n" + ); + + + $templateCache.put('templates/quickstart.html', + "

      AppEnlight quickstart

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

      \n" + + " 1\n" + + " For AppEnlight to operate, you need to\n" + + " create an app profile that allows\n" + + " you to\n" + + " obtain an API key that one of the clients can use.\n" + + "

      \n" + "\n" + - "

      {{report.report.error}}

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

      \n" + + " 2\n" + + " It is a good idea to configure an\n" + + " \n" + + " email alert channel that you can use to receive\n" + + " notifications about events that happen in your application.\n" + + "

      \n" + "\n" + - "

      Traceback

      \n" + + "

      \n" + + " It can be the same email account you used to register withing AppEnlight -\n" + + " although we often recommend using a separate errors@... account\n" + + " designated for alert notifications.\n" + + "

      \n" + "\n" + - " \n" + - "\n" + - "
      \n" + - "
      {{report.rawTraceback}}
      \n" + - "
      \n" + - "
      \n" + - "\n" + - "
      = report.traceback.length-10 || report.traceback.length <= 10 || report.showLong\">\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" + - " in {{frame.fn || 'Unknown function'}}\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" + - " Slow Calls\n" + - " \n" + - "\n" + - "

      Slow Calls

      \n" + - "\n" + - "
      0\">\n" + - "
      \n" + - "
      \n" + - "\n" + - "
      \n" + - " No slow calls reported\n" + - "
      \n" + - "\n" + - "
      \n" + - "\n" + - "\n" + - " \n" + - " \n" + - " Request details\n" + - " \n" + - "\n" + - "

      Extra

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

      Request details

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

      No logs found

      \n" + - "\n" + - " 0\">\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" + - " \n" + - " \n" + - " Comments\n" + - " {{report.report.comments.length}}\n" + - "\n" + - " \n" + - "\n" + - "

      Comments

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

      No comments yet - be first to add one!

      \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" + - " Affected users\n" + - " {{report.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" + + " 3\n" + + " In order for your application to stream meaningful information, you will need to\n" + + " integrate a compatible client for your language of choice.\n" + + "

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

      Head over to the \n" + + " developers section for information on currently available\n" + + " clients that you can plug into your software

      \n" + ); + + + $templateCache.put('templates/register.html', + "" + ); + + + $templateCache.put('templates/reports/small_report_group_list.html', + "\n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + "
      {{ report_group.occurences|numberToThousands }}\n" + + " \n" + + " {{ report_group.error || \"Slow Report\"}}\n" + + "
      \n" + + " {{report_group.summed_duration/report_group.occurences|round:2}}s\n" + + " {{ report_group.view_name || report_group.url_path}}\n" + + "
      \n" + + " @{{applications[report_group.resource_id].resource_name}}
      \n" + + " {{report_group.last_timestamp | isoToRelativeTime}}\n" + + "
      \n" + ); + + + $templateCache.put('templates/reports/small_report_list.html', + "\n" + + " 0\" class=\"animate-repeat\">\n" + + " \n" + + " \n" + + " \n" + + " \n" + + "
      {{ report.group.occurences|numberToThousands }}\n" + + " \n" + + " {{ report.error || \"Slow Report\"}}\n" + + "
      \n" + + " {{report.group.summed_duration/report.group.occurences|round:2}}s\n" + + " {{ report.view_name || report.url_path}}\n" + + "
      \n" + + " @{{applications[report.resource_id].resource_name}}
      \n" + + " {{report.last_timestamp | isoToRelativeTime}}\n" + + "
      \n" ); @@ -8784,275 +8782,345 @@ function LogsBrowserController($location, stateHolder, typeAheadTagHelper, logsN // # 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/ - -angular.module('appenlight.components.userAlertChannelsListView', []) - .component('userAlertChannelsListView', { - templateUrl: 'components/views/user-alert-channels-list-view/user-alert-channels-list-view.html', - controller: userAlertChannelsListViewController - }); - -userAlertChannelsListViewController.$inject = ['$state','userSelfPropertyResource', 'applicationsNoIdResource']; - -function userAlertChannelsListViewController($state, userSelfPropertyResource, applicationsNoIdResource) { - - var vm = this; - vm.$state = $state; - vm.loading = {channels: true, applications: true, actions:true}; - - 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; - }); - - 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' + }, + 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 }; - 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.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 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' + var result = _.filter(users, function(u){ + return u.label.toLowerCase().indexOf(term) !== -1; + }); + vm.mentionedPeople = result; + }); }; - vm.ruleDefinitions = { - fieldOps: fieldOps, - allOps: allOps, - possibleFields: possibleFields + 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.addAction = function (channel) { - - userSelfPropertyResource.save({key: 'alert_channels_rules'}, {}, function (data) { - vm.alertActions.push(data); - }, function (response) { - if (response.status == 422) { - - } - }); + 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.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]; + vm.fetchLogs = function () { + if (!vm.report.request_id){ + return } - userSelfPropertyResource.update(params, toUpdate, function (data) { - _.extend(channel, data); + 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.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.addComment = function () { + reportGroupPropertyResource.save({ + groupId: vm.report.group_id, + key: 'comments' + }, {body: vm.comment}, + function (data) { + vm.report.comments.push(data); }); - }); - - } + vm.comment = ''; + }; -} + 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"; + }); -;// # 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 (stateHolder.AeUser.id){ + vm.fetchHistory(); + } -angular.module('appenlight.components.userAuthTokensView', []) - .component('userAuthTokensView', { - templateUrl: 'components/views/user-auth-tokens-view/user-auth-tokens-view.html', - controller: userAuthTokensViewController - }); + vm.selectedTab($cookies.selectedReportTab); -userAuthTokensViewController.$inject = ['$state', 'userSelfPropertyResource', 'AeConfig']; + }, 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; + }); + }; -function userAuthTokensViewController($state, userSelfPropertyResource, AeConfig) { - - var vm = this; - vm.$state = $state; - vm.loading = {tokens: true}; + vm.selectedTab = function(tab_name){ + $cookies.selectedReportTab = tab_name; + if (tab_name == 'logs' && vm.reportLogs === null) { + vm.fetchLogs(); + } + }; - vm.expireOptions = AeConfig.timeOptions; + vm.markFixed = function () { + reportGroupResource.update({ + groupId: vm.report.group_id + }, {fixed: !vm.report.group.fixed}, + function (data) { + vm.report.group.fixed = data.fixed; + }); + }; - vm.tokens = userSelfPropertyResource.query({key: 'auth_tokens'}, - function (data) { - vm.loading.tokens = false; - }); + vm.markPublic = function () { + reportGroupResource.update({ + groupId: vm.report.group_id + }, {public: !vm.report.group.public}, + function (data) { + vm.report.group.public = data.public; + }); + }; - vm.addToken = function () { - vm.loading.tokens = true; - userSelfPropertyResource.save({key: 'auth_tokens'}, - vm.form, + vm.delete = function () { + reportGroupResource.delete({'groupId': vm.report.group_id}, 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); + $state.go('report.list'); + }) + }; + + 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.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); + 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.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; } - }) - } + } + }; + 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 @@ -9074,188 +9142,605 @@ 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); + } + + 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.paginationChange = function(){ + $location.search('page', vm.page); + vm.refresh(); + }; + + 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(':'); + } + } + 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(); + } + + 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; + }; + + 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; + 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.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 +// # +// # 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/ + +'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); } -} - -;// # 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.userPasswordView', []) - .component('userPasswordView', { - templateUrl: 'components/views/user-password-view/user-password-view.html', - controller: UserPasswordViewController - }); - -UserPasswordViewController.$inject = ['$state', 'userSelfPropertyResource']; -function UserPasswordViewController($state, userSelfPropertyResource) { - - var vm = this; - vm.$state = $state; - vm.loading = {password: false}; - vm.form = {}; + vm.changeRelativeTime = function () { + $cookies.notRelativeTime = JSON.stringify(vm.notRelativeTime); + }; - 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); - - } - vm.loading.password = false; + _.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' + }); + }); -;// # 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.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(':'); + } + } -angular.module('appenlight.components.userProfileView', []) - .component('userProfileView', { - templateUrl: 'components/views/user-profile-view/user-profile-view.html', - controller: UserProfileViewController - }); + // 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(); + } -UserProfileViewController.$inject = ['$state', 'userSelfResource']; + 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; + }; -function UserProfileViewController($state, userSelfResource) { - - var vm = this; - vm.$state = $state; - vm.loading = {profile: true}; + vm.paginationChange = function(){ + $location.search('page', vm.page); + vm.refresh(); + }; - vm.user = userSelfResource.get(null, function (data) { - vm.loading.profile = false; - - }); + 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.updateProfile = function () { - 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.$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 = 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; }); - } -} + }; -;// # 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.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); + }; -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; -}); + //initial load + vm.refresh(); +} ;// # Copyright (C) 2010-2016 RhodeCode GmbH // # @@ -9276,22 +9761,18 @@ aeconfig.factory('AeConfig', function () { // # services, and proprietary license terms, please see // # https://rhodecode.com/licenses/ -angular.module('appenlight.controllers').controller('AdminApplicationsListController', AdminApplicationsListController); - -AdminApplicationsListController.$inject = ['applicationsResource']; +angular.module('appenlight.components.settingsView', []) + .component('settingsView', { + templateUrl: 'components/views/settings-view/settings-view.html', + controller: SettingsViewController + }); -function AdminApplicationsListController(applicationsResource) { - - var vm = this; - vm.loading = {applications: true}; +SettingsViewController.$inject = ['$state']; - vm.applications = applicationsResource.query({ - root_list: true, - resource_type: 'application' - }, function (data) { - vm.loading = {applications: false}; - }); -}; +function SettingsViewController($state) { + this.$state = $state; + console.info('SettingsViewController'); +} ;// # Copyright (C) 2010-2016 RhodeCode GmbH // # @@ -9312,44 +9793,37 @@ function AdminApplicationsListController(applicationsResource) { // # services, and proprietary license terms, please see // # https://rhodecode.com/licenses/ -angular.module('appenlight.controllers').controller('ConfigsListController', ConfigsListController); +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 + }); -ConfigsListController.$inject = ['configsResource', 'configsNoIdResource']; +AlertChannelsEmailController.$inject = ['$state','userSelfPropertyResource']; -function ConfigsListController(configsResource, configsNoIdResource) { +function AlertChannelsEmailController($state, userSelfPropertyResource) { + 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; - }); - }); + vm.$state = $state; + vm.loading = {email: false}; + vm.form = {}; - vm.save = function () { - vm.loading.config = true; - _.each(vm.configList, function (item) { - item.$save(); + 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.loading.email = false; }); - vm.loading.config = false; - }; - -}; + } +} ;// # Copyright (C) 2010-2016 RhodeCode GmbH // # @@ -9370,128 +9844,122 @@ 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.userAlertChannelsListView', []) + .component('userAlertChannelsListView', { + templateUrl: 'components/views/user-alert-channels-list-view/user-alert-channels-list-view.html', + controller: userAlertChannelsListViewController + }); -AdminGroupsCreateController.$inject = ['$state', 'groupsResource', 'groupsPropertyResource', 'sectionViewResource', 'AeConfig']; +userAlertChannelsListViewController.$inject = ['$state','userSelfPropertyResource', 'applicationsNoIdResource']; -function AdminGroupsCreateController($state, groupsResource, groupsPropertyResource, sectionViewResource, AeConfig) { +function userAlertChannelsListViewController($state, userSelfPropertyResource, applicationsNoIdResource) { var vm = this; - vm.loading = { - group: false, - resource_permissions: false, - users: false - }; + vm.$state = $state; + vm.loading = {channels: true, applications: true, actions:true}; - vm.form = { - autocompleteUser: '', - } + 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; + }); - 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.applications = applicationsNoIdResource.query({permission: 'view'}, + function (data) { + 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); + 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.resourcePermissions = tmpObj; - }); + 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.users = groupsPropertyResource.query( - {groupId: groupId, key: 'users'}, function (data) { - vm.loading.users = false; - }, function () { - vm.loading.users = false; - }); + 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' + }; - } - else { - var groupId = null; - } + vm.ruleDefinitions = { + fieldOps: fieldOps, + allOps: allOps, + possibleFields: possibleFields + }; - var formResponse = function (response) { - if (response.status === 422) { - setServerValidation(vm.groupForm, response.data); - } - vm.loading.group = false; + vm.addAction = function (channel) { + + userSelfPropertyResource.save({key: 'alert_channels_rules'}, {}, function (data) { + vm.alertActions.push(data); + }, function (response) { + if (response.status == 422) { + + } + }); }; - 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.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.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.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.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 // # @@ -9512,40 +9980,57 @@ 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.userAuthTokensView', []) + .component('userAuthTokensView', { + templateUrl: 'components/views/user-auth-tokens-view/user-auth-tokens-view.html', + controller: userAuthTokensViewController + }); -AdminGroupsController.$inject = ['groupsResource']; +userAuthTokensViewController.$inject = ['$state', 'userSelfPropertyResource', 'AeConfig']; -function AdminGroupsController(groupsResource) { +function userAuthTokensViewController($state, userSelfPropertyResource, AeConfig) { var vm = this; - vm.loading = {groups: true}; + vm.$state = $state; + vm.loading = {tokens: 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.expireOptions = AeConfig.timeOptions; + vm.tokens = userSelfPropertyResource.query({key: 'auth_tokens'}, + function (data) { + vm.loading.tokens = false; + }); - vm.removeGroup = function (group) { - groupsResource.remove({groupId: group.id}, function (data, responseHeaders) { - - if (data) { - var index = vm.groups.indexOf(group); + 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.groups.splice(index, 1); - vm.activeGroups -= 1; + vm.tokens.splice(index, 1); } - } - }); + }) } -}; +} ;// # Copyright (C) 2010-2016 RhodeCode GmbH // # @@ -9566,110 +10051,97 @@ 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.userIdentitiesView', []) + .component('userIdentitiesView', { + templateUrl: 'components/views/user-identities-view/user-identities-view.html', + controller: UserIdentitiesController + }); -AdminPartitionsController.$inject = ['sectionViewResource']; +UserIdentitiesController.$inject = ['$state', 'userSelfPropertyResource', 'AeConfig']; -function AdminPartitionsController(sectionViewResource) { +function UserIdentitiesController($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'; - } + vm.$state = $state; + vm.AeConfig = AeConfig; + vm.loading = {identities: true}; - 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.identities = userSelfPropertyResource.query( + {key: 'external_identities'}, + function (data) { + vm.loading.identities = false; + }); - } - - vm.transformPartitionList = function (inputList) { - var outputList = []; + 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 + }); + } - _.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) - } - }); - }); - +;// # 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.loading = {partitions: true}; - sectionViewResource.save({section:'admin_section', - view: 'partitions_remove'}, { - es_indices: es_indices, - pg_indices: pg_indices, - confirm: 'CONFIRM' - }, vm.loadPartitions); +angular.module('appenlight.components.userPasswordView', []) + .component('userPasswordView', { + templateUrl: 'components/views/user-password-view/user-password-view.html', + controller: UserPasswordViewController + }); - } +UserPasswordViewController.$inject = ['$state', 'userSelfPropertyResource']; + +function UserPasswordViewController($state, userSelfPropertyResource) { + + var vm = this; + vm.$state = $state; + vm.loading = {password: false}; + vm.form = {}; + 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); + + } + vm.loading.password = false; + }); + } } ;// # Copyright (C) 2010-2016 RhodeCode GmbH @@ -9691,31 +10163,40 @@ 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.userProfileView', []) + .component('userProfileView', { + templateUrl: 'components/views/user-profile-view/user-profile-view.html', + controller: UserProfileViewController + }); -AdminSystemController.$inject = ['sectionViewResource']; +UserProfileViewController.$inject = ['$state', 'userSelfResource']; -function AdminSystemController(sectionViewResource) { +function UserProfileViewController($state, userSelfResource) { + 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.loading = {profile: true}; - vm.loading.system = false; + vm.user = userSelfResource.get(null, function (data) { + vm.loading.profile = false; + }); -}; + + vm.updateProfile = function () { + vm.loading.profile = true; + + + 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 // # @@ -9736,106 +10217,57 @@ function AdminSystemController(sectionViewResource) { // # services, and proprietary license terms, please see // # https://rhodecode.com/licenses/ -angular.module('appenlight.controllers').controller('AdminUsersCreateController', AdminUsersCreateController); - -AdminUsersCreateController.$inject = ['$state', 'usersResource', 'usersPropertyResource', 'sectionViewResource', 'AeConfig']; - -function AdminUsersCreateController($state, usersResource, usersPropertyResource, sectionViewResource, AeConfig) { - - 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 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; +}); - var formResponse = function (response) { - if (response.status == 422) { - setServerValidation(vm.profileForm, response.data); - } - vm.loading.user = 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/ - 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); - } - } +angular.module('appenlight.controllers').controller('AdminApplicationsListController', AdminApplicationsListController); - 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; - - } +AdminApplicationsListController.$inject = ['applicationsResource']; - vm.reloginUser = function () { - sectionViewResource.get({ - section: 'admin_section', view: 'relogin_user', - user_id: vm.user.id - }, function () { - window.location = AeConfig.urls.baseUrl; - }); +function AdminApplicationsListController(applicationsResource) { + + var vm = this; + 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 @@ -9857,39 +10289,43 @@ 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.controllers').controller('ConfigsListController', ConfigsListController); -AdminUsersController.$inject = ['usersResource']; +ConfigsListController.$inject = ['configsResource', 'configsNoIdResource']; -function AdminUsersController(usersResource) { - +function ConfigsListController(configsResource, configsNoIdResource) { var vm = this; - vm.loading = {users: true}; + vm.loading = {config: 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); - - }); + 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.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.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 @@ -9911,80 +10347,128 @@ function AdminUsersController(usersResource) { // # services, and proprietary license terms, please see // # https://rhodecode.com/licenses/ -angular.module('appenlight.controllers') - .controller('BitbucketIntegrationCtrl', BitbucketIntegrationCtrl) +angular.module('appenlight.controllers').controller('AdminGroupsCreateController', AdminGroupsCreateController); -BitbucketIntegrationCtrl.$inject = ['$uibModalInstance', '$state', 'report', 'integrationName', 'integrationResource']; +AdminGroupsCreateController.$inject = ['$state', 'groupsResource', 'groupsPropertyResource', 'sectionViewResource', 'AeConfig']; -function BitbucketIntegrationCtrl($uibModalInstance, $state, report, integrationName, integrationResource) { +function AdminGroupsCreateController($state, groupsResource, groupsPropertyResource, sectionViewResource, AeConfig) { + var vm = this; - vm.loading = true; - vm.assignees = []; - vm.report = report; - vm.integrationName = integrationName; - vm.statuses = []; - vm.priorities = []; - vm.error_messages = []; + vm.loading = { + group: false, + resource_permissions: false, + users: false + }; + vm.form = { - content: '\n' + - 'Issue created for report: ' + - $state.href('report.view_detail', {groupId:report.group_id, reportId:report.id}, {absolute:true}) + 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.fetchInfo = function () { - integrationResource.get({ - resourceId: vm.report.resource_id, - action: 'info', - integration: vm.integrationName - }, null, + 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 = false; - if (data.error_messages) { - vm.error_messages = data.error_messages; - } - vm.assignees = data.assignees; - vm.priorities = data.priorities; - vm.form.responsible = vm.assignees[0]; - vm.form.priority = vm.priorities[0]; - }, function (error_data) { - if (error_data.data.error_messages) { - vm.error_messages = error_data.data.error_messages; - } - else { - vm.error_messages = ['There was a problem processing your request']; - } + vm.loading.users = false; + vm.users = _.filter(vm.users, function (item) { + return item != user; + }); + }, function () { + vm.loading.users = false; }); }; - vm.ok = function () { - vm.loading = true; - vm.form.group_id = vm.report.group_id; - integrationResource.save({ - resourceId: vm.report.resource_id, - action: 'create-issue', - integration: vm.integrationName - }, vm.form, + + vm.addUser = function () { + groupsPropertyResource.save( + {groupId: groupId, key: 'users'}, + {user_name: vm.form.autocompleteUser}, function (data) { - vm.loading = false; - if (data.error_messages) { - vm.error_messages = data.error_messages; - } - if (data !== false) { - $uibModalInstance.dismiss('success'); - } - }, function (error_data) { - if (error_data.data.error_messages) { - vm.error_messages = error_data.data.error_messages; - } - else { - vm.error_messages = ['There was a problem processing your request']; - } + vm.loading.users = false; + vm.users.push(data); + vm.form.autocompleteUser = ''; + }, function () { + vm.loading.users = false; }); - }; - vm.cancel = function () { - $uibModalInstance.dismiss('cancel'); - }; - vm.fetchInfo(); -} + } + + 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 // # @@ -10005,82 +10489,40 @@ function BitbucketIntegrationCtrl($uibModalInstance, $state, report, integration // # services, and proprietary license terms, please see // # https://rhodecode.com/licenses/ -angular.module('appenlight.controllers') - .controller('GithubIntegrationCtrl', GithubIntegrationCtrl); +angular.module('appenlight.controllers').controller('AdminGroupsController', AdminGroupsController); -GithubIntegrationCtrl.$inject = ['$uibModalInstance', '$state', 'report', 'integrationName', 'integrationResource']; +AdminGroupsController.$inject = ['groupsResource']; -function GithubIntegrationCtrl($uibModalInstance, $state, report, integrationName, integrationResource) { +function AdminGroupsController(groupsResource) { + var vm = this; - vm.loading = true; - vm.assignees = []; - vm.report = report; - vm.integrationName = integrationName; - vm.statuses = []; - vm.assignees = []; - vm.error_messages = []; - vm.form = { - content: '\n' + - 'Issue created for report: ' + - $state.href('report.view_detail', {groupId:report.group_id, reportId:report.id}, {absolute:true}) - }; + vm.loading = {groups: true}; - vm.fetchInfo = function () { - integrationResource.get({ - resourceId: vm.report.resource_id, - action: 'info', - integration: vm.integrationName - }, null, - function (data) { - vm.loading = false; - if (data.error_messages) { - vm.error_messages = data.error_messages; - } - else { - vm.assignees = data.assignees; - vm.statuses = data.statuses; - vm.form.responsible = vm.assignees[0]; - vm.form.status = vm.statuses[0]; - } - }, function (error_data) { - if (error_data.data.error_messages) { - vm.error_messages = error_data.data.error_messages; - } - else { - vm.error_messages = ['There was a problem processing your request']; - } - }); - }; - vm.ok = function () { - vm.loading = true; - vm.form.group_id = vm.report.group_id; - integrationResource.save({ - resourceId: vm.report.resource_id, - action: 'create-issue', - integration: vm.integrationName - }, vm.form, - function (data) { - vm.loading = false; - if (data.error_messages) { - vm.error_messages = data.error_messages; - } - else { - $uibModalInstance.dismiss('success'); - } - }, function (error_data) { - if (error_data.data.error_messages) { - vm.error_messages = error_data.data.error_messages; - } - else { - vm.error_messages = ['There was a problem processing your request']; + 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.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.cancel = function () { - $uibModalInstance.dismiss('cancel'); - }; - vm.fetchInfo(); -} + } + }); + } +}; ;// # Copyright (C) 2010-2016 RhodeCode GmbH // # @@ -10101,83 +10543,110 @@ function GithubIntegrationCtrl($uibModalInstance, $state, report, integrationNam // # services, and proprietary license terms, please see // # https://rhodecode.com/licenses/ -angular.module('appenlight.controllers') - .controller('JiraIntegrationCtrl', JiraIntegrationCtrl) +angular.module('appenlight.controllers').controller('AdminPartitionsController', AdminPartitionsController); -JiraIntegrationCtrl.$inject = ['$uibModalInstance', '$state', 'report', 'integrationName', 'integrationResource']; +AdminPartitionsController.$inject = ['sectionViewResource']; -function JiraIntegrationCtrl($uibModalInstance, $state, report, integrationName, integrationResource) { +function AdminPartitionsController(sectionViewResource) { var vm = this; - vm.loading = true; - vm.assignees = []; - vm.report = report; - vm.integrationName = integrationName; - vm.statuses = []; - vm.priorities = []; - vm.issue_types = []; - vm.error_messages = []; - vm.form = { - content: '\n' + - 'Issue created for report: ' + - $state.href('report.view_detail', {groupId:report.group_id, reportId:report.id}, {absolute:true}) + 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.fetchInfo = function () { - integrationResource.get({ - resourceId: vm.report.resource_id, - action: 'info', - integration: vm.integrationName - }, null, - function (data) { - vm.loading = false; - if (data.error_messages) { - vm.error_messages = data.error_messages; - } - vm.assignees = data.assignees; - vm.priorities = data.priorities; - vm.issue_types = data.issue_types; - vm.form.issue_type = vm.issue_types[0]; - vm.form.responsible = vm.assignees[0]; - vm.form.priority = vm.priorities[0]; - }, function (error_data) { - - if (error_data.data.error_messages) { - vm.error_messages = error_data.data.error_messages; - } - else { - vm.error_messages = ['There was a problem processing your request']; - } + 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.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; }; - vm.ok = function () { - vm.loading = true; - vm.form.group_id = vm.report.group_id; - integrationResource.save({ - resourceId: vm.report.resource_id, - action: 'create-issue', - integration: vm.integrationName - }, vm.form, - function (data) { - vm.loading = false; - if (data.error_messages) { - vm.error_messages = data.error_messages; - } - if (data !== false) { - $uibModalInstance.dismiss('success'); - } - }, function (error_data) { - if (error_data.data.error_messages) { - vm.error_messages = error_data.data.error_messages; + + 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) } - else { - vm.error_messages = ['There was a problem processing your request']; + }); + _.each(item[1].elasticsearch, function (index) { + if (index.checked) { + es_indices.push(index.name) } }); - }; - vm.cancel = function () { - $uibModalInstance.dismiss('cancel'); - }; - vm.fetchInfo(); + }); + + + vm.loading = {partitions: true}; + sectionViewResource.save({section:'admin_section', + view: 'partitions_remove'}, { + es_indices: es_indices, + pg_indices: pg_indices, + confirm: 'CONFIRM' + }, vm.loadPartitions); + + } + } ;// # Copyright (C) 2010-2016 RhodeCode GmbH @@ -10199,72 +10668,31 @@ function JiraIntegrationCtrl($uibModalInstance, $state, report, integrationName, // # services, and proprietary license terms, please see // # https://rhodecode.com/licenses/ -angular.module('appenlight.controllers').controller('AssignReportCtrl', AssignReportCtrl); -AssignReportCtrl.$inject = ['$uibModalInstance', 'reportGroupPropertyResource', 'report']; - -function AssignReportCtrl($uibModalInstance, reportGroupPropertyResource, report) { - var vm = this; - vm.loading = true; - vm.assignedUsers = []; - vm.unAssignedUsers = []; - vm.report = report; - vm.fetchAssignments = function () { - reportGroupPropertyResource.get({ - groupId: vm.report.group_id, - key: 'assigned_users' - }, null, - function (data) { - vm.assignedUsers = data.assigned; - vm.unAssignedUsers = data.unassigned; - vm.loading = false; - }); - } - - vm.reassignUser = function (user) { - var is_assigned = vm.assignedUsers.indexOf(user); - if (is_assigned != -1) { - vm.assignedUsers.splice(is_assigned, 1); - vm.unAssignedUsers.push(user); - return - } - var is_unassigned = vm.unAssignedUsers.indexOf(user); - if (is_unassigned != -1) { - vm.unAssignedUsers.splice(is_unassigned, 1); - vm.assignedUsers.push(user); - return - } - } - vm.updateAssignments = function () { - var post = {'unassigned': [], 'assigned': []}; - _.each(vm.assignedUsers, function (u) { - post['assigned'].push(u.user_name) - }); - _.each(vm.unAssignedUsers, function (u) { - post['unassigned'].push(u.user_name) - }); - vm.loading = true; - reportGroupPropertyResource.update({ - groupId: vm.report.group_id, - key: 'assigned_users' - }, post, - function (data) { - vm.loading = false; - $uibModalInstance.close(vm.report); - }); - }; - - - vm.ok = function () { - vm.updateAssignments(); - }; +angular.module('appenlight.controllers').controller('AdminSystemController', AdminSystemController); - vm.cancel = function () { - $uibModalInstance.dismiss('cancel'); - }; +AdminSystemController.$inject = ['sectionViewResource']; - vm.fetchAssignments(); +function AdminSystemController(sectionViewResource) { + 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.loading.system = false; + }); +}; ;// # Copyright (C) 2010-2016 RhodeCode GmbH // # @@ -10285,281 +10713,107 @@ function AssignReportCtrl($uibModalInstance, reportGroupPropertyResource, report // # services, and proprietary license terms, please see // # https://rhodecode.com/licenses/ -'use strict'; - -/* Controllers */ - -angular.module('appenlight.controllers') - .controller('ReportsListSlowController', ReportsListSlowController); +angular.module('appenlight.controllers').controller('AdminUsersCreateController', AdminUsersCreateController); -ReportsListSlowController.$inject = ['$location', '$cookies', - 'stateHolder', 'typeAheadTagHelper', 'slowReportsResource'] +AdminUsersCreateController.$inject = ['$state', 'usersResource', 'usersPropertyResource', 'sectionViewResource', 'AeConfig']; -function ReportsListSlowController($location, $cookies, stateHolder, typeAheadTagHelper, slowReportsResource) { +function AdminUsersCreateController($state, usersResource, usersPropertyResource, sectionViewResource, AeConfig) { + 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); - } - - - vm.changeRelativeTime = function () { - $cookies.notRelativeTime = JSON.stringify(vm.notRelativeTime); - }; + vm.loading = {user: false}; - _.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(':'); + 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; } - } - - // 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(); - }; + 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.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.resourcePermissions = tmpObj; + }); - var reportPresentation = function (report) { - report.presentation = {}; - if (report.group.public) { - report.presentation.className = 'public'; - report.presentation.tooltip = 'Public'; + } + else { + var userId = null; + vm.user = { + status: true } - else if (report.group.fixed) { - report.presentation.className = 'fixed'; - report.presentation.tooltip = 'Fixed'; + } + + var formResponse = function (response) { + if (response.status == 422) { + setServerValidation(vm.profileForm, response.data); } - else if (report.group.read) { - report.presentation.className = 'reviewed'; - report.presentation.tooltip = 'Reviewed'; + 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 { - report.presentation.className = 'new'; - report.presentation.tooltip = 'New'; + usersResource.save(vm.user, function (data) { + $state.go('admin.user.update', {userId: data.id}); + }, formResponse); } - return report; - }; + } - 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.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.filterId = function (log) { - vm.searchParams.tags.push({ - type: "request_id", - value: log.request_id + vm.reloginUser = function () { + sectionViewResource.get({ + section: 'admin_section', view: 'relogin_user', + user_id: vm.user.id + }, function () { + window.location = AeConfig.urls.baseUrl; }); - 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 // # @@ -10580,303 +10834,229 @@ function ReportsListSlowController($location, $cookies, stateHolder, typeAheadTa // # services, and proprietary license terms, please see // # https://rhodecode.com/licenses/ -angular.module('appenlight.controllers') - .controller('ReportsListController', ReportsListController); +angular.module('appenlight.controllers').controller('AdminUsersController', AdminUsersController); -ReportsListController.$inject = ['$location', '$cookies', - 'stateHolder', 'typeAheadTagHelper', 'reportsResource']; +AdminUsersController.$inject = ['usersResource']; -function ReportsListController($location, $cookies, stateHolder, - typeAheadTagHelper, reportsResource) { +function AdminUsersController(usersResource) { + 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.loading = {users: true}; - 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); - } + 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.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.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.paginationChange = function(){ - $location.search('page', vm.page); - vm.refresh(); - }; + } +}; - vm.typeAheadTag = function (event) { - var text = vm.filterTypeAhead; - if (_.isObject(vm.filterTypeAhead)) { - text = vm.filterTypeAhead.text; - } - if (!vm.filterTypeAhead) { - return - } +;// # 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 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(':'); - } - } - else { - tag.type = 'error'; - tag.value = parsed.join(':'); - } +angular.module('appenlight.controllers') + .controller('BitbucketIntegrationCtrl', BitbucketIntegrationCtrl) - // 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(); - } +BitbucketIntegrationCtrl.$inject = ['$uibModalInstance', '$state', 'report', 'integrationName', 'integrationResource']; - 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; +function BitbucketIntegrationCtrl($uibModalInstance, $state, report, integrationName, integrationResource) { + var vm = this; + vm.loading = true; + vm.assignees = []; + vm.report = report; + vm.integrationName = integrationName; + vm.statuses = []; + vm.priorities = []; + vm.error_messages = []; + vm.form = { + content: '\n' + + 'Issue created for report: ' + + $state.href('report.view_detail', {groupId:report.group_id, reportId:report.id}, {absolute:true}) }; - 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.fetchInfo = function () { + integrationResource.get({ + resourceId: vm.report.resource_id, + action: 'info', + integration: vm.integrationName + }, null, + function (data) { + vm.loading = false; + if (data.error_messages) { + vm.error_messages = data.error_messages; + } + vm.assignees = data.assignees; + vm.priorities = data.priorities; + vm.form.responsible = vm.assignees[0]; + vm.form.priority = vm.priorities[0]; + }, function (error_data) { + if (error_data.data.error_messages) { + vm.error_messages = error_data.data.error_messages; + } + else { + vm.error_messages = ['There was a problem processing your request']; + } + }); + }; + vm.ok = function () { + vm.loading = true; + vm.form.group_id = vm.report.group_id; + integrationResource.save({ + resourceId: vm.report.resource_id, + action: 'create-issue', + integration: vm.integrationName + }, vm.form, + function (data) { + vm.loading = false; + if (data.error_messages) { + vm.error_messages = data.error_messages; + } + if (data !== false) { + $uibModalInstance.dismiss('success'); + } + }, function (error_data) { + if (error_data.data.error_messages) { + vm.error_messages = error_data.data.error_messages; + } + else { + vm.error_messages = ['There was a problem processing your request']; + } + }); }; + vm.cancel = function () { + $uibModalInstance.dismiss('cancel'); + }; + vm.fetchInfo(); +} - 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; +;// # 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('GithubIntegrationCtrl', GithubIntegrationCtrl); + +GithubIntegrationCtrl.$inject = ['$uibModalInstance', '$state', 'report', 'integrationName', 'integrationResource']; + +function GithubIntegrationCtrl($uibModalInstance, $state, report, integrationName, integrationResource) { + var vm = this; + vm.loading = true; + vm.assignees = []; + vm.report = report; + vm.integrationName = integrationName; + vm.statuses = []; + vm.assignees = []; + vm.error_messages = []; + vm.form = { + content: '\n' + + 'Issue created for report: ' + + $state.href('report.view_detail', {groupId:report.group_id, reportId:report.id}, {absolute:true}) }; - 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.fetchInfo = function () { + integrationResource.get({ + resourceId: vm.report.resource_id, + action: 'info', + integration: vm.integrationName + }, null, + function (data) { + vm.loading = false; + if (data.error_messages) { + vm.error_messages = data.error_messages; + } + else { + vm.assignees = data.assignees; + vm.statuses = data.statuses; + vm.form.responsible = vm.assignees[0]; + vm.form.status = vm.statuses[0]; + } + }, function (error_data) { + if (error_data.data.error_messages) { + vm.error_messages = error_data.data.error_messages; + } + else { + vm.error_messages = ['There was a problem processing your request']; + } }); - 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.ok = function () { + vm.loading = true; + vm.form.group_id = vm.report.group_id; + integrationResource.save({ + resourceId: vm.report.resource_id, + action: 'create-issue', + integration: vm.integrationName + }, vm.form, + function (data) { + vm.loading = false; + if (data.error_messages) { + vm.error_messages = data.error_messages; + } + else { + $uibModalInstance.dismiss('success'); + } + }, function (error_data) { + if (error_data.data.error_messages) { + vm.error_messages = error_data.data.error_messages; + } + else { + vm.error_messages = ['There was a problem processing your request']; + } + }); }; - - vm.refresh = function(){ - vm.searchParams = parseSearchToTags($location.search()); - vm.page = Number(vm.searchParams.page) || 1; - var params = parseTagsToSearch(vm.searchParams); - - vm.fetchReports(params); + vm.cancel = function () { + $uibModalInstance.dismiss('cancel'); }; - // initial load - vm.refresh(); + vm.fetchInfo(); } ;// # Copyright (C) 2010-2016 RhodeCode GmbH @@ -10898,339 +11078,168 @@ function ReportsListController($location, $cookies, stateHolder, // # services, and proprietary license terms, please see // # https://rhodecode.com/licenses/ -angular.module('appenlight.controllers').controller('ReportsViewController', ReportsViewController); -ReportsViewController.$inject = ['$window', '$location', '$state', '$uibModal', - '$cookies', 'reportGroupPropertyResource', 'reportGroupResource', - 'logsNoIdResource', 'stateHolder']; - -function ReportsViewController($window, $location, $state, $uibModal, $cookies, reportGroupPropertyResource, reportGroupResource, logsNoIdResource, stateHolder) { - var vm = this; - vm.window = $window; - vm.stateHolder = stateHolder; - vm.$state = $state; - 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') - } - } - }, - 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 - }; - - 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.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.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.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.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); +angular.module('appenlight.controllers') + .controller('JiraIntegrationCtrl', JiraIntegrationCtrl) - }, 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; - }); - }; +JiraIntegrationCtrl.$inject = ['$uibModalInstance', '$state', 'report', 'integrationName', 'integrationResource']; - vm.selectedTab = function(tab_name){ - $cookies.selectedReportTab = tab_name; - if (tab_name == 'logs' && vm.reportLogs === null) { - vm.fetchLogs(); - } +function JiraIntegrationCtrl($uibModalInstance, $state, report, integrationName, integrationResource) { + var vm = this; + vm.loading = true; + vm.assignees = []; + vm.report = report; + vm.integrationName = integrationName; + vm.statuses = []; + vm.priorities = []; + vm.issue_types = []; + vm.error_messages = []; + vm.form = { + content: '\n' + + 'Issue created for report: ' + + $state.href('report.view_detail', {groupId:report.group_id, reportId:report.id}, {absolute:true}) }; - vm.markFixed = function () { - reportGroupResource.update({ - groupId: vm.report.group_id - }, {fixed: !vm.report.group.fixed}, + vm.fetchInfo = function () { + integrationResource.get({ + resourceId: vm.report.resource_id, + action: 'info', + integration: vm.integrationName + }, null, function (data) { - vm.report.group.fixed = data.fixed; + vm.loading = false; + if (data.error_messages) { + vm.error_messages = data.error_messages; + } + vm.assignees = data.assignees; + vm.priorities = data.priorities; + vm.issue_types = data.issue_types; + vm.form.issue_type = vm.issue_types[0]; + vm.form.responsible = vm.assignees[0]; + vm.form.priority = vm.priorities[0]; + }, function (error_data) { + + if (error_data.data.error_messages) { + vm.error_messages = error_data.data.error_messages; + } + else { + vm.error_messages = ['There was a problem processing your request']; + } }); }; - - vm.markPublic = function () { - reportGroupResource.update({ - groupId: vm.report.group_id - }, {public: !vm.report.group.public}, + vm.ok = function () { + vm.loading = true; + vm.form.group_id = vm.report.group_id; + integrationResource.save({ + resourceId: vm.report.resource_id, + action: 'create-issue', + integration: vm.integrationName + }, vm.form, function (data) { - vm.report.group.public = data.public; + vm.loading = false; + if (data.error_messages) { + vm.error_messages = data.error_messages; + } + if (data !== false) { + $uibModalInstance.dismiss('success'); + } + }, function (error_data) { + if (error_data.data.error_messages) { + vm.error_messages = error_data.data.error_messages; + } + else { + vm.error_messages = ['There was a problem processing your request']; + } }); }; - - vm.delete = function () { - reportGroupResource.delete({'groupId': vm.report.group_id}, - function (data) { - $state.go('report.list'); - }) + vm.cancel = function () { + $uibModalInstance.dismiss('cancel'); }; + vm.fetchInfo(); +} - 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()); - }); +;// # 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('AssignReportCtrl', AssignReportCtrl); +AssignReportCtrl.$inject = ['$uibModalInstance', 'reportGroupPropertyResource', 'report']; - 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; - }); - }; +function AssignReportCtrl($uibModalInstance, reportGroupPropertyResource, report) { + var vm = this; + vm.loading = true; + vm.assignedUsers = []; + vm.unAssignedUsers = []; + vm.report = report; + vm.fetchAssignments = function () { + reportGroupPropertyResource.get({ + groupId: vm.report.group_id, + key: 'assigned_users' + }, null, + function (data) { + vm.assignedUsers = data.assigned; + vm.unAssignedUsers = data.unassigned; + vm.loading = false; + }); + } - vm.nextDetail = function () { - $state.go('report.view_detail', { - groupId: vm.report.group_id, - reportId: vm.report.group.next_report + vm.reassignUser = function (user) { + var is_assigned = vm.assignedUsers.indexOf(user); + if (is_assigned != -1) { + vm.assignedUsers.splice(is_assigned, 1); + vm.unAssignedUsers.push(user); + return + } + var is_unassigned = vm.unAssignedUsers.indexOf(user); + if (is_unassigned != -1) { + vm.unAssignedUsers.splice(is_unassigned, 1); + vm.assignedUsers.push(user); + return + } + } + vm.updateAssignments = function () { + var post = {'unassigned': [], 'assigned': []}; + _.each(vm.assignedUsers, function (u) { + post['assigned'].push(u.user_name) }); - }; - vm.previousDetail = function () { - $state.go('report.view_detail', { - groupId: vm.report.group_id, - reportId: vm.report.group.previous_report + _.each(vm.unAssignedUsers, function (u) { + post['unassigned'].push(u.user_name) }); + vm.loading = true; + reportGroupPropertyResource.update({ + groupId: vm.report.group_id, + key: 'assigned_users' + }, post, + function (data) { + vm.loading = false; + $uibModalInstance.close(vm.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; - } - } - }; - var modalInstance = $uibModal.open(vm.opts); - modalInstance.result.then(function (report) { - - }, function () { - console.info('Modal dismissed at: ' + new Date()); - }); + vm.ok = function () { + vm.updateAssignments(); }; - // load report - vm.fetchReport(); + vm.cancel = function () { + $uibModalInstance.dismiss('cancel'); + }; + vm.fetchAssignments(); } @@ -12402,30 +12411,26 @@ angular.module('appenlight').config(['$stateProvider', '$urlRouterProvider', fun $stateProvider.state('report', { abstract: true, url: '/ui/report', - templateUrl: 'templates/reports/parent_view.html' + template: '' }); $stateProvider.state('report.list', { - url: '?start_date&min_duration&max_duration&{view_name:any}&{server_name:any}&resource', - templateUrl: 'templates/reports/list.html', - controller: 'ReportsListController as reports_list' + url: '/list?start_date&min_duration&max_duration&{view_name:any}&{server_name:any}&resource', + component: 'reportsBrowserView' }); $stateProvider.state('report.list_slow', { url: '/list_slow?start_date&min_duration&max_duration&{view_name:any}&{server_name:any}&resource', - templateUrl: 'templates/reports/list_slow.html', - controller: 'ReportsListSlowController as reports_list' + component: 'reportsSlowBrowserView' }); $stateProvider.state('report.view_detail', { url: '/:groupId/:reportId', - templateUrl: 'templates/reports/view.html', - controller: 'ReportsViewController as report' + component: 'reportView' }); $stateProvider.state('report.view_group', { url: '/:groupId', - templateUrl: 'templates/reports/view.html', - controller: 'ReportsViewController as report' + component: 'reportView' }); $stateProvider.state('events', { url: '/ui/events', diff --git a/frontend/src/app.js b/frontend/src/app.js index 12a0669..bb2839e 100644 --- a/frontend/src/app.js +++ b/frontend/src/app.js @@ -45,6 +45,9 @@ angular.module('appenlight.components', [ 'appenlight.components.appenlightHeader', 'appenlight.components.indexDashboardView', 'appenlight.components.logsBrowserView', + 'appenlight.components.reportView', + 'appenlight.components.reportsBrowserView', + 'appenlight.components.reportsSlowBrowserView', 'appenlight.components.eventBrowserView', 'appenlight.components.userProfileView', 'appenlight.components.userIdentitiesView', diff --git a/frontend/src/templates/reports/view.html b/frontend/src/components/views/report-view/report-view.html similarity index 76% rename from frontend/src/templates/reports/view.html rename to frontend/src/components/views/report-view/report-view.html index b56e52a..4c649e0 100644 --- a/frontend/src/templates/reports/view.html +++ b/frontend/src/components/views/report-view/report-view.html @@ -86,44 +86,44 @@
      - + -
      +
      OOPS something went wrong :(
      -
      +
      -
      +
      @@ -140,68 +140,68 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - +
      Occurences{{report.report.group.occurences}}{{$ctrl.report.group.occurences}}
      HTTP status{{report.report.http_status}}{{$ctrl.report.http_status}}
      Priority{{report.report.group.priority}}{{$ctrl.report.group.priority}}
      Public URL
      - +
      URL{{report.report.url}}{{$ctrl.report.url}}
      Remote IP{{report.report.ip}}{{$ctrl.report.ip}}
      User Agent{{report.report.user_agent}}{{$ctrl.report.user_agent}}
      Message{{report.report.message}}{{$ctrl.report.message}}
      Duration - {{report.report.duration}}s + {{$ctrl.report.duration}}s
      First occured - +
      Last occured - +
      -
      +

      Performance stats

      - {{stat.calls}} {{stat.name}} calls @@ -213,14 +213,14 @@
      0s
      - {{report.report.duration.toFixed(3)}}s + {{$ctrl.report.duration.toFixed(3)}}s
      @@ -230,14 +230,14 @@

      Tags

      - + - +
      Username/UIDView NameServer Name{{ tag }} {{ value }}{{ value }}
      @@ -250,61 +250,61 @@

      Report history

      -
      +
      - +
      - - {{report.report.start_time.replace('T', ' ')}} UTC - ID: {{report.report.request_id}} + + {{$ctrl.report.start_time.replace('T', ' ')}} UTC + ID: {{$ctrl.report.request_id}}
      -

      {{report.report.error}}

      +

      {{$ctrl.report.error}}

      -
      +

      Traceback

      -
      -
      {{report.rawTraceback}}
      +
      +
      {{$ctrl.rawTraceback}}
      -
      +
      -
      +
      - + Slow Calls

      Slow Calls

      -
      -
      +
      +
      -
      +
      No slow calls reported
      - + Request details

      Extra

      -
      +

      Request details

      -
      +
      - + Logs -
      +
      -

      No logs found

      +

      No logs found

      - +
      @@ -396,7 +396,7 @@ - +
      Logs
      level: {{log.log_level}} @@ -421,18 +421,18 @@ - + Comments - {{report.report.comments.length}} + {{$ctrl.report.comments.length}}

      Comments

      -

      No comments yet - be first to add one!

      +

      No comments yet - be first to add one!

      -
      +

      {{comment.user_name}} @@ -440,32 +440,32 @@

      {{comment.body}}

      -
      +
      - +
      - +
      -
      +
      - + Affected users - {{report.report.affected_users_count}} + {{$ctrl.report.affected_users_count}}

      50 most affected users ID's by this issue:

        -
      • +
      • {{user.username}} {{user.count}}
      diff --git a/frontend/src/controllers/reports/view.js b/frontend/src/components/views/report-view/report-view.js similarity index 89% rename from frontend/src/controllers/reports/view.js rename to frontend/src/components/views/report-view/report-view.js index eeb1a2a..655d054 100644 --- a/frontend/src/controllers/reports/view.js +++ b/frontend/src/components/views/report-view/report-view.js @@ -17,12 +17,17 @@ // # services, and proprietary license terms, please see // # https://rhodecode.com/licenses/ -angular.module('appenlight.controllers').controller('ReportsViewController', ReportsViewController); -ReportsViewController.$inject = ['$window', '$location', '$state', '$uibModal', +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']; -function ReportsViewController($window, $location, $state, $uibModal, $cookies, reportGroupPropertyResource, reportGroupResource, logsNoIdResource, stateHolder) { +function ReportViewController($window, $location, $state, $uibModal, $cookies, reportGroupPropertyResource, reportGroupResource, logsNoIdResource, stateHolder) { var vm = this; vm.window = $window; vm.stateHolder = stateHolder; diff --git a/frontend/src/templates/reports/list.html b/frontend/src/components/views/reports-browser-view/reports-browser-view.html similarity index 63% rename from frontend/src/templates/reports/list.html rename to frontend/src/components/views/reports-browser-view/reports-browser-view.html index e58cfaa..69d59cc 100644 --- a/frontend/src/templates/reports/list.html +++ b/frontend/src/components/views/reports-browser-view/reports-browser-view.html @@ -1,29 +1,29 @@ - + -
      +

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

      -
      -
      @@ -32,29 +32,29 @@
      - + ng-change="$ctrl.paginationChange()" + ng-show="!$ctrl.is_loading">
      - +
      - - + @@ -80,10 +80,10 @@
      - + ng-change="$ctrl.paginationChange()" + ng-show="!$ctrl.is_loading">
      diff --git a/frontend/src/controllers/reports/list.js b/frontend/src/components/views/reports-browser-view/reports-browser-view.js similarity index 88% rename from frontend/src/controllers/reports/list.js rename to frontend/src/components/views/reports-browser-view/reports-browser-view.js index 4b3761e..416615e 100644 --- a/frontend/src/controllers/reports/list.js +++ b/frontend/src/components/views/reports-browser-view/reports-browser-view.js @@ -17,13 +17,16 @@ // # services, and proprietary license terms, please see // # https://rhodecode.com/licenses/ -angular.module('appenlight.controllers') - .controller('ReportsListController', ReportsListController); +angular.module('appenlight.components.reportsBrowserView', []) + .component('reportsBrowserView', { + templateUrl: 'components/views/reports-browser-view/reports-browser-view.html', + controller: reportsBrowserViewController + }); -ReportsListController.$inject = ['$location', '$cookies', +reportsBrowserViewController.$inject = ['$location', '$cookies', 'stateHolder', 'typeAheadTagHelper', 'reportsResource']; -function ReportsListController($location, $cookies, stateHolder, +function reportsBrowserViewController($location, $cookies, stateHolder, typeAheadTagHelper, reportsResource) { var vm = this; vm.applications = stateHolder.AeUser.applications_map; diff --git a/frontend/src/templates/reports/list_slow.html b/frontend/src/components/views/reports-slow-browser-view/reports-slow-browser-view.html similarity index 64% rename from frontend/src/templates/reports/list_slow.html rename to frontend/src/components/views/reports-slow-browser-view/reports-slow-browser-view.html index 1acdc22..f25a62f 100644 --- a/frontend/src/templates/reports/list_slow.html +++ b/frontend/src/components/views/reports-slow-browser-view/reports-slow-browser-view.html @@ -1,14 +1,14 @@ - + -
      +

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

      @@ -16,16 +16,16 @@
      -
      -
      @@ -34,31 +34,31 @@
      - + ng-change="$ctrl.paginationChange()" + ng-show="!$ctrl.is_loading">
      -
      Reports
      # ApplicationWhen When Error
      {{report.group.priority}} @@ -65,10 +65,10 @@
      {{report.resource_name}}
      @{{report.tags.server_name}}
      - - {{report.group.last_timestamp.replace('T', ' ').slice(0,16)}} + {{report.group.last_timestamp.replace('T', ' ').slice(0,16)}} {{report.error || 'Unknown Exception'}}
      {{ report.tags.view_name || report.url_path}}
      +
      - - + @@ -86,10 +86,10 @@
      - + ng-change="$ctrl.paginationChange()" + ng-show="!$ctrl.is_loading">
      diff --git a/frontend/src/controllers/reports/list_slow.js b/frontend/src/components/views/reports-slow-browser-view/reports-slow-browser-view.js similarity index 94% rename from frontend/src/controllers/reports/list_slow.js rename to frontend/src/components/views/reports-slow-browser-view/reports-slow-browser-view.js index 96fe68e..3850209 100644 --- a/frontend/src/controllers/reports/list_slow.js +++ b/frontend/src/components/views/reports-slow-browser-view/reports-slow-browser-view.js @@ -21,13 +21,16 @@ /* Controllers */ -angular.module('appenlight.controllers') - .controller('ReportsListSlowController', ReportsListSlowController); +angular.module('appenlight.components.reportsSlowBrowserView', []) + .component('reportsSlowBrowserView', { + templateUrl: 'components/views/reports-slow-browser-view/reports-slow-browser-view.html', + controller: ReportsSlowBrowserViewController + }); -ReportsListSlowController.$inject = ['$location', '$cookies', +ReportsSlowBrowserViewController.$inject = ['$location', '$cookies', 'stateHolder', 'typeAheadTagHelper', 'slowReportsResource'] -function ReportsListSlowController($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'; diff --git a/frontend/src/routes.js b/frontend/src/routes.js index 00a20e8..f10c5f4 100644 --- a/frontend/src/routes.js +++ b/frontend/src/routes.js @@ -34,30 +34,26 @@ angular.module('appenlight').config(['$stateProvider', '$urlRouterProvider', fun $stateProvider.state('report', { abstract: true, url: '/ui/report', - templateUrl: 'templates/reports/parent_view.html' + template: '' }); $stateProvider.state('report.list', { - url: '?start_date&min_duration&max_duration&{view_name:any}&{server_name:any}&resource', - templateUrl: 'templates/reports/list.html', - controller: 'ReportsListController as reports_list' + url: '/list?start_date&min_duration&max_duration&{view_name:any}&{server_name:any}&resource', + component: 'reportsBrowserView' }); $stateProvider.state('report.list_slow', { url: '/list_slow?start_date&min_duration&max_duration&{view_name:any}&{server_name:any}&resource', - templateUrl: 'templates/reports/list_slow.html', - controller: 'ReportsListSlowController as reports_list' + component: 'reportsSlowBrowserView' }); $stateProvider.state('report.view_detail', { url: '/:groupId/:reportId', - templateUrl: 'templates/reports/view.html', - controller: 'ReportsViewController as report' + component: 'reportView' }); $stateProvider.state('report.view_group', { url: '/:groupId', - templateUrl: 'templates/reports/view.html', - controller: 'ReportsViewController as report' + component: 'reportView' }); $stateProvider.state('events', { url: '/ui/events', diff --git a/frontend/src/templates/reports/parent_view.html b/frontend/src/templates/reports/parent_view.html deleted file mode 100644 index f182cdd..0000000 --- a/frontend/src/templates/reports/parent_view.html +++ /dev/null @@ -1 +0,0 @@ -
      \ No newline at end of file
      Slow Request Reports
      # Avg. duration ApplicationWhen When Location
      {{report.group.priority}} @@ -70,10 +70,10 @@
      {{report.resource_name}}
      @{{report.tags.server_name}}
      - - {{report.group.last_timestamp.replace('T', ' ').slice(0,16)}} + {{report.group.last_timestamp.replace('T', ' ').slice(0,16)}} {{ report.tags.view_name || report.url_path}}