Skip to content
This repository has been archived by the owner on Sep 4, 2023. It is now read-only.

Add KPI matrix component #87

Merged
merged 74 commits into from
May 26, 2023
Merged
Show file tree
Hide file tree
Changes from 72 commits
Commits
Show all changes
74 commits
Select commit Hold shift + click to select a range
8427658
Created KpiMatrix component
Jasper123pyah Apr 21, 2023
064123e
Added modules and fixed comments
Jasper123pyah Apr 24, 2023
e304511
Fixed an issue where outcomes where duplicate
Jasper123pyah Apr 25, 2023
b469a79
Created KPIMatrix in word document
Jasper123pyah May 8, 2023
522c214
Fixed all remaining issues.
Jasper123pyah May 9, 2023
0f2ed39
Merge conflicts
Jasper123pyah May 9, 2023
230ffb9
Fixed MR requests
Jasper123pyah May 11, 2023
c5a8eb2
Changed course to allcourses
Jasper123pyah May 15, 2023
789536a
File restructure
NealGeilen May 16, 2023
c0f1b3d
Revised coding structure. Assignments that are not yest graded are al…
NealGeilen May 18, 2023
b508c11
Merge remote-tracking branch 'origin/poc/web-api-component-arch' into…
NealGeilen May 18, 2023
48e5038
Merged files in new structure
NealGeilen May 18, 2023
d5f3eb7
Colored rows
NealGeilen May 18, 2023
071c312
"Simplified"
NealGeilen May 18, 2023
8680552
Move HttpService class to Canvas project
Typiqally May 22, 2023
e60b1d2
Added legend and changed "GradeStatus" structure
NealGeilen May 23, 2023
0d21121
Remove unused constants
Typiqally May 23, 2023
6d0b42d
Modify persona page to accommodate new component architecture (#91)
kn4a-com May 23, 2023
881e035
Move HttpService class to Canvas project
Typiqally May 22, 2023
81bf1e1
Remove unused constants
Typiqally May 23, 2023
a6b3063
Modify persona page to accommodate new component architecture (#91)
kn4a-com May 23, 2023
92f0d97
Created KpiMatrix component
Jasper123pyah Apr 21, 2023
fcd4219
Added modules and fixed comments
Jasper123pyah Apr 24, 2023
e521d08
Merge conflicts
Jasper123pyah May 9, 2023
a7b9502
File restructure
NealGeilen May 16, 2023
5270f6d
Revised coding structure. Assignments that are not yest graded are al…
NealGeilen May 18, 2023
bc884ba
Created KpiMatrix component
Jasper123pyah Apr 21, 2023
325d314
Added modules and fixed comments
Jasper123pyah Apr 24, 2023
ab68843
Merge conflicts
Jasper123pyah May 9, 2023
a167198
File restructure
NealGeilen May 16, 2023
6cba853
Revised coding structure. Assignments that are not yest graded are al…
NealGeilen May 18, 2023
b04c3f8
Added legend and changed "GradeStatus" structure
NealGeilen May 23, 2023
779114f
Added extra grade type
NealGeilen May 23, 2023
9384808
Added legend to json result
NealGeilen May 23, 2023
2d29c6c
Working order
NealGeilen May 23, 2023
668cf8f
startDate & endDate implementation for document generator
NealGeilen May 23, 2023
a511a5a
POC working
NealGeilen May 23, 2023
5f5e44d
Created KpiMatrix component
Jasper123pyah Apr 21, 2023
16223e5
Added modules and fixed comments
Jasper123pyah Apr 24, 2023
bad4f0e
Fixed an issue where outcomes where duplicate
Jasper123pyah Apr 25, 2023
3fdcc82
Created KPIMatrix in word document
Jasper123pyah May 8, 2023
b0715fa
Fixed all remaining issues.
Jasper123pyah May 9, 2023
29dc2f6
Merge conflicts
Jasper123pyah May 9, 2023
12b58ff
Fixed MR requests
Jasper123pyah May 11, 2023
0885218
Changed course to allcourses
Jasper123pyah May 15, 2023
cb11da1
File restructure
NealGeilen May 16, 2023
94284e8
Revised coding structure. Assignments that are not yest graded are al…
NealGeilen May 18, 2023
be86b43
Merged files in new structure
NealGeilen May 18, 2023
aa02adc
Colored rows
NealGeilen May 18, 2023
1f4436e
"Simplified"
NealGeilen May 18, 2023
89c8370
Added legend and changed "GradeStatus" structure
NealGeilen May 23, 2023
7403cde
Created KpiMatrix component
Jasper123pyah Apr 21, 2023
60af6e1
Added modules and fixed comments
Jasper123pyah Apr 24, 2023
0ff2c3c
Merge conflicts
Jasper123pyah May 9, 2023
7f76d8a
File restructure
NealGeilen May 16, 2023
a07c9b3
Revised coding structure. Assignments that are not yest graded are al…
NealGeilen May 18, 2023
7b3f350
Created KpiMatrix component
Jasper123pyah Apr 21, 2023
5df36d5
Added modules and fixed comments
Jasper123pyah Apr 24, 2023
5528d25
Merge conflicts
Jasper123pyah May 9, 2023
836ef47
File restructure
NealGeilen May 16, 2023
44927c0
Revised coding structure. Assignments that are not yest graded are al…
NealGeilen May 18, 2023
6d89277
Added legend and changed "GradeStatus" structure
NealGeilen May 23, 2023
0dd2e3c
Added extra grade type
NealGeilen May 23, 2023
6b0e126
Added legend to json result
NealGeilen May 23, 2023
1dd5d3f
Working order
NealGeilen May 23, 2023
9c22569
startDate & endDate implementation for document generator
NealGeilen May 23, 2023
5a5e312
POC working
NealGeilen May 23, 2023
15b62e7
Merge remote-tracking branch 'origin/kpi-matrix' into kpi-matrix
NealGeilen May 23, 2023
103e902
changes
NealGeilen May 23, 2023
737e9c6
Lint fixes
NealGeilen May 25, 2023
9b9c1d6
Lint fixes
NealGeilen May 25, 2023
d98442a
Cleanup code and update coding guidelines
Typiqally May 26, 2023
b5d7192
Change outcome grade statuses
Typiqally May 26, 2023
6f9225a
Cleanup code
Typiqally May 26, 2023
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
2 changes: 1 addition & 1 deletion .editorconfig
Original file line number Diff line number Diff line change
Expand Up @@ -473,7 +473,7 @@ dotnet_diagnostic.ide0041.severity = error
dotnet_diagnostic.ide0042.severity = error
dotnet_diagnostic.ide0044.severity = error
dotnet_diagnostic.ide0045.severity = error
dotnet_diagnostic.ide0046.severity = error
dotnet_diagnostic.ide0046.severity = none
dotnet_diagnostic.ide0047.severity = error
dotnet_diagnostic.ide0048.severity = error
dotnet_diagnostic.ide0049.severity = error
Expand Down
4 changes: 2 additions & 2 deletions Epsilon.Abstractions/Component/CompetenceComponentFetcher.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ namespace Epsilon.Abstractions.Component;

public abstract class CompetenceComponentFetcher<TComponent> : ICompetenceComponentFetcher<TComponent> where TComponent : ICompetenceComponent
{
public async Task<ICompetenceComponent> FetchUnknown() => await Fetch();
public async Task<ICompetenceComponent> FetchUnknown(DateTime startDate, DateTime endDate) => await Fetch(startDate, endDate);

public abstract Task<TComponent> Fetch();
public abstract Task<TComponent> Fetch(DateTime startDate, DateTime endDate);
}
6 changes: 3 additions & 3 deletions Epsilon.Abstractions/Component/CompetenceProfile.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using DocumentFormat.OpenXml;
using DocumentFormat.OpenXml.Packaging;
using DocumentFormat.OpenXml.Wordprocessing;
using Epsilon.Abstractions.Model;
using Epsilon.Canvas.Abstractions.Model;
Expand All @@ -15,7 +15,7 @@ public record CompetenceProfile(
IEnumerable<DecayingAveragePerSkill> DecayingAveragesPerSkill
) : ICompetenceWordComponent
{
public OpenXmlElement ToWord()
public void AddToWordDocument(MainDocumentPart mainDocumentPart)
{
// TODO: This is simply an example to show the capability of the component architecture
var body = new Body();
Expand All @@ -31,6 +31,6 @@ public OpenXmlElement ToWord()
);
}

return body;
mainDocumentPart.Document.AppendChild(body);
}
}
4 changes: 2 additions & 2 deletions Epsilon.Abstractions/Component/ICompetenceComponentFetcher.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@

public interface ICompetenceComponentFetcher
{
public Task<ICompetenceComponent> FetchUnknown();
public Task<ICompetenceComponent> FetchUnknown(DateTime startDate, DateTime endDate);
}

public interface ICompetenceComponentFetcher<TComponent> : ICompetenceComponentFetcher
where TComponent : ICompetenceComponent
{
public Task<TComponent> Fetch();
public Task<TComponent> Fetch(DateTime startDate, DateTime endDate);
}
4 changes: 2 additions & 2 deletions Epsilon.Abstractions/Component/ICompetenceWordComponent.cs
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
using DocumentFormat.OpenXml;
using DocumentFormat.OpenXml.Packaging;

namespace Epsilon.Abstractions.Component;

public interface ICompetenceWordComponent : ICompetenceComponent
{
public OpenXmlElement ToWord();
public void AddToWordDocument(MainDocumentPart mainDocumentPart);
}
8 changes: 0 additions & 8 deletions Epsilon.Abstractions/Component/IWordDocumentBuilder.cs

This file was deleted.

6 changes: 6 additions & 0 deletions Epsilon.Abstractions/Component/KpiMatrixAssignment.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
namespace Epsilon.Abstractions.Component;
NealGeilen marked this conversation as resolved.
Show resolved Hide resolved

public record KpiMatrixAssignment(
string Name,
IEnumerable<KpiMatrixOutcome> Outcomes
);
196 changes: 196 additions & 0 deletions Epsilon.Abstractions/Component/KpiMatrixCollection.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,196 @@
using DocumentFormat.OpenXml;
NealGeilen marked this conversation as resolved.
Show resolved Hide resolved
using DocumentFormat.OpenXml.Packaging;
using DocumentFormat.OpenXml.Wordprocessing;

namespace Epsilon.Abstractions.Component;

[CompetenceComponentName("kpi_matrix")]
public record KpiMatrixCollection(
IEnumerable<KpiMatrixAssignment> KpiMatrixAssignments,
IDictionary<string, KpiMatrixOutcomeGradeStatus> GradeStatus
) : ICompetenceWordComponent
{
public static readonly IDictionary<string, KpiMatrixOutcomeGradeStatus> DefaultGradeStatus = new Dictionary<string, KpiMatrixOutcomeGradeStatus>
{
{
"Mastered", new KpiMatrixOutcomeGradeStatus("Mastered", "44F656")
},
{
"Insufficient", new KpiMatrixOutcomeGradeStatus("Insufficient", "FA1818")
},
{
"NotGradedAssessed", new KpiMatrixOutcomeGradeStatus("Not graded, Assignment assessed", "FAFF00")
},
{
"NotGradedNotAssessed", new KpiMatrixOutcomeGradeStatus("Not graded, Assignment not assessed", "9F2B68")
},
};

public void AddToWordDocument(MainDocumentPart mainDocumentPart)
{
var body = new Body();
// Create a table, with rows for the outcomes and columns for the assignments.
var table = new Table();

var assignments = KpiMatrixAssignments.OrderBy(static ass => ass.Name).ToList();

// Set table properties for formatting.
table.AppendChild(new TableProperties(
new TableWidth
{
Width = "0", Type = TableWidthUnitValues.Auto,
}));

// Calculate the header row height based on the longest assignment name.
var headerRowHeight = 0;
if (KpiMatrixAssignments.Any())
{
headerRowHeight = assignments.Max(static a => a.Name.Length) * 111;
}

// Create the table header row.
var headerRow = new TableRow();
headerRow.AppendChild(new TableRowProperties(new TableRowHeight
{
Val = (UInt32Value)(uint)headerRowHeight,
}));

// Empty top-left cell.
headerRow.AppendChild(CreateTableCellWithBorders("2500", new Paragraph(new Run(new Text("")))));

foreach (var assignment in assignments)
{
var cell = CreateTableCellWithBorders("100");
cell.FirstChild.Append(new TextDirection
{
Val = TextDirectionValues.TopToBottomLeftToRightRotated,
});

cell.Append(new Paragraph(new Run(new Text(assignment.Name))));
cell.FirstChild.Append(new Shading
{
Fill = assignments.IndexOf(assignment) % 2 == 0
? "FFFFFF"
: "d3d3d3",
});
headerRow.AppendChild(cell);
}

table.AppendChild(headerRow);

var listOfOutcomes = new Dictionary<int, KpiMatrixOutcome>();
foreach (var assignment in KpiMatrixAssignments)
{
foreach (var outcome in assignment.Outcomes)
{
listOfOutcomes.TryAdd(outcome.Id, outcome);
}
}

// Add the outcome rows.
foreach (var outcome in listOfOutcomes.OrderByDescending(static o => o.Value.Title))
{
var row = new TableRow();

// Add the outcome title cell.
row.AppendChild(CreateTableCellWithBorders("2500", new Paragraph(new Run(new Text(outcome.Value.Title)))));

// Add the assignment cells.
foreach (var assignment in assignments)
{
var outcomeAssignment = assignment.Outcomes.FirstOrDefault(o => o.Id == outcome.Key);
var cell = CreateTableCellWithBorders("100");

// Set cell color based on GradeStatus.
var fillColor = outcomeAssignment != null
? outcomeAssignment.KpiMatrixOutcomeGradeStatus.Color
//When no item is present give the cell alternating background color
: assignments.IndexOf(assignment) % 2 == 0
? "FFFFFF"
: "d3d3d3";

cell.FirstChild.Append(new Shading
{
Fill = fillColor,
});

// Add an empty text element since we're using color instead of text.
cell.Append(new Paragraph(new Run(new Text(""))));
row.AppendChild(cell);
}

table.AppendChild(row);
}

body.AppendChild(GetLegend());
body.Append(new Paragraph(new Run(new Text(""))));
body.AppendChild(table);

mainDocumentPart.Document.AppendChild(body);
}

private OpenXmlElement GetLegend()
{
var table = new Table();
foreach (var status in GradeStatus)
{
var row = new TableRow();
var cellName = CreateTableCellWithBorders("200");
cellName.Append(new Paragraph(new Run(new Text(status.Value.Status))));

var cellValue = CreateTableCellWithBorders("200");
cellValue.Append(new Paragraph(new Run(new Text(""))));
cellValue.FirstChild.Append(new Shading
{
Fill = status.Value.Color,
});
row.AppendChild(cellName);
row.AppendChild(cellValue);
table.AppendChild(row);
}

return table;
}


private static TableCell CreateTableCellWithBorders(string? width, params OpenXmlElement[] elements)
{
var cell = new TableCell();
var cellProperties = new TableCellProperties();
var borders = new TableCellBorders(
NealGeilen marked this conversation as resolved.
Show resolved Hide resolved
new LeftBorder
{
Val = BorderValues.Single,
},
new RightBorder
{
Val = BorderValues.Single,
},
new TopBorder
{
Val = BorderValues.Single,
},
new BottomBorder
{
Val = BorderValues.Single,
});

foreach (var element in elements)
{
cell.Append(element);
}

if (width != null)
{
cellProperties.Append(new TableCellWidth
{
Type = TableWidthUnitValues.Dxa, Width = width,
});
}

cellProperties.Append(borders);
cell.PrependChild(cellProperties);

return cell;
}
}
7 changes: 7 additions & 0 deletions Epsilon.Abstractions/Component/KpiMatrixOutcome.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@

namespace Epsilon.Abstractions.Component;
public record KpiMatrixOutcome(
int Id,
string Title,
KpiMatrixOutcomeGradeStatus KpiMatrixOutcomeGradeStatus
);
6 changes: 6 additions & 0 deletions Epsilon.Abstractions/Component/KpiMatrixOutcomeGradeStatus.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
namespace Epsilon.Abstractions.Component;

public record KpiMatrixOutcomeGradeStatus(
string Status,
string Color
);
25 changes: 25 additions & 0 deletions Epsilon.Abstractions/Component/PersonaPage.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
using System.Text;
using DocumentFormat.OpenXml.Packaging;
using DocumentFormat.OpenXml.Wordprocessing;

namespace Epsilon.Abstractions.Component;

[CompetenceComponentName("persona")]
public record PersonaPage(string PersonaHtml) : ICompetenceWordComponent
{
public void AddToWordDocument(MainDocumentPart mainDocumentPart)
{
var personaHtmlBuffer = Encoding.UTF8.GetPreamble().Concat(Encoding.UTF8.GetBytes($"<html>{PersonaHtml}</html>")).ToArray();
using var personaHtmlStream = new MemoryStream(personaHtmlBuffer);

var formatImportPart = mainDocumentPart.AddAlternativeFormatImportPart(AlternativeFormatImportPartType.Html);
formatImportPart.FeedData(personaHtmlStream);

mainDocumentPart.Document.AppendChild(new Body(
new AltChunk
{
Id = mainDocumentPart.GetIdOfPart(formatImportPart),
}
));
}
}
8 changes: 4 additions & 4 deletions Epsilon.Abstractions/Service/ICompetenceComponentService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,11 @@ namespace Epsilon.Abstractions.Service;

public interface ICompetenceComponentService
{
IAsyncEnumerable<ICompetenceComponent> GetComponents();
IAsyncEnumerable<ICompetenceComponent> GetComponents(DateTime startDate, DateTime endDate);

IAsyncEnumerable<TComponent> GetComponents<TComponent>() where TComponent : ICompetenceComponent;
IAsyncEnumerable<TComponent> GetComponents<TComponent>(DateTime startDate, DateTime endDate) where TComponent : ICompetenceComponent;

Task<ICompetenceComponent?> GetComponent(string name);
Task<ICompetenceComponent?> GetComponent(string name, DateTime startDate, DateTime endDate);

Task<TComponent?> GetComponent<TComponent>(string name) where TComponent : class, ICompetenceComponent;
Task<TComponent?> GetComponent<TComponent>(string name, DateTime startDate, DateTime endDate) where TComponent : class, ICompetenceComponent;
}
2 changes: 1 addition & 1 deletion Epsilon.Abstractions/Service/ICompetenceDocumentService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,5 @@ namespace Epsilon.Abstractions.Service;

public interface ICompetenceDocumentService
{
Task<Stream> WriteDocument(Stream stream);
Task<Stream> WriteDocument(Stream stream, DateTime startDate, DateTime endDate);
}
5 changes: 3 additions & 2 deletions Epsilon.Canvas.Abstractions/Model/GraphQl/AssessmentRating.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
namespace Epsilon.Canvas.Abstractions.Model.GraphQl;

public record AssessmentRating(
[property: JsonPropertyName("criterion")] Criterion Criterion,
[property: JsonPropertyName("points")] double? Points
[property: JsonPropertyName("criterion")] Criterion? Criterion,
[property: JsonPropertyName("points")] double? Points,
[property: JsonPropertyName("outcome")] Outcome? Outcome
);
3 changes: 2 additions & 1 deletion Epsilon.Canvas.Abstractions/Model/GraphQl/Assignment.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,6 @@ namespace Epsilon.Canvas.Abstractions.Model.GraphQl;

public record Assignment(
[property: JsonPropertyName("name")] string? Name,
[property: JsonPropertyName("modules")] IEnumerable<Module>? Modules
[property: JsonPropertyName("modules")] IEnumerable<Module>? Modules ,
[property: JsonPropertyName("rubric")] Rubric? Rubric
);
7 changes: 7 additions & 0 deletions Epsilon.Canvas.Abstractions/Model/GraphQl/Criteria.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
using System.Text.Json.Serialization;

namespace Epsilon.Canvas.Abstractions.Model.GraphQl;

public record Criteria(
[property: JsonPropertyName("outcome")] Outcome? Outcome
);
2 changes: 1 addition & 1 deletion Epsilon.Canvas.Abstractions/Model/GraphQl/Criterion.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,5 @@ namespace Epsilon.Canvas.Abstractions.Model.GraphQl;

public record Criterion(
[property: JsonPropertyName("masteryPoints")] double? MasteryPoints,
[property: JsonPropertyName("outcome")] Outcome Outcome
[property: JsonPropertyName("outcome")] Outcome? Outcome
);
Loading