diff --git a/KenticoInspector.Core/KenticoInspector.Core.csproj b/KenticoInspector.Core/KenticoInspector.Core.csproj
index 18a6dc4b..738c6f43 100644
--- a/KenticoInspector.Core/KenticoInspector.Core.csproj
+++ b/KenticoInspector.Core/KenticoInspector.Core.csproj
@@ -3,16 +3,17 @@
netcoreapp2.2
7.1
-
-
-
-
-
+
+
+
+
+
+
diff --git a/KenticoInspector.Infrastructure/KenticoInspector.Infrastructure.csproj b/KenticoInspector.Infrastructure/KenticoInspector.Infrastructure.csproj
index ff0bf8b8..4253e5dc 100644
--- a/KenticoInspector.Infrastructure/KenticoInspector.Infrastructure.csproj
+++ b/KenticoInspector.Infrastructure/KenticoInspector.Infrastructure.csproj
@@ -3,11 +3,11 @@
netcoreapp2.2
7.1
-
-
-
-
-
+
+
+
+
+
@@ -15,6 +15,7 @@
+
diff --git a/KenticoInspector.Reports.Tests/PageTypeAssignmentAnalysisTests.cs b/KenticoInspector.Reports.Tests/PageTypeAssignmentAnalysisTests.cs
new file mode 100644
index 00000000..eb05fb24
--- /dev/null
+++ b/KenticoInspector.Reports.Tests/PageTypeAssignmentAnalysisTests.cs
@@ -0,0 +1,98 @@
+using KenticoInspector.Core.Constants;
+using KenticoInspector.Reports.PageTypeAssignmentAnalysis;
+using KenticoInspector.Reports.PageTypeAssignmentAnalysis.Models;
+using NUnit.Framework;
+using System.Collections.Generic;
+
+namespace KenticoInspector.Reports.Tests
+{
+ [TestFixture(10)]
+ [TestFixture(11)]
+ [TestFixture(12)]
+ public class PageTypeAssignmentAnalysisTests : AbstractReportTest
+ {
+ private Report _mockReport;
+
+ public PageTypeAssignmentAnalysisTests(int majorVersion) : base(majorVersion)
+ {
+ _mockReport = new Report(_mockDatabaseService.Object, _mockReportMetadataService.Object);
+ }
+
+ [Test]
+ public void Should_ReturnListOfUnassignedPageTypes_When_SomeAreFound()
+ {
+ // Arrange
+ var unassignedPageTypes = GetListOfUnassignedPageTypes();
+ ArrangeDatabaseCalls(unassignedPageTypes);
+
+ // Act
+ var results = _mockReport.GetResults();
+
+ // Assert
+ Assert.That(results.Data.Rows.Count > 0, "Expected more than 0 page types to be returned");
+ Assert.That(results.Status == ReportResultsStatus.Warning,$"Expected Warning status, got {results.Status} status");
+ }
+
+ [Test]
+ public void Should_ReturnEmptyListOfIdenticalLayouts_When_NoneFound()
+ {
+ // Arrange
+ ArrangeDatabaseCalls();
+
+ // Act
+ var results = _mockReport.GetResults();
+ // Assert
+ Assert.That(results.Data.Rows.Count == 0, $"Expected 0 page types to be returned, got {results.Data.Rows.Count}");
+ Assert.That(results.Status == ReportResultsStatus.Good, $"Expected Good status, got {results.Status} status");
+ }
+
+ private void ArrangeDatabaseCalls(IEnumerable unassignedPageTypes = null) {
+ unassignedPageTypes = unassignedPageTypes ?? new List();
+ _mockDatabaseService
+ .Setup(p => p.ExecuteSqlFromFile(Scripts.GetPageTypesNotAssignedToSite))
+ .Returns(unassignedPageTypes);
+ }
+
+ private IEnumerable GetListOfUnassignedPageTypes()
+ {
+ return new List
+ {
+ new PageType
+ {
+ ClassName = "DancingGoatMvc.Article",
+ ClassDisplayName = "Article (MVC)",
+ NodeSiteID = 1,
+ NodeClassID = 5494
+ },
+ new PageType
+ {
+ ClassName = "DancingGoatMvc.Brewer",
+ ClassDisplayName = "Brewer (MVC)",
+ NodeSiteID = 1,
+ NodeClassID = 5477
+ },
+ new PageType
+ {
+ ClassName = "CMS.News",
+ ClassDisplayName = "News",
+ NodeSiteID = 2,
+ NodeClassID = 5502
+ },
+ new PageType
+ {
+ ClassName = "CMS.Office",
+ ClassDisplayName = "Office",
+ NodeSiteID = 2,
+ NodeClassID = 5514
+ },
+ new PageType
+ {
+ ClassName = "globaltypes.customtype",
+ ClassDisplayName = "Custom Type",
+ NodeSiteID = 2,
+ NodeClassID = 5497
+ },
+ };
+ }
+ }
+}
\ No newline at end of file
diff --git a/KenticoInspector.Reports/KenticoInspector.Reports.csproj b/KenticoInspector.Reports/KenticoInspector.Reports.csproj
index c175918e..0efbd8cd 100644
--- a/KenticoInspector.Reports/KenticoInspector.Reports.csproj
+++ b/KenticoInspector.Reports/KenticoInspector.Reports.csproj
@@ -3,11 +3,11 @@
netcoreapp2.2
7.1
-
-
-
-
-
+
+
+
+
+
@@ -121,6 +121,12 @@
Always
+
+ Always
+
+
+ Always
+
Always
diff --git a/KenticoInspector.Reports/PageTypeAssignmentAnalysis/Metadata/en-US.yaml b/KenticoInspector.Reports/PageTypeAssignmentAnalysis/Metadata/en-US.yaml
new file mode 100644
index 00000000..dad6a345
--- /dev/null
+++ b/KenticoInspector.Reports/PageTypeAssignmentAnalysis/Metadata/en-US.yaml
@@ -0,0 +1,9 @@
+details:
+ name: Page Type Assignment Analysis
+ shortDescription: Displays page types used by a certain site without being assigned to this site.
+ longDescription: |
+ If the page type is not assigned to the site and is used by this site, you will encounter problems while using import/export feature.
+terms:
+ warningSummary: page found that not assigned to the site used on.
+ unassignedPageTypesTableHeader: Page types not assigned to site
+ noIssuesFound: All page types are assigned to sites.
diff --git a/KenticoInspector.Reports/PageTypeAssignmentAnalysis/Models/PageType.cs b/KenticoInspector.Reports/PageTypeAssignmentAnalysis/Models/PageType.cs
new file mode 100644
index 00000000..a0fbda09
--- /dev/null
+++ b/KenticoInspector.Reports/PageTypeAssignmentAnalysis/Models/PageType.cs
@@ -0,0 +1,10 @@
+namespace KenticoInspector.Reports.PageTypeAssignmentAnalysis.Models
+{
+ public class PageType
+ {
+ public string ClassDisplayName { get; set; }
+ public string ClassName { get; set; }
+ public int NodeClassID { get; set; }
+ public int NodeSiteID { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/KenticoInspector.Reports/PageTypeAssignmentAnalysis/Models/Terms.cs b/KenticoInspector.Reports/PageTypeAssignmentAnalysis/Models/Terms.cs
new file mode 100644
index 00000000..afcf9c83
--- /dev/null
+++ b/KenticoInspector.Reports/PageTypeAssignmentAnalysis/Models/Terms.cs
@@ -0,0 +1,11 @@
+using KenticoInspector.Core.Models;
+
+namespace KenticoInspector.Reports.PageTypeAssignmentAnalysis.Models
+{
+ public class Terms
+ {
+ public Term WarningSummary { get; set; }
+ public Term UnassignedPageTypesTableHeader { get; set; }
+ public Term NoIssuesFound { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/KenticoInspector.Reports/PageTypeAssignmentAnalysis/Report.cs b/KenticoInspector.Reports/PageTypeAssignmentAnalysis/Report.cs
new file mode 100644
index 00000000..f2a85ce1
--- /dev/null
+++ b/KenticoInspector.Reports/PageTypeAssignmentAnalysis/Report.cs
@@ -0,0 +1,61 @@
+using KenticoInspector.Core;
+using KenticoInspector.Core.Constants;
+using KenticoInspector.Core.Helpers;
+using KenticoInspector.Core.Models;
+using KenticoInspector.Core.Services.Interfaces;
+using KenticoInspector.Reports.PageTypeAssignmentAnalysis.Models;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+
+namespace KenticoInspector.Reports.PageTypeAssignmentAnalysis
+{
+ public class Report : AbstractReport
+ {
+ private readonly IDatabaseService databaseService;
+
+ public Report(IDatabaseService databaseService, IReportMetadataService reportMetadataService) : base(reportMetadataService)
+ {
+ this.databaseService = databaseService;
+ }
+
+ public override IList CompatibleVersions => VersionHelper.GetVersionList("10", "11", "12");
+
+ public override IList Tags => new List
+ {
+ ReportTags.Health,
+ ReportTags.Consistency
+ };
+
+ public override ReportResults GetResults()
+ {
+ var unassignedPageTypes = databaseService.ExecuteSqlFromFile(Scripts.GetPageTypesNotAssignedToSite);
+
+ return CompileResults(unassignedPageTypes);
+ }
+
+ private ReportResults CompileResults(IEnumerable unassignedPageTypes)
+ {
+ var results = new ReportResults
+ {
+ Status = ReportResultsStatus.Good,
+ Summary = Metadata.Terms.NoIssuesFound,
+ Type = ReportResultsType.Table,
+ Data = new TableResult()
+ {
+ Name = Metadata.Terms.UnassignedPageTypesTableHeader,
+ Rows = unassignedPageTypes
+ }
+ };
+
+ var unassignedPageTypeCount = unassignedPageTypes.Count();
+ if (unassignedPageTypeCount > 0)
+ {
+ results.Status = ReportResultsStatus.Warning;
+ results.Summary = Metadata.Terms.WarningSummary.With(new { unassignedPageTypeCount });
+ }
+
+ return results;
+ }
+ }
+}
\ No newline at end of file
diff --git a/KenticoInspector.Reports/PageTypeAssignmentAnalysis/Scripts.cs b/KenticoInspector.Reports/PageTypeAssignmentAnalysis/Scripts.cs
new file mode 100644
index 00000000..28525aaf
--- /dev/null
+++ b/KenticoInspector.Reports/PageTypeAssignmentAnalysis/Scripts.cs
@@ -0,0 +1,9 @@
+namespace KenticoInspector.Reports.PageTypeAssignmentAnalysis
+{
+ public class Scripts
+ {
+ public static string BaseDirectory = $"{nameof(PageTypeAssignmentAnalysis)}/Scripts";
+
+ public static string GetPageTypesNotAssignedToSite = $"{BaseDirectory}/{nameof(GetPageTypesNotAssignedToSite)}.sql";
+ }
+}
\ No newline at end of file
diff --git a/KenticoInspector.Reports/PageTypeAssignmentAnalysis/Scripts/GetPageTypesNotAssignedToSite.sql b/KenticoInspector.Reports/PageTypeAssignmentAnalysis/Scripts/GetPageTypesNotAssignedToSite.sql
new file mode 100644
index 00000000..ee2c22ca
--- /dev/null
+++ b/KenticoInspector.Reports/PageTypeAssignmentAnalysis/Scripts/GetPageTypesNotAssignedToSite.sql
@@ -0,0 +1,6 @@
+SELECT DISTINCT NodeSiteID, NodeClassID, ClassName, ClassDisplayName
+ FROM View_CMS_Tree_Joined
+ LEFT JOIN CMS_ClassSite on
+ ClassID = NodeClassID AND
+ SiteID = NodeSiteID
+ WHERE SiteID is null
\ No newline at end of file
diff --git a/KenticoInspector.WebApplication/KenticoInspector.WebApplication.csproj b/KenticoInspector.WebApplication/KenticoInspector.WebApplication.csproj
index 3c1e0e8a..d4aa6887 100644
--- a/KenticoInspector.WebApplication/KenticoInspector.WebApplication.csproj
+++ b/KenticoInspector.WebApplication/KenticoInspector.WebApplication.csproj
@@ -5,11 +5,11 @@
InProcess
7.1
-
-
-
-
-
+
+
+
+
+
@@ -18,6 +18,7 @@
+
diff --git a/appveyor-before_package.ps1 b/appveyor-before_package.ps1
index 1e85f87d..490a4d95 100644
--- a/appveyor-before_package.ps1
+++ b/appveyor-before_package.ps1
@@ -6,8 +6,8 @@ dotnet publish KenticoInspector.WebApplication.csproj /p:PublishDir=..\publish -
# Copy compiled front-end to publish folder
Set-Location .\ClientApp
-mkdir "..\..\publish\dist"
-Copy-Item ".\dist\*" -Recurse -Destination "..\..\publish\dist\"
+mkdir "..\..\publish\ClientApp\dist"
+Copy-Item ".\dist\*" -Recurse -Destination "..\..\publish\ClientApp\dist\"
# Go back to root
Set-Location ..\..\