Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ protected FindIncidentsResultItem()
/// <summary>
/// Id of the application that this incident belongs to
/// </summary>
public string ApplicationId { get; set; }
public int ApplicationId { get; set; }

/// <summary>
/// Name of the application that this incident belongs to
Expand All @@ -43,6 +43,11 @@ protected FindIncidentsResultItem()
/// </summary>
public DateTime CreatedAtUtc { get; set; }

/// <summary>
/// When the incident was assigned to someone.
/// </summary>
public DateTime? AssignedAtUtc { get; set; }

/// <summary>
/// Incident id
/// </summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,8 @@ public async Task BuildReportAsync(ClaimsPrincipal user, string appKey, string s
throw new InvalidCredentialException($"AppKey was not found in the database. Key '{appKey}'.");
}

if (!ReportValidator.ValidateBody(application.SharedSecret, signatureProvidedByTheClient, reportBody))
// web(js) applications do not sign the body
if (signatureProvidedByTheClient != null && !ReportValidator.ValidateBody(application.SharedSecret, signatureProvidedByTheClient, reportBody))
{
await StoreInvalidReportAsync(appKey, signatureProvidedByTheClient, remoteAddress, reportBody);
throw new AuthenticationException(
Expand Down Expand Up @@ -158,6 +159,21 @@ private NewReportDTO DeserializeBody(byte[] body)

if (string.IsNullOrEmpty(dto.EnvironmentName) && !string.IsNullOrEmpty(dto.Environment))
dto.EnvironmentName = dto.Environment;

// Safeguard against malformed reports (other clients than the built in ones)
if (dto.Exception == null)
return null;
if (string.IsNullOrWhiteSpace(dto.Exception.Name) && string.IsNullOrWhiteSpace(dto.Exception.FullName))
return null;
if (string.IsNullOrWhiteSpace(dto.Exception.Name))
dto.Exception.Name = dto.Exception.FullName;
if (string.IsNullOrWhiteSpace(dto.Exception.FullName))
dto.Exception.FullName = dto.Exception.Name;
if (dto.Exception.BaseClasses == null)
dto.Exception.BaseClasses = new string[0];
if (dto.Exception.Namespace == null)
dto.Exception.Namespace = "";

return dto;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ public void Map(IDataRecord source, object destination)
public void Map(IDataRecord source, FindIncidentsResultItem destination)
{
destination.ApplicationName = (string) source["ApplicationName"];
destination.ApplicationId = source["ApplicationId"].ToString();
destination.ApplicationId = (int)source["ApplicationId"];
destination.IsReOpened = source["IsReopened"].Equals(1);
destination.ReportCount = (int) source["ReportCount"];
destination.CreatedAtUtc = (DateTime)source["CreatedAtUtc"];
Expand All @@ -31,6 +31,9 @@ public void Map(IDataRecord source, FindIncidentsResultItem destination)

value = source["LastReportAtUtc"];
destination.LastReportReceivedAtUtc = (DateTime) (value is DBNull ? destination.LastUpdateAtUtc : value);

value = source["AssignedAtUtc"];
destination.AssignedAtUtc = (DateTime?)(value is DBNull ? null : value);
}
}
}
1 change: 0 additions & 1 deletion src/Server/Coderr.Server.Web/ClientApp/boot.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ import Vue from "vue";
import VueRouter from "vue-router";
import moment from "moment";
import { AppRoot } from "./services/AppRoot"
//import VeeValidate from 'vee-validate';
import { IUser } from "./vue-shim";

//Vue.use(VeeValidate);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,12 @@ export default class AnalyzeIncidentComponent extends Vue {
currentCollectionName: string = '';

created() {
// required for contextnavigator
this.incidentId = parseInt(this.$route.params.incidentId, 10);
}

mounted() {
var incidentId = parseInt(this.$route.params.incidentId, 10);
this.loadIncident(incidentId);
this.loadIncident(this.incidentId);
MyIncidents.Instance.subscribeOnSelectedIncident(this.selectIncident);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ <h3>Quick facts</h3>
<div class="col">
<div class="card">
<div class="card-body">
<context-navigator :incidentId="incident.Id" :showAnalyzeFooter="true" />
<context-navigator :incidentId="incidentId" :showAnalyzeFooter="true" />
</div>
</div>
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,8 @@
.bg-light .router-link-exact-active {
color: #333333;
font-weight: bold;
}*/
}*/
td {
padding-right: 15px;
padding-top: 5px;
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import { PubSubService, MessageContext } from "../../services/PubSub";
import * as MenuApi from "../../services/menu/MenuApi";
import Vue from 'vue';
import Vue from "vue";
import { AppRoot } from '../../services/AppRoot';
import { Component, Watch } from 'vue-property-decorator';
import { MyIncidents, IMyIncident } from "./myincidents";

Expand All @@ -18,11 +20,15 @@ export default class AnalyzeMenuComponent extends Vue {
incidents: IMyIncident[] = [];
title = '';
incidentId: number | null = null;
toggleMenu = false;
applicationId: number | null = null;

created() {
if (this.$route.params.incidentId) {
this.incidentId = parseInt(this.$route.params.incidentId, 10);
}
this.applicationId = AppRoot.Instance.currentApplicationId;
PubSubService.Instance.subscribe(MenuApi.MessagingTopics.ApplicationChanged, this.onApplicationChangedInNavMenu);
MyIncidents.Instance.subscribeOnSelectedIncident(this.onIncidentSelected);
MyIncidents.Instance.subscribeOnListChanges(this.onListChanged);
}
Expand All @@ -41,6 +47,12 @@ export default class AnalyzeMenuComponent extends Vue {
destroyed() {
MyIncidents.Instance.unsubscribe(this.onIncidentSelected);
MyIncidents.Instance.unsubscribe(this.onListChanged);
PubSubService.Instance.unsubscribe(MenuApi.MessagingTopics.ApplicationChanged, this.onApplicationChangedInNavMenu);
}

toggleIncidentMenu() {
this.toggleMenu = !this.toggleMenu;

}

private onListChanged(args: any) {
Expand All @@ -62,6 +74,20 @@ export default class AnalyzeMenuComponent extends Vue {
}
}

@Watch('$route.params.applicationId')
onAppRoute(value: string, oldValue: string) {
if (!value) {
this.applicationId = null;
return;
} else {
this.applicationId = parseInt(value, 10);
}
}
private onApplicationChangedInNavMenu(ctx: MessageContext) {
var body = <MenuApi.ApplicationChanged>ctx.message.body;
this.applicationId = body.applicationId;
}

@Watch('$route.params.incidentId')
onIncidentRoute(value: string, oldValue: string) {
if (this.$route.fullPath.indexOf('/analyze/') === -1) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,39 +1,64 @@
<template>
<div class="mb-3 analyze-menu submenu" v-if="incidentId">
<div class="navbar-light navbar bg-light">
<ul class="nav">
<li class="nav-item dropdown">
<a class="nav-link dropdown-toggle" id="myIncidentsBtn" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
{{title}}
</a>
<div class="dropdown-menu" aria-labelledby="myIncidentsBtn">
<h6 class="dropdown-header">Select one of your incidents</h6>
<router-link class="dropdown-item" :to="{ name: 'analyzeIncident', params: {incidentId: item.incidentId.toString() }}" v-for="item in incidents" :key="item.incidentId">
<div class="mb-3">
<div class="mb-0 analyze-menu submenu" v-if="incidentId">
<div class="navbar-light navbar bg-light">
<ul class="nav">
<li class="nav-item dropdown">
<a href="#" @click.prevent="toggleIncidentMenu" class="nav-link" id="myIncidentsBtn">
<i class="fa fa-bars"></i>
</a>
</li>
<li class="nav-item">
<router-link class="nav-link" :to="{name: 'analyzeIncident', params: {incidentId: incidentId }}" exact>
<span class="fa fa-chart-line"></span> Overview
</router-link>
</li>
<li class="nav-item">
<router-link class="nav-link" :to="{name: 'analyzeOrigins', params: {incidentId: incidentId }}">
<span class="fa fa-globe"></span> Error origins
</router-link>
</li>
<li class="nav-item">
<router-link class="nav-link" :to="{name: 'analyzeReport', params: {incidentId: incidentId }}">
<span class="fa fa-table"></span> Analyze reports
</router-link>
</li>
<li class="nav-item">
<router-link class="nav-link" :to="{name: 'analyzeFeedback', params: {incidentId: incidentId }}">
<span class="fa fa-comment"></span> Bug reports
</router-link>
</li>
</ul>
</div>
</div>
<div v-show="toggleMenu" class="bg-dark text-blue mt-0 p-5">
<h3 class="text-blue">My incidents</h3>
<table>
<tr>
<th>Name</th>
<th v-if="applicationId == null">Application</th>
<th>Created</th>
<th>Assigned since</th>
</tr>
<tr v-for="item in incidents">
<td class="text-left">
<router-link :to="{ name: 'analyzeIncident', params: {incidentId: item.incidentId.toString() }}" :key="item.incidentId">
{{item.title}}
</router-link>
</div>
</li>
<li class="nav-item">
<router-link class="nav-link" :to="{name: 'analyzeIncident', params: {incidentId: incidentId }}" exact>
<span class="fa fa-chart-line"></span> Overview
</router-link>
</li>
<li class="nav-item">
<router-link class="nav-link" :to="{name: 'analyzeOrigins', params: {incidentId: incidentId }}">
<span class="fa fa-globe"></span> Error origins
</router-link>
</li>
<li class="nav-item">
<router-link class="nav-link" :to="{name: 'analyzeReport', params: {incidentId: incidentId }}">
<span class="fa fa-table"></span> Analyze reports
</router-link>
</li>
<li class="nav-item">
<router-link class="nav-link" :to="{name: 'analyzeFeedback', params: {incidentId: incidentId }}">
<span class="fa fa-comment"></span> Bug reports
</router-link>
</li>
</ul>
</td>
<td v-if="!applicationId">
{{item.applicationName}}
</td>
<td>
{{item.createdAtUtc|ago}}
</td>
<td>
{{item.assignedAtUtc|ago}}
</td>
</tr>

</table>

</div>
</div>
</template>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import * as MenuApi from "../../services/menu/MenuApi";
import { AppRoot } from "../../services/AppRoot";
import { PubSubService, MessageContext } from "../../services/PubSub";
import { IncidentTopcis, IncidentAssigned, IncidentClosed, IncidentIgnored } from "../../services/incidents/IncidentService";
import * as incidents from "../../dto/Core/Incidents";

/**
* null if the user do not have any assigned incidents (for the selected application)
Expand All @@ -21,6 +22,9 @@ export interface incidentListChanged {
export interface IMyIncident {
incidentId: number;
applicationId: number;
applicationName: string;
createdAtUtc: Date;
assignedAtUtc: Date;
title: string;

/**
Expand Down Expand Up @@ -142,9 +146,16 @@ export class MyIncidents {
var index = this.allMyIncidents$.findIndex(menuItem => menuItem.incidentId === assignedIncident.Id);
var item: IMyIncident;
if (index === -1) {
item = this.createItem(assignedIncident.Id,
item = this.createItem(
assignedIncident.Id,
assignedIncident.ApplicationId,
assignedIncident.Description);
'',
assignedIncident.CreatedAtUtc,
assignedIncident.AssignedAtUtc,
assignedIncident.Description
);
AppRoot.Instance.applicationService.get(assignedIncident.ApplicationId)
.then(x => item.applicationName = x.name);
this.allMyIncidents$.push(item);
} else {
item = this.allMyIncidents$[index];
Expand Down Expand Up @@ -182,7 +193,7 @@ export class MyIncidents {
}
mine.forEach(dto => {
if (!this.allMyIncidents$.find(item => item.incidentId === dto.Id)) {
var item = this.createItem(dto.Id, parseInt(dto.ApplicationId, 10), dto.Name);
var item = this.createItem2(dto);
this.allMyIncidents$.push(item);
}
});
Expand All @@ -200,7 +211,7 @@ export class MyIncidents {
});
}

private createItem(incidentId: number, applicationId: number, title: string): IMyIncident {
private createItem(incidentId: number, applicationId: number, applicationName: string, createdAtUtc: Date, assignedAtUtc: Date, title: string): IMyIncident {
let shortTitle = title;
if (shortTitle.length > 50) {
shortTitle = title.substr(0, 45) + '[...]';
Expand All @@ -210,7 +221,28 @@ export class MyIncidents {
title: title,
shortTitle: shortTitle,
incidentId: incidentId,
applicationId: applicationId
createdAtUtc: createdAtUtc,
applicationId: applicationId,
applicationName: applicationName,
assignedAtUtc: assignedAtUtc
};
return item;
}

private createItem2(incident: incidents.FindIncidentsResultItem): IMyIncident {
let shortTitle = incident.Name;
if (shortTitle.length > 50) {
shortTitle = incident.Name.substr(0, 45) + '[...]';
}

var item: IMyIncident = {
title: incident.Name,
shortTitle: shortTitle,
incidentId: incident.Id,
createdAtUtc: incident.CreatedAtUtc,
applicationId: incident.ApplicationId,
applicationName: incident.ApplicationName,
assignedAtUtc: incident.AssignedAtUtc
};
return item;
}
Expand All @@ -227,7 +259,7 @@ export class MyIncidents {
var foundItem: IMyIncident = null;
allMine.forEach(myIncident => {
if (myIncident.Id === incidentId) {
var item = this.createItem(myIncident.Id, parseInt(myIncident.ApplicationId, 10), myIncident.Name);
var item = this.createItem2(myIncident);
this.allMyIncidents$.push(item);
foundItem = item;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ <h3 class="">Report history</h3>
<div class="col">
<div class="card">
<div class="card-body">
<context-navigator :incidentId="incident.Id" />
<context-navigator :incidentId="incidentId" />
</div>
</div>
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -289,7 +289,7 @@ export default class IncidentSearchComponent extends Vue {
this.incidents.splice(0);
result.Items.forEach(item => {
var entity: Incident = {
ApplicationId: parseInt(item.ApplicationId, 10),
ApplicationId: item.ApplicationId,
ApplicationName: item.ApplicationName,
CreatedAtUtc: item.CreatedAtUtc,
Id: item.Id,
Expand Down
Loading