Skip to content

Commit eb9e542

Browse files
committed
Front-end rendering.
Reorganize actions per services.
1 parent 1eaf19c commit eb9e542

File tree

18 files changed

+421
-154
lines changed

18 files changed

+421
-154
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
@using System.Configuration
2+
@inherits Umbraco.Web.Mvc.UmbracoViewPage<List<Umbraco.Cms.Integrations.Commerce.Shopify.Models.ViewModels.ProductViewModel>>
3+
4+
<ul>
5+
@foreach (var item in Model)
6+
{
7+
<li>
8+
<img src="@item.Image" alt="@item.Title"/>
9+
<h1>@item.Title</h1>
10+
<p>
11+
@item.Body
12+
</p>
13+
</li>
14+
}
15+
</ul>
Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,22 @@
11

22
namespace Umbraco.Cms.Integrations.Commerce.Shopify
33
{
4-
public class Constants
4+
public static class Constants
55
{
6-
public static string UmbracoCmsIntegrationsCommerceShopifyApiVersion =
6+
public const string UmbracoCmsIntegrationsCommerceShopifyApiVersion =
77
"Umbraco.Cms.Integrations.Commerce.Shopify.ApiVersion";
88

9-
public static string UmbracoCmsIntegrationsCommerceShopifyShop =
9+
public const string UmbracoCmsIntegrationsCommerceShopifyShop =
1010
"Umbraco.Cms.Integrations.Commerce.Shopify.Shop";
1111

12-
public static string UmbracoCmsIntegrationsCommerceShopifyAccessToken =
12+
public const string UmbracoCmsIntegrationsCommerceShopifyAccessToken =
1313
"Umbraco.Cms.Integrations.Commerce.Shopify.AccessToken";
14+
15+
public const string AppPluginFolderPath = "~/App_Plugins/UmbracoCms.Integrations/Commerce/Shopify";
16+
17+
public static class PropertyEditors
18+
{
19+
public const string ProductPickerAlias = "Umbraco.Cms.Integrations.Commerce.Shopify.ProductPicker";
20+
}
1421
}
1522
}
Lines changed: 11 additions & 142 deletions
Original file line numberDiff line numberDiff line change
@@ -1,168 +1,37 @@
1-
using System;
2-
using System.Collections.Generic;
3-
using System.Net;
4-
using System.Net.Http;
5-
using System.Threading.Tasks;
1+
using System.Threading.Tasks;
62
using System.Web.Http;
7-
using Newtonsoft.Json;
8-
using Umbraco.Cms.Integrations.Commerce.Shopify.Models;
3+
94
using Umbraco.Cms.Integrations.Commerce.Shopify.Models.Dtos;
10-
using Umbraco.Cms.Integrations.Shared.Configuration;
11-
using Umbraco.Cms.Integrations.Shared.Controllers;
125
using Umbraco.Cms.Integrations.Shared.Models;
13-
using Umbraco.Core.Logging;
146
using Umbraco.Web.Mvc;
157
using Umbraco.Cms.Integrations.Shared.Models.Dtos;
16-
using Umbraco.Cms.Integrations.Shared.Resolvers;
178
using Umbraco.Cms.Integrations.Shared.Services;
9+
using Umbraco.Web.WebApi;
1810

1911
namespace Umbraco.Cms.Integrations.Commerce.Shopify.Controllers
2012
{
2113
[PluginController("UmbracoCmsIntegrationsCommerceShopify")]
22-
public class ProductsController : BaseAuthorizedApiController
14+
public class ProductsController : UmbracoAuthorizedApiController
2315
{
24-
private const string ProductsApiEndpoint = "https://{0}.myshopify.com/admin/api/{1}/products.json";
25-
26-
private const string OAuthClientId = "23c1bc3c70de807d84b79a29b12b49f5";
27-
28-
private const string ShopifyServiceName = "Shopify";
29-
private const string ShopifyServiceAddressReplace = "service_address_shop-replace";
30-
31-
private string ShopifyOAuthProxyUrl = $"{OAuthProxyBaseUrl}oauth/shopify";
32-
private const string ShopifyAuthorizationUrl =
33-
"https://{0}.myshopify.com/admin/oauth/authorize?client_id={1}&redirect_uri={2}&scope=read_products&grant_options[]=value";
16+
private readonly IApiService<ProductsListDto> _apiService;
3417

35-
private const string AccessTokenDbKey = "Umbraco.Cms.Integrations.Shopify.AccessTokenDbKey";
36-
37-
private readonly JsonSerializerSettings _serializerSettings;
38-
39-
public ProductsController(ILogger logger, IAppSettings appSettings, ITokenService tokenService) : base(logger, appSettings, tokenService)
18+
public ProductsController(IApiService<ProductsListDto> apiService)
4019
{
41-
var resolver = new JsonPropertyRenameContractResolver();
42-
resolver.RenameProperty(typeof(ResponseDto<ProductsListDto>), "Result", "products");
43-
44-
_serializerSettings = new JsonSerializerSettings();
45-
_serializerSettings.ContractResolver = resolver;
20+
_apiService = apiService;
4621
}
4722

4823
[HttpGet]
49-
public EditorSettings CheckConfiguration()
50-
{
51-
return GetConfiguration();
52-
}
24+
public EditorSettings CheckConfiguration() => _apiService.GetApiConfiguration();
5325

5426
[HttpGet]
55-
public string GetAuthorizationUrl()
56-
{
57-
return
58-
string.Format(ShopifyAuthorizationUrl,
59-
AppSettings[Constants.UmbracoCmsIntegrationsCommerceShopifyShop], OAuthClientId, ShopifyOAuthProxyUrl);
60-
}
27+
public string GetAuthorizationUrl() => _apiService.GetAuthorizationUrl();
6128

6229
[HttpPost]
63-
public async Task<string> GetAccessToken([FromBody] OAuthRequestDto authRequestDto)
64-
{
65-
var data = new Dictionary<string, string>
66-
{
67-
{ "client_id", OAuthClientId },
68-
{ "redirect_uri", string.Format(ShopifyOAuthProxyUrl, OAuthProxyBaseUrl) },
69-
{ "code", authRequestDto.Code }
70-
};
71-
72-
var requestMessage = new HttpRequestMessage
73-
{
74-
Method = HttpMethod.Post,
75-
RequestUri = new Uri(string.Format(OAuthProxyEndpoint, OAuthProxyBaseUrl)),
76-
Content = new FormUrlEncodedContent(data)
77-
};
78-
requestMessage.Headers.Add("service_name", ShopifyServiceName);
79-
requestMessage.Headers.Add(ShopifyServiceAddressReplace,
80-
AppSettings[Constants.UmbracoCmsIntegrationsCommerceShopifyShop]);
81-
82-
var response = await ClientFactory().SendAsync(requestMessage);
83-
if (response.IsSuccessStatusCode)
84-
{
85-
var result = await response.Content.ReadAsStringAsync();
86-
87-
var tokenDto = JsonConvert.DeserializeObject<TokenDto>(result);
88-
89-
TokenService.SaveParameters(AccessTokenDbKey, tokenDto.AccessToken);
30+
public async Task<string> GetAccessToken([FromBody] OAuthRequestDto authRequestDto) => await _apiService.GetAccessToken(authRequestDto);
9031

91-
return result;
92-
}
9332

94-
if (response.StatusCode == HttpStatusCode.BadRequest)
95-
{
96-
var errorResult = await response.Content.ReadAsStringAsync();
97-
var errorDto = JsonConvert.DeserializeObject<ErrorDto>(errorResult);
33+
public async Task<ResponseDto<ProductsListDto>> GetList() => await _apiService.GetResults();
9834

99-
return "Error: " + errorDto.Message;
100-
}
10135

102-
return "Error: An unexpected error occurred.";
103-
}
104-
105-
public async Task<ResponseDto<ProductsListDto>> GetList()
106-
{
107-
string accessToken;
108-
if(GetConfiguration().Type == ConfigurationType.OAuth)
109-
TokenService.TryGetParameters(AccessTokenDbKey, out accessToken);
110-
else
111-
{
112-
accessToken = AppSettings[Constants.UmbracoCmsIntegrationsCommerceShopifyAccessToken];
113-
}
114-
115-
if (string.IsNullOrEmpty(accessToken))
116-
{
117-
ApiLogger.Info<ProductsController>(message: "Cannot access Shopify - Access Token is missing.");
118-
119-
return new ResponseDto<ProductsListDto>();
120-
}
121-
122-
var requestMessage = new HttpRequestMessage
123-
{
124-
Method = HttpMethod.Get,
125-
RequestUri = new Uri(string.Format(ProductsApiEndpoint,
126-
AppSettings[Constants.UmbracoCmsIntegrationsCommerceShopifyShop],
127-
AppSettings[Constants.UmbracoCmsIntegrationsCommerceShopifyApiVersion]))
128-
};
129-
requestMessage.Headers.Add("X-Shopify-Access-Token", accessToken);
130-
131-
var response = await ClientFactory().SendAsync(requestMessage);
132-
if (response.StatusCode == HttpStatusCode.Unauthorized)
133-
{
134-
ApiLogger.Error<ProductsController>($"Failed to fetch products from Shopify store using access token: {response.ReasonPhrase}");
135-
136-
return new ResponseDto<ProductsListDto> { Message = response.ReasonPhrase };
137-
}
138-
139-
if (response.IsSuccessStatusCode)
140-
{
141-
var result = await response.Content.ReadAsStringAsync();
142-
return new ResponseDto<ProductsListDto>
143-
{
144-
IsValid = true,
145-
Result = JsonConvert.DeserializeObject<ProductsListDto>(result, _serializerSettings)
146-
};
147-
}
148-
149-
return new ResponseDto<ProductsListDto>();
150-
}
151-
152-
private EditorSettings GetConfiguration()
153-
{
154-
if (string.IsNullOrEmpty(AppSettings[Constants.UmbracoCmsIntegrationsCommerceShopifyShop])
155-
|| string.IsNullOrEmpty(AppSettings[Constants.UmbracoCmsIntegrationsCommerceShopifyApiVersion]))
156-
return new EditorSettings();
157-
158-
return
159-
!string.IsNullOrEmpty(AppSettings[Constants.UmbracoCmsIntegrationsCommerceShopifyAccessToken])
160-
? new EditorSettings { IsValid = true, Type = ConfigurationType.Api }
161-
: !string.IsNullOrEmpty(OAuthClientId)
162-
&& !string.IsNullOrEmpty(OAuthProxyBaseUrl)
163-
&& !string.IsNullOrEmpty(OAuthProxyEndpoint)
164-
? new EditorSettings { IsValid = true, Type = ConfigurationType.OAuth }
165-
: new EditorSettings();
166-
}
16736
}
16837
}

src/Umbraco.Cms.Integrations.Commerce.Shopify/ShopifyProductPickerConfiguration.cs renamed to src/Umbraco.Cms.Integrations.Commerce.Shopify/Editors/ShopifyProductPickerConfiguration.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
using Umbraco.Cms.Integrations.Commerce.Shopify.Models;
22
using Umbraco.Core.PropertyEditors;
33

4-
namespace Umbraco.Cms.Integrations.Commerce.Shopify
4+
namespace Umbraco.Cms.Integrations.Commerce.Shopify.Editors
55
{
66
public class ShopifyProductPickerConfiguration
77
{

src/Umbraco.Cms.Integrations.Commerce.Shopify/ShopifyProductPickerConfigurationEditor.cs renamed to src/Umbraco.Cms.Integrations.Commerce.Shopify/Editors/ShopifyProductPickerConfigurationEditor.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
using Umbraco.Core.PropertyEditors;
22

3-
namespace Umbraco.Cms.Integrations.Commerce.Shopify
3+
namespace Umbraco.Cms.Integrations.Commerce.Shopify.Editors
44
{
55
public class ShopifyProductPickerConfigurationEditor: ConfigurationEditor<ShopifyProductPickerConfiguration>
66
{

src/Umbraco.Cms.Integrations.Commerce.Shopify/ShopifyProductPickerPropertyEditor.cs renamed to src/Umbraco.Cms.Integrations.Commerce.Shopify/Editors/ShopifyProductPickerPropertyEditor.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
using Umbraco.Core.Logging;
22
using Umbraco.Core.PropertyEditors;
33

4-
namespace Umbraco.Cms.Integrations.Commerce.Shopify
4+
namespace Umbraco.Cms.Integrations.Commerce.Shopify.Editors
55
{
66
[DataEditor(
77
alias: "Umbraco.Cms.Integrations.Commerce.Shopify.ProductPicker",
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Linq;
4+
using System.Text;
5+
using System.Threading.Tasks;
6+
using System.Web.Mvc.Html;
7+
using Umbraco.Cms.Integrations.Commerce.Shopify.Models.Dtos;
8+
using Umbraco.Cms.Integrations.Commerce.Shopify.Models.ViewModels;
9+
using Umbraco.Cms.Integrations.Commerce.Shopify.Services;
10+
using Umbraco.Cms.Integrations.Shared.Models.Dtos;
11+
using Umbraco.Cms.Integrations.Shared.Services;
12+
using Umbraco.Core.Models.PublishedContent;
13+
using Umbraco.Core.PropertyEditors;
14+
15+
namespace Umbraco.Cms.Integrations.Commerce.Shopify.Editors
16+
{
17+
public class ShopifyProductPickerValueConverter : PropertyValueConverterBase
18+
{
19+
private readonly IApiService<ProductsListDto> _apiService;
20+
21+
public ShopifyProductPickerValueConverter(IApiService<ProductsListDto> apiService)
22+
{
23+
_apiService = apiService;
24+
}
25+
26+
public override bool IsConverter(IPublishedPropertyType propertyType) =>
27+
propertyType.EditorAlias == Constants.PropertyEditors.ProductPickerAlias;
28+
29+
public override Type GetPropertyValueType(IPublishedPropertyType propertyType) => typeof(List<ProductViewModel>);
30+
31+
public override PropertyCacheLevel GetPropertyCacheLevel(IPublishedPropertyType propertyType) =>
32+
PropertyCacheLevel.Snapshot;
33+
34+
public override object ConvertSourceToIntermediate(IPublishedElement owner, IPublishedPropertyType propertyType, object source,
35+
bool preview)
36+
{
37+
if (source == null) return null;
38+
39+
return source.ToString()
40+
.Split(new[] {','}, StringSplitOptions.RemoveEmptyEntries)
41+
.Select(long.Parse)
42+
.ToArray();
43+
}
44+
45+
public override object ConvertIntermediateToObject(IPublishedElement owner, IPublishedPropertyType propertyType,
46+
PropertyCacheLevel referenceCacheLevel, object inter, bool preview)
47+
{
48+
if (inter == null) return null;
49+
50+
var ids = (long[]) inter;
51+
52+
var t = Task.Run(async () => await _apiService.GetResults());
53+
var result = t.Result;
54+
55+
var products = from p in result.Result.Products
56+
where ids.Contains(p.Id)
57+
select new ProductViewModel
58+
{
59+
Title = p.Title,
60+
Body = p.Body,
61+
Image = p.Image.Src
62+
};
63+
64+
return products.ToList();
65+
}
66+
}
67+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
using System.Collections.Generic;
2+
using System.Web;
3+
using System.Web.Mvc;
4+
using System.Web.Mvc.Html;
5+
6+
using Umbraco.Cms.Integrations.Commerce.Shopify.Models.ViewModels;
7+
8+
namespace Umbraco.Cms.Integrations.Commerce.Shopify.Helpers
9+
{
10+
public static class ShopifyHtmlExtensions
11+
{
12+
public static IHtmlString RenderProductsList(this HtmlHelper htmlHelper, List<ProductViewModel> vm)
13+
{
14+
return htmlHelper.Partial($"{Constants.AppPluginFolderPath}/Render/Products.cshtml", vm);
15+
}
16+
}
17+
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+

2+
namespace Umbraco.Cms.Integrations.Commerce.Shopify.Models.ViewModels
3+
{
4+
public class ProductViewModel
5+
{
6+
public string Title { get; set; }
7+
8+
public string Body { get; set; }
9+
10+
public string Image { get; set; }
11+
}
12+
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+

2+
namespace Umbraco.Cms.Integrations.Commerce.Shopify.Services
3+
{
4+
public class SettingsService
5+
{
6+
public static string OAuthProxyBaseUrl = "https://localhost:44364/";
7+
8+
public static string OAuthProxyEndpoint = "{0}oauth/v1/token";
9+
10+
public static string ShopifyOAuthProxyUrl = $"{OAuthProxyBaseUrl}oauth/shopify";
11+
12+
public static string OAuthClientId = "23c1bc3c70de807d84b79a29b12b49f5";
13+
14+
public static string AccessTokenDbKey = "Umbraco.Cms.Integrations.Shopify.AccessTokenDbKey";
15+
16+
public static string ServiceName = "Shopify";
17+
18+
public static string ServiceAddressReplace = "service_address_shop-replace";
19+
20+
public static string AuthorizationUrl =
21+
"https://{0}.myshopify.com/admin/oauth/authorize?client_id={1}&redirect_uri={2}&scope=read_products&grant_options[]=value";
22+
23+
public static string ProductsApiEndpoint = "https://{0}.myshopify.com/admin/api/{1}/products.json";
24+
}
25+
}

0 commit comments

Comments
 (0)