From d9d6fbf403edef16ce0da39c4a5d560f8c74f891 Mon Sep 17 00:00:00 2001 From: Sebastian Stehle Date: Sat, 13 Apr 2019 16:26:42 +0200 Subject: [PATCH 1/7] Updated to Squidex 2.0. --- .../Management/Generated.cs | 896 ++++++++++++++---- .../Squidex.ClientLibrary.csproj | 2 +- .../SquidexClientExtensions.cs | 11 +- 3 files changed, 734 insertions(+), 175 deletions(-) diff --git a/csharp/Squidex.ClientLibrary/Squidex.ClientLibrary/Management/Generated.cs b/csharp/Squidex.ClientLibrary/Squidex.ClientLibrary/Management/Generated.cs index fbed5bb5..6abac1a7 100644 --- a/csharp/Squidex.ClientLibrary/Squidex.ClientLibrary/Management/Generated.cs +++ b/csharp/Squidex.ClientLibrary/Squidex.ClientLibrary/Management/Generated.cs @@ -415,6 +415,190 @@ private string ConvertToString(object value, System.Globalization.CultureInfo cu } } + [System.CodeDom.Compiler.GeneratedCode("NSwag", "12.0.6.0 (NJsonSchema v9.13.2.0 (Newtonsoft.Json v9.0.0.0))")] + public partial interface ITranslationsClient + { + /// Translate a text. + /// The name of the app. + /// The translation request. + /// Text translated. + /// A server side error occurred. + System.Threading.Tasks.Task GetLanguagesAsync(string app, TranslateDto request); + + /// Translate a text. + /// The name of the app. + /// The translation request. + /// Text translated. + /// A server side error occurred. + /// A cancellation token that can be used by other objects or threads to receive notice of cancellation. + System.Threading.Tasks.Task GetLanguagesAsync(string app, TranslateDto request, System.Threading.CancellationToken cancellationToken); + + } + + [System.CodeDom.Compiler.GeneratedCode("NSwag", "12.0.6.0 (NJsonSchema v9.13.2.0 (Newtonsoft.Json v9.0.0.0))")] + public partial class TranslationsClient : ITranslationsClient + { + private System.Net.Http.HttpClient _httpClient; + private System.Lazy _settings; + + public TranslationsClient(System.Net.Http.HttpClient httpClient) + { + _httpClient = httpClient; + _settings = new System.Lazy(() => + { + var settings = new Newtonsoft.Json.JsonSerializerSettings(); + UpdateJsonSerializerSettings(settings); + return settings; + }); + } + + protected Newtonsoft.Json.JsonSerializerSettings JsonSerializerSettings { get { return _settings.Value; } } + + partial void UpdateJsonSerializerSettings(Newtonsoft.Json.JsonSerializerSettings settings); + partial void PrepareRequest(System.Net.Http.HttpClient client, System.Net.Http.HttpRequestMessage request, string url); + partial void PrepareRequest(System.Net.Http.HttpClient client, System.Net.Http.HttpRequestMessage request, System.Text.StringBuilder urlBuilder); + partial void ProcessResponse(System.Net.Http.HttpClient client, System.Net.Http.HttpResponseMessage response); + + /// Translate a text. + /// The name of the app. + /// The translation request. + /// Text translated. + /// A server side error occurred. + public System.Threading.Tasks.Task GetLanguagesAsync(string app, TranslateDto request) + { + return GetLanguagesAsync(app, request, System.Threading.CancellationToken.None); + } + + /// Translate a text. + /// The name of the app. + /// The translation request. + /// Text translated. + /// A server side error occurred. + /// A cancellation token that can be used by other objects or threads to receive notice of cancellation. + public async System.Threading.Tasks.Task GetLanguagesAsync(string app, TranslateDto request, System.Threading.CancellationToken cancellationToken) + { + if (app == null) + throw new System.ArgumentNullException("app"); + + var urlBuilder_ = new System.Text.StringBuilder(); + urlBuilder_.Append("apps/{app}/translations"); + urlBuilder_.Replace("{app}", System.Uri.EscapeDataString(ConvertToString(app, System.Globalization.CultureInfo.InvariantCulture))); + + var client_ = _httpClient; + try + { + using (var request_ = new System.Net.Http.HttpRequestMessage()) + { + var content_ = new System.Net.Http.StringContent(Newtonsoft.Json.JsonConvert.SerializeObject(request, _settings.Value)); + content_.Headers.ContentType = System.Net.Http.Headers.MediaTypeHeaderValue.Parse("application/json"); + request_.Content = content_; + request_.Method = new System.Net.Http.HttpMethod("POST"); + request_.Headers.Accept.Add(System.Net.Http.Headers.MediaTypeWithQualityHeaderValue.Parse("application/json")); + + PrepareRequest(client_, request_, urlBuilder_); + var url_ = urlBuilder_.ToString(); + request_.RequestUri = new System.Uri(url_, System.UriKind.RelativeOrAbsolute); + PrepareRequest(client_, request_, url_); + + var response_ = await client_.SendAsync(request_, System.Net.Http.HttpCompletionOption.ResponseHeadersRead, cancellationToken).ConfigureAwait(false); + try + { + var headers_ = System.Linq.Enumerable.ToDictionary(response_.Headers, h_ => h_.Key, h_ => h_.Value); + if (response_.Content != null && response_.Content.Headers != null) + { + foreach (var item_ in response_.Content.Headers) + headers_[item_.Key] = item_.Value; + } + + ProcessResponse(client_, response_); + + var status_ = ((int)response_.StatusCode).ToString(); + if (status_ == "200") + { + var responseData_ = response_.Content == null ? null : await response_.Content.ReadAsStringAsync().ConfigureAwait(false); + var result_ = default(TranslationDto); + try + { + result_ = Newtonsoft.Json.JsonConvert.DeserializeObject(responseData_, _settings.Value); + return result_; + } + catch (System.Exception exception_) + { + throw new SquidexManagementException("Could not deserialize the response body.", (int)response_.StatusCode, responseData_, headers_, exception_); + } + } + else + if (status_ == "500") + { + var responseData_ = response_.Content == null ? null : await response_.Content.ReadAsStringAsync().ConfigureAwait(false); + var result_ = default(ErrorDto); + try + { + result_ = Newtonsoft.Json.JsonConvert.DeserializeObject(responseData_, _settings.Value); + } + catch (System.Exception exception_) + { + throw new SquidexManagementException("Could not deserialize the response body.", (int)response_.StatusCode, responseData_, headers_, exception_); + } + throw new SquidexManagementException("Operation failed", (int)response_.StatusCode, responseData_, headers_, result_, null); + } + else + if (status_ != "200" && status_ != "204") + { + var responseData_ = response_.Content == null ? null : await response_.Content.ReadAsStringAsync().ConfigureAwait(false); + throw new SquidexManagementException("The HTTP status code of the response was not expected (" + (int)response_.StatusCode + ").", (int)response_.StatusCode, responseData_, headers_, null); + } + + return default(TranslationDto); + } + finally + { + if (response_ != null) + response_.Dispose(); + } + } + } + finally + { + } + } + + private string ConvertToString(object value, System.Globalization.CultureInfo cultureInfo) + { + if (value is System.Enum) + { + string name = System.Enum.GetName(value.GetType(), value); + if (name != null) + { + var field = System.Reflection.IntrospectionExtensions.GetTypeInfo(value.GetType()).GetDeclaredField(name); + if (field != null) + { + var attribute = System.Reflection.CustomAttributeExtensions.GetCustomAttribute(field, typeof(System.Runtime.Serialization.EnumMemberAttribute)) + as System.Runtime.Serialization.EnumMemberAttribute; + if (attribute != null) + { + return attribute.Value; + } + } + } + } + else if (value is bool) { + return System.Convert.ToString(value, cultureInfo).ToLowerInvariant(); + } + else if (value is byte[]) + { + return System.Convert.ToBase64String((byte[]) value); + } + else if (value != null && value.GetType().IsArray) + { + var array = System.Linq.Enumerable.OfType((System.Array) value); + return string.Join(",", System.Linq.Enumerable.Select(array, o => ConvertToString(o, cultureInfo))); + } + + return System.Convert.ToString(value, cultureInfo); + } + } + [System.CodeDom.Compiler.GeneratedCode("NSwag", "12.0.6.0 (NJsonSchema v9.13.2.0 (Newtonsoft.Json v9.0.0.0))")] public partial interface IStatisticsClient { @@ -1446,13 +1630,13 @@ public partial interface ISchemasClient System.Threading.Tasks.Task DisableNestedFieldAsync(string app, string name, long parentId, long id, System.Threading.CancellationToken cancellationToken); /// Get schemas. - /// The name of the app to get the schemas for. + /// The name of the app. /// Schemas returned. /// A server side error occurred. System.Threading.Tasks.Task> GetSchemasAsync(string app); /// Get schemas. - /// The name of the app to get the schemas for. + /// The name of the app. /// Schemas returned. /// A server side error occurred. /// A cancellation token that can be used by other objects or threads to receive notice of cancellation. @@ -3895,7 +4079,7 @@ public async System.Threading.Tasks.Task DisableNestedFieldAsync(string app, str } /// Get schemas. - /// The name of the app to get the schemas for. + /// The name of the app. /// Schemas returned. /// A server side error occurred. public System.Threading.Tasks.Task> GetSchemasAsync(string app) @@ -3904,7 +4088,7 @@ public async System.Threading.Tasks.Task DisableNestedFieldAsync(string app, str } /// Get schemas. - /// The name of the app to get the schemas for. + /// The name of the app. /// Schemas returned. /// A server side error occurred. /// A cancellation token that can be used by other objects or threads to receive notice of cancellation. @@ -5153,17 +5337,6 @@ public partial interface IRulesClient /// A cancellation token that can be used by other objects or threads to receive notice of cancellation. System.Threading.Tasks.Task> GetActionsAsync(System.Threading.CancellationToken cancellationToken); - /// Get the supported rule triggers. - /// Rule triggers returned. - /// A server side error occurred. - System.Threading.Tasks.Task> GetTriggersAsync(); - - /// Get the supported rule triggers. - /// Rule triggers returned. - /// A server side error occurred. - /// A cancellation token that can be used by other objects or threads to receive notice of cancellation. - System.Threading.Tasks.Task> GetTriggersAsync(System.Threading.CancellationToken cancellationToken); - /// Get rules. /// The name of the app. /// Rules returned. @@ -5420,99 +5593,6 @@ public RulesClient(System.Net.Http.HttpClient httpClient) } } - /// Get the supported rule triggers. - /// Rule triggers returned. - /// A server side error occurred. - public System.Threading.Tasks.Task> GetTriggersAsync() - { - return GetTriggersAsync(System.Threading.CancellationToken.None); - } - - /// Get the supported rule triggers. - /// Rule triggers returned. - /// A server side error occurred. - /// A cancellation token that can be used by other objects or threads to receive notice of cancellation. - public async System.Threading.Tasks.Task> GetTriggersAsync(System.Threading.CancellationToken cancellationToken) - { - var urlBuilder_ = new System.Text.StringBuilder(); - urlBuilder_.Append("rules/triggers"); - - var client_ = _httpClient; - try - { - using (var request_ = new System.Net.Http.HttpRequestMessage()) - { - request_.Method = new System.Net.Http.HttpMethod("GET"); - request_.Headers.Accept.Add(System.Net.Http.Headers.MediaTypeWithQualityHeaderValue.Parse("application/json")); - - PrepareRequest(client_, request_, urlBuilder_); - var url_ = urlBuilder_.ToString(); - request_.RequestUri = new System.Uri(url_, System.UriKind.RelativeOrAbsolute); - PrepareRequest(client_, request_, url_); - - var response_ = await client_.SendAsync(request_, System.Net.Http.HttpCompletionOption.ResponseHeadersRead, cancellationToken).ConfigureAwait(false); - try - { - var headers_ = System.Linq.Enumerable.ToDictionary(response_.Headers, h_ => h_.Key, h_ => h_.Value); - if (response_.Content != null && response_.Content.Headers != null) - { - foreach (var item_ in response_.Content.Headers) - headers_[item_.Key] = item_.Value; - } - - ProcessResponse(client_, response_); - - var status_ = ((int)response_.StatusCode).ToString(); - if (status_ == "200") - { - var responseData_ = response_.Content == null ? null : await response_.Content.ReadAsStringAsync().ConfigureAwait(false); - var result_ = default(System.Collections.Generic.IDictionary); - try - { - result_ = Newtonsoft.Json.JsonConvert.DeserializeObject>(responseData_, _settings.Value); - return result_; - } - catch (System.Exception exception_) - { - throw new SquidexManagementException("Could not deserialize the response body.", (int)response_.StatusCode, responseData_, headers_, exception_); - } - } - else - if (status_ == "500") - { - var responseData_ = response_.Content == null ? null : await response_.Content.ReadAsStringAsync().ConfigureAwait(false); - var result_ = default(ErrorDto); - try - { - result_ = Newtonsoft.Json.JsonConvert.DeserializeObject(responseData_, _settings.Value); - } - catch (System.Exception exception_) - { - throw new SquidexManagementException("Could not deserialize the response body.", (int)response_.StatusCode, responseData_, headers_, exception_); - } - throw new SquidexManagementException("Operation failed", (int)response_.StatusCode, responseData_, headers_, result_, null); - } - else - if (status_ != "200" && status_ != "204") - { - var responseData_ = response_.Content == null ? null : await response_.Content.ReadAsStringAsync().ConfigureAwait(false); - throw new SquidexManagementException("The HTTP status code of the response was not expected (" + (int)response_.StatusCode + ").", (int)response_.StatusCode, responseData_, headers_, null); - } - - return default(System.Collections.Generic.IDictionary); - } - finally - { - if (response_ != null) - response_.Dispose(); - } - } - } - finally - { - } - } - /// Get rules. /// The name of the app. /// Rules returned. @@ -6983,33 +7063,198 @@ public async System.Threading.Tasks.Task GetPingAsync(System.Threading.Cancellat } } } - finally + finally + { + } + } + + /// Get ping status. + /// The name of the app. + /// Service ping successful. + /// A server side error occurred. + public System.Threading.Tasks.Task GetAppPingAsync(string app) + { + return GetAppPingAsync(app, System.Threading.CancellationToken.None); + } + + /// Get ping status. + /// The name of the app. + /// Service ping successful. + /// A server side error occurred. + /// A cancellation token that can be used by other objects or threads to receive notice of cancellation. + public async System.Threading.Tasks.Task GetAppPingAsync(string app, System.Threading.CancellationToken cancellationToken) + { + if (app == null) + throw new System.ArgumentNullException("app"); + + var urlBuilder_ = new System.Text.StringBuilder(); + urlBuilder_.Append("ping/{app}"); + urlBuilder_.Replace("{app}", System.Uri.EscapeDataString(ConvertToString(app, System.Globalization.CultureInfo.InvariantCulture))); + + var client_ = _httpClient; + try + { + using (var request_ = new System.Net.Http.HttpRequestMessage()) + { + request_.Method = new System.Net.Http.HttpMethod("GET"); + + PrepareRequest(client_, request_, urlBuilder_); + var url_ = urlBuilder_.ToString(); + request_.RequestUri = new System.Uri(url_, System.UriKind.RelativeOrAbsolute); + PrepareRequest(client_, request_, url_); + + var response_ = await client_.SendAsync(request_, System.Net.Http.HttpCompletionOption.ResponseHeadersRead, cancellationToken).ConfigureAwait(false); + try + { + var headers_ = System.Linq.Enumerable.ToDictionary(response_.Headers, h_ => h_.Key, h_ => h_.Value); + if (response_.Content != null && response_.Content.Headers != null) + { + foreach (var item_ in response_.Content.Headers) + headers_[item_.Key] = item_.Value; + } + + ProcessResponse(client_, response_); + + var status_ = ((int)response_.StatusCode).ToString(); + if (status_ == "204") + { + return; + } + else + if (status_ == "500") + { + var responseData_ = response_.Content == null ? null : await response_.Content.ReadAsStringAsync().ConfigureAwait(false); + var result_ = default(ErrorDto); + try + { + result_ = Newtonsoft.Json.JsonConvert.DeserializeObject(responseData_, _settings.Value); + } + catch (System.Exception exception_) + { + throw new SquidexManagementException("Could not deserialize the response body.", (int)response_.StatusCode, responseData_, headers_, exception_); + } + throw new SquidexManagementException("Operation failed", (int)response_.StatusCode, responseData_, headers_, result_, null); + } + else + if (status_ != "200" && status_ != "204") + { + var responseData_ = response_.Content == null ? null : await response_.Content.ReadAsStringAsync().ConfigureAwait(false); + throw new SquidexManagementException("The HTTP status code of the response was not expected (" + (int)response_.StatusCode + ").", (int)response_.StatusCode, responseData_, headers_, null); + } + } + finally + { + if (response_ != null) + response_.Dispose(); + } + } + } + finally + { + } + } + + private string ConvertToString(object value, System.Globalization.CultureInfo cultureInfo) + { + if (value is System.Enum) + { + string name = System.Enum.GetName(value.GetType(), value); + if (name != null) + { + var field = System.Reflection.IntrospectionExtensions.GetTypeInfo(value.GetType()).GetDeclaredField(name); + if (field != null) + { + var attribute = System.Reflection.CustomAttributeExtensions.GetCustomAttribute(field, typeof(System.Runtime.Serialization.EnumMemberAttribute)) + as System.Runtime.Serialization.EnumMemberAttribute; + if (attribute != null) + { + return attribute.Value; + } + } + } + } + else if (value is bool) { + return System.Convert.ToString(value, cultureInfo).ToLowerInvariant(); + } + else if (value is byte[]) + { + return System.Convert.ToBase64String((byte[]) value); + } + else if (value != null && value.GetType().IsArray) { + var array = System.Linq.Enumerable.OfType((System.Array) value); + return string.Join(",", System.Linq.Enumerable.Select(array, o => ConvertToString(o, cultureInfo))); } + + return System.Convert.ToString(value, cultureInfo); } + } - /// Get ping status. - /// The name of the app. - /// Service ping successful. + [System.CodeDom.Compiler.GeneratedCode("NSwag", "12.0.6.0 (NJsonSchema v9.13.2.0 (Newtonsoft.Json v9.0.0.0))")] + public partial interface INewsClient + { + /// Get features since version. + /// The latest received version. + /// Latest features returned. /// A server side error occurred. - public System.Threading.Tasks.Task GetAppPingAsync(string app) + System.Threading.Tasks.Task GetLanguagesAsync(int? version); + + /// Get features since version. + /// The latest received version. + /// Latest features returned. + /// A server side error occurred. + /// A cancellation token that can be used by other objects or threads to receive notice of cancellation. + System.Threading.Tasks.Task GetLanguagesAsync(int? version, System.Threading.CancellationToken cancellationToken); + + } + + [System.CodeDom.Compiler.GeneratedCode("NSwag", "12.0.6.0 (NJsonSchema v9.13.2.0 (Newtonsoft.Json v9.0.0.0))")] + public partial class NewsClient : INewsClient + { + private System.Net.Http.HttpClient _httpClient; + private System.Lazy _settings; + + public NewsClient(System.Net.Http.HttpClient httpClient) { - return GetAppPingAsync(app, System.Threading.CancellationToken.None); + _httpClient = httpClient; + _settings = new System.Lazy(() => + { + var settings = new Newtonsoft.Json.JsonSerializerSettings(); + UpdateJsonSerializerSettings(settings); + return settings; + }); } - /// Get ping status. - /// The name of the app. - /// Service ping successful. + protected Newtonsoft.Json.JsonSerializerSettings JsonSerializerSettings { get { return _settings.Value; } } + + partial void UpdateJsonSerializerSettings(Newtonsoft.Json.JsonSerializerSettings settings); + partial void PrepareRequest(System.Net.Http.HttpClient client, System.Net.Http.HttpRequestMessage request, string url); + partial void PrepareRequest(System.Net.Http.HttpClient client, System.Net.Http.HttpRequestMessage request, System.Text.StringBuilder urlBuilder); + partial void ProcessResponse(System.Net.Http.HttpClient client, System.Net.Http.HttpResponseMessage response); + + /// Get features since version. + /// The latest received version. + /// Latest features returned. /// A server side error occurred. - /// A cancellation token that can be used by other objects or threads to receive notice of cancellation. - public async System.Threading.Tasks.Task GetAppPingAsync(string app, System.Threading.CancellationToken cancellationToken) + public System.Threading.Tasks.Task GetLanguagesAsync(int? version) { - if (app == null) - throw new System.ArgumentNullException("app"); + return GetLanguagesAsync(version, System.Threading.CancellationToken.None); + } + /// Get features since version. + /// The latest received version. + /// Latest features returned. + /// A server side error occurred. + /// A cancellation token that can be used by other objects or threads to receive notice of cancellation. + public async System.Threading.Tasks.Task GetLanguagesAsync(int? version, System.Threading.CancellationToken cancellationToken) + { var urlBuilder_ = new System.Text.StringBuilder(); - urlBuilder_.Append("ping/{app}"); - urlBuilder_.Replace("{app}", System.Uri.EscapeDataString(ConvertToString(app, System.Globalization.CultureInfo.InvariantCulture))); + urlBuilder_.Append("news/features?"); + if (version != null) + { + urlBuilder_.Append("version=").Append(System.Uri.EscapeDataString(ConvertToString(version, System.Globalization.CultureInfo.InvariantCulture))).Append("&"); + } + urlBuilder_.Length--; var client_ = _httpClient; try @@ -7017,6 +7262,7 @@ public async System.Threading.Tasks.Task GetAppPingAsync(string app, System.Thre using (var request_ = new System.Net.Http.HttpRequestMessage()) { request_.Method = new System.Net.Http.HttpMethod("GET"); + request_.Headers.Accept.Add(System.Net.Http.Headers.MediaTypeWithQualityHeaderValue.Parse("application/json")); PrepareRequest(client_, request_, urlBuilder_); var url_ = urlBuilder_.ToString(); @@ -7036,9 +7282,19 @@ public async System.Threading.Tasks.Task GetAppPingAsync(string app, System.Thre ProcessResponse(client_, response_); var status_ = ((int)response_.StatusCode).ToString(); - if (status_ == "204") + if (status_ == "200") { - return; + var responseData_ = response_.Content == null ? null : await response_.Content.ReadAsStringAsync().ConfigureAwait(false); + var result_ = default(FeaturesDto); + try + { + result_ = Newtonsoft.Json.JsonConvert.DeserializeObject(responseData_, _settings.Value); + return result_; + } + catch (System.Exception exception_) + { + throw new SquidexManagementException("Could not deserialize the response body.", (int)response_.StatusCode, responseData_, headers_, exception_); + } } else if (status_ == "500") @@ -7061,6 +7317,8 @@ public async System.Threading.Tasks.Task GetAppPingAsync(string app, System.Thre var responseData_ = response_.Content == null ? null : await response_.Content.ReadAsStringAsync().ConfigureAwait(false); throw new SquidexManagementException("The HTTP status code of the response was not expected (" + (int)response_.StatusCode + ").", (int)response_.StatusCode, responseData_, headers_, null); } + + return default(FeaturesDto); } finally { @@ -8811,24 +9069,28 @@ public partial interface IAssetsClient { /// Get the asset content. /// The id of the asset. + /// Optional suffix that can be used to seo-optimize the link to the image Has not effect. /// The optional version of the asset. /// The target width of the asset, if it is an image. /// The target height of the asset, if it is an image. + /// Optional image quality, it is is an jpeg image. /// The resize mode when the width and height is defined. /// Asset found and content or (resized) image returned. /// A server side error occurred. - System.Threading.Tasks.Task GetAssetContentAsync(string id, long? version, int? width, int? height, string mode); + System.Threading.Tasks.Task GetAssetContentAsync(string id, string more, long? version, int? width, int? height, int? quality, string mode); /// Get the asset content. /// The id of the asset. + /// Optional suffix that can be used to seo-optimize the link to the image Has not effect. /// The optional version of the asset. /// The target width of the asset, if it is an image. /// The target height of the asset, if it is an image. + /// Optional image quality, it is is an jpeg image. /// The resize mode when the width and height is defined. /// Asset found and content or (resized) image returned. /// A server side error occurred. /// A cancellation token that can be used by other objects or threads to receive notice of cancellation. - System.Threading.Tasks.Task GetAssetContentAsync(string id, long? version, int? width, int? height, string mode, System.Threading.CancellationToken cancellationToken); + System.Threading.Tasks.Task GetAssetContentAsync(string id, string more, long? version, int? width, int? height, int? quality, string mode, System.Threading.CancellationToken cancellationToken); /// Get assets tags. /// The name of the app. @@ -8908,7 +9170,7 @@ public partial interface IAssetsClient /// The asset object that needs to updated. /// Asset updated. /// A server side error occurred. - System.Threading.Tasks.Task PutAssetAsync(string app, string id, UpdateAssetDto request); + System.Threading.Tasks.Task PutAssetAsync(string app, string id, AnnotateAssetDto request); /// Updates the asset. /// The name of the app. @@ -8917,7 +9179,7 @@ public partial interface IAssetsClient /// Asset updated. /// A server side error occurred. /// A cancellation token that can be used by other objects or threads to receive notice of cancellation. - System.Threading.Tasks.Task PutAssetAsync(string app, string id, UpdateAssetDto request, System.Threading.CancellationToken cancellationToken); + System.Threading.Tasks.Task PutAssetAsync(string app, string id, AnnotateAssetDto request, System.Threading.CancellationToken cancellationToken); /// Delete an asset. /// The name of the app. @@ -8977,34 +9239,42 @@ public AssetsClient(System.Net.Http.HttpClient httpClient) /// Get the asset content. /// The id of the asset. + /// Optional suffix that can be used to seo-optimize the link to the image Has not effect. /// The optional version of the asset. /// The target width of the asset, if it is an image. /// The target height of the asset, if it is an image. + /// Optional image quality, it is is an jpeg image. /// The resize mode when the width and height is defined. /// Asset found and content or (resized) image returned. /// A server side error occurred. - public System.Threading.Tasks.Task GetAssetContentAsync(string id, long? version, int? width, int? height, string mode) + public System.Threading.Tasks.Task GetAssetContentAsync(string id, string more, long? version, int? width, int? height, int? quality, string mode) { - return GetAssetContentAsync(id, version, width, height, mode, System.Threading.CancellationToken.None); + return GetAssetContentAsync(id, more, version, width, height, quality, mode, System.Threading.CancellationToken.None); } /// Get the asset content. /// The id of the asset. + /// Optional suffix that can be used to seo-optimize the link to the image Has not effect. /// The optional version of the asset. /// The target width of the asset, if it is an image. /// The target height of the asset, if it is an image. + /// Optional image quality, it is is an jpeg image. /// The resize mode when the width and height is defined. /// Asset found and content or (resized) image returned. /// A server side error occurred. /// A cancellation token that can be used by other objects or threads to receive notice of cancellation. - public async System.Threading.Tasks.Task GetAssetContentAsync(string id, long? version, int? width, int? height, string mode, System.Threading.CancellationToken cancellationToken) + public async System.Threading.Tasks.Task GetAssetContentAsync(string id, string more, long? version, int? width, int? height, int? quality, string mode, System.Threading.CancellationToken cancellationToken) { if (id == null) throw new System.ArgumentNullException("id"); + if (more == null) + throw new System.ArgumentNullException("more"); + var urlBuilder_ = new System.Text.StringBuilder(); - urlBuilder_.Append("assets/{id}?"); + urlBuilder_.Append("assets/{id}/{more}?"); urlBuilder_.Replace("{id}", System.Uri.EscapeDataString(ConvertToString(id, System.Globalization.CultureInfo.InvariantCulture))); + urlBuilder_.Replace("{more}", System.Uri.EscapeDataString(ConvertToString(more, System.Globalization.CultureInfo.InvariantCulture))); if (version != null) { urlBuilder_.Append("version=").Append(System.Uri.EscapeDataString(ConvertToString(version, System.Globalization.CultureInfo.InvariantCulture))).Append("&"); @@ -9017,6 +9287,10 @@ public async System.Threading.Tasks.Task GetAssetContentAsync(stri { urlBuilder_.Append("height=").Append(System.Uri.EscapeDataString(ConvertToString(height, System.Globalization.CultureInfo.InvariantCulture))).Append("&"); } + if (quality != null) + { + urlBuilder_.Append("quality=").Append(System.Uri.EscapeDataString(ConvertToString(quality, System.Globalization.CultureInfo.InvariantCulture))).Append("&"); + } if (mode != null) { urlBuilder_.Append("mode=").Append(System.Uri.EscapeDataString(ConvertToString(mode, System.Globalization.CultureInfo.InvariantCulture))).Append("&"); @@ -9602,7 +9876,7 @@ public async System.Threading.Tasks.Task GetAssetAsync(string app, st /// The asset object that needs to updated. /// Asset updated. /// A server side error occurred. - public System.Threading.Tasks.Task PutAssetAsync(string app, string id, UpdateAssetDto request) + public System.Threading.Tasks.Task PutAssetAsync(string app, string id, AnnotateAssetDto request) { return PutAssetAsync(app, id, request, System.Threading.CancellationToken.None); } @@ -9614,7 +9888,7 @@ public System.Threading.Tasks.Task PutAssetAsync(string app, string id, UpdateAs /// Asset updated. /// A server side error occurred. /// A cancellation token that can be used by other objects or threads to receive notice of cancellation. - public async System.Threading.Tasks.Task PutAssetAsync(string app, string id, UpdateAssetDto request, System.Threading.CancellationToken cancellationToken) + public async System.Threading.Tasks.Task PutAssetAsync(string app, string id, AnnotateAssetDto request, System.Threading.CancellationToken cancellationToken) { if (app == null) throw new System.ArgumentNullException("app"); @@ -12931,9 +13205,9 @@ public partial class UISettingsDto [System.ComponentModel.DataAnnotations.Required] public string MapKey { get; set; } - /// Indicates whether twitter actions are supported. - [Newtonsoft.Json.JsonProperty("supportsTwitterActions", Required = Newtonsoft.Json.Required.DisallowNull, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] - public bool SupportsTwitterActions { get; set; } + /// True when the user can create apps. + [Newtonsoft.Json.JsonProperty("canCreateApps", Required = Newtonsoft.Json.Required.DisallowNull, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public bool CanCreateApps { get; set; } public string ToJson() { @@ -12969,6 +13243,10 @@ public static UpdateSettingDto FromJson(string data) [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "9.13.2.0 (Newtonsoft.Json v9.0.0.0)")] public abstract partial class IJsonValue { + [Newtonsoft.Json.JsonProperty("type", Required = Newtonsoft.Json.Required.DisallowNull, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + [Newtonsoft.Json.JsonConverter(typeof(Newtonsoft.Json.Converters.StringEnumConverter))] + public JsonValueType Type { get; set; } + public string ToJson() { return Newtonsoft.Json.JsonConvert.SerializeObject(this); @@ -12982,26 +13260,25 @@ public static IJsonValue FromJson(string data) } [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "9.13.2.0 (Newtonsoft.Json v9.0.0.0)")] - public partial class TokenRequest + public enum JsonValueType { - [Newtonsoft.Json.JsonProperty("pinCode", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] - public string PinCode { get; set; } + [System.Runtime.Serialization.EnumMember(Value = "Array")] + Array = 0, - [Newtonsoft.Json.JsonProperty("requestToken", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] - public string RequestToken { get; set; } + [System.Runtime.Serialization.EnumMember(Value = "Boolean")] + Boolean = 1, - [Newtonsoft.Json.JsonProperty("requestTokenSecret", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] - public string RequestTokenSecret { get; set; } + [System.Runtime.Serialization.EnumMember(Value = "Null")] + Null = 2, - public string ToJson() - { - return Newtonsoft.Json.JsonConvert.SerializeObject(this); - } - - public static TokenRequest FromJson(string data) - { - return Newtonsoft.Json.JsonConvert.DeserializeObject(data); - } + [System.Runtime.Serialization.EnumMember(Value = "Number")] + Number = 3, + + [System.Runtime.Serialization.EnumMember(Value = "Object")] + Object = 4, + + [System.Runtime.Serialization.EnumMember(Value = "String")] + String = 5, } @@ -13163,6 +13440,79 @@ public static ErrorDto FromJson(string data) } + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "9.13.2.0 (Newtonsoft.Json v9.0.0.0)")] + public partial class TranslationDto + { + /// The result of the translation. + [Newtonsoft.Json.JsonProperty("result", Required = Newtonsoft.Json.Required.DisallowNull, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + [Newtonsoft.Json.JsonConverter(typeof(Newtonsoft.Json.Converters.StringEnumConverter))] + public TranslationResult Result { get; set; } + + /// The translated text. + [Newtonsoft.Json.JsonProperty("text", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public string Text { get; set; } + + public string ToJson() + { + return Newtonsoft.Json.JsonConvert.SerializeObject(this); + } + + public static TranslationDto FromJson(string data) + { + return Newtonsoft.Json.JsonConvert.DeserializeObject(data); + } + + } + + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "9.13.2.0 (Newtonsoft.Json v9.0.0.0)")] + public enum TranslationResult + { + [System.Runtime.Serialization.EnumMember(Value = "Translated")] + Translated = 0, + + [System.Runtime.Serialization.EnumMember(Value = "LanguageNotSupported")] + LanguageNotSupported = 1, + + [System.Runtime.Serialization.EnumMember(Value = "NotTranslated")] + NotTranslated = 2, + + [System.Runtime.Serialization.EnumMember(Value = "NotImplemented")] + NotImplemented = 3, + + [System.Runtime.Serialization.EnumMember(Value = "Failed")] + Failed = 4, + + } + + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "9.13.2.0 (Newtonsoft.Json v9.0.0.0)")] + public partial class TranslateDto + { + /// The text to translate. + [Newtonsoft.Json.JsonProperty("text", Required = Newtonsoft.Json.Required.Always)] + [System.ComponentModel.DataAnnotations.Required] + public string Text { get; set; } + + /// The target language. + [Newtonsoft.Json.JsonProperty("targetLanguage", Required = Newtonsoft.Json.Required.Always)] + [System.ComponentModel.DataAnnotations.Required(AllowEmptyStrings = true)] + public string TargetLanguage { get; set; } + + /// The optional source language. + [Newtonsoft.Json.JsonProperty("sourceLanguage", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public string SourceLanguage { get; set; } + + public string ToJson() + { + return Newtonsoft.Json.JsonConvert.SerializeObject(this); + } + + public static TranslateDto FromJson(string data) + { + return Newtonsoft.Json.JsonConvert.DeserializeObject(data); + } + + } + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "9.13.2.0 (Newtonsoft.Json v9.0.0.0)")] public partial class LogDownloadDto { @@ -13492,6 +13842,7 @@ public partial class BooleanFieldPropertiesDto : FieldPropertiesDto /// The editor that is used to manage this field. [Newtonsoft.Json.JsonProperty("editor", Required = Newtonsoft.Json.Required.DisallowNull, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + [Newtonsoft.Json.JsonConverter(typeof(Newtonsoft.Json.Converters.StringEnumConverter))] public BooleanFieldEditor Editor { get; set; } public string ToJson() @@ -13509,8 +13860,10 @@ public static BooleanFieldPropertiesDto FromJson(string data) [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "9.13.2.0 (Newtonsoft.Json v9.0.0.0)")] public enum BooleanFieldEditor { + [System.Runtime.Serialization.EnumMember(Value = "Checkbox")] Checkbox = 0, + [System.Runtime.Serialization.EnumMember(Value = "Toggle")] Toggle = 1, } @@ -13532,10 +13885,12 @@ public partial class DateTimeFieldPropertiesDto : FieldPropertiesDto /// The editor that is used to manage this field. [Newtonsoft.Json.JsonProperty("editor", Required = Newtonsoft.Json.Required.DisallowNull, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + [Newtonsoft.Json.JsonConverter(typeof(Newtonsoft.Json.Converters.StringEnumConverter))] public DateTimeFieldEditor Editor { get; set; } /// The calculated default value for the field value. [Newtonsoft.Json.JsonProperty("calculatedDefaultValue", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + [Newtonsoft.Json.JsonConverter(typeof(Newtonsoft.Json.Converters.StringEnumConverter))] public DateTimeCalculatedDefaultValue? CalculatedDefaultValue { get; set; } public string ToJson() @@ -13553,8 +13908,10 @@ public static DateTimeFieldPropertiesDto FromJson(string data) [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "9.13.2.0 (Newtonsoft.Json v9.0.0.0)")] public enum DateTimeFieldEditor { + [System.Runtime.Serialization.EnumMember(Value = "Date")] Date = 0, + [System.Runtime.Serialization.EnumMember(Value = "DateTime")] DateTime = 1, } @@ -13562,8 +13919,10 @@ public enum DateTimeFieldEditor [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "9.13.2.0 (Newtonsoft.Json v9.0.0.0)")] public enum DateTimeCalculatedDefaultValue { + [System.Runtime.Serialization.EnumMember(Value = "Now")] Now = 0, + [System.Runtime.Serialization.EnumMember(Value = "Today")] Today = 1, } @@ -13577,6 +13936,7 @@ public partial class GeolocationFieldPropertiesDto : FieldPropertiesDto /// The editor that is used to manage this field. [Newtonsoft.Json.JsonProperty("editor", Required = Newtonsoft.Json.Required.DisallowNull, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + [Newtonsoft.Json.JsonConverter(typeof(Newtonsoft.Json.Converters.StringEnumConverter))] public GeolocationFieldEditor Editor { get; set; } public string ToJson() @@ -13594,6 +13954,7 @@ public static GeolocationFieldPropertiesDto FromJson(string data) [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "9.13.2.0 (Newtonsoft.Json v9.0.0.0)")] public enum GeolocationFieldEditor { + [System.Runtime.Serialization.EnumMember(Value = "Map")] Map = 0, } @@ -13642,6 +14003,7 @@ public partial class NumberFieldPropertiesDto : FieldPropertiesDto /// The editor that is used to manage this field. [Newtonsoft.Json.JsonProperty("editor", Required = Newtonsoft.Json.Required.DisallowNull, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + [Newtonsoft.Json.JsonConverter(typeof(Newtonsoft.Json.Converters.StringEnumConverter))] public NumberFieldEditor Editor { get; set; } public string ToJson() @@ -13659,12 +14021,16 @@ public static NumberFieldPropertiesDto FromJson(string data) [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "9.13.2.0 (Newtonsoft.Json v9.0.0.0)")] public enum NumberFieldEditor { + [System.Runtime.Serialization.EnumMember(Value = "Input")] Input = 0, + [System.Runtime.Serialization.EnumMember(Value = "Radio")] Radio = 1, + [System.Runtime.Serialization.EnumMember(Value = "Dropdown")] Dropdown = 2, + [System.Runtime.Serialization.EnumMember(Value = "Stars")] Stars = 3, } @@ -13733,6 +14099,7 @@ public partial class StringFieldPropertiesDto : FieldPropertiesDto /// The editor that is used to manage this field. [Newtonsoft.Json.JsonProperty("editor", Required = Newtonsoft.Json.Required.DisallowNull, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + [Newtonsoft.Json.JsonConverter(typeof(Newtonsoft.Json.Converters.StringEnumConverter))] public StringFieldEditor Editor { get; set; } public string ToJson() @@ -13750,22 +14117,31 @@ public static StringFieldPropertiesDto FromJson(string data) [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "9.13.2.0 (Newtonsoft.Json v9.0.0.0)")] public enum StringFieldEditor { + [System.Runtime.Serialization.EnumMember(Value = "Input")] Input = 0, + [System.Runtime.Serialization.EnumMember(Value = "Color")] Color = 1, + [System.Runtime.Serialization.EnumMember(Value = "Markdown")] Markdown = 2, + [System.Runtime.Serialization.EnumMember(Value = "Dropdown")] Dropdown = 3, + [System.Runtime.Serialization.EnumMember(Value = "Html")] Html = 4, + [System.Runtime.Serialization.EnumMember(Value = "Radio")] Radio = 5, + [System.Runtime.Serialization.EnumMember(Value = "RichText")] RichText = 6, + [System.Runtime.Serialization.EnumMember(Value = "Slug")] Slug = 7, + [System.Runtime.Serialization.EnumMember(Value = "TextArea")] TextArea = 8, } @@ -13787,6 +14163,7 @@ public partial class TagsFieldPropertiesDto : FieldPropertiesDto /// The editor that is used to manage this field. [Newtonsoft.Json.JsonProperty("editor", Required = Newtonsoft.Json.Required.DisallowNull, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + [Newtonsoft.Json.JsonConverter(typeof(Newtonsoft.Json.Converters.StringEnumConverter))] public TagsFieldEditor Editor { get; set; } public string ToJson() @@ -13804,10 +14181,13 @@ public static TagsFieldPropertiesDto FromJson(string data) [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "9.13.2.0 (Newtonsoft.Json v9.0.0.0)")] public enum TagsFieldEditor { + [System.Runtime.Serialization.EnumMember(Value = "Tags")] Tags = 0, + [System.Runtime.Serialization.EnumMember(Value = "Checkboxes")] Checkboxes = 1, + [System.Runtime.Serialization.EnumMember(Value = "Dropdown")] Dropdown = 2, } @@ -14410,6 +14790,11 @@ public partial class RuleElementDto [Newtonsoft.Json.JsonProperty("readMore", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] public string ReadMore { get; set; } + /// The properties. + [Newtonsoft.Json.JsonProperty("properties", Required = Newtonsoft.Json.Required.Always)] + [System.ComponentModel.DataAnnotations.Required] + public System.Collections.Generic.ICollection Properties { get; set; } = new System.Collections.ObjectModel.Collection(); + public string ToJson() { return Newtonsoft.Json.JsonConvert.SerializeObject(this); @@ -14422,6 +14807,75 @@ public static RuleElementDto FromJson(string data) } + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "9.13.2.0 (Newtonsoft.Json v9.0.0.0)")] + public partial class RuleElementPropertyDto + { + /// The html editor. + [Newtonsoft.Json.JsonProperty("editor", Required = Newtonsoft.Json.Required.Always)] + [System.ComponentModel.DataAnnotations.Required] + [Newtonsoft.Json.JsonConverter(typeof(Newtonsoft.Json.Converters.StringEnumConverter))] + public RuleActionPropertyEditor Editor { get; set; } + + /// The name of the editor. + [Newtonsoft.Json.JsonProperty("name", Required = Newtonsoft.Json.Required.Always)] + [System.ComponentModel.DataAnnotations.Required] + public string Name { get; set; } + + /// The label to use. + [Newtonsoft.Json.JsonProperty("display", Required = Newtonsoft.Json.Required.Always)] + [System.ComponentModel.DataAnnotations.Required] + public string Display { get; set; } + + /// The optional description. + [Newtonsoft.Json.JsonProperty("description", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public string Description { get; set; } + + /// Indicates if the property is formattable. + [Newtonsoft.Json.JsonProperty("isFormattable", Required = Newtonsoft.Json.Required.DisallowNull, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public bool IsFormattable { get; set; } + + /// Indicates if the property is required. + [Newtonsoft.Json.JsonProperty("isRequired", Required = Newtonsoft.Json.Required.DisallowNull, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public bool IsRequired { get; set; } + + public string ToJson() + { + return Newtonsoft.Json.JsonConvert.SerializeObject(this); + } + + public static RuleElementPropertyDto FromJson(string data) + { + return Newtonsoft.Json.JsonConvert.DeserializeObject(data); + } + + } + + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "9.13.2.0 (Newtonsoft.Json v9.0.0.0)")] + public enum RuleActionPropertyEditor + { + [System.Runtime.Serialization.EnumMember(Value = "Checkbox")] + Checkbox = 0, + + [System.Runtime.Serialization.EnumMember(Value = "Email")] + Email = 1, + + [System.Runtime.Serialization.EnumMember(Value = "Number")] + Number = 2, + + [System.Runtime.Serialization.EnumMember(Value = "Password")] + Password = 3, + + [System.Runtime.Serialization.EnumMember(Value = "Text")] + Text = 4, + + [System.Runtime.Serialization.EnumMember(Value = "TextArea")] + TextArea = 5, + + [System.Runtime.Serialization.EnumMember(Value = "Url")] + Url = 6, + + } + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "9.13.2.0 (Newtonsoft.Json v9.0.0.0)")] public partial class RuleDto { @@ -14479,6 +14933,7 @@ public static RuleDto FromJson(string data) [Newtonsoft.Json.JsonConverter(typeof(JsonInheritanceConverter), "triggerType")] [JsonInheritanceAttribute("AssetChanged", typeof(AssetChangedRuleTriggerDto))] [JsonInheritanceAttribute("ContentChanged", typeof(ContentChangedRuleTriggerDto))] + [JsonInheritanceAttribute("SchemaChanged", typeof(SchemaChangedRuleTriggerDto))] [JsonInheritanceAttribute("Usage", typeof(UsageRuleTriggerDto))] [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "9.13.2.0 (Newtonsoft.Json v9.0.0.0)")] public abstract partial class RuleTriggerDto @@ -14561,6 +15016,25 @@ public static ContentChangedRuleTriggerSchemaDto FromJson(string data) } + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "9.13.2.0 (Newtonsoft.Json v9.0.0.0)")] + public partial class SchemaChangedRuleTriggerDto : RuleTriggerDto + { + /// Javascript condition when to trigger. + [Newtonsoft.Json.JsonProperty("condition", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public string Condition { get; set; } + + public string ToJson() + { + return Newtonsoft.Json.JsonConvert.SerializeObject(this); + } + + public static SchemaChangedRuleTriggerDto FromJson(string data) + { + return Newtonsoft.Json.JsonConvert.DeserializeObject(data); + } + + } + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "9.13.2.0 (Newtonsoft.Json v9.0.0.0)")] public partial class UsageRuleTriggerDto : RuleTriggerDto { @@ -14718,10 +15192,12 @@ public partial class RuleEventDto /// The result of the event. [Newtonsoft.Json.JsonProperty("result", Required = Newtonsoft.Json.Required.DisallowNull, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + [Newtonsoft.Json.JsonConverter(typeof(Newtonsoft.Json.Converters.StringEnumConverter))] public RuleResult Result { get; set; } /// The result of the job. [Newtonsoft.Json.JsonProperty("jobResult", Required = Newtonsoft.Json.Required.DisallowNull, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + [Newtonsoft.Json.JsonConverter(typeof(Newtonsoft.Json.Converters.StringEnumConverter))] public RuleJobResult JobResult { get; set; } public string ToJson() @@ -14739,12 +15215,16 @@ public static RuleEventDto FromJson(string data) [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "9.13.2.0 (Newtonsoft.Json v9.0.0.0)")] public enum RuleResult { + [System.Runtime.Serialization.EnumMember(Value = "Pending")] Pending = 0, + [System.Runtime.Serialization.EnumMember(Value = "Success")] Success = 1, + [System.Runtime.Serialization.EnumMember(Value = "Failed")] Failed = 2, + [System.Runtime.Serialization.EnumMember(Value = "Timeout")] Timeout = 3, } @@ -14752,14 +15232,19 @@ public enum RuleResult [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "9.13.2.0 (Newtonsoft.Json v9.0.0.0)")] public enum RuleJobResult { + [System.Runtime.Serialization.EnumMember(Value = "Pending")] Pending = 0, + [System.Runtime.Serialization.EnumMember(Value = "Success")] Success = 1, + [System.Runtime.Serialization.EnumMember(Value = "Retry")] Retry = 2, + [System.Runtime.Serialization.EnumMember(Value = "Failed")] Failed = 3, + [System.Runtime.Serialization.EnumMember(Value = "Cancelled")] Cancelled = 4, } @@ -14885,6 +15370,55 @@ public static ChangePlanDto FromJson(string data) } + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "9.13.2.0 (Newtonsoft.Json v9.0.0.0)")] + public partial class FeaturesDto + { + /// The latest features. + [Newtonsoft.Json.JsonProperty("features", Required = Newtonsoft.Json.Required.Always)] + [System.ComponentModel.DataAnnotations.Required] + public System.Collections.Generic.ICollection Features { get; set; } = new System.Collections.ObjectModel.Collection(); + + /// The recent version. + [Newtonsoft.Json.JsonProperty("version", Required = Newtonsoft.Json.Required.DisallowNull, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public int Version { get; set; } + + public string ToJson() + { + return Newtonsoft.Json.JsonConvert.SerializeObject(this); + } + + public static FeaturesDto FromJson(string data) + { + return Newtonsoft.Json.JsonConvert.DeserializeObject(data); + } + + } + + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "9.13.2.0 (Newtonsoft.Json v9.0.0.0)")] + public partial class FeatureDto + { + /// The name of the feature. + [Newtonsoft.Json.JsonProperty("name", Required = Newtonsoft.Json.Required.Always)] + [System.ComponentModel.DataAnnotations.Required] + public string Name { get; set; } + + /// The description text. + [Newtonsoft.Json.JsonProperty("text", Required = Newtonsoft.Json.Required.Always)] + [System.ComponentModel.DataAnnotations.Required] + public string Text { get; set; } + + public string ToJson() + { + return Newtonsoft.Json.JsonConvert.SerializeObject(this); + } + + public static FeatureDto FromJson(string data) + { + return Newtonsoft.Json.JsonConvert.DeserializeObject(data); + } + + } + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "9.13.2.0 (Newtonsoft.Json v9.0.0.0)")] public partial class HistoryEventDto { @@ -14962,7 +15496,7 @@ public partial class CommentDto /// The time when the comment was created or updated last. [Newtonsoft.Json.JsonProperty("time", Required = Newtonsoft.Json.Required.Always)] - [System.ComponentModel.DataAnnotations.Required(AllowEmptyStrings = true)] + [System.ComponentModel.DataAnnotations.Required] public System.DateTimeOffset Time { get; set; } /// The user who created or updated the comment. @@ -15032,6 +15566,7 @@ public partial class BackupJobDto /// The status of the operation. [Newtonsoft.Json.JsonProperty("status", Required = Newtonsoft.Json.Required.DisallowNull, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + [Newtonsoft.Json.JsonConverter(typeof(Newtonsoft.Json.Converters.StringEnumConverter))] public JobStatus Status { get; set; } public string ToJson() @@ -15049,12 +15584,16 @@ public static BackupJobDto FromJson(string data) [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "9.13.2.0 (Newtonsoft.Json v9.0.0.0)")] public enum JobStatus { + [System.Runtime.Serialization.EnumMember(Value = "Created")] Created = 0, + [System.Runtime.Serialization.EnumMember(Value = "Started")] Started = 1, + [System.Runtime.Serialization.EnumMember(Value = "Completed")] Completed = 2, + [System.Runtime.Serialization.EnumMember(Value = "Failed")] Failed = 3, } @@ -15082,6 +15621,7 @@ public partial class RestoreJobDto /// The status of the operation. [Newtonsoft.Json.JsonProperty("status", Required = Newtonsoft.Json.Required.DisallowNull, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + [Newtonsoft.Json.JsonConverter(typeof(Newtonsoft.Json.Converters.StringEnumConverter))] public JobStatus Status { get; set; } public string ToJson() @@ -15157,6 +15697,11 @@ public partial class AssetDto [System.ComponentModel.DataAnnotations.Required] public string FileName { get; set; } + /// The slug. + [Newtonsoft.Json.JsonProperty("slug", Required = Newtonsoft.Json.Required.Always)] + [System.ComponentModel.DataAnnotations.Required] + public string Slug { get; set; } + /// The mime type. [Newtonsoft.Json.JsonProperty("mimeType", Required = Newtonsoft.Json.Required.Always)] [System.ComponentModel.DataAnnotations.Required] @@ -15242,6 +15787,11 @@ public partial class AssetCreatedDto [System.ComponentModel.DataAnnotations.Required] public string FileName { get; set; } + /// The slug. + [Newtonsoft.Json.JsonProperty("slug", Required = Newtonsoft.Json.Required.Always)] + [System.ComponentModel.DataAnnotations.Required] + public string Slug { get; set; } + /// The mime type. [Newtonsoft.Json.JsonProperty("mimeType", Required = Newtonsoft.Json.Required.Always)] [System.ComponentModel.DataAnnotations.Required] @@ -15333,12 +15883,16 @@ public static AssetReplacedDto FromJson(string data) } [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "9.13.2.0 (Newtonsoft.Json v9.0.0.0)")] - public partial class UpdateAssetDto + public partial class AnnotateAssetDto { /// The new name of the asset. [Newtonsoft.Json.JsonProperty("fileName", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] public string FileName { get; set; } + /// The new slug of the asset. + [Newtonsoft.Json.JsonProperty("slug", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public string Slug { get; set; } + /// The new asset tags. [Newtonsoft.Json.JsonProperty("tags", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] public System.Collections.Generic.ICollection Tags { get; set; } @@ -15348,9 +15902,9 @@ public string ToJson() return Newtonsoft.Json.JsonConvert.SerializeObject(this); } - public static UpdateAssetDto FromJson(string data) + public static AnnotateAssetDto FromJson(string data) { - return Newtonsoft.Json.JsonConvert.DeserializeObject(data); + return Newtonsoft.Json.JsonConvert.DeserializeObject(data); } } @@ -15887,7 +16441,7 @@ public static CreateAppDto FromJson(string data) [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "9.13.2.0 (Newtonsoft.Json v9.0.0.0)")] public partial class Webhook : RuleAction { - /// he url to the webhook. + /// The url to the webhook. [Newtonsoft.Json.JsonProperty("url", Required = Newtonsoft.Json.Required.Always)] [System.ComponentModel.DataAnnotations.Required] public System.Uri Url { get; set; } @@ -16010,14 +16564,14 @@ public partial class Medium : RuleAction [Newtonsoft.Json.JsonProperty("canonicalUrl", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] public string CanonicalUrl { get; set; } - /// Optional publication id. - [Newtonsoft.Json.JsonProperty("publicationId", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] - public string PublicationId { get; set; } - /// The optional comma separated list of tags. [Newtonsoft.Json.JsonProperty("tags", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] public string Tags { get; set; } + /// Optional publication id. + [Newtonsoft.Json.JsonProperty("publicationId", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public string PublicationId { get; set; } + /// Indicates whether the content is markdown or html. [Newtonsoft.Json.JsonProperty("isHtml", Required = Newtonsoft.Json.Required.DisallowNull, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] public bool IsHtml { get; set; } @@ -16075,16 +16629,16 @@ public partial class Email : RuleAction [Newtonsoft.Json.JsonProperty("serverUseSsl", Required = Newtonsoft.Json.Required.Always)] public bool ServerUseSsl { get; set; } - /// The username for the SMTP server. - [Newtonsoft.Json.JsonProperty("serverUsername", Required = Newtonsoft.Json.Required.Always)] - [System.ComponentModel.DataAnnotations.Required] - public string ServerUsername { get; set; } - /// The password for the SMTP server. [Newtonsoft.Json.JsonProperty("serverPassword", Required = Newtonsoft.Json.Required.Always)] [System.ComponentModel.DataAnnotations.Required] public string ServerPassword { get; set; } + /// The username for the SMTP server. + [Newtonsoft.Json.JsonProperty("serverUsername", Required = Newtonsoft.Json.Required.Always)] + [System.ComponentModel.DataAnnotations.Required] + public string ServerUsername { get; set; } + /// The email sending address. [Newtonsoft.Json.JsonProperty("messageFrom", Required = Newtonsoft.Json.Required.Always)] [System.ComponentModel.DataAnnotations.Required] @@ -16120,7 +16674,7 @@ public static Email FromJson(string data) [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "9.13.2.0 (Newtonsoft.Json v9.0.0.0)")] public partial class ElasticSearch : RuleAction { - /// The hostname of the elastic search instance or cluster. + /// The url to the elastic search instance or cluster. [Newtonsoft.Json.JsonProperty("host", Required = Newtonsoft.Json.Required.Always)] [System.ComponentModel.DataAnnotations.Required] public System.Uri Host { get; set; } @@ -16158,7 +16712,7 @@ public static ElasticSearch FromJson(string data) [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "9.13.2.0 (Newtonsoft.Json v9.0.0.0)")] public partial class Discourse : RuleAction { - /// he url to the discourse server. + /// The url to the discourse server. [Newtonsoft.Json.JsonProperty("url", Required = Newtonsoft.Json.Required.Always)] [System.ComponentModel.DataAnnotations.Required] public System.Uri Url { get; set; } @@ -16240,7 +16794,7 @@ public partial class Algolia : RuleAction [System.ComponentModel.DataAnnotations.Required] public string ApiKey { get; set; } - /// THe name of the index. + /// The name of the index. [Newtonsoft.Json.JsonProperty("indexName", Required = Newtonsoft.Json.Required.Always)] [System.ComponentModel.DataAnnotations.Required] public string IndexName { get; set; } diff --git a/csharp/Squidex.ClientLibrary/Squidex.ClientLibrary/Squidex.ClientLibrary.csproj b/csharp/Squidex.ClientLibrary/Squidex.ClientLibrary/Squidex.ClientLibrary.csproj index 23e7446b..4f7a4e69 100644 --- a/csharp/Squidex.ClientLibrary/Squidex.ClientLibrary/Squidex.ClientLibrary.csproj +++ b/csharp/Squidex.ClientLibrary/Squidex.ClientLibrary/Squidex.ClientLibrary.csproj @@ -10,7 +10,7 @@ https://raw.githubusercontent.com/Squidex/squidex/master/media/logo-squared.png https://github.com/Squidex/squidex/blob/master/LICENSE.txt https://github.com/Squidex/squidex/ - 2.8 + 2.10 true diff --git a/csharp/Squidex.ClientLibrary/Squidex.ClientLibrary/SquidexClientExtensions.cs b/csharp/Squidex.ClientLibrary/Squidex.ClientLibrary/SquidexClientExtensions.cs index fc314ce1..25876520 100644 --- a/csharp/Squidex.ClientLibrary/Squidex.ClientLibrary/SquidexClientExtensions.cs +++ b/csharp/Squidex.ClientLibrary/Squidex.ClientLibrary/SquidexClientExtensions.cs @@ -1,12 +1,17 @@ +// ========================================================================== +// Squidex Headless CMS +// ========================================================================== +// Copyright (c) Squidex UG (haftungsbeschraenkt) +// All rights reserved. Licensed under the MIT license. +// ========================================================================== + using System.Threading.Tasks; namespace Squidex.ClientLibrary { public static class SquidexClientExtensions { - public static async Task> GetAllAsync( - this SquidexClient client, - int batchSize = 200) + public static async Task> GetAllAsync(this SquidexClient client, int batchSize = 200) where TEntity : SquidexEntityBase where TData : class, new() { From 76cc5ef2d563104c26b4ecce1055aea4e01864f1 Mon Sep 17 00:00:00 2001 From: Yehuda Kremer Date: Thu, 18 Apr 2019 12:45:31 +0300 Subject: [PATCH 2/7] Create jstree-editor.html add custom editor plugin: "jstree-editor" --- editors/jstree-editor.html | 112 +++++++++++++++++++++++++++++++++++++ 1 file changed, 112 insertions(+) create mode 100644 editors/jstree-editor.html diff --git a/editors/jstree-editor.html b/editors/jstree-editor.html new file mode 100644 index 00000000..ef1e477b --- /dev/null +++ b/editors/jstree-editor.html @@ -0,0 +1,112 @@ + + + + + + + + + + + + + + + + + + + From 7251a7e122d579fea5d6fd7ef99ed21ace10b3e4 Mon Sep 17 00:00:00 2001 From: Sebastian Stehle Date: Thu, 18 Apr 2019 18:00:29 +0200 Subject: [PATCH 3/7] Option name improved. --- .../Squidex.CLI/Commands/App_Backup.cs | 104 ++++++++++++++++++ .../Squidex.CLI/Commands/App_Config.cs | 8 +- .../Squidex.CLI/Commands/App_Content.cs | 4 +- .../Squidex.CLI/Commands/App_Schemas.cs | 8 +- .../Squidex.CLI/Commands/App_Twitter.cs | 2 +- 5 files changed, 115 insertions(+), 11 deletions(-) create mode 100644 cli/Squidex.CLI/Squidex.CLI/Commands/App_Backup.cs diff --git a/cli/Squidex.CLI/Squidex.CLI/Commands/App_Backup.cs b/cli/Squidex.CLI/Squidex.CLI/Commands/App_Backup.cs new file mode 100644 index 00000000..4bad0ea3 --- /dev/null +++ b/cli/Squidex.CLI/Squidex.CLI/Commands/App_Backup.cs @@ -0,0 +1,104 @@ +// ========================================================================== +// Squidex Headless CMS +// ========================================================================== +// Copyright (c) Squidex UG (haftungsbeschraenkt) +// All rights reserved. Licensed under the MIT license. +// ========================================================================== + +using System; +using System.IO; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using CommandDotNet; +using CommandDotNet.Attributes; +using FluentValidation; +using FluentValidation.Attributes; +using Squidex.CLI.Configuration; +using Squidex.ClientLibrary.Management; + +namespace Squidex.CLI.Commands +{ + public sealed partial class App + { + [ApplicationMetadata(Name = "backup", Description = "Manage backups.")] + [SubCommand] + public sealed class Backup + { + [InjectProperty] + public IConfigurationService Configuration { get; set; } + + [ApplicationMetadata(Name = "create", Description = "Create and download an backup.")] + public async Task Create(CreateArguments arguments) + { + var (app, service) = Configuration.GetClient(); + + var backupStarted = DateTime.UtcNow.AddMinutes(-5); + var backupsClient = service.CreateBackupsClient(); + + await backupsClient.PostBackupAsync(app); + + Console.WriteLine("Backup started, waiting for completion..."); + + BackupJobDto foundBackup = null; + + using (var tcs = new CancellationTokenSource(TimeSpan.FromMinutes(arguments.Timeout))) + { + while (!tcs.Token.IsCancellationRequested) + { + var backups = await backupsClient.GetJobsAsync(app); + var backup = backups.FirstOrDefault(x => x.Started >= backupStarted); + + if (backup != null && backup.Stopped.HasValue) + { + foundBackup = backup; + break; + } + } + + await Task.Delay(5000); + } + + if (foundBackup == null) + { + Console.WriteLine("Failed to receive the backup in time."); + } + else if (foundBackup.Status == JobStatus.Completed) + { + Console.WriteLine("Backup completed. Downloading..."); + + using (var fs = new FileStream(arguments.File, FileMode.CreateNew)) + { + var download = await backupsClient.GetBackupContentAsync(app, foundBackup.Id.ToString()); + + await download.Stream.CopyToAsync(fs); + } + + Console.WriteLine("Backup completed. Download completed"); + } + else + { + Console.WriteLine("Failed to make the backup, check the logs for details."); + } + } + + [Validator(typeof(Validator))] + public sealed class CreateArguments : IArgumentModel + { + [Option(LongName = "timeout", Description = "The timeout to wait for the backup in minutes.")] + public int Timeout { get; set; } = 30; + + [Argument(Name = "file", Description = "The target file.")] + public string File { get; set; } + + public sealed class Validator : AbstractValidator + { + public Validator() + { + RuleFor(x => x.File).NotEmpty(); + } + } + } + } + } +} diff --git a/cli/Squidex.CLI/Squidex.CLI/Commands/App_Config.cs b/cli/Squidex.CLI/Squidex.CLI/Commands/App_Config.cs index 5b5a8f94..2d83da7d 100644 --- a/cli/Squidex.CLI/Squidex.CLI/Commands/App_Config.cs +++ b/cli/Squidex.CLI/Squidex.CLI/Commands/App_Config.cs @@ -19,7 +19,7 @@ public partial class App { [ApplicationMetadata(Name = "config", Description = "Manage configurations.")] [SubCommand] - public class Config + public sealed class Config { [InjectProperty] public IConfigurationService Configuration { get; set; } @@ -84,7 +84,7 @@ public void Use(UseArguments arguments) [Validator(typeof(Validator))] public sealed class ListArguments : IArgumentModel { - [Option(Description = "Output as table")] + [Option(LongName = "table", ShortName = "t", Description = "Output as table")] public bool Table { get; set; } public sealed class Validator : AbstractValidator @@ -134,10 +134,10 @@ public sealed class AddArguments : IArgumentModel [Argument(Name = "client-secret", Description = "The client secret.")] public string ClientSecret { get; set; } - [Option(LongName = "url", Description = "The optional url to your squidex installation. Default: https://cloud.squidex.io")] + [Option(LongName = "url", ShortName = "u", Description = "The optional url to your squidex installation. Default: https://cloud.squidex.io")] public string ServiceUrl { get; set; } - [Option(LongName = "label", Description = "Optional label for this app.")] + [Option(LongName = "label", ShortName = "l", Description = "Optional label for this app.")] public string Label { get; set; } public string ToEntryName() diff --git a/cli/Squidex.CLI/Squidex.CLI/Commands/App_Content.cs b/cli/Squidex.CLI/Squidex.CLI/Commands/App_Content.cs index a86f4299..9642351d 100644 --- a/cli/Squidex.CLI/Squidex.CLI/Commands/App_Content.cs +++ b/cli/Squidex.CLI/Squidex.CLI/Commands/App_Content.cs @@ -24,9 +24,9 @@ namespace Squidex.CLI.Commands { public partial class App { - [ApplicationMetadata(Name = "content", Description = "Manage content.")] + [ApplicationMetadata(Name = "content", Description = "Manage contents.")] [SubCommand] - public class Content + public sealed class Content { [InjectProperty] public IConfigurationService Configuration { get; set; } diff --git a/cli/Squidex.CLI/Squidex.CLI/Commands/App_Schemas.cs b/cli/Squidex.CLI/Squidex.CLI/Commands/App_Schemas.cs index d9b77a9f..9eac0528 100644 --- a/cli/Squidex.CLI/Squidex.CLI/Commands/App_Schemas.cs +++ b/cli/Squidex.CLI/Squidex.CLI/Commands/App_Schemas.cs @@ -26,7 +26,7 @@ public partial class App { [ApplicationMetadata(Name = "schemas", Description = "Manage schemas.")] [SubCommand] - public class Schemas + public sealed class Schemas { [InjectProperty] public IConfigurationService Configuration { get; set; } @@ -85,10 +85,9 @@ public async Task Sync(SyncArguments arguments) var schemasClient = service.CreateSchemasClient(); - var schemaText = (string)null; + var schemaText = string.Empty; var schemaName = arguments.Name; - var targetSchema = (SchemaDetailsDto)null; try { schemaText = File.ReadAllText(arguments.File); @@ -117,6 +116,7 @@ public async Task Sync(SyncArguments arguments) throw new SquidexException("Schema name cannot be empty."); } + SchemaDetailsDto targetSchema; try { targetSchema = await schemasClient.GetSchemaAsync(app, schemaName); @@ -166,7 +166,7 @@ public async Task Sync(SyncArguments arguments) [Validator(typeof(Validator))] public sealed class ListArguments : IArgumentModel { - [Option(Description = "Output as table")] + [Option(LongName = "table", ShortName = "t", Description = "Output as table")] public bool Table { get; set; } public sealed class Validator : AbstractValidator diff --git a/cli/Squidex.CLI/Squidex.CLI/Commands/App_Twitter.cs b/cli/Squidex.CLI/Squidex.CLI/Commands/App_Twitter.cs index 344f214a..f45aa26a 100644 --- a/cli/Squidex.CLI/Squidex.CLI/Commands/App_Twitter.cs +++ b/cli/Squidex.CLI/Squidex.CLI/Commands/App_Twitter.cs @@ -20,7 +20,7 @@ public sealed partial class App { [ApplicationMetadata(Name = "twitter", Description = "Manage twitter.")] [SubCommand] - public class Twitter + public sealed class Twitter { [ApplicationMetadata(Name = "auth", Description = "Starts the authentication.")] public async Task Auth(AuthArguments arguments) From d99fb07fedbed264b83da1d682432141fb18cfb4 Mon Sep 17 00:00:00 2001 From: Sebastian Stehle Date: Thu, 18 Apr 2019 19:20:45 +0200 Subject: [PATCH 4/7] Update jstree-editor.html --- editors/jstree-editor.html | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/editors/jstree-editor.html b/editors/jstree-editor.html index ef1e477b..00ce2c59 100644 --- a/editors/jstree-editor.html +++ b/editors/jstree-editor.html @@ -3,8 +3,10 @@ - + + + From f6ffbd76f05e4ebad5a43414fa2212f1d1488b38 Mon Sep 17 00:00:00 2001 From: Sebastian Stehle Date: Sat, 20 Apr 2019 10:36:15 +0200 Subject: [PATCH 5/7] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 93a18099..0dc98f0b 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ This repository contains samples for Squidex CMS. -## How to make feature requests or report bugs? +## How to make feature requests, get help or report bugs? Please join our community forum: https://support.squidex.io From 660f0fcb59f061b14d8ddc44f201b399d42b6ee9 Mon Sep 17 00:00:00 2001 From: Sebastian Stehle Date: Sun, 12 May 2019 11:55:51 +0200 Subject: [PATCH 6/7] Import finalized. --- .../Squidex.CLI.Tests/MapFromSquidexTests.cs | 211 ++++++++++++ .../Squidex.CLI.Tests/MapToSquidexTests.cs | 301 ++++++++++++++++++ .../Squidex.CLI.Tests.csproj | 30 ++ cli/Squidex.CLI/Squidex.CLI.sln | 10 +- .../Squidex.CLI/Commands/App_Content.cs | 195 ++++++------ .../Implementation/Csv2SquidexConverter.cs | 129 ++++++++ .../Commands/Implementation/JsonMapping.cs | 114 +++++++ .../Commands/Implementation/JsonPath.cs | 35 ++ .../Implementation/Squidex2CsvConverter.cs | 122 +++++++ 9 files changed, 1039 insertions(+), 108 deletions(-) create mode 100644 cli/Squidex.CLI/Squidex.CLI.Tests/MapFromSquidexTests.cs create mode 100644 cli/Squidex.CLI/Squidex.CLI.Tests/MapToSquidexTests.cs create mode 100644 cli/Squidex.CLI/Squidex.CLI.Tests/Squidex.CLI.Tests.csproj create mode 100644 cli/Squidex.CLI/Squidex.CLI/Commands/Implementation/Csv2SquidexConverter.cs create mode 100644 cli/Squidex.CLI/Squidex.CLI/Commands/Implementation/JsonMapping.cs create mode 100644 cli/Squidex.CLI/Squidex.CLI/Commands/Implementation/JsonPath.cs create mode 100644 cli/Squidex.CLI/Squidex.CLI/Commands/Implementation/Squidex2CsvConverter.cs diff --git a/cli/Squidex.CLI/Squidex.CLI.Tests/MapFromSquidexTests.cs b/cli/Squidex.CLI/Squidex.CLI.Tests/MapFromSquidexTests.cs new file mode 100644 index 00000000..5de46b39 --- /dev/null +++ b/cli/Squidex.CLI/Squidex.CLI.Tests/MapFromSquidexTests.cs @@ -0,0 +1,211 @@ +// ========================================================================== +// Squidex Headless CMS +// ========================================================================== +// Copyright (c) Squidex UG (haftungsbeschraenkt) +// All rights reserved. Licensed under the MIT license. +// ========================================================================== + +using System; +using System.Collections.Generic; +using System.Linq; +using Newtonsoft.Json.Linq; +using Squidex.CLI.Commands; +using Squidex.CLI.Commands.Implementation; +using Squidex.ClientLibrary; +using Xunit; + +namespace Squidex.CLI.Tests +{ + public class MapFromSquidexTests + { + private readonly DummyEntity content; + + public MapFromSquidexTests() + { + content = new DummyEntity + { + DataDraft = new DummyData + { + ["name"] = new Dictionary + { + ["iv"] = "Hello World" + } + }, + Created = DateTimeOffset.Now + }; + + content.Data["text"] = new Dictionary + { + ["iv"] = "Hello World" + }; + + content.Data["localizedText"] = new Dictionary + { + ["en"] = "Hello World" + }; + + content.Data["multilineText"] = new Dictionary + { + ["iv"] = "Hello\nWorld" + }; + + content.Data["user"] = new Dictionary + { + ["iv"] = new JObject(new JProperty("name", "Squidex")) + }; + + content.Data["products"] = new Dictionary + { + ["iv"] = new JArray("Squidex", "CLI") + }; + } + + [Fact] + public void Should_throw_exception_if_field_names_is_null() + { + Assert.Throws(() => new Squidex2CsvConverter(null)); + } + + [Fact] + public void Should_throw_exception_if_field_names_is_empty() + { + Assert.Throws(() => new Squidex2CsvConverter(string.Empty)); + } + + [Fact] + public void Should_use_direct_field_names() + { + var sut = new Squidex2CsvConverter("created,lastModified,data.name.iv"); + + Assert.Equal(new[] { "created", "lastModified", "data.name.iv" }, sut.FieldNames); + } + + [Fact] + public void Should_use_alias_field_names() + { + var sut = new Squidex2CsvConverter("created,name=data.name.iv"); + + Assert.Equal(new[] { "created", "name" }, sut.FieldNames); + } + + [Fact] + public void Should_extract_value_from_property() + { + var sut = new Squidex2CsvConverter("created"); + + var values = sut.GetValues(content).ToArray(); + + Assert.Equal(new object[] { content.Created }, values); + } + + [Fact] + public void Should_return_invalid_if_property_not_found() + { + var sut = new Squidex2CsvConverter("invalid"); + + var values = sut.GetValues(content).ToArray(); + + Assert.Equal(new object[] { "" }, values); + } + + [Fact] + public void Should_extract_value_from_invariant_data_draft() + { + var sut = new Squidex2CsvConverter("dataDraft.name"); + + var values = sut.GetValues(content).ToArray(); + + Assert.Equal(new object[] { "Hello World" }, values); + } + + [Fact] + public void Should_extract_value_from_invariant_data() + { + var sut = new Squidex2CsvConverter("data.text"); + + var values = sut.GetValues(content).ToArray(); + + Assert.Equal(new object[] { "Hello World" }, values); + } + + [Fact] + public void Should_extract_value_from_localized_data() + { + var sut = new Squidex2CsvConverter("data.localizedText.en"); + + var values = sut.GetValues(content).ToArray(); + + Assert.Equal(new object[] { "Hello World" }, values); + } + + [Fact] + public void Should_extract_value_from_invariant_data_and_escape() + { + var sut = new Squidex2CsvConverter("data.multilineText"); + + var values = sut.GetValues(content).ToArray(); + + Assert.Equal(new object[] { "Hello\\nWorld" }, values); + } + + [Fact] + public void Should_return_invalid_if_field_not_found() + { + var sut = new Squidex2CsvConverter("data.invalid"); + + var values = sut.GetValues(content).ToArray(); + + Assert.Equal(new object[] { "" }, values); + } + + [Fact] + public void Should_extract_value_from_nested_object() + { + var sut = new Squidex2CsvConverter("data.user.iv.name"); + + var values = sut.GetValues(content).ToArray(); + + Assert.Equal(new object[] { "Squidex" }, values); + } + + [Fact] + public void Should_return_invalid_if_property_in_nested_object_not_found() + { + var sut = new Squidex2CsvConverter("data.invalid"); + + var values = sut.GetValues(content).ToArray(); + + Assert.Equal(new object[] { "" }, values); + } + + [Fact] + public void Should_extract_value_from_nested_array() + { + var sut = new Squidex2CsvConverter("data.products.iv.1"); + + var values = sut.GetValues(content).ToArray(); + + Assert.Equal(new object[] { "CLI" }, values); + } + + [Fact] + public void Should_return_invalid_if_index_out_of_range() + { + var sut = new Squidex2CsvConverter("data.products.iv.3"); + + var values = sut.GetValues(content).ToArray(); + + Assert.Equal(new object[] { "" }, values); + } + + [Fact] + public void Should_extract_value_as_json() + { + var sut = new Squidex2CsvConverter("data.products"); + + var values = sut.GetValues(content).ToArray(); + + Assert.Equal(new object[] { "[\"Squidex\",\"CLI\"]" }, values); + } + } +} diff --git a/cli/Squidex.CLI/Squidex.CLI.Tests/MapToSquidexTests.cs b/cli/Squidex.CLI/Squidex.CLI.Tests/MapToSquidexTests.cs new file mode 100644 index 00000000..0c45a40e --- /dev/null +++ b/cli/Squidex.CLI/Squidex.CLI.Tests/MapToSquidexTests.cs @@ -0,0 +1,301 @@ +// ========================================================================== +// Squidex Headless CMS +// ========================================================================== +// Copyright (c) Squidex UG (haftungsbeschraenkt) +// All rights reserved. Licensed under the MIT license. +// ========================================================================== + +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using CsvHelper; +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; +using Squidex.CLI.Commands; +using Squidex.CLI.Commands.Implementation; +using Squidex.ClientLibrary; +using Xunit; + +namespace Squidex.CLI.Tests +{ + public class MapToSquidexTests + { + private readonly CsvReader csvReader; + + public MapToSquidexTests() + { + var csv = new StringBuilder(); + + using (var stringWriter = new StringWriter(csv)) + { + using (var writer = new CsvWriter(stringWriter)) + { + writer.WriteField("text"); + writer.WriteField("boolean"); + writer.WriteField("number"); + writer.WriteField("array"); + writer.WriteField("object"); + writer.NextRecord(); + + writer.WriteField("Hello World"); + writer.WriteField("true"); + writer.WriteField("1234"); + writer.WriteField("[\"Squidex\",\"CLI\"]".Replace('\"', '\''), true); + writer.WriteField("{\"Squidex\":\"CLI\"}".Replace('\"', '\''), true); + writer.NextRecord(); + + writer.Flush(); + } + } + + csvReader = new CsvReader(new StringReader(csv.ToString())); + } + + [Fact] + public void Should_throw_exception_if_field_names_is_null() + { + Assert.Throws(() => new Csv2SquidexConverter(null)); + } + + [Fact] + public void Should_throw_exception_if_field_names_is_empty() + { + Assert.Throws(() => new Csv2SquidexConverter(string.Empty)); + } + + [Fact] + public void Should_read_string_to_invariant() + { + var sut = new Csv2SquidexConverter("text"); + + var actual = sut.ReadAll(csvReader).First(); + + var expected = new DummyData + { + ["text"] = new Dictionary + { + ["iv"] = "Hello World" + } + }; + + EqualJson(expected, actual); + } + + [Fact] + public void Should_read_boolean_to_invariant() + { + var sut = new Csv2SquidexConverter("boolean"); + + var actual = sut.ReadAll(csvReader).First(); + + var expected = new DummyData + { + ["boolean"] = new Dictionary + { + ["iv"] = true + } + }; + + EqualJson(expected, actual); + } + + [Fact] + public void Should_read_number_to_invariant() + { + var sut = new Csv2SquidexConverter("number"); + + var actual = sut.ReadAll(csvReader).First(); + + var expected = new DummyData + { + ["number"] = new Dictionary + { + ["iv"] = 1234 + } + }; + + EqualJson(expected, actual); + } + + [Fact] + public void Should_read_string_to_localized() + { + var sut = new Csv2SquidexConverter("text.de=text"); + + var actual = sut.ReadAll(csvReader).First(); + + var expected = new DummyData + { + ["text"] = new Dictionary + { + ["de"] = "Hello World" + } + }; + + EqualJson(expected, actual); + } + + [Fact] + public void Should_read_array_to_invariant() + { + var sut = new Csv2SquidexConverter("array"); + + var actual = sut.ReadAll(csvReader).First(); + + var expected = new DummyData + { + ["array"] = new Dictionary + { + ["iv"] = new JArray("Squidex", "CLI") + } + }; + + EqualJson(expected, actual); + } + + [Fact] + public void Should_read_object_to_invariant() + { + var sut = new Csv2SquidexConverter("object"); + + var actual = sut.ReadAll(csvReader).First(); + + var expected = new DummyData + { + ["object"] = new Dictionary + { + ["iv"] = new JObject(new JProperty("Squidex", "CLI")) + } + }; + + EqualJson(expected, actual); + } + + [Fact] + public void Should_read_string_to_array() + { + var sut = new Csv2SquidexConverter("json.iv.1=text"); + + var actual = sut.ReadAll(csvReader).First(); + + var expected = new DummyData + { + ["json"] = new Dictionary + { + ["iv"] = new JArray(null, "Hello World") + } + }; + + EqualJson(expected, actual); + } + + [Fact] + public void Should_read_multiple_values_to_array() + { + var sut = new Csv2SquidexConverter("json.iv.1=text,json.iv.0=number"); + + var actual = sut.ReadAll(csvReader).First(); + + var expected = new DummyData + { + ["json"] = new Dictionary + { + ["iv"] = new JArray(1234, "Hello World") + } + }; + + EqualJson(expected, actual); + } + + [Fact] + public void Should_read_string_to_nested_array() + { + var sut = new Csv2SquidexConverter("json.iv.1.0=text"); + + var actual = sut.ReadAll(csvReader).First(); + + var expected = new DummyData + { + ["json"] = new Dictionary + { + ["iv"] = new JArray(null, new JArray("Hello World")) + } + }; + + EqualJson(expected, actual); + } + + [Fact] + public void Should_read_string_to_object() + { + var sut = new Csv2SquidexConverter("json.iv.a=text"); + + var actual = sut.ReadAll(csvReader).First(); + + var expected = new DummyData + { + ["json"] = new Dictionary + { + ["iv"] = new JObject + { + ["a"] = "Hello World" + } + } + }; + + EqualJson(expected, actual); + } + + [Fact] + public void Should_read_multiple_values_to_object() + { + var sut = new Csv2SquidexConverter("json.iv.a=text,json.iv.b=number"); + + var actual = sut.ReadAll(csvReader).First(); + + var expected = new DummyData + { + ["json"] = new Dictionary + { + ["iv"] = new JObject + { + ["a"] = "Hello World", + ["b"] = 1234 + } + } + }; + + EqualJson(expected, actual); + } + + [Fact] + public void Should_read_string_to_nested_object() + { + var sut = new Csv2SquidexConverter("json.iv.a0.a1=text"); + + var actual = sut.ReadAll(csvReader).First(); + + var expected = new DummyData + { + ["json"] = new Dictionary + { + ["iv"] = new JObject + { + ["a0"] = new JObject + { + ["a1"] = "Hello World" + } + } + } + }; + + EqualJson(expected, actual); + } + + private void EqualJson(DummyData expected, DummyData actual) + { + Assert.Equal(JsonConvert.SerializeObject(expected, Formatting.Indented), JsonConvert.SerializeObject(actual, Formatting.Indented)); + } + } +} diff --git a/cli/Squidex.CLI/Squidex.CLI.Tests/Squidex.CLI.Tests.csproj b/cli/Squidex.CLI/Squidex.CLI.Tests/Squidex.CLI.Tests.csproj new file mode 100644 index 00000000..93e54c84 --- /dev/null +++ b/cli/Squidex.CLI/Squidex.CLI.Tests/Squidex.CLI.Tests.csproj @@ -0,0 +1,30 @@ + + + + netcoreapp2.2 + + false + + + + + + + + + + + + + ..\Squidex.ruleset + + + + + + + + + + + diff --git a/cli/Squidex.CLI/Squidex.CLI.sln b/cli/Squidex.CLI/Squidex.CLI.sln index d6829cf5..297e38f8 100644 --- a/cli/Squidex.CLI/Squidex.CLI.sln +++ b/cli/Squidex.CLI/Squidex.CLI.sln @@ -1,10 +1,12 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 15 -VisualStudioVersion = 15.0.28307.168 +# Visual Studio Version 16 +VisualStudioVersion = 16.0.28803.202 MinimumVisualStudioVersion = 10.0.40219.1 Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Squidex.CLI", "Squidex.CLI\Squidex.CLI.csproj", "{2D435C5F-73FB-47F6-BEDA-49E9F9D8E9F7}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Squidex.CLI.Tests", "Squidex.CLI.Tests\Squidex.CLI.Tests.csproj", "{3DCBE36E-07EE-4EC2-81F9-8D471DD89896}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -15,6 +17,10 @@ Global {2D435C5F-73FB-47F6-BEDA-49E9F9D8E9F7}.Debug|Any CPU.Build.0 = Debug|Any CPU {2D435C5F-73FB-47F6-BEDA-49E9F9D8E9F7}.Release|Any CPU.ActiveCfg = Release|Any CPU {2D435C5F-73FB-47F6-BEDA-49E9F9D8E9F7}.Release|Any CPU.Build.0 = Release|Any CPU + {3DCBE36E-07EE-4EC2-81F9-8D471DD89896}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {3DCBE36E-07EE-4EC2-81F9-8D471DD89896}.Debug|Any CPU.Build.0 = Debug|Any CPU + {3DCBE36E-07EE-4EC2-81F9-8D471DD89896}.Release|Any CPU.ActiveCfg = Release|Any CPU + {3DCBE36E-07EE-4EC2-81F9-8D471DD89896}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/cli/Squidex.CLI/Squidex.CLI/Commands/App_Content.cs b/cli/Squidex.CLI/Squidex.CLI/Commands/App_Content.cs index 9642351d..14ad9cbf 100644 --- a/cli/Squidex.CLI/Squidex.CLI/Commands/App_Content.cs +++ b/cli/Squidex.CLI/Squidex.CLI/Commands/App_Content.cs @@ -6,19 +6,20 @@ // ========================================================================== using System; -using System.Collections; using System.Collections.Generic; using System.IO; -using System.Linq; using System.Threading.Tasks; using CommandDotNet; using CommandDotNet.Attributes; using CsvHelper; using FluentValidation; using FluentValidation.Attributes; -using Newtonsoft.Json.Linq; +using Squidex.CLI.Commands.Implementation; using Squidex.CLI.Configuration; using Squidex.ClientLibrary; +using CsvOptions = CsvHelper.Configuration.Configuration; + +#pragma warning disable IDE0059 // Value assigned to symbol is never used namespace Squidex.CLI.Commands { @@ -31,6 +32,36 @@ public sealed class Content [InjectProperty] public IConfigurationService Configuration { get; set; } + [ApplicationMetadata(Name = "import", Description = "Import the content to a schema.", + ExtendedHelpText = +@"Use the following format to define fields from the CSV file: + - name (for invariant fields) + - name=other(for invariant fields from another field) + - name.de=name (for localized fields) +")] + public async Task Import(ImportArguments arguments) + { + var converter = new Csv2SquidexConverter(arguments.Fields); + + using (var stream = new FileStream(arguments.File, FileMode.Open, FileAccess.Read)) + { + using (var streamReader = new StreamReader(stream)) + { + var csvOptions = new CsvOptions + { + Delimiter = arguments.Delimiter + }; + + using (var reader = new CsvReader(streamReader, csvOptions)) + { + var datas = converter.ReadAll(reader); + + await ImportAsync(arguments, datas); + } + } + } + } + [ApplicationMetadata(Name = "export", Description = "Export the content for a schema.", ExtendedHelpText = @"Use the following format to define fields for CSV: @@ -41,9 +72,9 @@ public sealed class Content - lastModified - version - data.name (for invariant fields) - - Name=data.name (for invariant fields with alias) - data.name.de (for localized fields) - - Name (German)=data.name.de (for localized fields with alias) + - name=data.name (for invariant fields with alias) + - name (German)=data.name.de (for localized fields with alias) ")] public async Task Export(ExportArguments arguments) { @@ -116,35 +147,33 @@ await ExportAsync(arguments, entity => file = $"{arguments.Schema}_{DateTime.UtcNow:yyyy-MM-dd-hh-mm-ss}.csv"; } - var fields = GetFields(arguments); + var converter = new Squidex2CsvConverter(arguments.Fields); using (var stream = new FileStream(file, FileMode.Create, FileAccess.Write)) { using (var streamWriter = new StreamWriter(stream)) { - var csvOptions = new CsvHelper.Configuration.Configuration + var csvOptions = new CsvOptions { Delimiter = ";" }; using (var writer = new CsvWriter(streamWriter, csvOptions)) { - foreach (var field in fields) + foreach (var fieldName in converter.FieldNames) { - writer.WriteField(field.Name); + writer.WriteField(fieldName); } writer.NextRecord(); await ExportAsync(arguments, entity => { - foreach (var field in fields) + foreach (var value in converter.GetValues(entity)) { - var value = GetValue(entity, field.Path); - - if (value is string s) + if (value is string text) { - writer.WriteField(s.Replace("\n", "\\n"), true); + writer.WriteField(text, true); } else { @@ -160,41 +189,27 @@ await ExportAsync(arguments, entity => } } - private static List<(string Name, string[] Path)> GetFields(ExportArguments arguments) + private async Task ImportAsync(ImportArguments arguments, IEnumerable datas) { - var fields = new List<(string Name, string[] Path)>(); + var client = Configuration.GetClient().Client.GetClient(arguments.Schema); - foreach (var item in arguments.Fields.Split(new[] { ',', ';' }, StringSplitOptions.RemoveEmptyEntries)) - { - var parts = item.Split('='); + var totalWritten = 0; - string[] GetPath(string value) - { - var path = value.Split('.', StringSplitOptions.RemoveEmptyEntries); + var consoleTop = Console.CursorTop; - if (path.Length == 2 && string.Equals(path[0], "Data", StringComparison.OrdinalIgnoreCase)) - { - return path.Union(Enumerable.Repeat("iv", 1)).ToArray(); - } + var handled = new HashSet(); - return path; - } + foreach (var data in datas) + { + await client.CreateAsync(data, !arguments.Unpublished); - if (parts.Length == 1) - { - fields.Add((parts[0], GetPath(parts[0]))); - } - else if (parts.Length == 2) - { - fields.Add((parts[0], GetPath(parts[1]))); - } - else - { - throw new SquidexException("Field definition not valid."); - } + totalWritten++; + + Console.WriteLine("> Imported: {0}.", totalWritten); + Console.SetCursorPosition(0, consoleTop); } - return fields; + Console.WriteLine("> Imported: {0}. Completed.", totalWritten); } private async Task ExportAsync(ExportArguments arguments, Action handler) @@ -242,78 +257,42 @@ private async Task ExportAsync(ExportArguments arguments, Action ha Console.WriteLine("> Exported: {0} of {1}. Completed.", totalRead, total); } - private object GetValue(object current, string[] path) + public enum Format { - foreach (var element in path) - { - if (current is JObject obj) - { - if (obj.TryGetValue(element, out var temp)) - { - current = temp; - } - else - { - return ""; - } - } - else if (current is IDictionary dict) - { - if (dict.Contains(element)) - { - current = dict[element]; - } - else - { - return ""; - } - } - else if (current is JArray arr) - { - if (int.TryParse(element, out var idx) && idx > 0 && idx < arr.Count) - { - return arr[idx]; - } - else - { - return ""; - } - } - else - { - var property = current.GetType().GetProperties().FirstOrDefault(x => x.CanRead && string.Equals(x.Name, element, StringComparison.OrdinalIgnoreCase)); + CSV, + JSON + } - if (property != null) - { - current = property.GetValue(current); - } - else - { - return ""; - } - } - } + [Validator(typeof(ImportArgumentsValidator))] + public sealed class ImportArguments : IArgumentModel + { + [Argument(Name = "schema", Description = "The name of the schema.")] + public string Schema { get; set; } - if (current is JValue value) - { - return value.Value; - } - else if (current?.GetType().IsClass == true) - { - return current.JsonString(); - } - else + [Argument(Name = "file", Description = "The path to the csv file.")] + public string File { get; set; } + + [Option(LongName = "fields", Description = "Comma separated list of fields to import.")] + public string Fields { get; set; } + + [Option(LongName = "unpublished", ShortName = "u", Description = "Import unpublished content.")] + public bool Unpublished { get; set; } + + [Option(LongName = "delimiter", Description = "The csv delimiter.")] + public string Delimiter { get; set; } = ";"; + + public sealed class ImportArgumentsValidator : AbstractValidator { - return current; + public ImportArgumentsValidator() + { + RuleFor(x => x.Delimiter).NotEmpty(); + RuleFor(x => x.Fields).NotEmpty(); + RuleFor(x => x.File).NotEmpty(); + RuleFor(x => x.Schema).NotEmpty(); + } } } - public enum Format - { - CSV, - JSON - } - [Validator(typeof(ExportArgumentsValidator))] public sealed class ExportArguments : IArgumentModel { @@ -332,6 +311,9 @@ public sealed class ExportArguments : IArgumentModel [Option(LongName = "output", Description = "Optional file or folder name. Default: Schema name.")] public string Output { get; set; } + [Option(LongName = "delimiter", Description = "The csv delimiter.")] + public string Delimiter { get; set; } = ";"; + [Option(LongName = "unpublished", ShortName = "u", Description = "Export unpublished content.")] public bool Unpublished { get; set; } @@ -348,6 +330,7 @@ public sealed class ExportArgumentsValidator : AbstractValidator x.Delimiter).NotEmpty(); RuleFor(x => x.Schema).NotEmpty(); } } diff --git a/cli/Squidex.CLI/Squidex.CLI/Commands/Implementation/Csv2SquidexConverter.cs b/cli/Squidex.CLI/Squidex.CLI/Commands/Implementation/Csv2SquidexConverter.cs new file mode 100644 index 00000000..6a30ec80 --- /dev/null +++ b/cli/Squidex.CLI/Squidex.CLI/Commands/Implementation/Csv2SquidexConverter.cs @@ -0,0 +1,129 @@ +// ========================================================================== +// Squidex Headless CMS +// ========================================================================== +// Copyright (c) Squidex UG (haftungsbeschraenkt) +// All rights reserved. Licensed under the MIT license. +// ========================================================================== + +using System.Collections.Generic; +using CsvHelper; +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; +using Squidex.ClientLibrary; + +namespace Squidex.CLI.Commands.Implementation +{ + public sealed class Csv2SquidexConverter + { + private readonly JsonMapping mapping = new JsonMapping(); + + public Csv2SquidexConverter(string fields) + { + mapping = JsonMapping.ForCsv2Json(fields); + } + + public IEnumerable ReadAll(CsvReader csvReader) + { + if (csvReader.Read()) + { + csvReader.ReadHeader(); + + while (csvReader.Read()) + { + var data = new DummyData(); + + foreach (var field in mapping) + { + if (csvReader.TryGetField(field.Name, out var value)) + { + try + { + SetValue(data, JToken.Parse(value), field.Path); + } + catch (JsonReaderException) + { + SetValue(data, JToken.Parse($"\"{value}\""), field.Path); + } + } + } + + yield return data; + } + } + } + + private void SetValue(DummyData data, JToken value, JsonPath path) + { + if (!data.TryGetValue(path[0].Key, out var property)) + { + property = new Dictionary(); + + data[path[0].Key] = property; + } + + object AddElement(object parent, string key, int index, JToken currentValue, bool merge) + { + if (index >= 0) + { + if (parent is JArray array) + { + while (array.Count < index + 1) + { + array.Add(null); + } + + if (merge && array[index].Type == currentValue.Type) + { + return array[index]; + } + + array[index] = currentValue; + + return currentValue; + } + } + else + { + if (parent is IDictionary obj) + { + if (merge && obj.TryGetValue(key, out var temp) && temp.Type == currentValue.Type) + { + return temp; + } + + obj[key] = currentValue; + + return currentValue; + } + } + + throw new SquidexException("Invalid json mapping."); + } + + object container = property; + + for (var i = 1; i < path.Count; i++) + { + var (key, index) = path[i]; + + if (i == path.Count - 1) + { + AddElement(container, key, index, value, false); + } + else + { + var (_, next) = path[i + 1]; + + if (next >= 0) + { + container = AddElement(container, key, index, new JArray(), true); + } + else + { + container = AddElement(container, key, index, new JObject(), true); + } + } + } + } + } +} diff --git a/cli/Squidex.CLI/Squidex.CLI/Commands/Implementation/JsonMapping.cs b/cli/Squidex.CLI/Squidex.CLI/Commands/Implementation/JsonMapping.cs new file mode 100644 index 00000000..59021ea0 --- /dev/null +++ b/cli/Squidex.CLI/Squidex.CLI/Commands/Implementation/JsonMapping.cs @@ -0,0 +1,114 @@ +// ========================================================================== +// Squidex Headless CMS +// ========================================================================== +// Copyright (c) Squidex UG (haftungsbeschraenkt) +// All rights reserved. Licensed under the MIT license. +// ========================================================================== + +using System; +using System.Collections.Generic; +using Squidex.ClientLibrary; + +namespace Squidex.CLI.Commands.Implementation +{ + public sealed class JsonMapping : List<(string Name, JsonPath Path)> + { + public static JsonMapping ForJson2Csv(string fields) + { + fields = fields ?? string.Empty; + + var result = new JsonMapping(); + + foreach (var item in fields.Split(new[] { ',', ';' }, StringSplitOptions.RemoveEmptyEntries)) + { + var parts = item.Split('='); + + JsonPath GetPath(string value) + { + var path = JsonPath.Parse(value); + + if (path.Count == 2 && (IsData(path) || IsDataDraft(path))) + { + path.Add(("iv", -1)); + } + + return path; + } + + if (parts.Length == 1) + { + result.Add((parts[0], GetPath(parts[0]))); + } + else if (parts.Length == 2) + { + result.Add((parts[0], GetPath(parts[1]))); + } + else + { + throw new SquidexException("Field definition not valid."); + } + } + + if (result.Count == 0) + { + throw new SquidexException("Field definition not valid."); + } + + return result; + } + + public static JsonMapping ForCsv2Json(string fields) + { + fields = fields ?? string.Empty; + + var result = new JsonMapping(); + + foreach (var item in fields.Split(new[] { ',', ';' }, StringSplitOptions.RemoveEmptyEntries)) + { + var parts = item.Split('='); + + JsonPath GetPath(string value) + { + var path = JsonPath.Parse(value); + + if (path.Count == 1) + { + path.Add(("iv", -1)); + } + + return path; + } + + if (parts.Length == 1) + { + result.Add((parts[0], GetPath(parts[0]))); + } + else if (parts.Length == 2) + { + result.Add((parts[1], GetPath(parts[0]))); + } + else + { + throw new SquidexException("Field definition not valid."); + } + } + + if (result.Count == 0) + { + throw new SquidexException("Field definition not valid."); + } + + return result; + } + + private static bool IsDataDraft(JsonPath path) + { + return string.Equals(path[0].Key, "DataDraft", StringComparison.OrdinalIgnoreCase); + } + + private static bool IsData(JsonPath path) + { + return string.Equals(path[0].Key, "Data", StringComparison.OrdinalIgnoreCase); + } + } +} diff --git a/cli/Squidex.CLI/Squidex.CLI/Commands/Implementation/JsonPath.cs b/cli/Squidex.CLI/Squidex.CLI/Commands/Implementation/JsonPath.cs new file mode 100644 index 00000000..650a57ff --- /dev/null +++ b/cli/Squidex.CLI/Squidex.CLI/Commands/Implementation/JsonPath.cs @@ -0,0 +1,35 @@ +// ========================================================================== +// Squidex Headless CMS +// ========================================================================== +// Copyright (c) Squidex UG (haftungsbeschraenkt) +// All rights reserved. Licensed under the MIT license. +// ========================================================================== + +using System; +using System.Collections.Generic; +using System.Globalization; + +namespace Squidex.CLI.Commands.Implementation +{ + public sealed class JsonPath : List<(string Key, int Index)> + { + public static JsonPath Parse(string value) + { + var result = new JsonPath(); + + var path = value.Split('.', StringSplitOptions.RemoveEmptyEntries); + + foreach (var element in path) + { + if (!int.TryParse(element, NumberStyles.Integer, CultureInfo.InvariantCulture, out var index)) + { + index = -1; + } + + result.Add((element, index)); + } + + return result; + } + } +} diff --git a/cli/Squidex.CLI/Squidex.CLI/Commands/Implementation/Squidex2CsvConverter.cs b/cli/Squidex.CLI/Squidex.CLI/Commands/Implementation/Squidex2CsvConverter.cs new file mode 100644 index 00000000..a25cda80 --- /dev/null +++ b/cli/Squidex.CLI/Squidex.CLI/Commands/Implementation/Squidex2CsvConverter.cs @@ -0,0 +1,122 @@ +// ========================================================================== +// Squidex Headless CMS +// ========================================================================== +// Copyright (c) Squidex UG (haftungsbeschraenkt) +// All rights reserved. Licensed under the MIT license. +// ========================================================================== + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Linq; +using Newtonsoft.Json.Linq; + +namespace Squidex.CLI.Commands.Implementation +{ + public sealed class Squidex2CsvConverter + { + private readonly JsonMapping mapping; + + public IEnumerable FieldNames + { + get { return mapping.Select(x => x.Name); } + } + + public Squidex2CsvConverter(string fields) + { + mapping = JsonMapping.ForJson2Csv(fields); + } + + public IEnumerable GetValues(DummyEntity entity) + { + foreach (var field in mapping) + { + var value = GetValue(entity, field.Path); + + if (value is JValue jValue) + { + value = jValue.Value; + } + else if (value is JToken jToken) + { + value = jToken.ToString(); + } + + if (value is string text) + { + yield return text.Replace("\n", "\\n"); + } + else + { + yield return value; + } + } + } + + private object GetValue(object current, JsonPath path) + { + foreach (var (key, index) in path) + { + if (current is JObject obj) + { + if (obj.TryGetValue(key, out var temp)) + { + current = temp; + } + else + { + return ""; + } + } + else if (current is IDictionary dict) + { + if (dict.Contains(key)) + { + current = dict[key]; + } + else + { + return ""; + } + } + else if (current is JArray arr) + { + if (index >= 0 && index < arr.Count) + { + return arr[index]; + } + else + { + return ""; + } + } + else + { + var property = current.GetType().GetProperties().FirstOrDefault(x => x.CanRead && string.Equals(x.Name, key, StringComparison.OrdinalIgnoreCase)); + + if (property != null) + { + current = property.GetValue(current); + } + else + { + return ""; + } + } + } + + if (current is JValue value) + { + return value.Value; + } + else if (current?.GetType().IsClass == true) + { + return current.JsonString(); + } + else + { + return current; + } + } + } +} From 0a6b0d44c074989230147d372e442b5aafb4ba82 Mon Sep 17 00:00:00 2001 From: Alexander Winnen Date: Sun, 2 Jun 2019 19:54:46 +0200 Subject: [PATCH 7/7] add option to remove backup from app after it has been downloaded --- cli/Squidex.CLI/Squidex.CLI/Commands/App_Backup.cs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/cli/Squidex.CLI/Squidex.CLI/Commands/App_Backup.cs b/cli/Squidex.CLI/Squidex.CLI/Commands/App_Backup.cs index 4bad0ea3..e10762b0 100644 --- a/cli/Squidex.CLI/Squidex.CLI/Commands/App_Backup.cs +++ b/cli/Squidex.CLI/Squidex.CLI/Commands/App_Backup.cs @@ -75,6 +75,12 @@ public async Task Create(CreateArguments arguments) } Console.WriteLine("Backup completed. Download completed"); + + if (arguments.DeleteAfterDownload) + { + Console.WriteLine("Removing backup from app..."); + await backupsClient.DeleteBackupAsync(app, foundBackup.Id.ToString()); + } } else { @@ -88,6 +94,9 @@ public sealed class CreateArguments : IArgumentModel [Option(LongName = "timeout", Description = "The timeout to wait for the backup in minutes.")] public int Timeout { get; set; } = 30; + [Option(LongName = "deleteAfterDownload", Description = "Defines wether the created backup shall be deleted from app after the backup task is completed")] + public bool DeleteAfterDownload { get; set; } + [Argument(Name = "file", Description = "The target file.")] public string File { get; set; }