From 6433edb9d403ff3ce4a409be24c2d529bddf1198 Mon Sep 17 00:00:00 2001 From: Ivar Date: Tue, 26 Apr 2022 11:54:39 +0200 Subject: [PATCH 1/7] WIP: Auto generate model First somewhat working sample --- .../Altinn.App.ModelGenerator.Tests.csproj | 31 ++ .../LayoutToModelTests.cs | 31 ++ .../TestData/FileDataAttribute.cs | 20 ++ .../TestData/LayoutToModel/FormLayout.json | 332 ++++++++++++++++++ .../TestData/LayoutToModel/Summary.json | 137 ++++++++ .../TestData/LayoutToModel/model.cs | 40 +++ .../Altinn.App.ModelGenerator.csproj | 19 + .../LayoutToModel.cs | 53 +++ .../ModelSourceGenerator.cs | 37 ++ .../models/ThreeRep.cs | 42 +++ .../utils/PathUtils.cs | 39 ++ src/App/AppRef.csproj | 12 +- 12 files changed, 791 insertions(+), 2 deletions(-) create mode 100644 src/Altinn.App.ModelGenerator.Tests/Altinn.App.ModelGenerator.Tests.csproj create mode 100644 src/Altinn.App.ModelGenerator.Tests/LayoutToModelTests.cs create mode 100644 src/Altinn.App.ModelGenerator.Tests/TestData/FileDataAttribute.cs create mode 100644 src/Altinn.App.ModelGenerator.Tests/TestData/LayoutToModel/FormLayout.json create mode 100644 src/Altinn.App.ModelGenerator.Tests/TestData/LayoutToModel/Summary.json create mode 100644 src/Altinn.App.ModelGenerator.Tests/TestData/LayoutToModel/model.cs create mode 100644 src/Altinn.App.ModelGenerator/Altinn.App.ModelGenerator.csproj create mode 100644 src/Altinn.App.ModelGenerator/LayoutToModel.cs create mode 100644 src/Altinn.App.ModelGenerator/ModelSourceGenerator.cs create mode 100644 src/Altinn.App.ModelGenerator/models/ThreeRep.cs create mode 100644 src/Altinn.App.ModelGenerator/utils/PathUtils.cs diff --git a/src/Altinn.App.ModelGenerator.Tests/Altinn.App.ModelGenerator.Tests.csproj b/src/Altinn.App.ModelGenerator.Tests/Altinn.App.ModelGenerator.Tests.csproj new file mode 100644 index 00000000..8d207c3f --- /dev/null +++ b/src/Altinn.App.ModelGenerator.Tests/Altinn.App.ModelGenerator.Tests.csproj @@ -0,0 +1,31 @@ + + + + net6.0 + enable + + false + + + + + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + + + + + + Always + + + + diff --git a/src/Altinn.App.ModelGenerator.Tests/LayoutToModelTests.cs b/src/Altinn.App.ModelGenerator.Tests/LayoutToModelTests.cs new file mode 100644 index 00000000..d1e93c1f --- /dev/null +++ b/src/Altinn.App.ModelGenerator.Tests/LayoutToModelTests.cs @@ -0,0 +1,31 @@ +using System.Text.Json; +using System.Collections.Generic; +using Altinn.App.ModelGenerator; +using Xunit; + +namespace Altinn.App.ModelGenerator.Tests; + +public class LayoutToModelTests +{ + [Theory] + [FileDataAttribute("LayoutToModel/FormLayout.json", "LayoutToModel/Summary.json", "LayoutToModel/bindings.json", "LayoutToModel/model.cs")] + public void TestGetModelDataBindings(string FormLayout, string summary, string expectedBindings, string expectedModel) + { + // while (!System.Diagnostics.Debugger.IsAttached) + // System.Threading.Thread.Sleep(500); + // System.Diagnostics.Debugger.Break(); + + var bindings = LayoutToModel.GetDataModelBindings(new string[]{FormLayout, summary}); + Assert.Equal(JsonSerializer.Deserialize>(expectedBindings), bindings); + var generatedModel = LayoutToModel.Convert(bindings, "Altinn.App.Models.Model"); + Assert.Equal(expectedModel, generatedModel); + } + [Theory] + [InlineData("Altinn.App.Models.KRT1226Gjenopprettingsplaner_M", "Altinn.App.Models", "KRT1226Gjenopprettingsplaner_M")] + public void TestSplitNamespace(string fullClassName, string expectedNs, string expectedClassName) + { + var(ns, className) = LayoutToModel.SplitFullClassname(fullClassName); + Assert.Equal(expectedNs, ns); + Assert.Equal(expectedClassName, className); + } +} \ No newline at end of file diff --git a/src/Altinn.App.ModelGenerator.Tests/TestData/FileDataAttribute.cs b/src/Altinn.App.ModelGenerator.Tests/TestData/FileDataAttribute.cs new file mode 100644 index 00000000..ad5e765a --- /dev/null +++ b/src/Altinn.App.ModelGenerator.Tests/TestData/FileDataAttribute.cs @@ -0,0 +1,20 @@ +using Xunit.Sdk; +using System.Collections.Generic; +using System.IO; +using System.Reflection; +using System.Linq; + +namespace Altinn.App.ModelGenerator.Tests; + +public class FileDataAttribute : DataAttribute +{ + private readonly string[] Files; + public FileDataAttribute(params string[] files) + { + Files = files; + } + public override IEnumerable GetData(MethodInfo methodInfo) + { + return new List{Files.Select(f=>File.ReadAllText(Path.Join("TestData",f))).ToArray()}; + } +} \ No newline at end of file diff --git a/src/Altinn.App.ModelGenerator.Tests/TestData/LayoutToModel/FormLayout.json b/src/Altinn.App.ModelGenerator.Tests/TestData/LayoutToModel/FormLayout.json new file mode 100644 index 00000000..07a176ad --- /dev/null +++ b/src/Altinn.App.ModelGenerator.Tests/TestData/LayoutToModel/FormLayout.json @@ -0,0 +1,332 @@ +{ + "$schema": "https://altinncdn.no/schemas/json/layout/layout.schema.v1.json", + "data": { + "layout": [ + { + "id": "Info", + "type": "Paragraph", + "textResourceBindings": { + "title": "0.info" + }, + "dataModelBindings": {} + }, + { + "id": "Header1", + "type": "Header", + "textResourceBindings": { + "title": "1.generalInfo" + }, + "dataModelBindings": {}, + "size": "S", + "readOnly": true + }, + { + "id": "1-1", + "type": "Input", + "textResourceBindings": { + "title": "1.1.orgNr" + }, + "dataModelBindings": { + "simpleBinding": "rapport.innsender.foretak.organisasjonsnummer.value" + }, + "required": true, + "readOnly": true, + "grid": { + "labelGrid": { + "sm": 6 + }, + "innerGrid": { + "sm": 6 + } + } + }, + { + "id": "1-2", + "type": "Input", + "textResourceBindings": { + "title": "1.2.name" + }, + "dataModelBindings": { + "simpleBinding": "rapport.innsender.foretak.navn.value" + }, + "grid": { + "labelGrid": { + "sm": 6 + }, + "innerGrid": { + "sm": 6 + } + }, + "required": true, + "readOnly": true + }, + { + "id": "1-3-address", + "type": "Input", + "textResourceBindings": { + "title": "1.3.address" + }, + "dataModelBindings": { + "simpleBinding": "rapport.innsender.adresse.adresselinje1.value" + }, + "required": false, + "readOnly": true, + "grid": { + "labelGrid": { + "sm": 6 + }, + "innerGrid": { + "sm": 6 + } + } + }, + { + "id": "1-4-postcode", + "type": "Input", + "textResourceBindings": { + "title": "1.4.postCode" + }, + "dataModelBindings": { + "simpleBinding": "rapport.innsender.adresse.postnummer.value" + }, + "required": false, + "readOnly": true, + "grid": { + "sm": 6, + "innerGrid": { + "sm": 6 + } + } + }, + { + "id": "1-5-postcity", + "type": "Input", + "textResourceBindings": { + "title": "1.5.postCity" + }, + "dataModelBindings": { + "simpleBinding": "rapport.innsender.adresse.poststed.value" + }, + "grid": { + "sm": 4 + }, + "required": false, + "readOnly": true + }, + { + "id": "Header2", + "type": "Header", + "textResourceBindings": { + "title": "2.contactInfo" + }, + "dataModelBindings": {}, + "size": "S", + "readOnly": true + }, + { + "id": "2-1", + "type": "Input", + "textResourceBindings": { + "title": "2.1.contact1.name" + }, + "dataModelBindings": { + "simpleBinding": "rapport.rapportering.kontaktperson1.navn.value" + }, + "required": true, + "readOnly": false, + "grid": { + "labelGrid": { + "sm": 6 + }, + "innerGrid": { + "sm": 6 + } + } + }, + { + "id": "2-2", + "type": "Input", + "textResourceBindings": { + "title": "2.2.contact1.mail" + }, + "dataModelBindings": { + "simpleBinding": "rapport.rapportering.kontaktperson1.epost.value" + }, + "required": true, + "readOnly": false, + "grid": { + "labelGrid": { + "sm": 6 + }, + "innerGrid": { + "sm": 6 + }, + "formatting":{ + "Input": "Email" + } + } + }, + { + "id": "2-3Prefix", + "type": "Input", + "textResourceBindings": { + "title": "2.3.contact1.prefix" + }, + "dataModelBindings": { + "simpleBinding": "rapport.rapportering.kontaktperson1.telefonprefiks.value" + }, + "grid": { + "sm": 6, + "innerGrid": { + "sm": 3 + } + }, + "required": true, + "readOnly": false + }, + { + "id": "2-3", + "type": "Input", + "textResourceBindings": { + "title": "2.3.contact1.tlf" + }, + "dataModelBindings": { + "simpleBinding": "rapport.rapportering.kontaktperson1.telefonnummer.value" + }, + "grid": { + "sm": 6, + "innerGrid": { + "sm": 6 + } + }, + "required": true, + "readOnly": false, + "formatting": { + "number": { + "format": "### ## ###" + } + } + }, + { + "id": "2-4", + "type": "Input", + "textResourceBindings": { + "title": "2.4.contact2.name" + }, + "dataModelBindings": { + "simpleBinding": "rapport.rapportering.kontaktperson2.navn.value" + }, + "required": false, + "readOnly": false, + "grid": { + "labelGrid": { + "sm": 6 + }, + "innerGrid": { + "sm": 6 + } + } + }, + { + "id": "2-5", + "type": "Input", + "textResourceBindings": { + "title": "2.5.contact2.mail" + }, + "dataModelBindings": { + "simpleBinding": "rapport.rapportering.kontaktperson2.epost.value" + }, + "required": false, + "readOnly": false, + "grid": { + "labelGrid": { + "sm": 6 + }, + "innerGrid": { + "sm": 6 + } + } + }, + { + "id": "2-6Prefix", + "type": "Input", + "textResourceBindings": { + "title": "2.6.contact2.prefix" + }, + "dataModelBindings": { + "simpleBinding": "rapport.rapportering.kontaktperson2.telefonprefiks.value" + }, + "grid": { + "sm": 6, + "innerGrid": { + "sm": 3 + } + }, + "required": false, + "readOnly": false + }, + { + "id": "I2-6", + "type": "Input", + "textResourceBindings": { + "title": "2.6.contact2.tlf" + }, + "dataModelBindings": { + "simpleBinding": "rapport.rapportering.kontaktperson2.telefonnummer.value" + }, + "grid": { + "sm": 6, + "innerGrid": { + "sm": 6 + } + }, + "required": false, + "readOnly": false, + "formatting": { + "number": { + "format": "### ## ###" + } + } + }, + { + "id": "FilOpplasting", + "type": "FileUpload", + "textResourceBindings": { + "title": "Vedlegg" + }, + "dataModelBindings": {}, + "maxFileSizeInMB": 190, + "maxNumberOfAttachments": 25, + "minNumberOfAttachments": 1, + "displayMode": "list", + "required": true, + "hasCustomFileEndings": true, + "validFileEndings": ".pdf, .xls, .xlsx, .doc, .docx, .rtf, .jpg, .jpeg, .txt, .pptx, .ppt, .zip, .odp, .ods, .odt" + }, + { + "id": "4-0", + "type": "TextArea", + "textResourceBindings": { + "title": "4.description", + "help": "4.description.hint" + }, + "dataModelBindings": { + "simpleBinding": "rapport.rapportering.beskrivelse.value" + }, + "required": false, + "readOnly": false + }, + { + "id": "Tilbake-knapp", + "type": "NavigationButtons", + "componentType": "NavigationButtons", + "textResourceBindings": { + "next": "button.next", + "back": "back" + }, + "dataModelBindings": {}, + "showBackButton": false + } + ] + } + } \ No newline at end of file diff --git a/src/Altinn.App.ModelGenerator.Tests/TestData/LayoutToModel/Summary.json b/src/Altinn.App.ModelGenerator.Tests/TestData/LayoutToModel/Summary.json new file mode 100644 index 00000000..d3bf5857 --- /dev/null +++ b/src/Altinn.App.ModelGenerator.Tests/TestData/LayoutToModel/Summary.json @@ -0,0 +1,137 @@ +{ + "$schema": "https://altinncdn.no/schemas/json/layout/layout.schema.v1.json", + "data": { + "layout": [ + { + "id": "summary-1header", + "type": "Summary", + "componentRef": "Header1", + "pageRef": "FormLayout" + + }, + { + "id": "summary-11-orgnr", + "type": "Summary", + "componentRef": "1-1", + "pageRef": "FormLayout" + }, + { + "id": "summary-12-orgname", + "type": "Summary", + "componentRef": "1-2", + "pageRef": "FormLayout" + }, + { + "id": "summary-13-orgadresse", + "type": "Summary", + "componentRef": "1-3-address", + "pageRef": "FormLayout" + }, + { + "id": "summary-14-orgpostcode", + "type": "Summary", + "componentRef": "1-4-postcode", + "pageRef": "FormLayout", + "grid": { + "sm": 4 + } + }, + { + "id": "summary-15-orgpostcity", + "type": "Summary", + "componentRef": "1-5-postcity", + "pageRef": "FormLayout", + "grid": { + "sm": 8 + } + }, + { + "id": "summary-2header", + "type": "Summary", + "componentRef": "Header2", + "pageRef": "FormLayout" + + }, + { + "id": "summary-21-name1", + "type": "Summary", + "componentRef": "2-1", + "pageRef": "FormLayout" + }, + { + "id": "summary-22-email1", + "type": "Summary", + "componentRef": "2-2", + "pageRef": "FormLayout" + }, + { + "id": "summary-23-tlfprefix1", + "type": "Summary", + "componentRef": "2-3Prefix", + "pageRef": "FormLayout", + "grid": { + "sm": 4 + } + }, + { + "id": "summary-23-tlf1", + "type": "Summary", + "componentRef": "2-3", + "pageRef": "FormLayout", + "grid": { + "sm": 8 + } + }, + { + "id": "summary-24-name2", + "type": "Summary", + "componentRef": "2-4", + "pageRef": "FormLayout" + }, + { + "id": "summary-25-email2", + "type": "Summary", + "componentRef": "2-5", + "pageRef": "FormLayout" + }, + { + "id": "summary-26-tlfprefix2", + "type": "Summary", + "componentRef": "2-6Prefix", + "pageRef": "FormLayout", + "grid": { + "sm": 4 + } + }, + { + "id": "summary-26-tlf2", + "type": "Summary", + "componentRef": "I2-6", + "pageRef": "FormLayout", + "grid": { + "sm": 8 + } + }, + { + "id": "summary-16", + "type": "Summary", + "componentRef": "FilOpplasting", + "pageRef": "FormLayout" + }, + { + "id": "summary-4", + "type": "Summary", + "componentRef": "4-0", + "pageRef": "FormLayout" + }, + { + "id": "88b9ba10-cb72-44b8-b218-a724fd9106fb", + "type": "Button", + "textResourceBindings": { + "title": "Send inn" + }, + "dataModelBindings": {} + } + ] + } + } \ No newline at end of file diff --git a/src/Altinn.App.ModelGenerator.Tests/TestData/LayoutToModel/model.cs b/src/Altinn.App.ModelGenerator.Tests/TestData/LayoutToModel/model.cs new file mode 100644 index 00000000..3e50ee1a --- /dev/null +++ b/src/Altinn.App.ModelGenerator.Tests/TestData/LayoutToModel/model.cs @@ -0,0 +1,40 @@ +public class model +{ + public rapport? rapport { get; set; } +} + +public class rapport +{ + public innsender? innsender { get; set; } + public rapportering? rapportering { get; set; } +} + +public class innsender +{ + public foretak? foretak { get; set; } + public adresse? adresse { get; set; } +} + +public class foretak +{ + public organisasjonsnummer? organisasjonsnummer { get; set; } + public navn? navn { get; set; } +} + +public class organisasjonsnummer +{ +} + + + +public class navn +{ +} + + + +public class adresse +{ +} + +public class rapportering {} diff --git a/src/Altinn.App.ModelGenerator/Altinn.App.ModelGenerator.csproj b/src/Altinn.App.ModelGenerator/Altinn.App.ModelGenerator.csproj new file mode 100644 index 00000000..f11a1445 --- /dev/null +++ b/src/Altinn.App.ModelGenerator/Altinn.App.ModelGenerator.csproj @@ -0,0 +1,19 @@ + + + + netstandard2.0 + enable + 8 + + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + + + \ No newline at end of file diff --git a/src/Altinn.App.ModelGenerator/LayoutToModel.cs b/src/Altinn.App.ModelGenerator/LayoutToModel.cs new file mode 100644 index 00000000..6716af88 --- /dev/null +++ b/src/Altinn.App.ModelGenerator/LayoutToModel.cs @@ -0,0 +1,53 @@ +using System.Collections.Generic; +using System.Linq; +using System.Text.Json; +using System.Text.Json.Nodes; +namespace Altinn.App.ModelGenerator +{ + public class LayoutToModel + { + public static string Convert(IEnumerable bindings, string fullClassName) + { + var (ns, className) = SplitFullClassname(fullClassName); + var three = new ThreeRep(className); + foreach (var binding in bindings) + { + three.AddDottedPath(binding); + } + return $"// Auto-generated\n#nullable enable\nnamespace {ns}\n{{\n\n{three.ToPoco()}\n}}\n"; + } + + public static (string, string) SplitFullClassname(string fullClassName) + { + var index = fullClassName.LastIndexOf('.'); + return (fullClassName.Substring(0,index), fullClassName.Substring(index+1)); + } + + public static List GetDataModelBindings(IEnumerable layouts) + { + var ret = new List(); + foreach (var layout in layouts) + { + var node = JsonNode.Parse(layout)?["data"]?["layout"] as JsonArray; + if (node != null) + { + foreach (var component in node) + { + var bindings = component?["dataModelBindings"] as JsonObject; + if(bindings != null) + { + foreach(var binding in bindings) + { + if((binding.Value as JsonValue)?.TryGetValue(out string? value) ?? false) + { + ret.Add(value!); + } + } + } + } + } + } + return ret; + } + } +} \ No newline at end of file diff --git a/src/Altinn.App.ModelGenerator/ModelSourceGenerator.cs b/src/Altinn.App.ModelGenerator/ModelSourceGenerator.cs new file mode 100644 index 00000000..f4a3fe8f --- /dev/null +++ b/src/Altinn.App.ModelGenerator/ModelSourceGenerator.cs @@ -0,0 +1,37 @@ +using System.Linq; +using System.IO; +using System.Text.Json.Nodes; +using Microsoft.CodeAnalysis; + +namespace Altinn.App.ModelGenerator +{ + [Generator] + public class ModelSourceGenerator : ISourceGenerator + { + public void Execute(GeneratorExecutionContext context) + { + // while (!System.Diagnostics.Debugger.IsAttached) + // System.Threading.Thread.Sleep(500); + // System.Diagnostics.Debugger.Break(); + + var layouts = context.AdditionalFiles.Where(af=>PathUtils.IsLayoutPath(af.Path)).ToDictionary(af=> new FileInfo(af.Path).Name, af=>af.GetText()!.ToString()); + var resources = context.AdditionalFiles.Where(af=>PathUtils.IsResourcePath(af.Path)).ToDictionary(af=> new FileInfo(af.Path).Name, af=>af.GetText()!.ToString()); + var applicationMetadata = context.AdditionalFiles.FirstOrDefault(af=>PathUtils.IsApplicationmetadata(af.Path))?.GetText()?.ToString(); + var settings = context.AdditionalFiles.FirstOrDefault(af=>PathUtils.IsSettings(af.Path))?.GetText()?.ToString(); + // TODO: run validations and create errors; + + var modelName = (JsonNode.Parse(applicationMetadata!)?["dataTypes"] as JsonArray)?.FirstOrDefault(dt=>dt?["appLogic"] != null)?["appLogic"]?["classRef"]?.GetValue(); + // modelName = "Altinn.App.Models.KRT1226Gjenopprettingsplaner_M"; + var bindings = LayoutToModel.GetDataModelBindings(layouts.Values); + var generatedModel = LayoutToModel.Convert(bindings, modelName!); + + + context.AddSource("model.g.cs", generatedModel); + } + + public void Initialize(GeneratorInitializationContext context) + { + // No initialization required for this one + } + } +} \ No newline at end of file diff --git a/src/Altinn.App.ModelGenerator/models/ThreeRep.cs b/src/Altinn.App.ModelGenerator/models/ThreeRep.cs new file mode 100644 index 00000000..505481b7 --- /dev/null +++ b/src/Altinn.App.ModelGenerator/models/ThreeRep.cs @@ -0,0 +1,42 @@ +using System; +using System.Collections.Generic; +using System.Linq; + +namespace Altinn.App.ModelGenerator +{ + public class ThreeRep + { + private readonly string Name; + public readonly Dictionary dict = new Dictionary(); + + public ThreeRep(string name) + { + Name = name; + } + + public void AddDottedPath(string dottedPath) + { + var path = dottedPath.Split(new char[] { '.' }, 2); + var t = path[0]; + if (!dict.ContainsKey(t)) + { + dict[t] = new ThreeRep(t); + } + if (path.Length == 2) + { + var rest = path[1]; + dict[t].AddDottedPath(rest); + return; + } + } + public string ToPoco() + { + var classname = Name; + var props = dict.Select(element => $"\n\tpublic {(element.Value.dict.Count == 0 ? "string" : element.Key)}? {element.Key} {{ get; set; }}").ToList(); + if (props.Count > 0) + return $"public partial class {classname}\n{{{string.Join("", props)}\n}}\n\n" + string.Join("\n\n", dict.Values.Select(tr => tr.ToPoco())); + + return ""; + } + } +} \ No newline at end of file diff --git a/src/Altinn.App.ModelGenerator/utils/PathUtils.cs b/src/Altinn.App.ModelGenerator/utils/PathUtils.cs new file mode 100644 index 00000000..0a11b7ba --- /dev/null +++ b/src/Altinn.App.ModelGenerator/utils/PathUtils.cs @@ -0,0 +1,39 @@ +using System.IO; + +namespace Altinn.App.ModelGenerator +{ + public static class PathUtils + { + public static bool IsLayoutPath(string filePath) + { + var fileInfo = new FileInfo(filePath); + if(!fileInfo.Extension.Equals(".json", System.StringComparison.InvariantCultureIgnoreCase)) return false; + if(!fileInfo.Directory.Name.Equals("layouts", System.StringComparison.InvariantCultureIgnoreCase)) return false; + if(!fileInfo.Directory.Parent.Name.Equals("ui", System.StringComparison.InvariantCultureIgnoreCase)) return false; + return true; + } + public static bool IsResourcePath(string filePath) + { + var fileInfo = new FileInfo(filePath); + if(!fileInfo.Extension.Equals(".json", System.StringComparison.InvariantCultureIgnoreCase)) return false; + if(!fileInfo.Name.StartsWith("resource.", System.StringComparison.InvariantCultureIgnoreCase)) return false; + if(!fileInfo.Directory.Name.Equals("texts", System.StringComparison.InvariantCultureIgnoreCase)) return false; + if(!fileInfo.Directory.Parent.Name.Equals("config", System.StringComparison.InvariantCultureIgnoreCase)) return false; + return true; + } + public static bool IsApplicationmetadata(string filePath) + { + var fileInfo = new FileInfo(filePath); + if(!fileInfo.Name.Equals("applicationmetadata.json", System.StringComparison.InvariantCultureIgnoreCase)) return false; + if(!fileInfo.Directory.Name.Equals("config", System.StringComparison.InvariantCultureIgnoreCase)) return false; + return true; + } + public static bool IsSettings(string filePath) + { + var fileInfo = new FileInfo(filePath); + if(!fileInfo.Name.Equals("settings.json", System.StringComparison.InvariantCultureIgnoreCase)) return false; + if(!fileInfo.Directory.Name.Equals("ui", System.StringComparison.InvariantCultureIgnoreCase)) return false; + return true; + } + } +} \ No newline at end of file diff --git a/src/App/AppRef.csproj b/src/App/AppRef.csproj index e50c8281..ab45761f 100644 --- a/src/App/AppRef.csproj +++ b/src/App/AppRef.csproj @@ -1,9 +1,10 @@ - net5.0 + net6.0 Altinn.App Altinn.App + true @@ -18,7 +19,7 @@ - + all runtime; build; native; contentfiles; analyzers @@ -27,6 +28,13 @@ + + + + + + + ..\..\Altinn3.ruleset From f5cb7f9dfc766c6fddddde96f9cac7d83a00c879 Mon Sep 17 00:00:00 2001 From: Ivar Nesje Date: Tue, 26 Apr 2022 16:23:50 +0200 Subject: [PATCH 2/7] Add soultion references --- .../LayoutToModelTests.cs | 2 +- .../App.IntegrationTestsRef.csproj | 2 +- src/App/App.csproj | 2 +- src/AppRef.sln | 12 ++++++++++++ 4 files changed, 15 insertions(+), 3 deletions(-) diff --git a/src/Altinn.App.ModelGenerator.Tests/LayoutToModelTests.cs b/src/Altinn.App.ModelGenerator.Tests/LayoutToModelTests.cs index d1e93c1f..5b853f86 100644 --- a/src/Altinn.App.ModelGenerator.Tests/LayoutToModelTests.cs +++ b/src/Altinn.App.ModelGenerator.Tests/LayoutToModelTests.cs @@ -8,7 +8,7 @@ namespace Altinn.App.ModelGenerator.Tests; public class LayoutToModelTests { [Theory] - [FileDataAttribute("LayoutToModel/FormLayout.json", "LayoutToModel/Summary.json", "LayoutToModel/bindings.json", "LayoutToModel/model.cs")] + [FileData("LayoutToModel/FormLayout.json", "LayoutToModel/Summary.json", "LayoutToModel/bindings.json", "LayoutToModel/model.cs")] public void TestGetModelDataBindings(string FormLayout, string summary, string expectedBindings, string expectedModel) { // while (!System.Diagnostics.Debugger.IsAttached) diff --git a/src/App.IntegrationTests/App.IntegrationTestsRef.csproj b/src/App.IntegrationTests/App.IntegrationTestsRef.csproj index 007f28ba..05caabe3 100644 --- a/src/App.IntegrationTests/App.IntegrationTestsRef.csproj +++ b/src/App.IntegrationTests/App.IntegrationTestsRef.csproj @@ -1,7 +1,7 @@  - net5.0 + net6.0 false diff --git a/src/App/App.csproj b/src/App/App.csproj index 82b2430f..ddd7970f 100644 --- a/src/App/App.csproj +++ b/src/App/App.csproj @@ -1,7 +1,7 @@ - net5.0 + net6.0 Altinn.App Altinn.App diff --git a/src/AppRef.sln b/src/AppRef.sln index cf2295ba..aad63846 100644 --- a/src/AppRef.sln +++ b/src/AppRef.sln @@ -15,6 +15,10 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Altinn.App.PlatformServices EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Altinn.App.PlatformServices.Tests", "Altinn.App.PlatformServices.Tests\Altinn.App.PlatformServices.Tests.csproj", "{17D7DCE9-7797-4BC1-B448-D0529FD6FB3D}" EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Altinn.App.ModelGenerator", "Altinn.App.ModelGenerator\Altinn.App.ModelGenerator.csproj", "{1241191A-8D8A-4CD6-854C-FBA5B99B3302}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Altinn.App.ModelGenerator.Tests", "Altinn.App.ModelGenerator.Tests\Altinn.App.ModelGenerator.Tests.csproj", "{2D7A024B-6E20-4FA8-BE41-B54025A78901}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -45,6 +49,14 @@ Global {17D7DCE9-7797-4BC1-B448-D0529FD6FB3D}.Debug|Any CPU.Build.0 = Debug|Any CPU {17D7DCE9-7797-4BC1-B448-D0529FD6FB3D}.Release|Any CPU.ActiveCfg = Release|Any CPU {17D7DCE9-7797-4BC1-B448-D0529FD6FB3D}.Release|Any CPU.Build.0 = Release|Any CPU + {1241191A-8D8A-4CD6-854C-FBA5B99B3302}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {1241191A-8D8A-4CD6-854C-FBA5B99B3302}.Debug|Any CPU.Build.0 = Debug|Any CPU + {1241191A-8D8A-4CD6-854C-FBA5B99B3302}.Release|Any CPU.ActiveCfg = Release|Any CPU + {1241191A-8D8A-4CD6-854C-FBA5B99B3302}.Release|Any CPU.Build.0 = Release|Any CPU + {2D7A024B-6E20-4FA8-BE41-B54025A78901}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {2D7A024B-6E20-4FA8-BE41-B54025A78901}.Debug|Any CPU.Build.0 = Debug|Any CPU + {2D7A024B-6E20-4FA8-BE41-B54025A78901}.Release|Any CPU.ActiveCfg = Release|Any CPU + {2D7A024B-6E20-4FA8-BE41-B54025A78901}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE From 24ebf581b947aeb3ff06e215a8279e233ecae2a4 Mon Sep 17 00:00:00 2001 From: Ivar Date: Tue, 26 Apr 2022 16:26:36 +0200 Subject: [PATCH 3/7] Include sample layout (for easy testing) --- .../TestData/LayoutToModel/bindings.json | 16 + src/App/ui/Settings.json | 10 + src/App/ui/layouts/FormLayout.json | 332 ++++++++++++++++++ src/App/ui/layouts/Summary.json | 137 ++++++++ 4 files changed, 495 insertions(+) create mode 100644 src/Altinn.App.ModelGenerator.Tests/TestData/LayoutToModel/bindings.json create mode 100644 src/App/ui/Settings.json create mode 100644 src/App/ui/layouts/FormLayout.json create mode 100644 src/App/ui/layouts/Summary.json diff --git a/src/Altinn.App.ModelGenerator.Tests/TestData/LayoutToModel/bindings.json b/src/Altinn.App.ModelGenerator.Tests/TestData/LayoutToModel/bindings.json new file mode 100644 index 00000000..721860b3 --- /dev/null +++ b/src/Altinn.App.ModelGenerator.Tests/TestData/LayoutToModel/bindings.json @@ -0,0 +1,16 @@ +[ + "rapport.innsender.foretak.organisasjonsnummer.value", + "rapport.innsender.foretak.navn.value", + "rapport.innsender.adresse.adresselinje1.value", + "rapport.innsender.adresse.postnummer.value", + "rapport.innsender.adresse.poststed.value", + "rapport.rapportering.kontaktperson1.navn.value", + "rapport.rapportering.kontaktperson1.epost.value", + "rapport.rapportering.kontaktperson1.telefonprefiks.value", + "rapport.rapportering.kontaktperson1.telefonnummer.value", + "rapport.rapportering.kontaktperson2.navn.value", + "rapport.rapportering.kontaktperson2.epost.value", + "rapport.rapportering.kontaktperson2.telefonprefiks.value", + "rapport.rapportering.kontaktperson2.telefonnummer.value", + "rapport.rapportering.beskrivelse.value" +] diff --git a/src/App/ui/Settings.json b/src/App/ui/Settings.json new file mode 100644 index 00000000..de2b4e4c --- /dev/null +++ b/src/App/ui/Settings.json @@ -0,0 +1,10 @@ +{ + "$schema": "https://altinncdn.no/schemas/json/layout/layoutSettings.schema.v1.json", + "pages": { + "excludeFromPdf": ["Summary"], + "order": [ + "FormLayout", + "Summary" + ] + } +} \ No newline at end of file diff --git a/src/App/ui/layouts/FormLayout.json b/src/App/ui/layouts/FormLayout.json new file mode 100644 index 00000000..67a270b7 --- /dev/null +++ b/src/App/ui/layouts/FormLayout.json @@ -0,0 +1,332 @@ +{ + "$schema": "https://altinncdn.no/schemas/json/layout/layout.schema.v1.json", + "data": { + "layout": [ + { + "id": "Info", + "type": "Paragraph", + "textResourceBindings": { + "title": "0.info" + }, + "dataModelBindings": {} + }, + { + "id": "Header1", + "type": "Header", + "textResourceBindings": { + "title": "1.generalInfo" + }, + "dataModelBindings": {}, + "size": "S", + "readOnly": true + }, + { + "id": "1-1", + "type": "Input", + "textResourceBindings": { + "title": "1.1.orgNr" + }, + "dataModelBindings": { + "simpleBinding": "rapport.innsender.foretak.organisasjonsnummer.value" + }, + "required": true, + "readOnly": true, + "grid": { + "labelGrid": { + "sm": 6 + }, + "innerGrid": { + "sm": 6 + } + } + }, + { + "id": "1-2", + "type": "Input", + "textResourceBindings": { + "title": "1.2.name" + }, + "dataModelBindings": { + "simpleBinding": "rapport.innsender.foretak.navn.value" + }, + "grid": { + "labelGrid": { + "sm": 6 + }, + "innerGrid": { + "sm": 6 + } + }, + "required": true, + "readOnly": true + }, + { + "id": "1-3-address", + "type": "Input", + "textResourceBindings": { + "title": "1.3.address" + }, + "dataModelBindings": { + "simpleBinding": "rapport.innsender.adresse.adresselinje1.value" + }, + "required": false, + "readOnly": true, + "grid": { + "labelGrid": { + "sm": 6 + }, + "innerGrid": { + "sm": 6 + } + } + }, + { + "id": "1-4-postcode", + "type": "Input", + "textResourceBindings": { + "title": "1.4.postCode" + }, + "dataModelBindings": { + "simpleBinding": "rapport.innsender.adresse.postnummer.value" + }, + "required": false, + "readOnly": true, + "grid": { + "sm": 6, + "innerGrid": { + "sm": 6 + } + } + }, + { + "id": "1-5-postcity", + "type": "Input", + "textResourceBindings": { + "title": "1.5.postCity" + }, + "dataModelBindings": { + "simpleBinding": "rapport.innsender.adresse.poststed.value" + }, + "grid": { + "sm": 4 + }, + "required": false, + "readOnly": true + }, + { + "id": "Header2", + "type": "Header", + "textResourceBindings": { + "title": "2.contactInfo" + }, + "dataModelBindings": {}, + "size": "S", + "readOnly": true + }, + { + "id": "2-1", + "type": "Input", + "textResourceBindings": { + "title": "2.1.contact1.name" + }, + "dataModelBindings": { + "simpleBinding": "rapport.rapportering.kontaktperson1.navn1.value" + }, + "required": true, + "readOnly": false, + "grid": { + "labelGrid": { + "sm": 6 + }, + "innerGrid": { + "sm": 6 + } + } + }, + { + "id": "2-2", + "type": "Input", + "textResourceBindings": { + "title": "2.2.contact1.mail" + }, + "dataModelBindings": { + "simpleBinding": "rapport.rapportering.kontaktperson1.epost1.value" + }, + "required": true, + "readOnly": false, + "grid": { + "labelGrid": { + "sm": 6 + }, + "innerGrid": { + "sm": 6 + }, + "formatting":{ + "Input": "Email" + } + } + }, + { + "id": "2-3Prefix", + "type": "Input", + "textResourceBindings": { + "title": "2.3.contact1.prefix" + }, + "dataModelBindings": { + "simpleBinding": "rapport.rapportering.kontaktperson1.telefonprefiks1.value" + }, + "grid": { + "sm": 6, + "innerGrid": { + "sm": 3 + } + }, + "required": true, + "readOnly": false + }, + { + "id": "2-3", + "type": "Input", + "textResourceBindings": { + "title": "2.3.contact1.tlf" + }, + "dataModelBindings": { + "simpleBinding": "rapport.rapportering.kontaktperson1.telefonnummer1.value" + }, + "grid": { + "sm": 6, + "innerGrid": { + "sm": 6 + } + }, + "required": true, + "readOnly": false, + "formatting": { + "number": { + "format": "### ## ###" + } + } + }, + { + "id": "2-4", + "type": "Input", + "textResourceBindings": { + "title": "2.4.contact2.name" + }, + "dataModelBindings": { + "simpleBinding": "rapport.rapportering.kontaktperson2.navn2.value" + }, + "required": false, + "readOnly": false, + "grid": { + "labelGrid": { + "sm": 6 + }, + "innerGrid": { + "sm": 6 + } + } + }, + { + "id": "2-5", + "type": "Input", + "textResourceBindings": { + "title": "2.5.contact2.mail" + }, + "dataModelBindings": { + "simpleBinding": "rapport.rapportering.kontaktperson2.epost2.value" + }, + "required": false, + "readOnly": false, + "grid": { + "labelGrid": { + "sm": 6 + }, + "innerGrid": { + "sm": 6 + } + } + }, + { + "id": "2-6Prefix", + "type": "Input", + "textResourceBindings": { + "title": "2.6.contact2.prefix" + }, + "dataModelBindings": { + "simpleBinding": "rapport.rapportering.kontaktperson2.telefonprefiks2.value" + }, + "grid": { + "sm": 6, + "innerGrid": { + "sm": 3 + } + }, + "required": false, + "readOnly": false + }, + { + "id": "I2-6", + "type": "Input", + "textResourceBindings": { + "title": "2.6.contact2.tlf" + }, + "dataModelBindings": { + "simpleBinding": "rapport.rapportering.kontaktperson2.telefonnummer2.value" + }, + "grid": { + "sm": 6, + "innerGrid": { + "sm": 6 + } + }, + "required": false, + "readOnly": false, + "formatting": { + "number": { + "format": "### ## ###" + } + } + }, + { + "id": "FilOpplasting", + "type": "FileUpload", + "textResourceBindings": { + "title": "Vedlegg" + }, + "dataModelBindings": {}, + "maxFileSizeInMB": 190, + "maxNumberOfAttachments": 25, + "minNumberOfAttachments": 1, + "displayMode": "list", + "required": true, + "hasCustomFileEndings": true, + "validFileEndings": ".pdf, .xls, .xlsx, .doc, .docx, .rtf, .jpg, .jpeg, .txt, .pptx, .ppt, .zip, .odp, .ods, .odt" + }, + { + "id": "4-0", + "type": "TextArea", + "textResourceBindings": { + "title": "4.description", + "help": "4.description.hint" + }, + "dataModelBindings": { + "simpleBinding": "rapport.rapportering.beskrivelse.value" + }, + "required": false, + "readOnly": false + }, + { + "id": "Tilbake-knapp", + "type": "NavigationButtons", + "componentType": "NavigationButtons", + "textResourceBindings": { + "next": "button.next", + "back": "back" + }, + "dataModelBindings": {}, + "showBackButton": false + } + ] + } + } \ No newline at end of file diff --git a/src/App/ui/layouts/Summary.json b/src/App/ui/layouts/Summary.json new file mode 100644 index 00000000..d3bf5857 --- /dev/null +++ b/src/App/ui/layouts/Summary.json @@ -0,0 +1,137 @@ +{ + "$schema": "https://altinncdn.no/schemas/json/layout/layout.schema.v1.json", + "data": { + "layout": [ + { + "id": "summary-1header", + "type": "Summary", + "componentRef": "Header1", + "pageRef": "FormLayout" + + }, + { + "id": "summary-11-orgnr", + "type": "Summary", + "componentRef": "1-1", + "pageRef": "FormLayout" + }, + { + "id": "summary-12-orgname", + "type": "Summary", + "componentRef": "1-2", + "pageRef": "FormLayout" + }, + { + "id": "summary-13-orgadresse", + "type": "Summary", + "componentRef": "1-3-address", + "pageRef": "FormLayout" + }, + { + "id": "summary-14-orgpostcode", + "type": "Summary", + "componentRef": "1-4-postcode", + "pageRef": "FormLayout", + "grid": { + "sm": 4 + } + }, + { + "id": "summary-15-orgpostcity", + "type": "Summary", + "componentRef": "1-5-postcity", + "pageRef": "FormLayout", + "grid": { + "sm": 8 + } + }, + { + "id": "summary-2header", + "type": "Summary", + "componentRef": "Header2", + "pageRef": "FormLayout" + + }, + { + "id": "summary-21-name1", + "type": "Summary", + "componentRef": "2-1", + "pageRef": "FormLayout" + }, + { + "id": "summary-22-email1", + "type": "Summary", + "componentRef": "2-2", + "pageRef": "FormLayout" + }, + { + "id": "summary-23-tlfprefix1", + "type": "Summary", + "componentRef": "2-3Prefix", + "pageRef": "FormLayout", + "grid": { + "sm": 4 + } + }, + { + "id": "summary-23-tlf1", + "type": "Summary", + "componentRef": "2-3", + "pageRef": "FormLayout", + "grid": { + "sm": 8 + } + }, + { + "id": "summary-24-name2", + "type": "Summary", + "componentRef": "2-4", + "pageRef": "FormLayout" + }, + { + "id": "summary-25-email2", + "type": "Summary", + "componentRef": "2-5", + "pageRef": "FormLayout" + }, + { + "id": "summary-26-tlfprefix2", + "type": "Summary", + "componentRef": "2-6Prefix", + "pageRef": "FormLayout", + "grid": { + "sm": 4 + } + }, + { + "id": "summary-26-tlf2", + "type": "Summary", + "componentRef": "I2-6", + "pageRef": "FormLayout", + "grid": { + "sm": 8 + } + }, + { + "id": "summary-16", + "type": "Summary", + "componentRef": "FilOpplasting", + "pageRef": "FormLayout" + }, + { + "id": "summary-4", + "type": "Summary", + "componentRef": "4-0", + "pageRef": "FormLayout" + }, + { + "id": "88b9ba10-cb72-44b8-b218-a724fd9106fb", + "type": "Button", + "textResourceBindings": { + "title": "Send inn" + }, + "dataModelBindings": {} + } + ] + } + } \ No newline at end of file From b7c2486e45f0c82b10a75776358ec65982fb49fa Mon Sep 17 00:00:00 2001 From: Ivar Nesje Date: Tue, 26 Apr 2022 20:39:26 +0200 Subject: [PATCH 4/7] Fixes in Visual Studio * Fix transitive dependencies in source generator * Add changes to sample app for it to work. * Add fixes suggested by Visual Studio --- .../Altinn.App.ModelGenerator.csproj | 38 +- .../LayoutToModel.cs | 10 +- .../ModelSourceGenerator.cs | 17 +- src/App/App.csproj | 7 + src/App/config/applicationmetadata.json | 14 +- src/App/logic/InstantiationHandler.cs | 5 + src/App/ui/Settings.json | 7 +- src/App/ui/layouts/FormLayout.json | 614 +++++++++--------- 8 files changed, 381 insertions(+), 331 deletions(-) diff --git a/src/Altinn.App.ModelGenerator/Altinn.App.ModelGenerator.csproj b/src/Altinn.App.ModelGenerator/Altinn.App.ModelGenerator.csproj index f11a1445..24d5d5ea 100644 --- a/src/Altinn.App.ModelGenerator/Altinn.App.ModelGenerator.csproj +++ b/src/Altinn.App.ModelGenerator/Altinn.App.ModelGenerator.csproj @@ -4,16 +4,50 @@ netstandard2.0 enable 8 + true - + all runtime; build; native; contentfiles; analyzers; buildtransitive - + + + + + + + + + + + + + + $(GetTargetPathDependsOn);GetDependencyTargetPaths + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/Altinn.App.ModelGenerator/LayoutToModel.cs b/src/Altinn.App.ModelGenerator/LayoutToModel.cs index 6716af88..f00610ce 100644 --- a/src/Altinn.App.ModelGenerator/LayoutToModel.cs +++ b/src/Altinn.App.ModelGenerator/LayoutToModel.cs @@ -28,17 +28,15 @@ public static List GetDataModelBindings(IEnumerable layouts) var ret = new List(); foreach (var layout in layouts) { - var node = JsonNode.Parse(layout)?["data"]?["layout"] as JsonArray; - if (node != null) + if (JsonNode.Parse(layout)?["data"]?["layout"] is JsonArray node) { foreach (var component in node) { - var bindings = component?["dataModelBindings"] as JsonObject; - if(bindings != null) + if (component?["dataModelBindings"] is JsonObject bindings) { - foreach(var binding in bindings) + foreach (var binding in bindings) { - if((binding.Value as JsonValue)?.TryGetValue(out string? value) ?? false) + if ((binding.Value as JsonValue)?.TryGetValue(out string? value) ?? false) { ret.Add(value!); } diff --git a/src/Altinn.App.ModelGenerator/ModelSourceGenerator.cs b/src/Altinn.App.ModelGenerator/ModelSourceGenerator.cs index f4a3fe8f..10ea0486 100644 --- a/src/Altinn.App.ModelGenerator/ModelSourceGenerator.cs +++ b/src/Altinn.App.ModelGenerator/ModelSourceGenerator.cs @@ -14,18 +14,19 @@ public void Execute(GeneratorExecutionContext context) // System.Threading.Thread.Sleep(500); // System.Diagnostics.Debugger.Break(); - var layouts = context.AdditionalFiles.Where(af=>PathUtils.IsLayoutPath(af.Path)).ToDictionary(af=> new FileInfo(af.Path).Name, af=>af.GetText()!.ToString()); - var resources = context.AdditionalFiles.Where(af=>PathUtils.IsResourcePath(af.Path)).ToDictionary(af=> new FileInfo(af.Path).Name, af=>af.GetText()!.ToString()); - var applicationMetadata = context.AdditionalFiles.FirstOrDefault(af=>PathUtils.IsApplicationmetadata(af.Path))?.GetText()?.ToString(); - var settings = context.AdditionalFiles.FirstOrDefault(af=>PathUtils.IsSettings(af.Path))?.GetText()?.ToString(); + var layouts = context.AdditionalFiles.Where(af => PathUtils.IsLayoutPath(af.Path)).ToDictionary(af => new FileInfo(af.Path).Name, af => af.GetText()!.ToString()); + var resources = context.AdditionalFiles.Where(af => PathUtils.IsResourcePath(af.Path)).ToDictionary(af => new FileInfo(af.Path).Name, af => af.GetText()!.ToString()); + var applicationMetadata = context.AdditionalFiles.FirstOrDefault(af => PathUtils.IsApplicationmetadata(af.Path))?.GetText()?.ToString(); + var settings = context.AdditionalFiles.FirstOrDefault(af => PathUtils.IsSettings(af.Path))?.GetText()?.ToString(); // TODO: run validations and create errors; - - var modelName = (JsonNode.Parse(applicationMetadata!)?["dataTypes"] as JsonArray)?.FirstOrDefault(dt=>dt?["appLogic"] != null)?["appLogic"]?["classRef"]?.GetValue(); + + + var modelName = (JsonNode.Parse(applicationMetadata!)?["dataTypes"] as JsonArray)?.FirstOrDefault(dt => dt?["appLogic"] != null)?["appLogic"]?["classRef"]?.GetValue(); // modelName = "Altinn.App.Models.KRT1226Gjenopprettingsplaner_M"; var bindings = LayoutToModel.GetDataModelBindings(layouts.Values); var generatedModel = LayoutToModel.Convert(bindings, modelName!); - - + + context.AddSource("model.g.cs", generatedModel); } diff --git a/src/App/App.csproj b/src/App/App.csproj index ddd7970f..8d43f4e6 100644 --- a/src/App/App.csproj +++ b/src/App/App.csproj @@ -16,6 +16,13 @@ + + + + + + + diff --git a/src/App/config/applicationmetadata.json b/src/App/config/applicationmetadata.json index 82255041..b1433c6c 100644 --- a/src/App/config/applicationmetadata.json +++ b/src/App/config/applicationmetadata.json @@ -5,17 +5,25 @@ "createdBy": "username", "title": { "nb": "Bestillingseksempelapp" }, "dataTypes": [ + { + "id": "model", + "allowedContentTypes": [ "application/xml" ], + "appLogic": { + + "classRef":"Altinn.App.Models.TestModel" + } + }, { "id": "vedlegg", "allowedContentTypes": [ "application/pdf", "image/png", "image/jpeg" ], "minCount": 0, - "taskId": "Task_1", + "taskId": "Task_1" }, { "id": "ref-data-as-pdf", "allowedContentTypes": [ "application/pdf" ], - "minCount": 0, - "taskId": "Task_1", + "minCount": 0, + "taskId": "Task_1" } ], "partyTypesAllowed": { diff --git a/src/App/logic/InstantiationHandler.cs b/src/App/logic/InstantiationHandler.cs index c1b4ac94..160f98a8 100644 --- a/src/App/logic/InstantiationHandler.cs +++ b/src/App/logic/InstantiationHandler.cs @@ -56,6 +56,11 @@ public async Task RunInstantiationValidation(Inst /// External prefill available under instansiation if supplied public async Task DataCreation(Instance instance, object data, Dictionary prefill) { + if (data is Altinn.App.Models.TestModel model) + { + var addr = model?.rapport?.innsender?.adresse; + } + await Task.CompletedTask; } } diff --git a/src/App/ui/Settings.json b/src/App/ui/Settings.json index de2b4e4c..cc8eb4a1 100644 --- a/src/App/ui/Settings.json +++ b/src/App/ui/Settings.json @@ -2,9 +2,6 @@ "$schema": "https://altinncdn.no/schemas/json/layout/layoutSettings.schema.v1.json", "pages": { "excludeFromPdf": ["Summary"], - "order": [ - "FormLayout", - "Summary" - ] + "order": ["FormLayout", "Summary"] } -} \ No newline at end of file +} diff --git a/src/App/ui/layouts/FormLayout.json b/src/App/ui/layouts/FormLayout.json index 67a270b7..35b91efb 100644 --- a/src/App/ui/layouts/FormLayout.json +++ b/src/App/ui/layouts/FormLayout.json @@ -1,332 +1,332 @@ { - "$schema": "https://altinncdn.no/schemas/json/layout/layout.schema.v1.json", - "data": { - "layout": [ - { - "id": "Info", - "type": "Paragraph", - "textResourceBindings": { - "title": "0.info" - }, - "dataModelBindings": {} + "$schema": "https://altinncdn.no/schemas/json/layout/layout.schema.v1.json", + "data": { + "layout": [ + { + "id": "Info", + "type": "Paragraph", + "textResourceBindings": { + "title": "0.info" }, - { - "id": "Header1", - "type": "Header", - "textResourceBindings": { - "title": "1.generalInfo" - }, - "dataModelBindings": {}, - "size": "S", - "readOnly": true - }, - { - "id": "1-1", - "type": "Input", - "textResourceBindings": { - "title": "1.1.orgNr" - }, - "dataModelBindings": { - "simpleBinding": "rapport.innsender.foretak.organisasjonsnummer.value" - }, - "required": true, - "readOnly": true, - "grid": { - "labelGrid": { - "sm": 6 - }, - "innerGrid": { - "sm": 6 - } + "dataModelBindings": {} + }, + { + "id": "Header1", + "type": "Header", + "textResourceBindings": { + "title": "1.generalInfo" + }, + "dataModelBindings": {}, + "size": "S", + "readOnly": true + }, + { + "id": "1-1", + "type": "Input", + "textResourceBindings": { + "title": "1.1.orgNr" + }, + "dataModelBindings": { + "simpleBinding": "rapport.innsender.foretak.organisasjonsnummer.value" + }, + "required": true, + "readOnly": true, + "grid": { + "labelGrid": { + "sm": 6 + }, + "innerGrid": { + "sm": 6 } + } + }, + { + "id": "1-2", + "type": "Input", + "textResourceBindings": { + "title": "1.2.name" }, - { - "id": "1-2", - "type": "Input", - "textResourceBindings": { - "title": "1.2.name" - }, - "dataModelBindings": { - "simpleBinding": "rapport.innsender.foretak.navn.value" - }, - "grid": { - "labelGrid": { - "sm": 6 - }, - "innerGrid": { - "sm": 6 - } - }, - "required": true, - "readOnly": true - }, - { - "id": "1-3-address", - "type": "Input", - "textResourceBindings": { - "title": "1.3.address" - }, - "dataModelBindings": { - "simpleBinding": "rapport.innsender.adresse.adresselinje1.value" + "dataModelBindings": { + "simpleBinding": "rapport.innsender.foretak.navn.value" + }, + "grid": { + "labelGrid": { + "sm": 6 }, - "required": false, - "readOnly": true, - "grid": { - "labelGrid": { - "sm": 6 - }, - "innerGrid": { - "sm": 6 - } + "innerGrid": { + "sm": 6 } }, - { - "id": "1-4-postcode", - "type": "Input", - "textResourceBindings": { - "title": "1.4.postCode" - }, - "dataModelBindings": { - "simpleBinding": "rapport.innsender.adresse.postnummer.value" - }, - "required": false, - "readOnly": true, - "grid": { - "sm": 6, - "innerGrid": { - "sm": 6 - } + "required": true, + "readOnly": true + }, + { + "id": "1-3-address", + "type": "Input", + "textResourceBindings": { + "title": "1.3.address" + }, + "dataModelBindings": { + "simpleBinding": "rapport.innsender.adresse.adresselinje1.value" + }, + "required": false, + "readOnly": true, + "grid": { + "labelGrid": { + "sm": 6 + }, + "innerGrid": { + "sm": 6 } + } + }, + { + "id": "1-4-postcode", + "type": "Input", + "textResourceBindings": { + "title": "1.4.postCode" }, - { - "id": "1-5-postcity", - "type": "Input", - "textResourceBindings": { - "title": "1.5.postCity" - }, - "dataModelBindings": { - "simpleBinding": "rapport.innsender.adresse.poststed.value" - }, - "grid": { - "sm": 4 - }, - "required": false, - "readOnly": true - }, - { - "id": "Header2", - "type": "Header", - "textResourceBindings": { - "title": "2.contactInfo" - }, - "dataModelBindings": {}, - "size": "S", - "readOnly": true - }, - { - "id": "2-1", - "type": "Input", - "textResourceBindings": { - "title": "2.1.contact1.name" - }, - "dataModelBindings": { - "simpleBinding": "rapport.rapportering.kontaktperson1.navn1.value" - }, - "required": true, - "readOnly": false, - "grid": { - "labelGrid": { - "sm": 6 - }, - "innerGrid": { - "sm": 6 - } + "dataModelBindings": { + "simpleBinding": "rapport.innsender.adresse.postnummer.value" + }, + "required": false, + "readOnly": true, + "grid": { + "sm": 6, + "innerGrid": { + "sm": 6 } + } + }, + { + "id": "1-5-postcity", + "type": "Input", + "textResourceBindings": { + "title": "1.5.postCity" }, - { - "id": "2-2", - "type": "Input", - "textResourceBindings": { - "title": "2.2.contact1.mail" - }, - "dataModelBindings": { - "simpleBinding": "rapport.rapportering.kontaktperson1.epost1.value" - }, - "required": true, - "readOnly": false, - "grid": { - "labelGrid": { - "sm": 6 - }, - "innerGrid": { - "sm": 6 - }, - "formatting":{ - "Input": "Email" - } + "dataModelBindings": { + "simpleBinding": "rapport.innsender.adresse.poststed.value" + }, + "grid": { + "sm": 4 + }, + "required": false, + "readOnly": true + }, + { + "id": "Header2", + "type": "Header", + "textResourceBindings": { + "title": "2.contactInfo" + }, + "dataModelBindings": {}, + "size": "S", + "readOnly": true + }, + { + "id": "2-1", + "type": "Input", + "textResourceBindings": { + "title": "2.1.contact1.name" + }, + "dataModelBindings": { + "simpleBinding": "rapport.rapportering.kontaktperson1.navn1.value" + }, + "required": true, + "readOnly": false, + "grid": { + "labelGrid": { + "sm": 6 + }, + "innerGrid": { + "sm": 6 } + } + }, + { + "id": "2-2", + "type": "Input", + "textResourceBindings": { + "title": "2.2.contact1.mail" }, - { - "id": "2-3Prefix", - "type": "Input", - "textResourceBindings": { - "title": "2.3.contact1.prefix" - }, - "dataModelBindings": { - "simpleBinding": "rapport.rapportering.kontaktperson1.telefonprefiks1.value" - }, - "grid": { - "sm": 6, - "innerGrid": { - "sm": 3 - } - }, - "required": true, - "readOnly": false - }, - { - "id": "2-3", - "type": "Input", - "textResourceBindings": { - "title": "2.3.contact1.tlf" - }, - "dataModelBindings": { - "simpleBinding": "rapport.rapportering.kontaktperson1.telefonnummer1.value" + "dataModelBindings": { + "simpleBinding": "rapport.rapportering.kontaktperson1.epost1.value" + }, + "required": true, + "readOnly": false, + "grid": { + "labelGrid": { + "sm": 6 }, - "grid": { - "sm": 6, - "innerGrid": { - "sm": 6 - } + "innerGrid": { + "sm": 6 }, - "required": true, - "readOnly": false, "formatting": { - "number": { - "format": "### ## ###" - } + "Input": "Email" } + } + }, + { + "id": "2-3Prefix", + "type": "Input", + "textResourceBindings": { + "title": "2.3.contact1.prefix" }, - { - "id": "2-4", - "type": "Input", - "textResourceBindings": { - "title": "2.4.contact2.name" - }, - "dataModelBindings": { - "simpleBinding": "rapport.rapportering.kontaktperson2.navn2.value" - }, - "required": false, - "readOnly": false, - "grid": { - "labelGrid": { - "sm": 6 - }, - "innerGrid": { - "sm": 6 - } + "dataModelBindings": { + "simpleBinding": "rapport.rapportering.kontaktperson1.telefonprefiks1.value" + }, + "grid": { + "sm": 6, + "innerGrid": { + "sm": 3 } }, - { - "id": "2-5", - "type": "Input", - "textResourceBindings": { - "title": "2.5.contact2.mail" - }, - "dataModelBindings": { - "simpleBinding": "rapport.rapportering.kontaktperson2.epost2.value" - }, - "required": false, - "readOnly": false, - "grid": { - "labelGrid": { - "sm": 6 - }, - "innerGrid": { - "sm": 6 - } + "required": true, + "readOnly": false + }, + { + "id": "2-3", + "type": "Input", + "textResourceBindings": { + "title": "2.3.contact1.tlf" + }, + "dataModelBindings": { + "simpleBinding": "rapport.rapportering.kontaktperson1.telefonnummer1.value" + }, + "grid": { + "sm": 6, + "innerGrid": { + "sm": 6 } }, - { - "id": "2-6Prefix", - "type": "Input", - "textResourceBindings": { - "title": "2.6.contact2.prefix" - }, - "dataModelBindings": { - "simpleBinding": "rapport.rapportering.kontaktperson2.telefonprefiks2.value" - }, - "grid": { - "sm": 6, - "innerGrid": { - "sm": 3 - } - }, - "required": false, - "readOnly": false - }, - { - "id": "I2-6", - "type": "Input", - "textResourceBindings": { - "title": "2.6.contact2.tlf" - }, - "dataModelBindings": { - "simpleBinding": "rapport.rapportering.kontaktperson2.telefonnummer2.value" - }, - "grid": { - "sm": 6, - "innerGrid": { - "sm": 6 - } - }, - "required": false, - "readOnly": false, - "formatting": { - "number": { - "format": "### ## ###" - } + "required": true, + "readOnly": false, + "formatting": { + "number": { + "format": "### ## ###" } + } + }, + { + "id": "2-4", + "type": "Input", + "textResourceBindings": { + "title": "2.4.contact2.name" }, - { - "id": "FilOpplasting", - "type": "FileUpload", - "textResourceBindings": { - "title": "Vedlegg" - }, - "dataModelBindings": {}, - "maxFileSizeInMB": 190, - "maxNumberOfAttachments": 25, - "minNumberOfAttachments": 1, - "displayMode": "list", - "required": true, - "hasCustomFileEndings": true, - "validFileEndings": ".pdf, .xls, .xlsx, .doc, .docx, .rtf, .jpg, .jpeg, .txt, .pptx, .ppt, .zip, .odp, .ods, .odt" - }, - { - "id": "4-0", - "type": "TextArea", - "textResourceBindings": { - "title": "4.description", - "help": "4.description.hint" - }, - "dataModelBindings": { - "simpleBinding": "rapport.rapportering.beskrivelse.value" - }, - "required": false, - "readOnly": false - }, - { - "id": "Tilbake-knapp", - "type": "NavigationButtons", - "componentType": "NavigationButtons", - "textResourceBindings": { - "next": "button.next", - "back": "back" - }, - "dataModelBindings": {}, - "showBackButton": false + "dataModelBindings": { + "simpleBinding": "rapport.rapportering.kontaktperson2.navn2.value" + }, + "required": false, + "readOnly": false, + "grid": { + "labelGrid": { + "sm": 6 + }, + "innerGrid": { + "sm": 6 + } + } + }, + { + "id": "2-5", + "type": "Input", + "textResourceBindings": { + "title": "2.5.contact2.mail" + }, + "dataModelBindings": { + "simpleBinding": "rapport.rapportering.kontaktperson2.epost2.value" + }, + "required": false, + "readOnly": false, + "grid": { + "labelGrid": { + "sm": 6 + }, + "innerGrid": { + "sm": 6 + } } - ] - } - } \ No newline at end of file + }, + { + "id": "2-6Prefix", + "type": "Input", + "textResourceBindings": { + "title": "2.6.contact2.prefix" + }, + "dataModelBindings": { + "simpleBinding": "rapport.rapportering.kontaktperson2.telefonprefiks2.value" + }, + "grid": { + "sm": 6, + "innerGrid": { + "sm": 3 + } + }, + "required": false, + "readOnly": false + }, + { + "id": "I2-6", + "type": "Input", + "textResourceBindings": { + "title": "2.6.contact2.tlf" + }, + "dataModelBindings": { + "simpleBinding": "rapport.rapportering.kontaktperson2.telefonnummer2.value" + }, + "grid": { + "sm": 6, + "innerGrid": { + "sm": 6 + } + }, + "required": false, + "readOnly": false, + "formatting": { + "number": { + "format": "### ## ###" + } + } + }, + { + "id": "FilOpplasting", + "type": "FileUpload", + "textResourceBindings": { + "title": "Vedlegg" + }, + "dataModelBindings": {}, + "maxFileSizeInMB": 190, + "maxNumberOfAttachments": 25, + "minNumberOfAttachments": 1, + "displayMode": "list", + "required": true, + "hasCustomFileEndings": true, + "validFileEndings": ".pdf, .xls, .xlsx, .doc, .docx, .rtf, .jpg, .jpeg, .txt, .pptx, .ppt, .zip, .odp, .ods, .odt" + }, + { + "id": "4-0", + "type": "TextArea", + "textResourceBindings": { + "title": "4.description", + "help": "4.description.hint" + }, + "dataModelBindings": { + "simpleBinding": "rapport.rapportering.beskrivelse.value" + }, + "required": false, + "readOnly": false + }, + { + "id": "Tilbake-knapp", + "type": "NavigationButtons", + "componentType": "NavigationButtons", + "textResourceBindings": { + "next": "button.next", + "back": "back" + }, + "dataModelBindings": {}, + "showBackButton": false + } + ] + } +} \ No newline at end of file From 27917f90d1e02546b76be0b67a9e76f91bc06a28 Mon Sep 17 00:00:00 2001 From: Ivar Date: Wed, 27 Apr 2022 08:33:01 +0200 Subject: [PATCH 5/7] Fix tests so that they look green. --- .../TestData/LayoutToModel/FormLayout.json | 614 +++++++++--------- .../TestData/LayoutToModel/bindings.json | 16 +- .../TestData/LayoutToModel/model.cs | 132 +++- 3 files changed, 439 insertions(+), 323 deletions(-) diff --git a/src/Altinn.App.ModelGenerator.Tests/TestData/LayoutToModel/FormLayout.json b/src/Altinn.App.ModelGenerator.Tests/TestData/LayoutToModel/FormLayout.json index 07a176ad..35b91efb 100644 --- a/src/Altinn.App.ModelGenerator.Tests/TestData/LayoutToModel/FormLayout.json +++ b/src/Altinn.App.ModelGenerator.Tests/TestData/LayoutToModel/FormLayout.json @@ -1,332 +1,332 @@ { - "$schema": "https://altinncdn.no/schemas/json/layout/layout.schema.v1.json", - "data": { - "layout": [ - { - "id": "Info", - "type": "Paragraph", - "textResourceBindings": { - "title": "0.info" - }, - "dataModelBindings": {} + "$schema": "https://altinncdn.no/schemas/json/layout/layout.schema.v1.json", + "data": { + "layout": [ + { + "id": "Info", + "type": "Paragraph", + "textResourceBindings": { + "title": "0.info" }, - { - "id": "Header1", - "type": "Header", - "textResourceBindings": { - "title": "1.generalInfo" - }, - "dataModelBindings": {}, - "size": "S", - "readOnly": true - }, - { - "id": "1-1", - "type": "Input", - "textResourceBindings": { - "title": "1.1.orgNr" - }, - "dataModelBindings": { - "simpleBinding": "rapport.innsender.foretak.organisasjonsnummer.value" - }, - "required": true, - "readOnly": true, - "grid": { - "labelGrid": { - "sm": 6 - }, - "innerGrid": { - "sm": 6 - } + "dataModelBindings": {} + }, + { + "id": "Header1", + "type": "Header", + "textResourceBindings": { + "title": "1.generalInfo" + }, + "dataModelBindings": {}, + "size": "S", + "readOnly": true + }, + { + "id": "1-1", + "type": "Input", + "textResourceBindings": { + "title": "1.1.orgNr" + }, + "dataModelBindings": { + "simpleBinding": "rapport.innsender.foretak.organisasjonsnummer.value" + }, + "required": true, + "readOnly": true, + "grid": { + "labelGrid": { + "sm": 6 + }, + "innerGrid": { + "sm": 6 } + } + }, + { + "id": "1-2", + "type": "Input", + "textResourceBindings": { + "title": "1.2.name" }, - { - "id": "1-2", - "type": "Input", - "textResourceBindings": { - "title": "1.2.name" - }, - "dataModelBindings": { - "simpleBinding": "rapport.innsender.foretak.navn.value" - }, - "grid": { - "labelGrid": { - "sm": 6 - }, - "innerGrid": { - "sm": 6 - } - }, - "required": true, - "readOnly": true - }, - { - "id": "1-3-address", - "type": "Input", - "textResourceBindings": { - "title": "1.3.address" - }, - "dataModelBindings": { - "simpleBinding": "rapport.innsender.adresse.adresselinje1.value" + "dataModelBindings": { + "simpleBinding": "rapport.innsender.foretak.navn.value" + }, + "grid": { + "labelGrid": { + "sm": 6 }, - "required": false, - "readOnly": true, - "grid": { - "labelGrid": { - "sm": 6 - }, - "innerGrid": { - "sm": 6 - } + "innerGrid": { + "sm": 6 } }, - { - "id": "1-4-postcode", - "type": "Input", - "textResourceBindings": { - "title": "1.4.postCode" - }, - "dataModelBindings": { - "simpleBinding": "rapport.innsender.adresse.postnummer.value" - }, - "required": false, - "readOnly": true, - "grid": { - "sm": 6, - "innerGrid": { - "sm": 6 - } + "required": true, + "readOnly": true + }, + { + "id": "1-3-address", + "type": "Input", + "textResourceBindings": { + "title": "1.3.address" + }, + "dataModelBindings": { + "simpleBinding": "rapport.innsender.adresse.adresselinje1.value" + }, + "required": false, + "readOnly": true, + "grid": { + "labelGrid": { + "sm": 6 + }, + "innerGrid": { + "sm": 6 } + } + }, + { + "id": "1-4-postcode", + "type": "Input", + "textResourceBindings": { + "title": "1.4.postCode" }, - { - "id": "1-5-postcity", - "type": "Input", - "textResourceBindings": { - "title": "1.5.postCity" - }, - "dataModelBindings": { - "simpleBinding": "rapport.innsender.adresse.poststed.value" - }, - "grid": { - "sm": 4 - }, - "required": false, - "readOnly": true - }, - { - "id": "Header2", - "type": "Header", - "textResourceBindings": { - "title": "2.contactInfo" - }, - "dataModelBindings": {}, - "size": "S", - "readOnly": true - }, - { - "id": "2-1", - "type": "Input", - "textResourceBindings": { - "title": "2.1.contact1.name" - }, - "dataModelBindings": { - "simpleBinding": "rapport.rapportering.kontaktperson1.navn.value" - }, - "required": true, - "readOnly": false, - "grid": { - "labelGrid": { - "sm": 6 - }, - "innerGrid": { - "sm": 6 - } + "dataModelBindings": { + "simpleBinding": "rapport.innsender.adresse.postnummer.value" + }, + "required": false, + "readOnly": true, + "grid": { + "sm": 6, + "innerGrid": { + "sm": 6 } + } + }, + { + "id": "1-5-postcity", + "type": "Input", + "textResourceBindings": { + "title": "1.5.postCity" }, - { - "id": "2-2", - "type": "Input", - "textResourceBindings": { - "title": "2.2.contact1.mail" - }, - "dataModelBindings": { - "simpleBinding": "rapport.rapportering.kontaktperson1.epost.value" - }, - "required": true, - "readOnly": false, - "grid": { - "labelGrid": { - "sm": 6 - }, - "innerGrid": { - "sm": 6 - }, - "formatting":{ - "Input": "Email" - } + "dataModelBindings": { + "simpleBinding": "rapport.innsender.adresse.poststed.value" + }, + "grid": { + "sm": 4 + }, + "required": false, + "readOnly": true + }, + { + "id": "Header2", + "type": "Header", + "textResourceBindings": { + "title": "2.contactInfo" + }, + "dataModelBindings": {}, + "size": "S", + "readOnly": true + }, + { + "id": "2-1", + "type": "Input", + "textResourceBindings": { + "title": "2.1.contact1.name" + }, + "dataModelBindings": { + "simpleBinding": "rapport.rapportering.kontaktperson1.navn1.value" + }, + "required": true, + "readOnly": false, + "grid": { + "labelGrid": { + "sm": 6 + }, + "innerGrid": { + "sm": 6 } + } + }, + { + "id": "2-2", + "type": "Input", + "textResourceBindings": { + "title": "2.2.contact1.mail" }, - { - "id": "2-3Prefix", - "type": "Input", - "textResourceBindings": { - "title": "2.3.contact1.prefix" - }, - "dataModelBindings": { - "simpleBinding": "rapport.rapportering.kontaktperson1.telefonprefiks.value" - }, - "grid": { - "sm": 6, - "innerGrid": { - "sm": 3 - } - }, - "required": true, - "readOnly": false - }, - { - "id": "2-3", - "type": "Input", - "textResourceBindings": { - "title": "2.3.contact1.tlf" - }, - "dataModelBindings": { - "simpleBinding": "rapport.rapportering.kontaktperson1.telefonnummer.value" + "dataModelBindings": { + "simpleBinding": "rapport.rapportering.kontaktperson1.epost1.value" + }, + "required": true, + "readOnly": false, + "grid": { + "labelGrid": { + "sm": 6 }, - "grid": { - "sm": 6, - "innerGrid": { - "sm": 6 - } + "innerGrid": { + "sm": 6 }, - "required": true, - "readOnly": false, "formatting": { - "number": { - "format": "### ## ###" - } + "Input": "Email" } + } + }, + { + "id": "2-3Prefix", + "type": "Input", + "textResourceBindings": { + "title": "2.3.contact1.prefix" }, - { - "id": "2-4", - "type": "Input", - "textResourceBindings": { - "title": "2.4.contact2.name" - }, - "dataModelBindings": { - "simpleBinding": "rapport.rapportering.kontaktperson2.navn.value" - }, - "required": false, - "readOnly": false, - "grid": { - "labelGrid": { - "sm": 6 - }, - "innerGrid": { - "sm": 6 - } + "dataModelBindings": { + "simpleBinding": "rapport.rapportering.kontaktperson1.telefonprefiks1.value" + }, + "grid": { + "sm": 6, + "innerGrid": { + "sm": 3 } }, - { - "id": "2-5", - "type": "Input", - "textResourceBindings": { - "title": "2.5.contact2.mail" - }, - "dataModelBindings": { - "simpleBinding": "rapport.rapportering.kontaktperson2.epost.value" - }, - "required": false, - "readOnly": false, - "grid": { - "labelGrid": { - "sm": 6 - }, - "innerGrid": { - "sm": 6 - } + "required": true, + "readOnly": false + }, + { + "id": "2-3", + "type": "Input", + "textResourceBindings": { + "title": "2.3.contact1.tlf" + }, + "dataModelBindings": { + "simpleBinding": "rapport.rapportering.kontaktperson1.telefonnummer1.value" + }, + "grid": { + "sm": 6, + "innerGrid": { + "sm": 6 } }, - { - "id": "2-6Prefix", - "type": "Input", - "textResourceBindings": { - "title": "2.6.contact2.prefix" - }, - "dataModelBindings": { - "simpleBinding": "rapport.rapportering.kontaktperson2.telefonprefiks.value" - }, - "grid": { - "sm": 6, - "innerGrid": { - "sm": 3 - } - }, - "required": false, - "readOnly": false - }, - { - "id": "I2-6", - "type": "Input", - "textResourceBindings": { - "title": "2.6.contact2.tlf" - }, - "dataModelBindings": { - "simpleBinding": "rapport.rapportering.kontaktperson2.telefonnummer.value" - }, - "grid": { - "sm": 6, - "innerGrid": { - "sm": 6 - } - }, - "required": false, - "readOnly": false, - "formatting": { - "number": { - "format": "### ## ###" - } + "required": true, + "readOnly": false, + "formatting": { + "number": { + "format": "### ## ###" } + } + }, + { + "id": "2-4", + "type": "Input", + "textResourceBindings": { + "title": "2.4.contact2.name" }, - { - "id": "FilOpplasting", - "type": "FileUpload", - "textResourceBindings": { - "title": "Vedlegg" - }, - "dataModelBindings": {}, - "maxFileSizeInMB": 190, - "maxNumberOfAttachments": 25, - "minNumberOfAttachments": 1, - "displayMode": "list", - "required": true, - "hasCustomFileEndings": true, - "validFileEndings": ".pdf, .xls, .xlsx, .doc, .docx, .rtf, .jpg, .jpeg, .txt, .pptx, .ppt, .zip, .odp, .ods, .odt" - }, - { - "id": "4-0", - "type": "TextArea", - "textResourceBindings": { - "title": "4.description", - "help": "4.description.hint" - }, - "dataModelBindings": { - "simpleBinding": "rapport.rapportering.beskrivelse.value" - }, - "required": false, - "readOnly": false - }, - { - "id": "Tilbake-knapp", - "type": "NavigationButtons", - "componentType": "NavigationButtons", - "textResourceBindings": { - "next": "button.next", - "back": "back" - }, - "dataModelBindings": {}, - "showBackButton": false + "dataModelBindings": { + "simpleBinding": "rapport.rapportering.kontaktperson2.navn2.value" + }, + "required": false, + "readOnly": false, + "grid": { + "labelGrid": { + "sm": 6 + }, + "innerGrid": { + "sm": 6 + } + } + }, + { + "id": "2-5", + "type": "Input", + "textResourceBindings": { + "title": "2.5.contact2.mail" + }, + "dataModelBindings": { + "simpleBinding": "rapport.rapportering.kontaktperson2.epost2.value" + }, + "required": false, + "readOnly": false, + "grid": { + "labelGrid": { + "sm": 6 + }, + "innerGrid": { + "sm": 6 + } } - ] - } - } \ No newline at end of file + }, + { + "id": "2-6Prefix", + "type": "Input", + "textResourceBindings": { + "title": "2.6.contact2.prefix" + }, + "dataModelBindings": { + "simpleBinding": "rapport.rapportering.kontaktperson2.telefonprefiks2.value" + }, + "grid": { + "sm": 6, + "innerGrid": { + "sm": 3 + } + }, + "required": false, + "readOnly": false + }, + { + "id": "I2-6", + "type": "Input", + "textResourceBindings": { + "title": "2.6.contact2.tlf" + }, + "dataModelBindings": { + "simpleBinding": "rapport.rapportering.kontaktperson2.telefonnummer2.value" + }, + "grid": { + "sm": 6, + "innerGrid": { + "sm": 6 + } + }, + "required": false, + "readOnly": false, + "formatting": { + "number": { + "format": "### ## ###" + } + } + }, + { + "id": "FilOpplasting", + "type": "FileUpload", + "textResourceBindings": { + "title": "Vedlegg" + }, + "dataModelBindings": {}, + "maxFileSizeInMB": 190, + "maxNumberOfAttachments": 25, + "minNumberOfAttachments": 1, + "displayMode": "list", + "required": true, + "hasCustomFileEndings": true, + "validFileEndings": ".pdf, .xls, .xlsx, .doc, .docx, .rtf, .jpg, .jpeg, .txt, .pptx, .ppt, .zip, .odp, .ods, .odt" + }, + { + "id": "4-0", + "type": "TextArea", + "textResourceBindings": { + "title": "4.description", + "help": "4.description.hint" + }, + "dataModelBindings": { + "simpleBinding": "rapport.rapportering.beskrivelse.value" + }, + "required": false, + "readOnly": false + }, + { + "id": "Tilbake-knapp", + "type": "NavigationButtons", + "componentType": "NavigationButtons", + "textResourceBindings": { + "next": "button.next", + "back": "back" + }, + "dataModelBindings": {}, + "showBackButton": false + } + ] + } +} \ No newline at end of file diff --git a/src/Altinn.App.ModelGenerator.Tests/TestData/LayoutToModel/bindings.json b/src/Altinn.App.ModelGenerator.Tests/TestData/LayoutToModel/bindings.json index 721860b3..80684d2a 100644 --- a/src/Altinn.App.ModelGenerator.Tests/TestData/LayoutToModel/bindings.json +++ b/src/Altinn.App.ModelGenerator.Tests/TestData/LayoutToModel/bindings.json @@ -4,13 +4,13 @@ "rapport.innsender.adresse.adresselinje1.value", "rapport.innsender.adresse.postnummer.value", "rapport.innsender.adresse.poststed.value", - "rapport.rapportering.kontaktperson1.navn.value", - "rapport.rapportering.kontaktperson1.epost.value", - "rapport.rapportering.kontaktperson1.telefonprefiks.value", - "rapport.rapportering.kontaktperson1.telefonnummer.value", - "rapport.rapportering.kontaktperson2.navn.value", - "rapport.rapportering.kontaktperson2.epost.value", - "rapport.rapportering.kontaktperson2.telefonprefiks.value", - "rapport.rapportering.kontaktperson2.telefonnummer.value", + "rapport.rapportering.kontaktperson1.navn1.value", + "rapport.rapportering.kontaktperson1.epost1.value", + "rapport.rapportering.kontaktperson1.telefonprefiks1.value", + "rapport.rapportering.kontaktperson1.telefonnummer1.value", + "rapport.rapportering.kontaktperson2.navn2.value", + "rapport.rapportering.kontaktperson2.epost2.value", + "rapport.rapportering.kontaktperson2.telefonprefiks2.value", + "rapport.rapportering.kontaktperson2.telefonnummer2.value", "rapport.rapportering.beskrivelse.value" ] diff --git a/src/Altinn.App.ModelGenerator.Tests/TestData/LayoutToModel/model.cs b/src/Altinn.App.ModelGenerator.Tests/TestData/LayoutToModel/model.cs index 3e50ee1a..2e021230 100644 --- a/src/Altinn.App.ModelGenerator.Tests/TestData/LayoutToModel/model.cs +++ b/src/Altinn.App.ModelGenerator.Tests/TestData/LayoutToModel/model.cs @@ -1,40 +1,156 @@ -public class model +// Auto-generated +#nullable enable +namespace Altinn.App.Models +{ + +public partial class Model { public rapport? rapport { get; set; } } -public class rapport +public partial class rapport { public innsender? innsender { get; set; } public rapportering? rapportering { get; set; } } -public class innsender +public partial class innsender { public foretak? foretak { get; set; } public adresse? adresse { get; set; } } -public class foretak +public partial class foretak { public organisasjonsnummer? organisasjonsnummer { get; set; } public navn? navn { get; set; } } -public class organisasjonsnummer +public partial class organisasjonsnummer +{ + public string? value { get; set; } +} + + + +public partial class navn +{ + public string? value { get; set; } +} + + + +public partial class adresse +{ + public adresselinje1? adresselinje1 { get; set; } + public postnummer? postnummer { get; set; } + public poststed? poststed { get; set; } +} + +public partial class adresselinje1 +{ + public string? value { get; set; } +} + + + +public partial class postnummer +{ + public string? value { get; set; } +} + + + +public partial class poststed +{ + public string? value { get; set; } +} + + + +public partial class rapportering +{ + public kontaktperson1? kontaktperson1 { get; set; } + public kontaktperson2? kontaktperson2 { get; set; } + public beskrivelse? beskrivelse { get; set; } +} + +public partial class kontaktperson1 +{ + public navn1? navn1 { get; set; } + public epost1? epost1 { get; set; } + public telefonprefiks1? telefonprefiks1 { get; set; } + public telefonnummer1? telefonnummer1 { get; set; } +} + +public partial class navn1 { + public string? value { get; set; } } -public class navn +public partial class epost1 { + public string? value { get; set; } } -public class adresse +public partial class telefonprefiks1 { + public string? value { get; set; } } -public class rapportering {} + + +public partial class telefonnummer1 +{ + public string? value { get; set; } +} + + + +public partial class kontaktperson2 +{ + public navn2? navn2 { get; set; } + public epost2? epost2 { get; set; } + public telefonprefiks2? telefonprefiks2 { get; set; } + public telefonnummer2? telefonnummer2 { get; set; } +} + +public partial class navn2 +{ + public string? value { get; set; } +} + + + +public partial class epost2 +{ + public string? value { get; set; } +} + + + +public partial class telefonprefiks2 +{ + public string? value { get; set; } +} + + + +public partial class telefonnummer2 +{ + public string? value { get; set; } +} + + + +public partial class beskrivelse +{ + public string? value { get; set; } +} + + +} From 8d96cf2aed6297fa91c8de4a912d9af387afc024 Mon Sep 17 00:00:00 2001 From: Ivar Date: Thu, 12 May 2022 14:52:07 +0200 Subject: [PATCH 6/7] Make json errors dotnet build errors --- .../Altinn.App.ModelGenerator.csproj | 4 +-- .../ModelSourceGenerator.cs | 21 ++++++++++++-- .../utils/PathUtils.cs | 9 ++++++ .../AltinnDiagnosticsDescriptors.cs | 15 ++++++++++ .../validators/JsonValidator.cs | 29 +++++++++++++++++++ 5 files changed, 73 insertions(+), 5 deletions(-) create mode 100644 src/Altinn.App.ModelGenerator/validators/AltinnDiagnosticsDescriptors.cs create mode 100644 src/Altinn.App.ModelGenerator/validators/JsonValidator.cs diff --git a/src/Altinn.App.ModelGenerator/Altinn.App.ModelGenerator.csproj b/src/Altinn.App.ModelGenerator/Altinn.App.ModelGenerator.csproj index 24d5d5ea..a7922e72 100644 --- a/src/Altinn.App.ModelGenerator/Altinn.App.ModelGenerator.csproj +++ b/src/Altinn.App.ModelGenerator/Altinn.App.ModelGenerator.csproj @@ -2,9 +2,9 @@ netstandard2.0 + 10.0 enable - 8 - true + enable diff --git a/src/Altinn.App.ModelGenerator/ModelSourceGenerator.cs b/src/Altinn.App.ModelGenerator/ModelSourceGenerator.cs index 10ea0486..39311dcf 100644 --- a/src/Altinn.App.ModelGenerator/ModelSourceGenerator.cs +++ b/src/Altinn.App.ModelGenerator/ModelSourceGenerator.cs @@ -14,13 +14,14 @@ public void Execute(GeneratorExecutionContext context) // System.Threading.Thread.Sleep(500); // System.Diagnostics.Debugger.Break(); - var layouts = context.AdditionalFiles.Where(af => PathUtils.IsLayoutPath(af.Path)).ToDictionary(af => new FileInfo(af.Path).Name, af => af.GetText()!.ToString()); - var resources = context.AdditionalFiles.Where(af => PathUtils.IsResourcePath(af.Path)).ToDictionary(af => new FileInfo(af.Path).Name, af => af.GetText()!.ToString()); + var layouts = context.AdditionalFiles.Where(af => PathUtils.IsLayoutPath(af.Path)).ToDictionary(af => PathUtils.FileNameFromPath(af.Path), af => af.GetText()!.ToString()); + var resources = context.AdditionalFiles.Where(af => PathUtils.IsResourcePath(af.Path)).ToDictionary(af => PathUtils.FileNameFromPath(af.Path), af => af.GetText()!.ToString()); var applicationMetadata = context.AdditionalFiles.FirstOrDefault(af => PathUtils.IsApplicationmetadata(af.Path))?.GetText()?.ToString(); var settings = context.AdditionalFiles.FirstOrDefault(af => PathUtils.IsSettings(af.Path))?.GetText()?.ToString(); - // TODO: run validations and create errors; + ValidateJsonFiles(context); + // Generate code; var modelName = (JsonNode.Parse(applicationMetadata!)?["dataTypes"] as JsonArray)?.FirstOrDefault(dt => dt?["appLogic"] != null)?["appLogic"]?["classRef"]?.GetValue(); // modelName = "Altinn.App.Models.KRT1226Gjenopprettingsplaner_M"; var bindings = LayoutToModel.GetDataModelBindings(layouts.Values); @@ -29,6 +30,20 @@ public void Execute(GeneratorExecutionContext context) context.AddSource("model.g.cs", generatedModel); } + + public void ValidateJsonFiles(GeneratorExecutionContext context) + { + foreach(var jsonFile in context.AdditionalFiles.Where(af=>af.Path.EndsWith(".json"))) + { + var path = jsonFile?.Path; + var content = jsonFile?.GetText()?.ToString(); + if(path == null || content == null) continue; + foreach(var diagnostic in JsonValidator.GetJsonParseDiagnostics(path, content)) + { + context.ReportDiagnostic(diagnostic); + }; + } + } public void Initialize(GeneratorInitializationContext context) { diff --git a/src/Altinn.App.ModelGenerator/utils/PathUtils.cs b/src/Altinn.App.ModelGenerator/utils/PathUtils.cs index 0a11b7ba..f6ee5281 100644 --- a/src/Altinn.App.ModelGenerator/utils/PathUtils.cs +++ b/src/Altinn.App.ModelGenerator/utils/PathUtils.cs @@ -12,6 +12,7 @@ public static bool IsLayoutPath(string filePath) if(!fileInfo.Directory.Parent.Name.Equals("ui", System.StringComparison.InvariantCultureIgnoreCase)) return false; return true; } + public static bool IsResourcePath(string filePath) { var fileInfo = new FileInfo(filePath); @@ -21,6 +22,7 @@ public static bool IsResourcePath(string filePath) if(!fileInfo.Directory.Parent.Name.Equals("config", System.StringComparison.InvariantCultureIgnoreCase)) return false; return true; } + public static bool IsApplicationmetadata(string filePath) { var fileInfo = new FileInfo(filePath); @@ -28,6 +30,7 @@ public static bool IsApplicationmetadata(string filePath) if(!fileInfo.Directory.Name.Equals("config", System.StringComparison.InvariantCultureIgnoreCase)) return false; return true; } + public static bool IsSettings(string filePath) { var fileInfo = new FileInfo(filePath); @@ -35,5 +38,11 @@ public static bool IsSettings(string filePath) if(!fileInfo.Directory.Name.Equals("ui", System.StringComparison.InvariantCultureIgnoreCase)) return false; return true; } + + public static string FileNameFromPath(string filePath) + { + var fileInfo = new FileInfo(filePath); + return fileInfo.Name; + } } } \ No newline at end of file diff --git a/src/Altinn.App.ModelGenerator/validators/AltinnDiagnosticsDescriptors.cs b/src/Altinn.App.ModelGenerator/validators/AltinnDiagnosticsDescriptors.cs new file mode 100644 index 00000000..92c1e4f6 --- /dev/null +++ b/src/Altinn.App.ModelGenerator/validators/AltinnDiagnosticsDescriptors.cs @@ -0,0 +1,15 @@ +using Microsoft.CodeAnalysis; + +namespace Altinn.App.ModelGenerator; + +public static class AltinnDiagnosticsDescriptors +{ + public static readonly DiagnosticDescriptor JsonParseError + = new DiagnosticDescriptor( + id: "ALT001", + title: "Error in json parsing", + messageFormat: "{0}", + category: "AltinnAnalyzer", + defaultSeverity: DiagnosticSeverity.Error, + isEnabledByDefault: true ); +} diff --git a/src/Altinn.App.ModelGenerator/validators/JsonValidator.cs b/src/Altinn.App.ModelGenerator/validators/JsonValidator.cs new file mode 100644 index 00000000..fc478ddb --- /dev/null +++ b/src/Altinn.App.ModelGenerator/validators/JsonValidator.cs @@ -0,0 +1,29 @@ +using System.Text.Json; +using System.Text.Json.Nodes; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.Text; +namespace Altinn.App.ModelGenerator; + +public static class JsonValidator +{ + public static List GetJsonParseDiagnostics(string filename, string content) + { + var ret = new List(); + try + { + var options = new JsonDocumentOptions() + { + CommentHandling = JsonCommentHandling.Skip, // stylecop.json includes comments + }; + JsonNode.Parse(content, null, options); + } + catch (JsonException e) + { + var linePosition = new LinePosition((int)e.LineNumber, (int)e.BytePositionInLine); + ret.Add(Diagnostic.Create(AltinnDiagnosticsDescriptors.JsonParseError, + Location.Create(filename, new TextSpan(0, content.Length), new LinePositionSpan(linePosition, linePosition)), + e.Message)); + } + return ret; + } +} From e04d38ee14d878acb00ee31f8221237ecda97ce1 Mon Sep 17 00:00:00 2001 From: Ivar Date: Thu, 12 May 2022 15:14:12 +0200 Subject: [PATCH 7/7] Attempt to fix tests on Github actions --- src/Altinn.App.ModelGenerator.Tests/LayoutToModelTests.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/Altinn.App.ModelGenerator.Tests/LayoutToModelTests.cs b/src/Altinn.App.ModelGenerator.Tests/LayoutToModelTests.cs index 5b853f86..370d25bc 100644 --- a/src/Altinn.App.ModelGenerator.Tests/LayoutToModelTests.cs +++ b/src/Altinn.App.ModelGenerator.Tests/LayoutToModelTests.cs @@ -18,7 +18,9 @@ public void TestGetModelDataBindings(string FormLayout, string summary, string e var bindings = LayoutToModel.GetDataModelBindings(new string[]{FormLayout, summary}); Assert.Equal(JsonSerializer.Deserialize>(expectedBindings), bindings); var generatedModel = LayoutToModel.Convert(bindings, "Altinn.App.Models.Model"); - Assert.Equal(expectedModel, generatedModel); + Assert.Equal( + expectedModel.Replace("\r\n","\n"), //Github actions has configured git to translate LF to CRLF + generatedModel); } [Theory] [InlineData("Altinn.App.Models.KRT1226Gjenopprettingsplaner_M", "Altinn.App.Models", "KRT1226Gjenopprettingsplaner_M")]