Skip to content

Commit 8c3c2d7

Browse files
committed
Admin UI for looking up URL - Handle having different base URLs
1 parent eae2fc7 commit 8c3c2d7

File tree

16 files changed

+114
-53
lines changed

16 files changed

+114
-53
lines changed

.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -352,3 +352,4 @@ MigrationBackup/
352352
# Ionide (cross platform F# VS Code tools) working folder
353353
.ionide/
354354
/src/WeeklyXamarin.Mobile/WeeklyXamarin.Mobile/WeeklyXamarin.Mobile.csproj (Debug;AnyCPU {D36E000B-0F38-4958-847C-1AAC5E249DA0})..db
355+
/src/WeeklyXamarin.Mobile/WeeklyXamarin.Blazor/Server/Properties/ServiceDependencies/WeeklyXamarin - Web Deploy

src/WeeklyXamarin.Mobile/WeeklyXamarin.AdminServices/Services/CuratedService.cs

+17-6
Original file line numberDiff line numberDiff line change
@@ -4,29 +4,41 @@
44
using System.Net.Http.Json;
55
using System.Text;
66
using System.Threading.Tasks;
7+
using WeeklyXamarin.Core.Helpers;
78
using WeeklyXamarin.Core.Models;
89
using WeeklyXamarin.Core.Models.Api;
10+
using WeeklyXamarin.Core.Services;
911

1012
namespace WeeklyXamarin.AdminServices.Services
1113
{
1214
public class CuratedService : ICuratedService
1315
{
1416

1517
HttpClient httpClient;
16-
private const string baseUrl = "https://api.curated.co/api/v3";
18+
private IDataStore dataStore;
1719

1820
public string ApiKey { get; set; } = default!;
1921
public string Subscription { get; set; } = default!;
2022

21-
public CuratedService(HttpClient httpClient)
23+
public CuratedService(IHttpClientFactory httpClientFactory, IDataStore datastore)
2224
{
23-
this.httpClient = httpClient;
25+
this.httpClient = httpClientFactory.CreateClient(Constants.HttpClientKeys.Curated);
26+
this.dataStore = datastore;
2427
}
2528

2629
public async Task<string> PostArticleToCurated(Article article)
2730
{
28-
// doo all the call stuff
29-
var url = $"{baseUrl}/publications/{Subscription}/links";
31+
if (article == null)
32+
throw new ArgumentNullException(nameof(article));
33+
34+
// for curated we have a special format at the end of the article including the
35+
// article link title and author
36+
Author author = await dataStore.SearchAuthorsAsync(article.Author);
37+
var curatedByLine = $"[**{article?.Title}**]({article?.Url}) by [{author?.Name}]({author?.PreferredContact})";
38+
39+
article.Description = article?.Description + Environment.NewLine + Environment.NewLine + curatedByLine;
40+
41+
var url = $"publications/{Subscription}/links";
3042
var requestBody = article;
3143

3244
httpClient.DefaultRequestHeaders.Add("authorization", $"Token token=\"{ApiKey}\"");
@@ -35,7 +47,6 @@ public async Task<string> PostArticleToCurated(Article article)
3547
var result = await response.Content.ReadAsStringAsync();
3648
Console.WriteLine(result);
3749
return result;
38-
3950
}
4051
}
4152
}

src/WeeklyXamarin.Mobile/WeeklyXamarin.Blazor/Client/Pages/LookupUrl.razor

+5-1
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,13 @@
88
<MatTextField Label="Enter article URL" @bind-Value="@Url" Style="flex-grow: 1;" Class="wx-field"></MatTextField>
99

1010
<MatButton Disabled="@(string.IsNullOrWhiteSpace(Url) || !Uri.TryCreate(Url, UriKind.Absolute, out _))" OnClick="LoadArticle" Label="Process" Class="wx-field"></MatButton>
11+
<p/>
12+
<MatButton OnClick="NewArticle " Label="New Article" Class="wx-field"></MatButton>
13+
1114
@if(Article != null)
1215
{
1316
<MatTextField Label="Title" @bind-Value="@Article.Title" Style="flex-grow: 1;" Class="wx-field" ></MatTextField>
17+
<MatTextField Label="Url" @bind-Value="@Article.Url" Style="flex-grow: 1;" Class="wx-field" ></MatTextField>
1418
<MatTextField TextArea="true" Label="Description" @bind-Value="@Article.Description"
1519
FullWidth="true" Style="flex-grow: 1;" Class="wx-field"></MatTextField>
1620

@@ -33,7 +37,6 @@
3337
}
3438

3539
<pre>@Article.ToJson()</pre>
36-
<pre>@CuratedByLine</pre>
3740
}
3841
</div>
3942
</div>
@@ -46,6 +49,7 @@
4649
<MatTextField Label="Curated Publication ID" @bind-Value="@CuratedPublicationId" Style="flex-grow: 1;" Class="wx-field" Icon="lock_outline" IconTrailing="true" FullWidth="true" Required="true" Type="password"></MatTextField>
4750
*@
4851
<MatButton OnClick="PostToCurated" Label="Post To Curated" Class="wx-field"></MatButton>
52+
<pre>@CuratedStatusMessage</pre>
4953
</div>
5054
</div>
5155

src/WeeklyXamarin.Mobile/WeeklyXamarin.Blazor/Client/Pages/LookupUrl.razor.cs

+10-20
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,8 @@ public partial class LookupUrl : ComponentBase
1818
Article? Article { get; set; }
1919
List<string>? Categories { get; set; }
2020
List<string>? AuthorNames { get; set; }
21-
string? CuratedByLine { get; set; }
22-
string? CuratedKey { get; set; }
23-
string? CuratedPublicationId { get; set; }
21+
22+
string CuratedStatusMessage { get; set; }
2423

2524

2625
protected override async Task OnAfterRenderAsync(bool firstRender)
@@ -37,40 +36,31 @@ protected override async Task OnAfterRenderAsync(bool firstRender)
3736
public async Task LoadArticle()
3837
{
3938
Article = await ArticleRestService.GetArticleDetailsFromUrl(Url);
40-
if (Article.Author != null)
41-
await UpdateByLine(Article.Author);
39+
CuratedStatusMessage = "";
4240

4341
}
4442

45-
private async Task UpdateByLine(string authorName)
43+
public void NewArticle()
4644
{
47-
Author author = await DataStore.SearchAuthorsAsync(authorName);
48-
CuratedByLine = $"[**{Article?.Title}**]({Article?.Url}) by [{author.Name}]({author.PreferredContact})";
45+
Article = new Article();
46+
CuratedStatusMessage = "";
4947
}
5048

5149
public async Task AuthorSelected(string s)
5250
{
5351
if (Article != null)
5452
Article.Author = s;
55-
await UpdateByLine(s);
5653
}
5754

5855
public async Task PostToCurated()
5956
{
57+
CuratedStatusMessage = "Select an Article First";
6058
if (Article != null)
6159
{
62-
// create article suitable for curated
63-
Article articleToPost = new Article();
64-
articleToPost.Title = Article.Title;
65-
articleToPost.Url = Article.Url;
66-
67-
var curatedDescription = new StringBuilder();
68-
curatedDescription.AppendLine(Article.Description);
69-
curatedDescription.AppendLine();
70-
curatedDescription.AppendLine(CuratedByLine);
71-
articleToPost.Description = curatedDescription.ToString();
60+
CuratedStatusMessage = "Posting to Curated";
61+
var result = await CuratedRestService.PostArticleToCurated(Article);
62+
CuratedStatusMessage = result;
7263

73-
await CuratedRestService.PostArticleToCurated(articleToPost);
7464
}
7565

7666
}

src/WeeklyXamarin.Mobile/WeeklyXamarin.Blazor/Client/Program.cs

+15-2
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@
1515
using WeeklyXamarin.Core.Services;
1616
using WeeklyXamarin.Core.ViewModels;
1717
using Xamarin.Essentials.Interfaces;
18+
using Microsoft.Extensions.DependencyInjection;
19+
using WeeklyXamarin.Core.Helpers;
1820

1921
namespace WeeklyXamarin.Blazor.Client
2022
{
@@ -25,8 +27,19 @@ public static async Task Main(string[] args)
2527
var builder = WebAssemblyHostBuilder.CreateDefault(args);
2628
builder.RootComponents.Add<App>("#app");
2729
builder.Services.AddBlazoredLocalStorage();
28-
builder.Services.AddScoped(sp => new HttpClient { BaseAddress = new Uri(builder.HostEnvironment.BaseAddress) });
29-
builder.Services.AddSingleton<HttpClient>(_ => new HttpClient());
30+
31+
builder.Services.AddHttpClient(Constants.HttpClientKeys.GitHub, client =>
32+
{
33+
client.BaseAddress = new Uri(@"https://raw.githubusercontent.com/weeklyxamarin/WeeklyXamarin.content/master/content/");
34+
});
35+
36+
builder.Services.AddHttpClient(Constants.HttpClientKeys.WeeklyXamarin, client =>
37+
{
38+
client.BaseAddress = new Uri(builder.HostEnvironment.BaseAddress);
39+
});
40+
41+
//builder.Services.AddScoped(sp => new HttpClient { BaseAddress = new Uri(builder.HostEnvironment.BaseAddress) });
42+
//builder.Services.AddTransient<HttpClient>(_ => new HttpClient());
3043
builder.Services.AddScoped<IDataStore, GithubDataStore>();
3144
builder.Services.AddScoped<IArticleRestService, ArticleRestService> ();
3245
builder.Services.AddScoped<ICuratedRestService, CuratedRestService> ();

src/WeeklyXamarin.Mobile/WeeklyXamarin.Blazor/Client/WeeklyXamarin.Blazor.Client.csproj

+1
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
<PackageReference Include="MatBlazor" Version="2.8.0" />
1616
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly" Version="6.0.1" />
1717
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.DevServer" Version="6.0.1" PrivateAssets="all" />
18+
<PackageReference Include="Microsoft.Extensions.Http" Version="6.0.0" />
1819
<PackageReference Include="System.Net.Http.Json" Version="6.0.0" />
1920
</ItemGroup>
2021

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
{
2+
"version": 1,
3+
"isRoot": true,
4+
"tools": {
5+
"dotnet-ef": {
6+
"version": "6.0.2",
7+
"commands": [
8+
"dotnet-ef"
9+
]
10+
}
11+
}
12+
}

src/WeeklyXamarin.Mobile/WeeklyXamarin.Blazor/Server/Controllers/CuratedController.cs

+8-9
Original file line numberDiff line numberDiff line change
@@ -14,30 +14,29 @@ namespace WeeklyXamarin.Blazor.Server.Controllers
1414
public class CuratedController : ControllerBase
1515
{
1616

17-
private readonly ICuratedService urlService;
17+
private readonly ICuratedService curatedService;
1818
private readonly IConfiguration config;
1919

20-
public CuratedController(ICuratedService urlService, IConfiguration config)
20+
public CuratedController(ICuratedService curatedService, IConfiguration config)
2121
{
22-
this.urlService = urlService;
22+
this.curatedService = curatedService;
2323
this.config = config;
24-
2524
}
2625

27-
// POST api/<ArticleController>
2826
[HttpPost]
2927
public async Task<string> PostArticleToCurated([FromBody] Article article)
3028
{
3129
ArgumentNullException.ThrowIfNull(article);
3230

31+
// get keys from environment variables
3332
var apiKey = config["curatedApiKey"];
3433
var subscription = config["subscriptionId"];
3534

36-
urlService.ApiKey = apiKey;
37-
urlService.Subscription = subscription;
35+
curatedService.ApiKey = apiKey;
36+
curatedService.Subscription = subscription;
3837

39-
var a = await urlService.PostArticleToCurated(article);
40-
return a;
38+
var responseSTring = await curatedService.PostArticleToCurated(article);
39+
return responseSTring;
4140
}
4241
}
4342
}

src/WeeklyXamarin.Mobile/WeeklyXamarin.Blazor/Server/Startup.cs

+15-1
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,12 @@
88
using Microsoft.Extensions.Logging;
99
using MonkeyCache;
1010
using MonkeyCache.FileStore;
11+
using System;
1112
using System.Linq;
1213
using WeeklyXamarin.AdminServices.Services;
1314
using WeeklyXamarin.Blazor.Client.Services;
1415
using WeeklyXamarin.Blazor.Server.Services;
16+
using WeeklyXamarin.Core.Helpers;
1517
using WeeklyXamarin.Core.Services;
1618
using Xamarin.Essentials.Interfaces;
1719

@@ -40,7 +42,19 @@ public void ConfigureServices(IServiceCollection services)
4042
services.AddSingleton<IConnectivity, Connectivity>();
4143
services.AddSingleton<IAnalytics, WasmAnalytics>();
4244
services.AddLogging(x => x.AddConsole());
43-
services.AddHttpClient();
45+
//services.AddHttpClient();
46+
47+
services.AddHttpClient(Constants.HttpClientKeys.GitHub, client =>
48+
{
49+
client.BaseAddress = new Uri(@"https://raw.githubusercontent.com/weeklyxamarin/WeeklyXamarin.content/master/content/");
50+
});
51+
52+
services.AddHttpClient(Constants.HttpClientKeys.Curated, client =>
53+
{
54+
client.BaseAddress = new Uri(@"https://api.curated.co/api/v3/");
55+
});
56+
57+
4458
}
4559

4660
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.

src/WeeklyXamarin.Mobile/WeeklyXamarin.Core/Helpers/Constants.cs

+8
Original file line numberDiff line numberDiff line change
@@ -61,5 +61,13 @@ public static class ToolbarIcons
6161
public const string Bookmark = "Bookmark.png";
6262
public const string Unbookmark = "BookmarkIndicator.png";
6363
}
64+
65+
public static class HttpClientKeys
66+
{
67+
// don't do this at home kids
68+
public static string Curated = nameof(Curated);
69+
public static string WeeklyXamarin = nameof(WeeklyXamarin);
70+
public const string GitHub = nameof(GitHub);
71+
}
6472
}
6573
}

src/WeeklyXamarin.Mobile/WeeklyXamarin.Core/Models/Author.cs

+1
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ public class Author
2525
public List<Alias> Aliases { get; set; }
2626
public string Website { get; set; }
2727

28+
[JsonIgnore] // we don't want to persist this
2829
public string PreferredContact {
2930
get
3031
{

src/WeeklyXamarin.Mobile/WeeklyXamarin.Core/Services/ArticleRestService.cs

+6-3
Original file line numberDiff line numberDiff line change
@@ -7,18 +7,21 @@
77
using System.Threading.Tasks;
88
using WeeklyXamarin.Core.Models;
99
using WeeklyXamarin.Core.Models.Api;
10+
using Microsoft.Extensions.Http;
11+
using WeeklyXamarin.Core.Helpers;
1012

1113
namespace WeeklyXamarin.Core.Services
1214
{
1315

1416
public class ArticleRestService : IArticleRestService
1517
{
1618
private readonly HttpClient httpClient;
17-
private const string baseUrl = "https://localhost:5001/api";
19+
private const string baseUrl = "/api";
1820

19-
public ArticleRestService(HttpClient httpClient)
21+
22+
public ArticleRestService(IHttpClientFactory httpClientFactory)
2023
{
21-
this.httpClient = httpClient;
24+
httpClient = httpClientFactory.CreateClient(Constants.HttpClientKeys.WeeklyXamarin);
2225
}
2326

2427
public async Task<Article> GetArticleDetailsFromUrl(string articleUrl)

src/WeeklyXamarin.Mobile/WeeklyXamarin.Core/Services/CuratedRestService.cs

+7-4
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
using System.Net.Http.Json;
55
using System.Text;
66
using System.Threading.Tasks;
7+
using WeeklyXamarin.Core.Helpers;
78
using WeeklyXamarin.Core.Models;
89
using WeeklyXamarin.Core.Models.Api;
910

@@ -12,22 +13,24 @@ namespace WeeklyXamarin.Core.Services
1213
public class CuratedRestService : ICuratedRestService
1314
{
1415
private readonly HttpClient httpClient;
15-
private const string baseUrl = "https://localhost:5001/api";
16+
private const string baseUrl = "/api";
1617

1718
public string PublicationId { get; set; }
1819
public string ApiKey { get; set; }
1920

20-
public CuratedRestService(HttpClient httpClient)
21+
public CuratedRestService(IHttpClientFactory httpClientFactory)
2122
{
22-
this.httpClient = httpClient;
23+
httpClient = httpClientFactory.CreateClient(Constants.HttpClientKeys.WeeklyXamarin);
2324
}
2425

25-
public async Task PostArticleToCurated(Article article)
26+
public async Task<string> PostArticleToCurated(Article article)
2627
{
2728
var url = $"{baseUrl}/curated";
2829
var requestBody = article;
2930

3031
var response = await httpClient.PostAsJsonAsync<Article>(url, requestBody);
32+
var result = await response.Content.ReadAsStringAsync();
33+
return result;
3134
}
3235
}
3336
}

src/WeeklyXamarin.Mobile/WeeklyXamarin.Core/Services/GithubDataStore.cs

+5-5
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
using System.Runtime.CompilerServices;
2020
using System.Threading;
2121
using WeeklyXamarin.Core.Responses;
22+
using Microsoft.Extensions.Http;
2223

2324
namespace WeeklyXamarin.Core.Services
2425
{
@@ -29,22 +30,21 @@ public class GithubDataStore : IDataStore
2930
private readonly IBarrel _barrel;
3031
private readonly ILogger<GithubDataStore> _logger;
3132
private readonly IAnalytics _analytics;
33+
private IHttpClientFactory httpClientFactory;
3234

33-
const string baseUrl = @"https://raw.githubusercontent.com/weeklyxamarin/WeeklyXamarin.content/master/content/";
3435
const string indexFile = "index.json";
3536
const string tagsFile = "categories.json";
3637
const string authorsFile = "authors.json";
3738
const string acknowledgementsFile = "acknowledgements.json";
3839

39-
public GithubDataStore(HttpClient httpClient, IConnectivity connectivity, IBarrel barrel, ILogger<GithubDataStore> logger, IAnalytics analytics)
40+
public GithubDataStore(IHttpClientFactory httpClientFactory, IConnectivity connectivity, IBarrel barrel, ILogger<GithubDataStore> logger, IAnalytics analytics)
4041
{
41-
_httpClient = httpClient;
42+
_httpClient= httpClientFactory.CreateClient(Constants.HttpClientKeys.GitHub);
43+
4244
_connectivity = connectivity;
4345
_barrel = barrel;
4446
_logger = logger;
4547
_analytics = analytics;
46-
47-
httpClient.BaseAddress = new Uri(baseUrl);
4848
}
4949

5050
public void CheckEditionForSavedArticles(Edition edition)

0 commit comments

Comments
 (0)