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 @@ -45,7 +45,7 @@ protected IncidentAssigned()
/// <summary>
/// When the incident was assigned (client side)
/// </summary>
public DateTime AssignedAtUtc { get; private set; }
public DateTime AssignedAtUtc { get; private set; }

/// <summary>
/// Incident being assigned
Expand Down
3 changes: 2 additions & 1 deletion src/Server/Coderr.Server.App/Core/Accounts/AccountService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -86,9 +86,10 @@ public async Task<ClaimsIdentity> ActivateAccount(ClaimsPrincipal user, string a
throw new ArgumentOutOfRangeException("ActivationKey", activationKey,
"Key was not found.");


account.Activate();
await _repository.UpdateAsync(account);


if (!user.IsCurrentAccount(account.Id))
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,11 @@ public string Description
set => _description = value;
}

/// <summary>
/// List of all environment names that the developer specified when reporting the errors.
/// </summary>
public string[] EnvironmentNames { get; set; }

/// <summary>
/// Full name of the exception message.
/// </summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ namespace Coderr.Server.SqlServer.Core.Accounts
public class AccountRepository : IAccountRepository
{
private readonly IAdoNetUnitOfWork _uow;
private ILog _logger = LogManager.GetLogger(typeof(AccountRepository));

public AccountRepository(IAdoNetUnitOfWork uow)
{
Expand Down Expand Up @@ -43,7 +44,12 @@ public async Task<Account> FindByActivationKeyAsync(string activationKey)
{
cmd.CommandText = "SELECT * FROM Accounts WHERE ActivationKey=@key";
cmd.AddParameter("key", activationKey);
return await cmd.FirstOrDefaultAsync(new AccountMapper());
var accounts= await cmd.ToListAsync(new AccountMapper());
if (accounts.Count == 0)
return null;

_logger.Error($"Found {accounts.Count} accounts, expected one.");
return accounts.First();
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ from Environments
begin
INSERT INTO IncidentEnvironments (IncidentId, EnvironmentId)
SELECT @incidentId, @environmentId
WHERE NOT EXISTS (SELECT IncidentId, EnvironmentId FROM IncidentEnvironment
WHERE NOT EXISTS (SELECT IncidentId, EnvironmentId FROM IncidentEnvironments
WHERE IncidentId=@incidentId AND EnvironmentId=@environmentId)
end;";
cmd.AddParameter("incidentId", incidentId);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@ public ErrorReportEntityMapper() : base("ErrorReports")
.ToPropertyValue(x => null)
.ToColumnValue(x => "");

Property(x => x.EnvironmentName)
.Ignore();

Property(x => x.ClientReportId)
.ColumnName("ErrorId");

Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<template>
<div>
<analyze-menu />
<div class="col">
<div class="cold">
<router-view></router-view>
</div>
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,5 +29,8 @@ export default class AnalyzeHomeComponent extends Vue {

private onReady() {
this.showWelcome = MyIncidents.Instance.myIncidents.length === 0;
if (MyIncidents.Instance.myIncidents.length > 0) {
MyIncidents.Instance.switchIncident(MyIncidents.Instance.myIncidents[0].incidentId);
}
}
}
Original file line number Diff line number Diff line change
@@ -1,111 +1,109 @@
<template>
<div class="IncidentView">
<div>
<div class="row">
<div class="col">
<div class="float-right">
<div class="dropdown">
<button type="button" class="btn btn-outline-primary dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
Actions
</button>
<div class="dropdown-menu">
<div class="row">
<div class="col pl-4">
<div class="float-right">
<div class="btn-group" role="group">
<button class="btn btn-primary text-light" v-on:click="closeIncident">Close incident</button>
<div class="dropdown" style="display: inline-block">
<button type="button" class="btn btn-outline-primary dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"></button>
<div class="dropdown-menu dropdown-menu-right">
<span class="dropdown-item" v-on:click="reAssign"><i class="fa-redo fa text-muted"></i> Re-assign</span>
<!--<span class="dropdown-item" v-on:click="addToTfs"><i class="fa-code-branch fa text-muted"></i> Add to TFS/VSTS</span>-->
<span class="dropdown-item" v-on:click="closeIncident"><i class="fa-lock fa text-muted"></i> Close incident</span>

</div>
</div>
</div>
</div>

<h3>{{incident.Description}} <span class="lead text-muted">[{{incident.FullName}}]</span></h3>
<h3>{{incident.Description}} <span class="lead text-muted">[{{incident.FullName}}]</span></h3>


<div class="tags">
<span v-for="tag in incident.Tags" class="badge badge-dark">{{tag}}</span>
</div>
<hr />
<div class="tags">
<span v-for="tag in incident.Tags" class="badge badge-dark">{{tag}}</span>
</div>
</div>
<div class="row" v-if="incident.Solution">
<div class="col">
<div class="card">
<div class="card-header">
Previous solution ({{incident.SolvedAtUtc|ago}})
</div>
<div class="card-body">
<div v-html="incident.Solution"></div>
</div>
</div>
<div class="row" v-if="incident.Solution">
<div class="col">
<div class="card">
<div class="card-header">
Previous solution ({{incident.SolvedAtUtc|ago}})
</div>
<div class="card-body">
<div v-html="incident.Solution"></div>
</div>
</div>

</div>
<div class="row">
<div class="col-xl-8 col-lg-6">
<div class="card">
<div class="card-body">
<h3>Stack trace</h3>
<pre style="min-height: 200px"><code>{{incident.StackTrace}}</code></pre>
</div>

</div>
<div class="row minimal-gutters">
<div class="col-xl-8 col-lg-6">
<div class="card">
<div class="card-body">
<h3>Stack trace</h3>
<pre style="min-height: 200px"><code>{{incident.StackTrace}}</code></pre>
</div>
</div>
<div class="col-xl-4 col-lg-6">
<div class="card" v-if="incident.Facts && incident.Facts.length > 0">
<div class="card-body">
<h3>Quick facts</h3>
<div>
<table class="table table-borderless">
<tbody>
<tr v-for="prop in incident.Facts" v-if="prop.Value != '0'">
<td>{{prop.Title}}</td>
<td>{{prop.Value}}</td>
</tr>
</tbody>
</table>
</div>
</div>
<div class="col-xl-4 col-lg-6">
<div class="card" v-if="incident.Facts && incident.Facts.length > 0">
<div class="card-body">
<h3>Quick facts</h3>
<div>
<table class="table table-borderless">
<tbody>
<tr v-for="prop in incident.Facts" v-if="prop.Value != '0'">
<td>{{prop.Title}}</td>
<td>{{prop.Value}}</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>

<div class="card">
<div class="card-body">
<h3>Context collections</h3>
<div>
<div class="dropdown" style="display: inline">
<button type="button" class="btn btn-light dropdown-toggle btn-sm" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
{{currentReportName}}
</button>
<div class="dropdown-menu">
<h6 class="dropdown-header">Select report</h6>
<div v-for="report in reports">
<a class="dropdown-item" href="#" v-on:click.prevent="loadReport(report.Id)"><i class="fa-desktop fa text-muted"></i> {{report.CreatedAtUtc|ago}}</a>
</div>
<div class="card">
<div class="card-body">
<h3>Context collections</h3>
<div>
<div class="dropdown" style="display: inline">
<button type="button" class="btn btn-light dropdown-toggle btn-sm" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
{{currentReportName}}
</button>
<div class="dropdown-menu">
<h6 class="dropdown-header">Select report</h6>
<div v-for="report in reports">
<a class="dropdown-item" href="#" v-on:click.prevent="loadReport(report.Id)"><i class="fa-desktop fa text-muted"></i> {{report.CreatedAtUtc|ago}}</a>
</div>
</div>
<div class="dropdown" style="display: inline">
<button type="button" class="btn btn-light dropdown-toggle btn-sm" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false" id="reportChooser">
{{currentCollectionName}}
</button>
<div class="dropdown-menu">
<h6 class="dropdown-header">Select context collection</h6>
<div v-for="collection in currentReport.ContextCollections">
<span class="dropdown-item" v-on:click="loadCollection(collection.Name)"><i class="fa-table fa text-muted"></i> {{collection.Name}}</span>
</div>
</div>
<div class="dropdown" style="display: inline">
<button type="button" class="btn btn-light dropdown-toggle btn-sm" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false" id="reportChooser">
{{currentCollectionName}}
</button>
<div class="dropdown-menu">
<h6 class="dropdown-header">Select context collection</h6>
<div v-for="collection in currentReport.ContextCollections">
<span class="dropdown-item" v-on:click="loadCollection(collection.Name)"><i class="fa-table fa text-muted"></i> {{collection.Name}}</span>
</div>
</div>
</div>
<div v-if="currentReport.Id > 0" style="overflow: auto">
<table class="table mt-3 mb-3">
<tbody>
<tr v-for="prop in currentCollection.Properties">
<td>{{prop.Key}}</td>
<td v-html="prop.Value"></td>
</tr>
</tbody>
</table>
</div>
<hr />
<em>
<router-link class="btn btn-primary btn-block" :to="{ name: 'analyzeReport', params: { reportId: currentReport.Id, incidentId: incident.Id}}">View entire report</router-link>
</em>
</div>
</div>
<div v-if="currentReport.Id > 0" style="overflow: auto">
<table class="table mt-3 mb-3">
<tbody>
<tr v-for="prop in currentCollection.Properties">
<td>{{prop.Key}}</td>
<td v-html="prop.Value"></td>
</tr>
</tbody>
</table>
</div>
<em v-if="currentReport.Id > 0" >
<router-link class="btn btn-primary btn-block" :to="{ name: 'analyzeReport', params: { reportId: currentReport.Id, incidentId: incident.Id}}">Report browser</router-link>
</em>

</div>
</div>
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,16 @@
display: none;
}

.ReportsView .contextCollections th, .ReportsView .contextCollections td {
.collection a {
padding: 5px;
margin: 5px;
display: block;
}
.ReportsView .contextCollections th, .ReportsView .contextCollections td, .ReportsView h4 {
padding: 0.15rem;
}


.contextCollections .card {
overflow-x: scroll;
overflow-y: auto
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@ export default class AnalyzeReportComponent extends Vue {

if (reportId !== this.reportId) {
this.reportId = reportId;
console.log('got report id', this.reportId);
this.$router.push({ name: 'analyzeReport', params: { reportId: reportId.toString(), incidentId: this.incidentId.toString() } });
}

Expand Down
30 changes: 7 additions & 23 deletions src/Server/Coderr.Server.Web/ClientApp/components/analyze/menu.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,33 +22,17 @@ export default class AnalyzeMenuComponent extends Vue {
created() {
MyIncidents.Instance.subscribeOnSelectedIncident(this.onIncidentSelected);
MyIncidents.Instance.subscribeOnListChanges(this.onListChanged);
MyIncidents.Instance.ready()
.then(x => {
this.incidents = MyIncidents.Instance.myIncidents;
});

if (this.$route.params.incidentId) {
this.incidentId = parseInt(this.$route.params.incidentId, 10);
MyIncidents.Instance.switchIncident(this.incidentId);
}
}

mounted() {
MyIncidents.Instance.ready().then(() => {
if (!this.$route.params.incidentId) {
if (MyIncidents.Instance.myIncidents.length === 0) {
return;
MyIncidents.Instance.ready()
.then(() => {
if (MyIncidents.Instance.incident) {
this.incidentId = MyIncidents.Instance.incident.incidentId;
this.title = MyIncidents.Instance.incident.title;
}

var incident = MyIncidents.Instance.myIncidents[0];
this.$router.push({ name: 'analyzeIncident', params: { incidentId: incident.incidentId.toString() } });
return;
}

if (this.incidentId) {
MyIncidents.Instance.switchIncident(this.incidentId);
}
});
this.incidents = MyIncidents.Instance.myIncidents;
});
}

destroyed() {
Expand Down
Loading