Skip to content

Commit

Permalink
PASopa for modern controls (#670)
Browse files Browse the repository at this point in the history
  • Loading branch information
marcelbf authored Jun 14, 2024
1 parent 929a800 commit 97a7fef
Show file tree
Hide file tree
Showing 5 changed files with 36 additions and 7 deletions.
4 changes: 2 additions & 2 deletions src/PAModel/CanvasDocument.cs
Original file line number Diff line number Diff line change
Expand Up @@ -350,7 +350,7 @@ internal void ApplyAfterMsAppLoadTransforms(ErrorContainer errors)
var templateDefaults = new Dictionary<string, ControlTemplate>();
foreach (var template in _templates.UsedTemplates)
{
if (!ControlTemplateParser.TryParseTemplate(_templateStore, template.Template, _properties.DocumentAppType, templateDefaults, out _, out _))
if (!ControlTemplateParser.TryParseTemplate(_templateStore, template.Template, _properties.DocumentAppType, templateDefaults, out _, out _, template.Name))
{
errors.GenericError($"Unable to parse template file {template.Name}");
throw new DocumentException();
Expand Down Expand Up @@ -405,7 +405,7 @@ internal void ApplyBeforeMsAppWriteTransforms(ErrorContainer errors)
var templateDefaults = new Dictionary<string, ControlTemplate>();
foreach (var template in _templates.UsedTemplates)
{
if (!ControlTemplateParser.TryParseTemplate(_templateStore, template.Template, _properties.DocumentAppType, templateDefaults, out _, out _))
if (!ControlTemplateParser.TryParseTemplate(_templateStore, template.Template, _properties.DocumentAppType, templateDefaults, out _, out _, template.Name))
{
errors.GenericError($"Unable to parse template file {template.Name}");
throw new DocumentException();
Expand Down
7 changes: 4 additions & 3 deletions src/PAModel/ControlTemplates/ControlTemplateParser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,10 @@ internal class ControlTemplateParser
internal static Regex _reservedIdentifierRegex = new(@"%([a-zA-Z]*)\.RESERVED%");

[System.Diagnostics.CodeAnalysis.SuppressMessage("Design", "CA1031:Do not catch general exception types", Justification = "<Pending>")]
internal static bool TryParseTemplate(TemplateStore templateStore, string templateString, AppType type, Dictionary<string, ControlTemplate> loadedTemplates, out ControlTemplate template, out string name)
internal static bool TryParseTemplate(TemplateStore templateStore, string templateString, AppType type, Dictionary<string, ControlTemplate> loadedTemplates, out ControlTemplate template, out string name, string templateName = null)
{
template = null;
name = string.Empty;
name = templateName;
try
{
var manifest = XDocument.Parse(templateString);
Expand All @@ -26,7 +26,8 @@ internal static bool TryParseTemplate(TemplateStore templateStore, string templa
if (widget.Name != ControlMetadataXNames.WidgetTag)
return false;

name = widget.Attribute(ControlMetadataXNames.NameAttribute).Value;
name ??= widget.Attribute(ControlMetadataXNames.NameAttribute).Value;

var id = widget.Attribute(ControlMetadataXNames.IdAttribute).Value;
var version = widget.Attribute(ControlMetadataXNames.VersionAttribute).Value;

Expand Down
5 changes: 3 additions & 2 deletions src/PAModel/Serializers/SourceSerializer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -310,7 +310,8 @@ private static void LoadTemplateFiles(ErrorContainer errors, CanvasDocument app,
foreach (var file in new DirectoryReader(packagesPath).EnumerateFiles(string.Empty, "*.xml", searchSubdirectories: false))
{
var xmlContents = file.GetContents();
if (!ControlTemplateParser.TryParseTemplate(new TemplateStore(), xmlContents, app._properties.DocumentAppType, loadedTemplates, out var parsedTemplate, out var templateName))
var templateNameFromFile = file._relativeName.Substring(0, file._relativeName.LastIndexOf('_'));
if (!ControlTemplateParser.TryParseTemplate(new TemplateStore(), xmlContents, app._properties.DocumentAppType, loadedTemplates, out var parsedTemplate, out var templateName, templateNameFromFile))
{
errors.GenericError($"Unable to parse template file {file._relativeName}");
throw new DocumentException();
Expand Down Expand Up @@ -523,7 +524,7 @@ public static void SaveAsSource(CanvasDocument app, string directory2, ErrorCont
{
var filename = $"{template.Name}_{template.Version}.xml";
dir.WriteAllXML(PackagesDir, new FilePath(filename), template.Template);
if (!ControlTemplateParser.TryParseTemplate(app._templateStore, template.Template, app._properties.DocumentAppType, templateDefaults, out _, out _))
if (!ControlTemplateParser.TryParseTemplate(app._templateStore, template.Template, app._properties.DocumentAppType, templateDefaults, out _, out _, template.Name))
throw new NotSupportedException($"Unable to parse template file {template.Name}");
}

Expand Down
Binary file added src/PAModelTests/Apps/ComboboxDropdown.msapp
Binary file not shown.
27 changes: 27 additions & 0 deletions src/PAModelTests/TemplateStoreTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -44,4 +44,31 @@ public void TestHostControlInstancesWithHostType(string appName)
Assert.IsTrue(MsAppTest.Compare(root, tempFile.FullPath, Console.Out));
}
}

// Validate a modern control that has a dynamic template.
// The template has a valid template name, but makes reference to another template.
// This example app has two modern controls (combobox and dropdown) that make reference to the same template.
[DataTestMethod]
[DataRow("ComboboxDropdown.msapp")]
public void TestModernControlWithDynamicTemplate(string appName)
{
//arrange
var root = Path.Combine(Environment.CurrentDirectory, "Apps", appName);
Assert.IsTrue(File.Exists(root), "MSAPP not found");

//act
(var msapp, var errors) = CanvasDocument.LoadFromMsapp(root);
errors.ThrowOnErrors();

//assert
Assert.IsTrue(msapp._templateStore.Contents.ContainsKey("PowerApps_CoreControls_DropdownCanvasTemplate_dataField"));
Assert.IsTrue(msapp._templateStore.Contents.ContainsKey("PowerApps_CoreControls_ComboboxCanvasTemplate_dataField"));

// Repack the app and validate it matches the initial msapp
using (var tempFile = new TempFile())
{
MsAppSerializer.SaveAsMsApp(msapp, tempFile.FullPath, new ErrorContainer());
Assert.IsTrue(MsAppTest.Compare(root, tempFile.FullPath, Console.Out));
}
}
}

0 comments on commit 97a7fef

Please sign in to comment.