diff --git a/src/Server/Coderr.Server.Api.Client/Coderr.Server.Api.Client.csproj b/src/Server/Coderr.Server.Api.Client/Coderr.Server.Api.Client.csproj index addd8493..f460fa1b 100644 --- a/src/Server/Coderr.Server.Api.Client/Coderr.Server.Api.Client.csproj +++ b/src/Server/Coderr.Server.Api.Client/Coderr.Server.Api.Client.csproj @@ -22,7 +22,7 @@ Coderr.Server.Api.Client - + diff --git a/src/Server/Coderr.Server.Api/Coderr.Server.Api.csproj b/src/Server/Coderr.Server.Api/Coderr.Server.Api.csproj index 314c6e2b..e80d8e6c 100644 --- a/src/Server/Coderr.Server.Api/Coderr.Server.Api.csproj +++ b/src/Server/Coderr.Server.Api/Coderr.Server.Api.csproj @@ -25,7 +25,7 @@ 1701;1702;1705;1591 - + diff --git a/src/Server/Coderr.Server.App/Coderr.Server.App.csproj b/src/Server/Coderr.Server.App/Coderr.Server.App.csproj index 8b1dd0d4..f4d7a3d1 100644 --- a/src/Server/Coderr.Server.App/Coderr.Server.App.csproj +++ b/src/Server/Coderr.Server.App/Coderr.Server.App.csproj @@ -21,7 +21,7 @@ NU1701 - + diff --git a/src/Server/Coderr.Server.Domain/Core/Incidents/Events/IncidentCreated.cs b/src/Server/Coderr.Server.Domain/Core/Incidents/Events/IncidentCreated.cs index b26c811f..964cf0fc 100644 --- a/src/Server/Coderr.Server.Domain/Core/Incidents/Events/IncidentCreated.cs +++ b/src/Server/Coderr.Server.Domain/Core/Incidents/Events/IncidentCreated.cs @@ -9,11 +9,13 @@ namespace Coderr.Server.Domain.Core.Incidents.Events /// public class IncidentCreated { - public IncidentCreated(int incidentId, string incidentDescription, string exceptionTypeName) + public IncidentCreated(int applicationId, int incidentId, string incidentDescription, string exceptionTypeName) { if (incidentDescription == null) throw new ArgumentNullException(nameof(incidentDescription)); if (exceptionTypeName == null) throw new ArgumentNullException(nameof(exceptionTypeName)); if (incidentId <= 0) throw new ArgumentOutOfRangeException(nameof(incidentId)); + if (applicationId <= 0) throw new ArgumentOutOfRangeException(nameof(applicationId)); + ApplicationId = applicationId; IncidentId = incidentId; var pos = incidentDescription.IndexOfAny(new[] {'\r', '\n'}); diff --git a/src/Server/Coderr.Server.Infrastructure/Coderr.Server.Infrastructure.csproj b/src/Server/Coderr.Server.Infrastructure/Coderr.Server.Infrastructure.csproj index 824b0ae5..a2778230 100644 --- a/src/Server/Coderr.Server.Infrastructure/Coderr.Server.Infrastructure.csproj +++ b/src/Server/Coderr.Server.Infrastructure/Coderr.Server.Infrastructure.csproj @@ -5,7 +5,7 @@ Coderr.Server.Infrastructure - + diff --git a/src/Server/Coderr.Server.ReportAnalyzer/Coderr.Server.ReportAnalyzer.csproj b/src/Server/Coderr.Server.ReportAnalyzer/Coderr.Server.ReportAnalyzer.csproj index d0a57536..e1380ca4 100644 --- a/src/Server/Coderr.Server.ReportAnalyzer/Coderr.Server.ReportAnalyzer.csproj +++ b/src/Server/Coderr.Server.ReportAnalyzer/Coderr.Server.ReportAnalyzer.csproj @@ -7,7 +7,7 @@ - + diff --git a/src/Server/Coderr.Server.ReportAnalyzer/ErrorOrigins/Handlers/StorePositionFromNewReport.cs b/src/Server/Coderr.Server.ReportAnalyzer/ErrorOrigins/Handlers/StorePositionFromNewReport.cs index 8e6a8394..ee74581f 100644 --- a/src/Server/Coderr.Server.ReportAnalyzer/ErrorOrigins/Handlers/StorePositionFromNewReport.cs +++ b/src/Server/Coderr.Server.ReportAnalyzer/ErrorOrigins/Handlers/StorePositionFromNewReport.cs @@ -49,14 +49,20 @@ public async Task HandleAsync(IMessageContext context, ReportAddedToIncident e) if (string.IsNullOrEmpty(_originConfiguration.Value?.ApiKey)) return; - if (e.Report.RemoteAddress == "::1") - return; - if (e.Report.RemoteAddress == "127.0.0.1") + // Random swedish IP for testing purposes + if (e.Report.RemoteAddress == "::1" || e.Report.RemoteAddress == "127.0.0.1") e.Report.RemoteAddress = "94.254.57.227"; + var errorOrigin = await LookupIpAddress(e); + await _repository.CreateAsync(errorOrigin, e.Incident.ApplicationId, e.Incident.Id, e.Report.Id); + } + + private async Task LookupIpAddress(ReportAddedToIncident e) + { var url = $"http://api.ipstack.com/{e.Report.RemoteAddress}?access_key={_originConfiguration.Value.ApiKey}"; var request = WebRequest.CreateHttp(url); - string json = ""; + var json = ""; + ErrorOrigin errorOrigin; try { var response = await request.GetResponseAsync(); @@ -71,7 +77,7 @@ public async Task HandleAsync(IMessageContext context, ReportAddedToIncident e) var lat = double.Parse(jsonObj["latitude"].Value(), CultureInfo.InvariantCulture); var lon = double.Parse(jsonObj["longitude"].Value(), CultureInfo.InvariantCulture); - var cmd = new ErrorOrigin(e.Report.RemoteAddress, lon, lat) + errorOrigin = new ErrorOrigin(e.Report.RemoteAddress, lon, lat) { City = jsonObj["city"].ToString(), CountryCode = jsonObj["country_code"].ToString(), @@ -80,13 +86,13 @@ public async Task HandleAsync(IMessageContext context, ReportAddedToIncident e) RegionName = jsonObj["region_name"].ToString(), ZipCode = jsonObj["zip"].ToString() }; - - await _repository.CreateAsync(cmd, e.Incident.ApplicationId, e.Incident.Id, e.Report.Id); } catch (Exception exception) { - _logger.Error($"Failed to store location for incident {e.Incident.Id}/report {e.Report.Id}: {json}", exception); + throw new InvalidOperationException($"Failed to call lookupService or parse the JSON: {json}.", exception); } + + return errorOrigin; } } } \ No newline at end of file diff --git a/src/Server/Coderr.Server.ReportAnalyzer/Inbound/Handlers/Reports/ReportAnalyzer.cs b/src/Server/Coderr.Server.ReportAnalyzer/Inbound/Handlers/Reports/ReportAnalyzer.cs index e72e96bd..a37bf2a1 100644 --- a/src/Server/Coderr.Server.ReportAnalyzer/Inbound/Handlers/Reports/ReportAnalyzer.cs +++ b/src/Server/Coderr.Server.ReportAnalyzer/Inbound/Handlers/Reports/ReportAnalyzer.cs @@ -90,7 +90,7 @@ public async Task Analyze(IMessageContext context, ErrorReportEntity report) incident = BuildIncident(report); _repository.CreateIncident(incident); - var evt = new IncidentCreated(incident.Id, incident.Description, incident.FullName) + var evt = new IncidentCreated(incident.ApplicationId, incident.Id, incident.Description, incident.FullName) { ApplicationVersion = applicationVersion }; diff --git a/src/Server/Coderr.Server.SqlServer.Tests/Coderr.Server.SqlServer.Tests.csproj b/src/Server/Coderr.Server.SqlServer.Tests/Coderr.Server.SqlServer.Tests.csproj index 5fa2ee73..43a28085 100644 --- a/src/Server/Coderr.Server.SqlServer.Tests/Coderr.Server.SqlServer.Tests.csproj +++ b/src/Server/Coderr.Server.SqlServer.Tests/Coderr.Server.SqlServer.Tests.csproj @@ -18,7 +18,7 @@ - + diff --git a/src/Server/Coderr.Server.SqlServer/Coderr.Server.SqlServer.csproj b/src/Server/Coderr.Server.SqlServer/Coderr.Server.SqlServer.csproj index 9fabf31c..32bef132 100644 --- a/src/Server/Coderr.Server.SqlServer/Coderr.Server.SqlServer.csproj +++ b/src/Server/Coderr.Server.SqlServer/Coderr.Server.SqlServer.csproj @@ -5,7 +5,7 @@ Coderr.Server.SqlServer - + diff --git a/src/Server/Coderr.Server.SqlServer/Core/Applications/ApplicationRepository.cs b/src/Server/Coderr.Server.SqlServer/Core/Applications/ApplicationRepository.cs index 1884c873..ed027981 100644 --- a/src/Server/Coderr.Server.SqlServer/Core/Applications/ApplicationRepository.cs +++ b/src/Server/Coderr.Server.SqlServer/Core/Applications/ApplicationRepository.cs @@ -31,7 +31,7 @@ public async Task GetForUserAsync(int accountId) if (accountId <= 0) throw new ArgumentOutOfRangeException(nameof(accountId)); using (var cmd = (DbCommand) _uow.CreateCommand()) { - cmd.CommandText = @"SELECT a.Id ApplicationId, a.Name ApplicationName, ApplicationMembers.Roles, a.NumberOfDevelopers + cmd.CommandText = @"SELECT a.Id ApplicationId, a.Name ApplicationName, ApplicationMembers.Roles, a.NumberOfFtes NumberOfDevelopers FROM Applications a JOIN ApplicationMembers ON (ApplicationMembers.ApplicationId = a.Id) WHERE ApplicationMembers.AccountId = @userId diff --git a/src/Server/Coderr.Server.Web/ClientApp/boot.ts b/src/Server/Coderr.Server.Web/ClientApp/boot.ts index 696128a7..f9335363 100644 --- a/src/Server/Coderr.Server.Web/ClientApp/boot.ts +++ b/src/Server/Coderr.Server.Web/ClientApp/boot.ts @@ -3,10 +3,10 @@ import Vue from "vue"; import VueRouter from "vue-router"; import moment from "moment"; import { AppRoot } from "./services/AppRoot" -import VeeValidate from 'vee-validate'; +//import VeeValidate from 'vee-validate'; import { IUser } from "./vue-shim"; -Vue.use(VeeValidate); +//Vue.use(VeeValidate); Vue.use(VueRouter); Vue.config.devtools = true; @@ -58,190 +58,193 @@ const routes = [ { name: "root", path: "/", - component: require("./components/home/home.vue.html") + component: require("./components/home/home.vue.html").default }, { name: "support", path: "/support/", - component: require("./components/home/support/support.vue.html") + component: require("./components/home/support/support.vue.html").default }, { name: "application", path: "/discover/application/:applicationId/", - component: require("./components/applications/application-details.vue.html") + component: require("./components/applications/application-details.vue.html").default }, { path: "/discover/", - component: require("./components/discover/discover.vue.html"), + component: require("./components/discover/discover.vue.html").default, children: [ { name: "findIncidents", path: "incidents/:applicationId?", - component: require("./components/discover/incidents/search.vue.html") + component: require("./components/discover/incidents/search.vue.html").default }, { name: "discoverIncident", path: "incidents/:applicationId/incident/:incidentId", - component: require("./components/discover/incidents/incident.vue.html") + component: require("./components/discover/incidents/incident.vue.html").default }, { name: "configureApplication", path: "application/:applicationId/configuration", - component: require("./components/discover/application/configure.vue.html") + component: require("./components/discover/application/configure.vue.html").default }, { name: "discoverApplication", path: "application/:applicationId/", - component: require("./components/discover/incidents/incident.vue.html") + component: require("./components/discover/incidents/incident.vue.html").default }, { name: "suggest", path: "suggest/:applicationId?", - component: require("./components/discover/incidents/suggestions.vue.html") + component: require("./components/discover/incidents/suggestions.vue.html").default }, { name: "suggestIncident", path: "suggest/:applicationId/incident/:incidentId", - component: require("./components/discover/incidents/incident.vue.html") + component: require("./components/discover/incidents/incident.vue.html").default }, { name: "discover", path: ":applicationId?", - component: require("./components/discover/home/home.vue.html") + component: require("./components/discover/home/home.vue.html").default } ] }, { path: "/analyze/", - component: require("./components/analyze/analyze.vue.html"), + component: require("./components/analyze/analyze.vue.html").default, children: [ { name: "analyzeHome", path: "", - component: require("./components/analyze/home/home.vue.html") + component: require("./components/analyze/home/home.vue.html").default }, { name: "analyzeIncident", path: "incident/:incidentId/", - component: require("./components/analyze/incidents/incident.vue.html") + component: require("./components/analyze/incidents/incident.vue.html").default }, { name: "analyzeReport", path: "incident/:incidentId/report/:reportId?", - component: require("./components/analyze/incidents/report.vue.html") + component: require("./components/analyze/incidents/report.vue.html").default }, { name: "analyzeOrigins", path: "incident/:incidentId/origins/", - component: require("./components/analyze/incidents/origins.vue.html") + component: require("./components/analyze/incidents/origins.vue.html").default }, { name: "closeIncident", path: "incident/:incidentId/close/", - component: require("./components/analyze/incidents/close.vue.html") + component: require("./components/analyze/incidents/close.vue.html").default }, { name: "analyzeFeedback", path: "incident/:incidentId/feedback/", - component: require("./components/analyze/incidents/feedback.vue.html") + component: require("./components/analyze/incidents/feedback.vue.html").default } ] }, { name: "notifyUsers", path: "users/notify/incident/:incidentId/", - component: require("./components/analyze/incidents/status.vue.html") + component: require("./components/analyze/incidents/status.vue.html").default }, { path: "/onboarding/", - component: require("./components/onboarding/onboarding.vue.html"), + component: require("./components/onboarding/onboarding.vue.html").default, children: [ { name: "onboardApp", path: "", - component: require("./components/onboarding/home/home.vue.html") + component: require("./components/onboarding/home/home.vue.html").default } ] }, { path: "/manage/application/", - component: require("./components/manage/application/app.vue.html"), + component: require("./components/manage/application/app.vue.html").default, children: [ { name: "manageAppSettings", path: ":applicationId/", - component: require("./components/manage/application/settings/settings.vue.html") + component: require("./components/manage/application/settings/settings.vue.html").default }, { name: "manageSecurity", path: ":applicationId/security/", - component: require("./components/manage/application/security/security.vue.html") + component: require("./components/manage/application/security/security.vue.html").default }, { name: "managePartitions", path: ":applicationId/partitions/", - component: require("./components/manage/application/partitions/partition.vue.html") + component: require("./components/manage/application/partitions/partition.vue.html").default }, { name: "createPartition", path: ":applicationId/partition/create/", - component: require("./components/manage/application/partitions/create.vue.html") + component: require("./components/manage/application/partitions/create.vue.html").default }, { name: "editPartition", path: ":applicationId/partition/:partitionId/edit", - component: require("./components/manage/application/partitions/edit.vue.html") + component: require("./components/manage/application/partitions/edit.vue.html").default } ] }, { path: "/manage/", - component: require("./components/manage/system/manage.vue.html"), + component: require("./components/manage/system/manage.vue.html").default, children: [ { name: "manageHome", path: "", - component: require("./components/manage/system/home/home.vue.html"), + component: require("./components/manage/system/home/home.vue.html").default, + }, { name: "createApp", path: "create/application/", - component: require("./components/manage/system/create/create.vue.html"), + component: require("./components/manage/system/create/create.vue.html").default, + }, { name: "manageApiKeys", path: "apikeys/", - component: require("./components/manage/system/apikeys/apikeys.vue.html") + component: require("./components/manage/system/apikeys/apikeys.vue.html").default }, { name: "manageApiKey", path: "apikey/:apiKey", - component: require("./components/manage/system/apikeys/apikey.vue.html") + component: require("./components/manage/system/apikeys/apikey.vue.html").default }, { name: "editApiKey", path: "apikey/:apiKey/edit", - component: require("./components/manage/system/apikeys/apikey-edit.vue.html") + component: require("./components/manage/system/apikeys/apikey-edit.vue.html").default }, { name: "createApiKey", path: "apikeys/create", - component: require("./components/manage/system/apikeys/apikey-create.vue.html") + component: require("./components/manage/system/apikeys/apikey-create.vue.html").default } ] }, { path: "/deployment/", - component: require("./components/deployment/deployment.vue.html"), + component: require("./components/deployment/deployment.vue.html").default, + children: [ { name: "deploymentHome", path: ":applicationId?/", - component: require("./components/deployment/home/home.vue.html") + component: require("./components/deployment/home/home.vue.html").default }, { name: "deploymentVersion", path: ":applicationId/version/:version", - component: require("./components/deployment/version/summary.vue.html") + component: require("./components/deployment/version/summary.vue.html").default } ] @@ -267,7 +270,7 @@ AppRoot.Instance.loadCurrentUser() ourVue = new Vue({ el: "#app-root", router: new VueRouter({ mode: "history", routes: routes }), - render: h => h(require("./components/home/app.vue.html")), + render: h => h(require("./components/home/app.vue.html").default), created: () => { hooks.created(ourVue); }, diff --git a/src/Server/Coderr.Server.Web/ClientApp/components/analyze/analyze.ts b/src/Server/Coderr.Server.Web/ClientApp/components/analyze/analyze.ts index aaaafd63..0b639530 100644 --- a/src/Server/Coderr.Server.Web/ClientApp/components/analyze/analyze.ts +++ b/src/Server/Coderr.Server.Web/ClientApp/components/analyze/analyze.ts @@ -3,7 +3,7 @@ import { Component } from 'vue-property-decorator'; @Component({ components: { - AnalyzeMenu: require('./menu.vue.html') + AnalyzeMenu: require('./menu.vue.html').default } }) export default class AnalyzeComponent extends Vue { diff --git a/src/Server/Coderr.Server.Web/ClientApp/components/analyze/incidents/incident.vue.html b/src/Server/Coderr.Server.Web/ClientApp/components/analyze/incidents/incident.vue.html index f2235da7..6b01a426 100644 --- a/src/Server/Coderr.Server.Web/ClientApp/components/analyze/incidents/incident.vue.html +++ b/src/Server/Coderr.Server.Web/ClientApp/components/analyze/incidents/incident.vue.html @@ -100,12 +100,12 @@ -
- - View entire report - - +
+ + View entire report + + diff --git a/src/Server/Coderr.Server.Web/ClientApp/components/analyze/incidents/report.vue.html b/src/Server/Coderr.Server.Web/ClientApp/components/analyze/incidents/report.vue.html index 406d5706..78849f17 100644 --- a/src/Server/Coderr.Server.Web/ClientApp/components/analyze/incidents/report.vue.html +++ b/src/Server/Coderr.Server.Web/ClientApp/components/analyze/incidents/report.vue.html @@ -56,7 +56,7 @@
Select collection

{{currentCollection.Name}}

- +
diff --git a/src/Server/Coderr.Server.Web/ClientApp/components/discover/discover.ts b/src/Server/Coderr.Server.Web/ClientApp/components/discover/discover.ts index 0403003e..0d134362 100644 --- a/src/Server/Coderr.Server.Web/ClientApp/components/discover/discover.ts +++ b/src/Server/Coderr.Server.Web/ClientApp/components/discover/discover.ts @@ -3,7 +3,7 @@ import { Component } from 'vue-property-decorator'; @Component({ components: { - DiscoverMenu: require('./menu.vue.html') + DiscoverMenu: require('./menu.vue.html').default } }) export default class DiscoverComponent extends Vue { diff --git a/src/Server/Coderr.Server.Web/ClientApp/components/discover/home/home.ts b/src/Server/Coderr.Server.Web/ClientApp/components/discover/home/home.ts index 7142f21d..f318ee93 100644 --- a/src/Server/Coderr.Server.Web/ClientApp/components/discover/home/home.ts +++ b/src/Server/Coderr.Server.Web/ClientApp/components/discover/home/home.ts @@ -3,7 +3,7 @@ import * as MenuApi from "../../../services/menu/MenuApi"; import { AppRoot } from "../../../services/AppRoot"; import { GetOverview, GetOverviewResult } from "../../../dto/Web/Overview" import { FindIncidentsResultItem } from "../../../dto/Core/Incidents" -import { GetApplicationOverview, GetApplicationOverviewResult } from "../../../dto/Core/Applications" +import { GetApplicationOverview, GetApplicationOverviewResult, GetApplicationList, ApplicationListItem } from "../../../dto/Core/Applications" import * as Mine from "../../../dto/Common/Mine" import Vue from "vue"; import { Component, Watch } from "vue-property-decorator"; @@ -24,6 +24,7 @@ export default class DiscoverComponent extends Vue { private static activeBtnTheme: string = 'btn-dark'; applicationId: number = 0; + firstApplicationId = 0; destroyed$ = false; // summary, changes when time window changes @@ -41,10 +42,12 @@ export default class DiscoverComponent extends Vue { onApplicationChanged(value: string, oldValue: string) { if (!value) { this.applicationId = 0; + this.firstApplicationId = 0; this.loadGenericOverview(); return; } this.applicationId = parseInt(value); + this.firstApplicationId = 0; if (this.$route.fullPath.indexOf('/discover/') === -1) { return; @@ -56,9 +59,19 @@ export default class DiscoverComponent extends Vue { if (this.$route.params.applicationId && this.$route.params.applicationId !== '0') { this.applicationId = parseInt(this.$route.params.applicationId, 10); this.loadApplication(this.applicationId); + this.firstApplicationId = this.applicationId; } else { this.loadGenericOverview(); + this.firstApplicationId = 0; } + + AppRoot.Instance.apiClient.query(new GetApplicationList()) + .then(result => { + if (this.destroyed$) { + return; + } + this.firstApplicationId = result[0].Id; + }); } mounted() { diff --git a/src/Server/Coderr.Server.Web/ClientApp/components/discover/home/home.vue.html b/src/Server/Coderr.Server.Web/ClientApp/components/discover/home/home.vue.html index e4936351..8c5091e8 100644 --- a/src/Server/Coderr.Server.Web/ClientApp/components/discover/home/home.vue.html +++ b/src/Server/Coderr.Server.Web/ClientApp/components/discover/home/home.vue.html @@ -3,20 +3,20 @@
-
+
Summary (last 30 days)
-
{{prop.Key}}
+
- + - + @@ -35,6 +35,18 @@ +
+
+
+

Report exceptions

+

+ You have not reported any exceptions yet. +

+ Configure your application +
+
+
+
diff --git a/src/Server/Coderr.Server.Web/ClientApp/components/discover/incidents/incident.vue.html b/src/Server/Coderr.Server.Web/ClientApp/components/discover/incidents/incident.vue.html index 4aed2c66..31893fe8 100644 --- a/src/Server/Coderr.Server.Web/ClientApp/components/discover/incidents/incident.vue.html +++ b/src/Server/Coderr.Server.Web/ClientApp/components/discover/incidents/incident.vue.html @@ -58,7 +58,7 @@

Report history

Quick facts
-
Number of incidentsNumber of incidents {{ incidentCount }}
Number of error reports {{ reportCount }}
+
diff --git a/src/Server/Coderr.Server.Web/ClientApp/components/discover/incidents/search.ts b/src/Server/Coderr.Server.Web/ClientApp/components/discover/incidents/search.ts index 8d3f84d8..38fc30c5 100644 --- a/src/Server/Coderr.Server.Web/ClientApp/components/discover/incidents/search.ts +++ b/src/Server/Coderr.Server.Web/ClientApp/components/discover/incidents/search.ts @@ -230,7 +230,8 @@ export default class IncidentSearchComponent extends Vue { excludeProperties: ["incidents", "availableApplications", "availableTags", "checkedIncidents"] }); } - + query.PageNumber = 1; + query.ItemsPerPage = 50; if (this.contextCollectionName != null && this.contextCollectionName !== "") { query.ContextCollectionName = this.contextCollectionName; } @@ -241,7 +242,7 @@ export default class IncidentSearchComponent extends Vue { query.ContextCollectionPropertyValue = this.contextCollectionPropertyValue; } - + AppRoot.Instance.apiClient.query(query) .then(result => { if (this.destroyed$) { diff --git a/src/Server/Coderr.Server.Web/ClientApp/components/discover/incidents/search.vue.html b/src/Server/Coderr.Server.Web/ClientApp/components/discover/incidents/search.vue.html index 57aff3bf..480a615b 100644 --- a/src/Server/Coderr.Server.Web/ClientApp/components/discover/incidents/search.vue.html +++ b/src/Server/Coderr.Server.Web/ClientApp/components/discover/incidents/search.vue.html @@ -77,38 +77,42 @@

Incidents

-
{{fact.Title}} {{fact.Value}}
+
- - - - - - - + + + + + + + - - - - - - - + + + + + + +
NameApplicationCreated Last report Report count
NameApplicationCreated Last report Report count
- - {{ incident.Name }} - - {{incident.ApplicationName}} - - {{ incident.CreatedAtUtc | ago }} - - {{ incident.LastReportReceivedAtUtc | ago }} - - {{ incident.ReportCount }} -
+ + {{ incident.Name }} + + {{incident.ApplicationName}} + + {{ incident.CreatedAtUtc | ago }} + + {{ incident.LastReportReceivedAtUtc | ago }} + + {{ incident.ReportCount }} +
- +
+ No incidents have been reported (or nothing matched your search). +
+
+