From 0f45c4ac995820e1f522cd1e81f1e7cd2d10816f Mon Sep 17 00:00:00 2001 From: Sebastian Stehle Date: Fri, 12 May 2017 17:43:42 +0200 Subject: [PATCH] Closes #46 Closes #47 --- src/Squidex.Core/Contents/ContentData.cs | 58 +++++++++++++++++-- .../Contents/MongoContentEntity.cs | 4 +- .../angular/json-editor.component.ts | 48 +++++++++------ .../Contents/ContentDataTests.cs | 52 +++++++++++++++-- 4 files changed, 135 insertions(+), 27 deletions(-) diff --git a/src/Squidex.Core/Contents/ContentData.cs b/src/Squidex.Core/Contents/ContentData.cs index 397a2daf3..04ac951a9 100644 --- a/src/Squidex.Core/Contents/ContentData.cs +++ b/src/Squidex.Core/Contents/ContentData.cs @@ -9,6 +9,7 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Text; using Newtonsoft.Json.Linq; using Squidex.Core.Schemas; using Squidex.Infrastructure; @@ -84,7 +85,7 @@ namespace Squidex.Core.Contents return result; } - public ContentData ToIdModel(Schema schema) + public ContentData ToIdModel(Schema schema, bool encodeJsonField) { Guard.NotNull(schema, nameof(schema)); @@ -97,13 +98,38 @@ namespace Squidex.Core.Contents continue; } - result[field.Id.ToString()] = fieldValue.Value; + var fieldId = field.Id.ToString(); + + if (encodeJsonField && field is JsonField) + { + var encodedValue = new ContentFieldData(); + + foreach (var languageValue in fieldValue.Value) + { + if (languageValue.Value == null || languageValue.Value.Type == JTokenType.Null) + { + encodedValue[languageValue.Key] = null; + } + else + { + var value = Convert.ToBase64String(Encoding.UTF8.GetBytes(languageValue.Value.ToString())); + + encodedValue[languageValue.Key] = value; + } + } + + result[fieldId] = encodedValue; + } + else + { + result[fieldId] = fieldValue.Value; + } } return result; } - public ContentData ToNameModel(Schema schema) + public ContentData ToNameModel(Schema schema, bool decodeJsonField) { Guard.NotNull(schema, nameof(schema)); @@ -116,7 +142,31 @@ namespace Squidex.Core.Contents continue; } - result[field.Name] = fieldValue.Value; + if (decodeJsonField && field is JsonField) + { + var encodedValue = new ContentFieldData(); + + foreach (var languageValue in fieldValue.Value) + { + if (languageValue.Value == null || languageValue.Value.Type == JTokenType.Null) + { + encodedValue[languageValue.Key] = null; + } + else + { + var value = Encoding.UTF8.GetString(Convert.FromBase64String(languageValue.Value.ToString())); + + encodedValue[languageValue.Key] = JToken.Parse(value); + } + } + + result[field.Name] = encodedValue; + } + else + { + + result[field.Name] = fieldValue.Value; + } } return result; diff --git a/src/Squidex.Read.MongoDb/Contents/MongoContentEntity.cs b/src/Squidex.Read.MongoDb/Contents/MongoContentEntity.cs index ff852b4e9..fcc151133 100644 --- a/src/Squidex.Read.MongoDb/Contents/MongoContentEntity.cs +++ b/src/Squidex.Read.MongoDb/Contents/MongoContentEntity.cs @@ -69,7 +69,7 @@ namespace Squidex.Read.MongoDb.Contents { if (Data != null) { - contentData = JsonConvert.DeserializeObject(Data.ToJson()).ToNameModel(schema); + contentData = JsonConvert.DeserializeObject(Data.ToJson()).ToNameModel(schema, true); } else { @@ -81,7 +81,7 @@ namespace Squidex.Read.MongoDb.Contents { if (newContentData != null) { - Data = BsonDocument.Parse(JsonConvert.SerializeObject(newContentData.ToIdModel(schema))); + Data = BsonDocument.Parse(JsonConvert.SerializeObject(newContentData.ToIdModel(schema, true))); } else { diff --git a/src/Squidex/app/framework/angular/json-editor.component.ts b/src/Squidex/app/framework/angular/json-editor.component.ts index 69f2de38f..281d7d863 100644 --- a/src/Squidex/app/framework/angular/json-editor.component.ts +++ b/src/Squidex/app/framework/angular/json-editor.component.ts @@ -30,7 +30,8 @@ export class JsonEditorComponent implements ControlValueAccessor, AfterViewInit private touchedCallback: () => void = NOOP; private valueChanged = new Subject(); private aceEditor: any; - private value: any; + private oldValue: any; + private oldValueString: string; private isDisabled = false; @ViewChild('editor') @@ -42,7 +43,8 @@ export class JsonEditorComponent implements ControlValueAccessor, AfterViewInit } public writeValue(value: any) { - this.value = value; + this.oldValue = value; + this.oldValueString = JSON.stringify(value); if (this.aceEditor) { this.setValue(value); @@ -66,21 +68,9 @@ export class JsonEditorComponent implements ControlValueAccessor, AfterViewInit } public ngAfterViewInit() { - this.valueChanged.debounceTime(1000) + this.valueChanged.debounceTime(500) .subscribe(() => { - const isValid = this.aceEditor.getSession().getAnnotations().length === 0; - - if (!isValid) { - this.changeCallback(null); - } else { - try { - const value = JSON.parse(this.aceEditor.getValue()); - - this.changeCallback(value); - } catch (e) { - this.changeCallback(null); - } - } + this.changeValue(); }); this.resourceLoader.loadScript('https://cdnjs.cloudflare.com/ajax/libs/ace/1.2.6/ace.js').then(() => { @@ -90,9 +80,10 @@ export class JsonEditorComponent implements ControlValueAccessor, AfterViewInit this.aceEditor.setReadOnly(this.isDisabled); this.aceEditor.setFontSize(14); - this.setValue(this.value); + this.setValue(this.oldValue); this.aceEditor.on('blur', () => { + this.changeValue(); this.touchedCallback(); }); @@ -102,6 +93,29 @@ export class JsonEditorComponent implements ControlValueAccessor, AfterViewInit }); } + private changeValue() { + const isValid = this.aceEditor.getSession().getAnnotations().length === 0; + + let newValue: any = null; + + if (isValid) { + try { + newValue = JSON.parse(this.aceEditor.getValue()); + } catch (e) { + newValue = null; + } + } + + const newValueString = JSON.stringify(newValue); + + if (this.oldValueString !== newValueString) { + this.changeCallback(newValue); + } + + this.oldValue = newValue; + this.oldValueString = newValueString; + } + private setValue(value: any) { if (value) { const jsonString = JSON.stringify(value, undefined, 4); diff --git a/tests/Squidex.Core.Tests/Contents/ContentDataTests.cs b/tests/Squidex.Core.Tests/Contents/ContentDataTests.cs index 62eca4396..de1fddc6c 100644 --- a/tests/Squidex.Core.Tests/Contents/ContentDataTests.cs +++ b/tests/Squidex.Core.Tests/Contents/ContentDataTests.cs @@ -24,6 +24,8 @@ namespace Squidex.Core.Contents new NumberFieldProperties { IsLocalizable = false })) .AddOrUpdateField(new NumberField(3, "field3", new NumberFieldProperties { IsLocalizable = false })) + .AddOrUpdateField(new JsonField(4, "json", + new JsonFieldProperties { IsLocalizable = true })) .HideField(3); private readonly LanguagesConfig languagesConfig = LanguagesConfig.Create(Language.EN, Language.DE); @@ -43,7 +45,7 @@ namespace Squidex.Core.Contents new ContentFieldData() .AddValue("iv", 3)); - var actual = input.ToIdModel(schema); + var actual = input.ToIdModel(schema, false); var expected = new ContentData() @@ -57,9 +59,33 @@ namespace Squidex.Core.Contents Assert.Equal(expected, actual); } - + + [Fact] + public void Should_convert_to_encoded_id_model() + { + var input = + new ContentData() + .AddField("json", + new ContentFieldData() + .AddValue("en", new JObject()) + .AddValue("de", null) + .AddValue("it", JValue.CreateNull())); + + var actual = input.ToIdModel(schema, true); + + var expected = + new ContentData() + .AddField("4", + new ContentFieldData() + .AddValue("en", "e30=") + .AddValue("de", null) + .AddValue("it", null)); + + Assert.Equal(expected, actual); + } + [Fact] - public void Should_convert_to_from_id_model() + public void Should_convert_from_id_model() { var input = new ContentData() @@ -74,7 +100,7 @@ namespace Squidex.Core.Contents new ContentFieldData() .AddValue("iv", 3)); - var actual = input.ToNameModel(schema); + var actual = input.ToNameModel(schema, false); var expected = new ContentData() @@ -88,6 +114,23 @@ namespace Squidex.Core.Contents Assert.Equal(expected, actual); } + + [Fact] + public void Should_convert_from_encoded_id_model() + { + var input = + new ContentData() + .AddField("4", + new ContentFieldData() + .AddValue("en", "e30=") + .AddValue("de", null) + .AddValue("it", null)); + + var actual = input.ToNameModel(schema, true); + + Assert.True(actual["json"]["en"] is JObject); + } + [Fact] public void Should_cleanup_old_fields() { @@ -112,6 +155,7 @@ namespace Squidex.Core.Contents Assert.Equal(expected, actual); } + [Fact] public void Should_cleanup_old_languages() {