Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

PASopa for modern controls #670

Merged
merged 3 commits into from
Jun 14, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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));
}
}
}
Loading