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

added support for Component Library on Component Instances #642

Merged
merged 7 commits into from
Apr 17, 2024
Merged
Show file tree
Hide file tree
Changes from 5 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
1 change: 1 addition & 0 deletions src/Persistence.Tests/Yaml/RoundTripTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ public void Screen_With_Component_Instance(string path, bool isControlIdentifier
customControl.Should().NotBeNull();
customControl.Name.Should().Be("This is custom component");
customControl.ComponentName.Should().Be("ComponentDefinition_1");
customControl.ComponentLibraryUniqueName.Should().Be("MyComponentLibrary");
mizrael marked this conversation as resolved.
Show resolved Hide resolved

// Act II: Serialize the object back into yaml.
var serializer = CreateSerializer(isControlIdentifiers);
Expand Down
31 changes: 31 additions & 0 deletions src/Persistence.Tests/Yaml/ValidSerializerTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -314,4 +314,35 @@ public void Serialize_ShouldCreateValidYamlForComponentDefinitions(ComponentType

serializedComponent.Should().Be(expectedYaml);
}

[TestMethod]
[DataRow(@"_TestData/ValidYaml{0}/Screen/with-component-instance.pa.yaml", true)]
[DataRow(@"_TestData/ValidYaml{0}/Screen/with-component-instance.pa.yaml", false)]
public void Serialize_ShouldCreateValidYamlForComponentInstance(string expectedPath, bool isControlIdentifiers)
{
var graph = ControlFactory.CreateScreen("Hello",
properties: new(),
children: new Control[]
{
new ComponentInstance()
{
Name = "This is custom component",
ComponentName = "ComponentDefinition_1",
ComponentLibraryUniqueName = "MyComponentLibrary",
Variant = string.Empty,
Template = new Microsoft.PowerPlatform.PowerApps.Persistence.Templates.ControlTemplate("http://localhost/Component"),
Properties = new()
{
new ControlProperty("X", "15"),
new ControlProperty("Y", "55"),
}
}
});
var sut = CreateSerializer(isControlIdentifiers: isControlIdentifiers);

var serializedGraph = sut.SerializeControl(graph).NormalizeNewlines();

var expectedYaml = File.ReadAllText(GetTestFilePath(expectedPath, isControlIdentifiers)).NormalizeNewlines();
serializedGraph.Should().Be(expectedYaml);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ Hello:
- This is custom component:
Control: Component
ComponentName: ComponentDefinition_1
ComponentLibraryUniqueName: MyComponentLibrary
mizrael marked this conversation as resolved.
Show resolved Hide resolved
Properties:
X: =15
Y: =55
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
Control: Screen
Name: Hello
Children:
- Control: Component
Name: This is custom component
ComponentName: ComponentDefinition_1
ComponentLibraryUniqueName: MyComponentLibrary
Properties:
X: =15
Y: =55
3 changes: 3 additions & 0 deletions src/Persistence/Models/ComponentInstance.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,4 +25,7 @@ public ComponentInstance(string name, string variant, ControlTemplate controlTem

[YamlMember(Order = 1)]
public string ComponentName { get; set; } = string.Empty;

[YamlMember(Order = 2)]
public string? ComponentLibraryUniqueName { get; set; } = string.Empty;
}
34 changes: 26 additions & 8 deletions src/Persistence/Templates/ControlFactory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,13 @@ public ControlFactory(IControlTemplateStore controlTemplateStore)
_controlTemplateStore = controlTemplateStore ?? throw new ArgumentNullException(nameof(controlTemplateStore));
}

public Control Create(string name, string template, string? componentDefinitionName = null, string? variant = null,
public Control Create(string name, string template,
string? componentDefinitionName = null,
string? componentLibraryUniqueName = null,
string? variant = null,
ControlPropertiesCollection? properties = null, IList<Control>? children = null)
{
if (TryCreateComponent(name, template, componentDefinitionName, variant, properties, children, controlDefinition: null, out var control))
if (TryCreateComponent(name, template, componentDefinitionName, componentLibraryUniqueName, variant, properties, children, controlDefinition: null, out var control))
return control;

if (_controlTemplateStore.TryGetByIdOrName(template, out var controlTemplate))
Expand All @@ -42,7 +45,10 @@ public Control Create(string name, string template, string? componentDefinitionN
};
}

public Control Create(string name, string template, string componentDefinitionName, Dictionary<string, object?>? controlDefinition)
public Control Create(string name, string template,
string componentDefinitionName,
string componentLibraryUniqueName,
Dictionary<string, object?>? controlDefinition)
{
string? variant = null;
ControlPropertiesCollection? properties = null;
Expand All @@ -55,7 +61,7 @@ public Control Create(string name, string template, string componentDefinitionNa
controlDefinition.TryGetValue(nameof(Control.Children), out children);
}

if (TryCreateComponent(name, template, componentDefinitionName, variant, properties, children, controlDefinition, out var control))
if (TryCreateComponent(name, template, componentDefinitionName, componentLibraryUniqueName, variant, properties, children, controlDefinition, out var control))
return control;

if (_controlTemplateStore.TryGetByIdOrName(template, out var controlTemplate))
Expand All @@ -79,9 +85,13 @@ public Control Create(string name, string template, string componentDefinitionNa
};
}

public Control Create(string name, ControlTemplate template, string? componentDefinitionName = null, string? variant = null, ControlPropertiesCollection? properties = null, IList<Control>? children = null)
public Control Create(string name, ControlTemplate template,
string? componentDefinitionName = null,
string? componentLibraryUniqueName = null,
string? variant = null,
ControlPropertiesCollection? properties = null, IList<Control>? children = null)
{
if (TryCreateComponent(name, template, componentDefinitionName, variant, properties, children, controlDefinition: null, out var control))
if (TryCreateComponent(name, template, componentDefinitionName, componentLibraryUniqueName, variant, properties, children, controlDefinition: null, out var control))
return control;

if (TryCreateFirstClassControl(name, template.Name, variant ?? string.Empty, properties, children, controlDefinition: null, out control))
Expand Down Expand Up @@ -112,7 +122,10 @@ public Screen CreateScreen(string name, ControlPropertiesCollection? properties
};
}

private bool TryCreateComponent(string name, string template, string? componentDefinitionName, string? variant,
private bool TryCreateComponent(string name, string template,
string? componentDefinitionName,
string? componentLibraryUniqueName,
string? variant,
ControlPropertiesCollection? properties, IList<Control>? children, Dictionary<string, object?>? controlDefinition,
[MaybeNullWhen(false)] out Control control)
{
Expand All @@ -123,6 +136,7 @@ private bool TryCreateComponent(string name, string template, string? componentD
new ControlTemplate(ComponentInstance.ComponentInstanceTemplateId) { Name = componentDefinitionName })
{
ComponentName = componentDefinitionName,
ComponentLibraryUniqueName = componentLibraryUniqueName,
Properties = properties ?? new(),
Children = children
};
Expand All @@ -142,7 +156,10 @@ private bool TryCreateComponent(string name, string template, string? componentD
return control != null;
}

private static bool TryCreateComponent(string name, ControlTemplate template, string? componentDefinitionName, string? variant,
private static bool TryCreateComponent(string name, ControlTemplate template,
string? componentDefinitionName,
string? componentLibraryUniqueName,
string? variant,
ControlPropertiesCollection? properties, IList<Control>? children, Dictionary<string, object?>? controlDefinition,
[MaybeNullWhen(false)] out Control control)
{
Expand All @@ -151,6 +168,7 @@ private static bool TryCreateComponent(string name, ControlTemplate template, st
control = new ComponentInstance(name, variant ?? string.Empty, template)
{
ComponentName = componentDefinitionName,
ComponentLibraryUniqueName = componentLibraryUniqueName,
Properties = properties ?? new(),
Children = children
};
Expand Down
5 changes: 0 additions & 5 deletions src/Persistence/Templates/ControlTemplate.cs
Original file line number Diff line number Diff line change
Expand Up @@ -81,10 +81,5 @@ public class CustomComponentInfo
/// The friendly identifier of the component.
/// </summary>
public required string Name { get; init; }

/// <summary>
/// The unique name of the component library if this component originates from a component library.
/// </summary>
public string? ComponentLibraryUniqueName { get; init; }
}
}
6 changes: 3 additions & 3 deletions src/Persistence/Templates/IControlFactory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,11 @@ namespace Microsoft.PowerPlatform.PowerApps.Persistence.Templates;

public interface IControlFactory
{
Control Create(string name, string template, string? componentDefinitionName = null, string? variant = null, ControlPropertiesCollection? properties = null, IList<Control>? children = null);
Control Create(string name, string template, string? componentDefinitionName = null, string? componentLibraryUniqueName = null, string? variant = null, ControlPropertiesCollection? properties = null, IList<Control>? children = null);

Control Create(string name, ControlTemplate template, string? componentDefinitionName = null, string? variant = null, ControlPropertiesCollection? properties = null, IList<Control>? children = null);
Control Create(string name, ControlTemplate template, string? componentDefinitionName = null, string? componentLibraryUniqueName = null, string? variant = null, ControlPropertiesCollection? properties = null, IList<Control>? children = null);

Control Create(string name, string template, string componentDefinitionName, Dictionary<string, object?>? controlDefinition);
Control Create(string name, string template, string componentDefinitionName, string componentLibraryUniqueName, Dictionary<string, object?>? controlDefinition);

App CreateApp(string name, ControlPropertiesCollection? properties = null);

Expand Down
1 change: 1 addition & 0 deletions src/Persistence/Yaml/ComponentConverter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ public override void OnWriteAfterName(IEmitter emitter, Control control)
if (control is ComponentInstance componentInstance)
{
emitter.Emit(nameof(ComponentInstance.ComponentName), componentInstance.ComponentName);
emitter.Emit(nameof(ComponentInstance.ComponentLibraryUniqueName), componentInstance.ComponentLibraryUniqueName);
base.OnWriteAfterName(emitter, control);
return;
}
Expand Down
13 changes: 9 additions & 4 deletions src/Persistence/Yaml/ControlConverter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,9 @@ public virtual bool Accepts(Type type)
ReadControlDefinitonHeader(parser, out var controlName, out var templateName);

var controlDefinition = new Dictionary<string, object?>();
var componentInstance = string.Empty;
var componentInstanceName = string.Empty;
var componentLibraryUniqueName = string.Empty;

while (!parser.Accept<MappingEnd>(out _))
{
var key = parser.Consume<Scalar>();
Expand Down Expand Up @@ -80,7 +82,9 @@ public virtual bool Accepts(Type type)
if (key.Value == nameof(Control))
templateName = (string)value;
else if (key.Value == nameof(ComponentInstance.ComponentName))
componentInstance = (string)value;
componentInstanceName = (string)value;
else if (key.Value == nameof(ComponentInstance.ComponentLibraryUniqueName))
componentLibraryUniqueName = (string)value;
}
else
{
Expand All @@ -97,7 +101,7 @@ public virtual bool Accepts(Type type)

if (Options.IsControlIdentifiers)
{
if (string.IsNullOrWhiteSpace(templateName) && string.IsNullOrWhiteSpace(componentInstance))
if (string.IsNullOrWhiteSpace(templateName) && string.IsNullOrWhiteSpace(componentInstanceName))
throw new YamlException(parser.Current!.Start, parser.Current.End, $"Control '{controlName}' doesn't have template name");
}

Expand All @@ -108,7 +112,8 @@ public virtual bool Accepts(Type type)
// Create control instance
var control = _controlFactory.Create(
string.IsNullOrWhiteSpace(controlName) ? templateName : controlName,
templateName, componentInstance, controlDefinition);
templateName, componentInstanceName, componentLibraryUniqueName, controlDefinition);

return control.AfterDeserialize(_controlFactory);
}

Expand Down