Skip to content

Commit f59c297

Browse files
committed
merge
2 parents 16cadeb + 7f024e5 commit f59c297

File tree

25 files changed

+204
-72
lines changed

25 files changed

+204
-72
lines changed

src/Server/Coderr.Server.Api/Core/Incidents/Queries/FindIncidentsResultItem.cs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ protected FindIncidentsResultItem()
3131
/// <summary>
3232
/// Id of the application that this incident belongs to
3333
/// </summary>
34-
public string ApplicationId { get; set; }
34+
public int ApplicationId { get; set; }
3535

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

46+
/// <summary>
47+
/// When the incident was assigned to someone.
48+
/// </summary>
49+
public DateTime? AssignedAtUtc { get; set; }
50+
4651
/// <summary>
4752
/// Incident id
4853
/// </summary>

src/Server/Coderr.Server.ReportAnalyzer/Inbound/SaveReportHandler.cs

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,8 @@ public async Task BuildReportAsync(ClaimsPrincipal user, string appKey, string s
6464
throw new InvalidCredentialException($"AppKey was not found in the database. Key '{appKey}'.");
6565
}
6666

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

159160
if (string.IsNullOrEmpty(dto.EnvironmentName) && !string.IsNullOrEmpty(dto.Environment))
160161
dto.EnvironmentName = dto.Environment;
162+
163+
// Safeguard against malformed reports (other clients than the built in ones)
164+
if (dto.Exception == null)
165+
return null;
166+
if (string.IsNullOrWhiteSpace(dto.Exception.Name) && string.IsNullOrWhiteSpace(dto.Exception.FullName))
167+
return null;
168+
if (string.IsNullOrWhiteSpace(dto.Exception.Name))
169+
dto.Exception.Name = dto.Exception.FullName;
170+
if (string.IsNullOrWhiteSpace(dto.Exception.FullName))
171+
dto.Exception.FullName = dto.Exception.Name;
172+
if (dto.Exception.BaseClasses == null)
173+
dto.Exception.BaseClasses = new string[0];
174+
if (dto.Exception.Namespace == null)
175+
dto.Exception.Namespace = "";
176+
161177
return dto;
162178
}
163179

src/Server/Coderr.Server.SqlServer/Core/Incidents/Queries/FindIncidentResultItemMapper.cs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ public void Map(IDataRecord source, object destination)
2020
public void Map(IDataRecord source, FindIncidentsResultItem destination)
2121
{
2222
destination.ApplicationName = (string) source["ApplicationName"];
23-
destination.ApplicationId = source["ApplicationId"].ToString();
23+
destination.ApplicationId = (int)source["ApplicationId"];
2424
destination.IsReOpened = source["IsReopened"].Equals(1);
2525
destination.ReportCount = (int) source["ReportCount"];
2626
destination.CreatedAtUtc = (DateTime)source["CreatedAtUtc"];
@@ -31,6 +31,9 @@ public void Map(IDataRecord source, FindIncidentsResultItem destination)
3131

3232
value = source["LastReportAtUtc"];
3333
destination.LastReportReceivedAtUtc = (DateTime) (value is DBNull ? destination.LastUpdateAtUtc : value);
34+
35+
value = source["AssignedAtUtc"];
36+
destination.AssignedAtUtc = (DateTime?)(value is DBNull ? null : value);
3437
}
3538
}
3639
}

src/Server/Coderr.Server.Web/ClientApp/boot.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ import Vue from "vue";
33
import VueRouter from "vue-router";
44
import moment from "moment";
55
import { AppRoot } from "./services/AppRoot"
6-
//import VeeValidate from 'vee-validate';
76
import { IUser } from "./vue-shim";
87

98
//Vue.use(VeeValidate);

src/Server/Coderr.Server.Web/ClientApp/components/analyze/incidents/incident.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ export default class AnalyzeIncidentComponent extends Vue {
2727
currentCollectionName: string = '';
2828

2929
created() {
30+
// required for contextnavigator
3031
this.incidentId = parseInt(this.$route.params.incidentId, 10);
3132
}
3233

src/Server/Coderr.Server.Web/ClientApp/components/analyze/incidents/incident.vue.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ <h3>Quick facts</h3>
6969
<div class="col">
7070
<div class="card">
7171
<div class="card-body">
72-
<context-navigator :incidentId="incident.Id" :showAnalyzeFooter="true" />
72+
<context-navigator :incidentId="incidentId" :showAnalyzeFooter="true" />
7373
</div>
7474
</div>
7575
</div>

src/Server/Coderr.Server.Web/ClientApp/components/analyze/menu.css

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,4 +10,8 @@
1010
.bg-light .router-link-exact-active {
1111
color: #333333;
1212
font-weight: bold;
13-
}*/
13+
}*/
14+
td {
15+
padding-right: 15px;
16+
padding-top: 5px;
17+
}

src/Server/Coderr.Server.Web/ClientApp/components/analyze/menu.ts

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
1+
import { PubSubService, MessageContext } from "../../services/PubSub";
12
import * as MenuApi from "../../services/menu/MenuApi";
2-
import Vue from 'vue';
3+
import Vue from "vue";
4+
import { AppRoot } from '../../services/AppRoot';
35
import { Component, Watch } from 'vue-property-decorator';
46
import { MyIncidents, IMyIncident } from "./myincidents";
57

@@ -18,11 +20,15 @@ export default class AnalyzeMenuComponent extends Vue {
1820
incidents: IMyIncident[] = [];
1921
title = '';
2022
incidentId: number | null = null;
23+
toggleMenu = false;
24+
applicationId: number | null = null;
2125

2226
created() {
2327
if (this.$route.params.incidentId) {
2428
this.incidentId = parseInt(this.$route.params.incidentId, 10);
2529
}
30+
this.applicationId = AppRoot.Instance.currentApplicationId;
31+
PubSubService.Instance.subscribe(MenuApi.MessagingTopics.ApplicationChanged, this.onApplicationChangedInNavMenu);
2632
MyIncidents.Instance.subscribeOnSelectedIncident(this.onIncidentSelected);
2733
MyIncidents.Instance.subscribeOnListChanges(this.onListChanged);
2834
}
@@ -41,6 +47,12 @@ export default class AnalyzeMenuComponent extends Vue {
4147
destroyed() {
4248
MyIncidents.Instance.unsubscribe(this.onIncidentSelected);
4349
MyIncidents.Instance.unsubscribe(this.onListChanged);
50+
PubSubService.Instance.unsubscribe(MenuApi.MessagingTopics.ApplicationChanged, this.onApplicationChangedInNavMenu);
51+
}
52+
53+
toggleIncidentMenu() {
54+
this.toggleMenu = !this.toggleMenu;
55+
4456
}
4557

4658
private onListChanged(args: any) {
@@ -62,6 +74,20 @@ export default class AnalyzeMenuComponent extends Vue {
6274
}
6375
}
6476

77+
@Watch('$route.params.applicationId')
78+
onAppRoute(value: string, oldValue: string) {
79+
if (!value) {
80+
this.applicationId = null;
81+
return;
82+
} else {
83+
this.applicationId = parseInt(value, 10);
84+
}
85+
}
86+
private onApplicationChangedInNavMenu(ctx: MessageContext) {
87+
var body = <MenuApi.ApplicationChanged>ctx.message.body;
88+
this.applicationId = body.applicationId;
89+
}
90+
6591
@Watch('$route.params.incidentId')
6692
onIncidentRoute(value: string, oldValue: string) {
6793
if (this.$route.fullPath.indexOf('/analyze/') === -1) {

src/Server/Coderr.Server.Web/ClientApp/components/analyze/menu.vue.html

Lines changed: 58 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,39 +1,64 @@
11
<template>
2-
<div class="mb-3 analyze-menu submenu" v-if="incidentId">
3-
<div class="navbar-light navbar bg-light">
4-
<ul class="nav">
5-
<li class="nav-item dropdown">
6-
<a class="nav-link dropdown-toggle" id="myIncidentsBtn" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
7-
{{title}}
8-
</a>
9-
<div class="dropdown-menu" aria-labelledby="myIncidentsBtn">
10-
<h6 class="dropdown-header">Select one of your incidents</h6>
11-
<router-link class="dropdown-item" :to="{ name: 'analyzeIncident', params: {incidentId: item.incidentId.toString() }}" v-for="item in incidents" :key="item.incidentId">
2+
<div class="mb-3">
3+
<div class="mb-0 analyze-menu submenu" v-if="incidentId">
4+
<div class="navbar-light navbar bg-light">
5+
<ul class="nav">
6+
<li class="nav-item dropdown">
7+
<a href="#" @click.prevent="toggleIncidentMenu" class="nav-link" id="myIncidentsBtn">
8+
<i class="fa fa-bars"></i>
9+
</a>
10+
</li>
11+
<li class="nav-item">
12+
<router-link class="nav-link" :to="{name: 'analyzeIncident', params: {incidentId: incidentId }}" exact>
13+
<span class="fa fa-chart-line"></span> Overview
14+
</router-link>
15+
</li>
16+
<li class="nav-item">
17+
<router-link class="nav-link" :to="{name: 'analyzeOrigins', params: {incidentId: incidentId }}">
18+
<span class="fa fa-globe"></span> Error origins
19+
</router-link>
20+
</li>
21+
<li class="nav-item">
22+
<router-link class="nav-link" :to="{name: 'analyzeReport', params: {incidentId: incidentId }}">
23+
<span class="fa fa-table"></span> Analyze reports
24+
</router-link>
25+
</li>
26+
<li class="nav-item">
27+
<router-link class="nav-link" :to="{name: 'analyzeFeedback', params: {incidentId: incidentId }}">
28+
<span class="fa fa-comment"></span> Bug reports
29+
</router-link>
30+
</li>
31+
</ul>
32+
</div>
33+
</div>
34+
<div v-show="toggleMenu" class="bg-dark text-blue mt-0 p-5">
35+
<h3 class="text-blue">My incidents</h3>
36+
<table>
37+
<tr>
38+
<th>Name</th>
39+
<th v-if="applicationId == null">Application</th>
40+
<th>Created</th>
41+
<th>Assigned since</th>
42+
</tr>
43+
<tr v-for="item in incidents">
44+
<td class="text-left">
45+
<router-link :to="{ name: 'analyzeIncident', params: {incidentId: item.incidentId.toString() }}" :key="item.incidentId">
1246
{{item.title}}
1347
</router-link>
14-
</div>
15-
</li>
16-
<li class="nav-item">
17-
<router-link class="nav-link" :to="{name: 'analyzeIncident', params: {incidentId: incidentId }}" exact>
18-
<span class="fa fa-chart-line"></span> Overview
19-
</router-link>
20-
</li>
21-
<li class="nav-item">
22-
<router-link class="nav-link" :to="{name: 'analyzeOrigins', params: {incidentId: incidentId }}">
23-
<span class="fa fa-globe"></span> Error origins
24-
</router-link>
25-
</li>
26-
<li class="nav-item">
27-
<router-link class="nav-link" :to="{name: 'analyzeReport', params: {incidentId: incidentId }}">
28-
<span class="fa fa-table"></span> Analyze reports
29-
</router-link>
30-
</li>
31-
<li class="nav-item">
32-
<router-link class="nav-link" :to="{name: 'analyzeFeedback', params: {incidentId: incidentId }}">
33-
<span class="fa fa-comment"></span> Bug reports
34-
</router-link>
35-
</li>
36-
</ul>
48+
</td>
49+
<td v-if="!applicationId">
50+
{{item.applicationName}}
51+
</td>
52+
<td>
53+
{{item.createdAtUtc|ago}}
54+
</td>
55+
<td>
56+
{{item.assignedAtUtc|ago}}
57+
</td>
58+
</tr>
59+
60+
</table>
61+
3762
</div>
3863
</div>
3964
</template>

src/Server/Coderr.Server.Web/ClientApp/components/analyze/myincidents.ts

Lines changed: 38 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import * as MenuApi from "../../services/menu/MenuApi";
22
import { AppRoot } from "../../services/AppRoot";
33
import { PubSubService, MessageContext } from "../../services/PubSub";
44
import { IncidentTopcis, IncidentAssigned, IncidentClosed, IncidentIgnored } from "../../services/incidents/IncidentService";
5+
import * as incidents from "../../dto/Core/Incidents";
56

67
/**
78
* null if the user do not have any assigned incidents (for the selected application)
@@ -21,6 +22,9 @@ export interface incidentListChanged {
2122
export interface IMyIncident {
2223
incidentId: number;
2324
applicationId: number;
25+
applicationName: string;
26+
createdAtUtc: Date;
27+
assignedAtUtc: Date;
2428
title: string;
2529

2630
/**
@@ -142,9 +146,16 @@ export class MyIncidents {
142146
var index = this.allMyIncidents$.findIndex(menuItem => menuItem.incidentId === assignedIncident.Id);
143147
var item: IMyIncident;
144148
if (index === -1) {
145-
item = this.createItem(assignedIncident.Id,
149+
item = this.createItem(
150+
assignedIncident.Id,
146151
assignedIncident.ApplicationId,
147-
assignedIncident.Description);
152+
'',
153+
assignedIncident.CreatedAtUtc,
154+
assignedIncident.AssignedAtUtc,
155+
assignedIncident.Description
156+
);
157+
AppRoot.Instance.applicationService.get(assignedIncident.ApplicationId)
158+
.then(x => item.applicationName = x.name);
148159
this.allMyIncidents$.push(item);
149160
} else {
150161
item = this.allMyIncidents$[index];
@@ -182,7 +193,7 @@ export class MyIncidents {
182193
}
183194
mine.forEach(dto => {
184195
if (!this.allMyIncidents$.find(item => item.incidentId === dto.Id)) {
185-
var item = this.createItem(dto.Id, parseInt(dto.ApplicationId, 10), dto.Name);
196+
var item = this.createItem2(dto);
186197
this.allMyIncidents$.push(item);
187198
}
188199
});
@@ -200,7 +211,7 @@ export class MyIncidents {
200211
});
201212
}
202213

203-
private createItem(incidentId: number, applicationId: number, title: string): IMyIncident {
214+
private createItem(incidentId: number, applicationId: number, applicationName: string, createdAtUtc: Date, assignedAtUtc: Date, title: string): IMyIncident {
204215
let shortTitle = title;
205216
if (shortTitle.length > 50) {
206217
shortTitle = title.substr(0, 45) + '[...]';
@@ -210,7 +221,28 @@ export class MyIncidents {
210221
title: title,
211222
shortTitle: shortTitle,
212223
incidentId: incidentId,
213-
applicationId: applicationId
224+
createdAtUtc: createdAtUtc,
225+
applicationId: applicationId,
226+
applicationName: applicationName,
227+
assignedAtUtc: assignedAtUtc
228+
};
229+
return item;
230+
}
231+
232+
private createItem2(incident: incidents.FindIncidentsResultItem): IMyIncident {
233+
let shortTitle = incident.Name;
234+
if (shortTitle.length > 50) {
235+
shortTitle = incident.Name.substr(0, 45) + '[...]';
236+
}
237+
238+
var item: IMyIncident = {
239+
title: incident.Name,
240+
shortTitle: shortTitle,
241+
incidentId: incident.Id,
242+
createdAtUtc: incident.CreatedAtUtc,
243+
applicationId: incident.ApplicationId,
244+
applicationName: incident.ApplicationName,
245+
assignedAtUtc: incident.AssignedAtUtc
214246
};
215247
return item;
216248
}
@@ -227,7 +259,7 @@ export class MyIncidents {
227259
var foundItem: IMyIncident = null;
228260
allMine.forEach(myIncident => {
229261
if (myIncident.Id === incidentId) {
230-
var item = this.createItem(myIncident.Id, parseInt(myIncident.ApplicationId, 10), myIncident.Name);
262+
var item = this.createItem2(myIncident);
231263
this.allMyIncidents$.push(item);
232264
foundItem = item;
233265
}

0 commit comments

Comments
 (0)