Skip to content

Commit 9be5d4b

Browse files
authored
Merge pull request #40 from linkdotnet/feature/disqus
Feature/disqus
2 parents ba5b200 + c1ea60f commit 9be5d4b

14 files changed

+183
-19
lines changed

Readme.md

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,10 @@ The appsettings.json file has a lot of options to customize the content of the b
4949
"RepositoryId": "id",
5050
"Category": "general",
5151
"CategoryId": "id"
52-
}
52+
},
53+
"Disqus": {
54+
"Shortname": "blog"
55+
}
5356
}
5457

5558
```
@@ -76,6 +79,7 @@ The appsettings.json file has a lot of options to customize the content of the b
7679
| Heading | string | Displayed under the name. For example job title |
7780
| ProfilePictureUrl | string | Displayed profile picture |
7881
| Giscus | node | Enables the comment section. If left empty the comment secion will not be shown. For more information checkout the section about comments down below |
82+
| Disqus | node | Enables the comment section. If left empty the comment secion will not be shown. For more information checkout the section about comments down below |
7983

8084
## Storage Provider
8185
Currently there are 4 Storage-Provider:
@@ -85,7 +89,12 @@ Currently there are 4 Storage-Provider:
8589
* SqlServer - Based on EF Core, so it can be easily adapted for other Sql Dialects
8690

8791
## Comment Section
88-
For comments the blog is using [giscus](https://giscus.app/). To provide the necessary values head over to https://giscus.app/ and go to the configuration section.
92+
For comments the blog is using [giscus](https://giscus.app/) or [disqus](https://disqus.com/).
93+
94+
**Note**: Please only register one service / provide the configuration for one note. The given configuration shows both only for demonstrational purposes.
95+
96+
### Giscus
97+
To provide the necessary values head over to https://giscus.app/ and go to the configuration section.
8998
There you can enter all the information. You will find a detailed guide on the site.
9099

91100
In short:
@@ -116,6 +125,9 @@ Now you can copy/paste those information into the appsettings.json. With the giv
116125
}
117126
```
118127

128+
### Disqus
129+
For disqus you only need the shortname (site-name) which you can find for example under your [home-tab](https://disqus.com/home/).
130+
119131
## Authorization
120132
There is only one real mechanism enabled via Auth0. For more information go to: https://auth0.com/docs/applications
121133

@@ -148,4 +160,4 @@ Furthermore the following tags are set:
148160
| Tag | Index | Display Blog Post |
149161
| ---------------------------------------- | ------------------------------------ | ----------------------------- |
150162
| Title of the web page | Defined in AppConfiguration.BlogName | Title of the blogpost |
151-
| <meta name="keyword" content="" /> | not set | Tags defined in the Blog Post |
163+
| <meta name="keyword" content="" /> | not set | Tags defined in the Blog Post |

src/LinkDotNet.Blog.Web/AppConfiguration.cs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,4 +30,8 @@ public record AppConfiguration
3030
public GiscusConfiguration GiscusConfiguration { get; init; }
3131

3232
public bool IsGiscusEnabled => GiscusConfiguration != null;
33-
}
33+
34+
public DisqusConfiguration DisqusConfiguration { get; init; }
35+
36+
public bool IsDisqusEnabled => DisqusConfiguration != null;
37+
}

src/LinkDotNet.Blog.Web/AppConfigurationFactory.cs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
using LinkDotNet.Blog.Domain;
1+
using System;
2+
using LinkDotNet.Blog.Domain;
23
using LinkDotNet.Blog.Web.Shared.Services;
34
using Microsoft.Extensions.Configuration;
45

@@ -10,6 +11,7 @@ public static AppConfiguration Create(IConfiguration config)
1011
{
1112
var profileInformation = config.GetSection("AboutMeProfileInformation").Get<ProfileInformation>();
1213
var giscus = config.GetSection("Giscus").Get<GiscusConfiguration>();
14+
var disqus = config.GetSection("Disqus").Get<DisqusConfiguration>();
1315
var configuration = new AppConfiguration
1416
{
1517
BlogName = config["BlogName"],
@@ -21,8 +23,9 @@ public static AppConfiguration Create(IConfiguration config)
2123
BlogPostsPerPage = int.Parse(config["BlogPostsPerPage"]),
2224
ProfileInformation = profileInformation,
2325
GiscusConfiguration = giscus,
26+
DisqusConfiguration = disqus,
2427
};
2528

2629
return configuration;
2730
}
28-
}
31+
}

src/LinkDotNet.Blog.Web/LinkDotNet.Blog.Web.csproj

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -40,11 +40,18 @@
4040
<InternalsVisibleTo Include="LinkDotNet.Blog.IntegrationTests" />
4141
</ItemGroup>
4242

43+
<ItemGroup>
44+
<None Update="Shared\Disqus.razor.js">
45+
<DependentUpon>Disqus.razor</DependentUpon>
46+
</None>
47+
</ItemGroup>
48+
4349
<ItemGroup>
44-
<None Update="Shared\Giscus.razor.js">
45-
<DependentUpon>Giscus.razor</DependentUpon>
46-
</None>
50+
<None Update="Shared\Giscus.razor.js">
51+
<DependentUpon>Giscus.razor</DependentUpon>
52+
</None>
4753
</ItemGroup>
54+
4855
<PropertyGroup>
4956
<CodeAnalysisRuleSet>..\..\stylecop.analyzers.ruleset</CodeAnalysisRuleSet>
5057
</PropertyGroup>

src/LinkDotNet.Blog.Web/Pages/BlogPostPage.razor

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,8 +40,8 @@ else
4040
<div class="d-flex justify-content-between py-2">
4141
<Like BlogPost="@BlogPost" OnBlogPostLiked="@UpdateLikes"></Like>
4242
<ShareBlogPost></ShareBlogPost>
43-
</div>
44-
<Giscus></Giscus>
43+
</div>
44+
<CommentSection></CommentSection>
4545
</div>
4646
</div>
4747
}

src/LinkDotNet.Blog.Web/Shared/AccessControl.razor

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
<li><h6 class="dropdown-header">Others</h6></li>
1717
<li><a class="dropdown-item" href="Sitemap">Sitemap</a></li>
1818
<li><hr class="dropdown-divider"></li>
19-
<li><a class="dropdown-item" target="_blank" href="https://github.com/linkdotnet/Blog/releases">Version 2.9.1</a></li>
19+
<li><a class="dropdown-item" target="_blank" href="https://github.com/linkdotnet/Blog/releases">Version 2.10</a></li>
2020
</ul>
2121
</li>
2222
<li class="nav-item"><a class="nav-link" href="logout">Log out</a></li>
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
@inject AppConfiguration appConfiguration
2+
3+
@if (MultipleCommentPlugins)
4+
{
5+
<div class="alert alert-danger" role="alert">
6+
There are multiple comment sections configured. Please set up the configuration so that only one comment section is active.
7+
</div>
8+
}
9+
10+
@if (appConfiguration.IsDisqusEnabled)
11+
{
12+
<Disqus></Disqus>
13+
}
14+
@if (appConfiguration.IsGiscusEnabled)
15+
{
16+
<Giscus></Giscus>
17+
}
18+
19+
@code {
20+
private bool MultipleCommentPlugins => appConfiguration.IsDisqusEnabled && appConfiguration.IsGiscusEnabled;
21+
22+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
@inject IJSRuntime jsRuntime
2+
@inject AppConfiguration appConfiguration
3+
<div id="disqus_thread">
4+
</div>
5+
6+
@code {
7+
protected override async Task OnAfterRenderAsync(bool firstRender)
8+
{
9+
if (firstRender && appConfiguration.IsDisqusEnabled)
10+
{
11+
await jsRuntime.InvokeAsync<IJSObjectReference>("import", "./Shared/Disqus.razor.js");
12+
await jsRuntime.InvokeVoidAsync("initDisqus", appConfiguration.DisqusConfiguration);
13+
}
14+
}
15+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
window.initDisqus = (disqus) => {
2+
var d = document, s = d.createElement('script');
3+
4+
s.src = `https://${disqus.shortname}.disqus.com/embed.js`;
5+
6+
s.setAttribute('data-timestamp', +new Date());
7+
d.body.appendChild(s);
8+
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
namespace LinkDotNet.Blog.Web.Shared.Services;
2+
3+
public record DisqusConfiguration
4+
{
5+
public string Shortname { get; init; }
6+
}

src/LinkDotNet.Blog.Web/appsettings.json

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -29,10 +29,7 @@
2929
"Heading": "Software Engineer",
3030
"ProfilePictureUrl": "assets/profile-picture.webp"
3131
},
32-
"Giscus": {
33-
"Repository": "",
34-
"RepositoryId": "",
35-
"Category": "",
36-
"CategoryId": ""
32+
"Disqus": {
33+
"Shortname": ""
3734
}
3835
}

tests/LinkDotNet.Blog.UnitTests/Web/AppConfigurationFactoryTests.cs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ public void ShouldMapFromAppConfiguration()
2929
{ "Giscus:RepositoryId", "repoid" },
3030
{ "Giscus:Category", "general" },
3131
{ "Giscus:CategoryId", "generalid" },
32+
{ "Disqus:Shortname", "blog" },
3233
};
3334
var configuration = new ConfigurationBuilder()
3435
.AddInMemoryCollection(inMemorySettings)
@@ -55,6 +56,7 @@ public void ShouldMapFromAppConfiguration()
5556
appConfiguration.GiscusConfiguration.RepositoryId.Should().Be("repoid");
5657
appConfiguration.GiscusConfiguration.Category.Should().Be("general");
5758
appConfiguration.GiscusConfiguration.CategoryId.Should().Be("generalid");
59+
appConfiguration.DisqusConfiguration.Shortname.Should().Be("blog");
5860
}
5961

6062
[Theory]
@@ -106,7 +108,7 @@ public void ShouldSetIsAboutMeEnabledToFalseWhenNoInformation()
106108
}
107109

108110
[Fact]
109-
public void ShouldSetGiscusToFalseWhenNoInformation()
111+
public void ShouldSetCommentPluginsToFalseWhenNoInformation()
110112
{
111113
var inMemorySettings = new Dictionary<string, string>
112114
{
@@ -122,5 +124,6 @@ public void ShouldSetGiscusToFalseWhenNoInformation()
122124
var appConfiguration = AppConfigurationFactory.Create(configuration);
123125

124126
appConfiguration.IsGiscusEnabled.Should().BeFalse();
127+
appConfiguration.IsDisqusEnabled.Should().BeFalse();
125128
}
126-
}
129+
}
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
using Bunit;
2+
using FluentAssertions;
3+
using LinkDotNet.Blog.Web;
4+
using LinkDotNet.Blog.Web.Shared;
5+
using LinkDotNet.Blog.Web.Shared.Services;
6+
using Microsoft.Extensions.DependencyInjection;
7+
using Xunit;
8+
9+
namespace LinkDotNet.Blog.UnitTests.Web.Shared;
10+
11+
public class CommentSectionTests : TestContext
12+
{
13+
[Fact]
14+
public void ShouldShowDisqusWhenConfigured()
15+
{
16+
Services.AddScoped(_ => new AppConfiguration { DisqusConfiguration = new DisqusConfiguration() });
17+
JSInterop.Mode = JSRuntimeMode.Loose;
18+
19+
var cut = RenderComponent<CommentSection>();
20+
21+
cut.FindComponents<Disqus>().Should().NotBeEmpty();
22+
}
23+
24+
[Fact]
25+
public void ShouldShowGiscusWhenConfigured()
26+
{
27+
Services.AddScoped(_ => new AppConfiguration { GiscusConfiguration = new GiscusConfiguration() });
28+
JSInterop.Mode = JSRuntimeMode.Loose;
29+
30+
var cut = RenderComponent<CommentSection>();
31+
32+
cut.FindComponents<Giscus>().Should().NotBeEmpty();
33+
}
34+
35+
[Fact]
36+
public void ShouldShowAlertWhenMultipleRegistered()
37+
{
38+
Services.AddScoped(_ => new AppConfiguration
39+
{ DisqusConfiguration = new DisqusConfiguration(), GiscusConfiguration = new GiscusConfiguration() });
40+
JSInterop.Mode = JSRuntimeMode.Loose;
41+
42+
var cut = RenderComponent<CommentSection>();
43+
44+
cut.FindAll(".alert-danger").Should().NotBeEmpty();
45+
}
46+
}
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
using System.Linq;
2+
using Bunit;
3+
using FluentAssertions;
4+
using LinkDotNet.Blog.Web;
5+
using LinkDotNet.Blog.Web.Shared;
6+
using LinkDotNet.Blog.Web.Shared.Services;
7+
using Microsoft.Extensions.DependencyInjection;
8+
using Xunit;
9+
10+
namespace LinkDotNet.Blog.UnitTests.Web.Shared;
11+
12+
public class DisqusTests : TestContext
13+
{
14+
[Fact]
15+
public void ShouldLoadJavascript()
16+
{
17+
var disqusData = new DisqusConfiguration()
18+
{
19+
Shortname = "blog",
20+
};
21+
Services.AddScoped(_ => new AppConfiguration { DisqusConfiguration = disqusData });
22+
JSInterop.SetupModule("./Shared/Disqus.razor.js");
23+
JSInterop.Mode = JSRuntimeMode.Loose;
24+
25+
RenderComponent<Disqus>();
26+
27+
var init = JSInterop.Invocations.SingleOrDefault(i => i.Identifier == "initDisqus");
28+
init.Should().NotBeNull();
29+
init.Arguments.Should().Contain(disqusData);
30+
}
31+
32+
[Fact]
33+
public void ShouldNotInitDisqusWhenNoInformationProvided()
34+
{
35+
Services.AddScoped(_ => new AppConfiguration());
36+
37+
RenderComponent<Disqus>();
38+
39+
JSInterop.Invocations.Should().BeEmpty();
40+
}
41+
}

0 commit comments

Comments
 (0)