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

Improve Summary screen by adding more details about applied resources #912

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
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,10 @@ public sealed class ElevatedConfigureUnitTaskResult
{
public string? UnitName { get; set; }

public string? Id { get; set; }

public string? Description { get; set; }

public string? Intent { get; set; }

public bool IsSkipped { get; set; }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,12 +34,18 @@ public IAsyncOperation<ElevatedConfigureTaskResult> ApplyConfiguration(StorageFi
taskResult.TaskAttempted = true;
taskResult.TaskSucceeded = result.Succeeded;
taskResult.RebootRequired = result.RequiresReboot;
taskResult.UnitResults = result.Result.UnitResults.Select(unitResult => new ElevatedConfigureUnitTaskResult
taskResult.UnitResults = result.Result.UnitResults.Select(unitResult =>
{
UnitName = unitResult.Unit.UnitName,
Intent = unitResult.Unit.Intent.ToString(),
IsSkipped = unitResult.State == ConfigurationUnitState.Skipped,
HResult = unitResult.ResultInformation?.ResultCode?.HResult ?? HRESULT.S_OK,
unitResult.Unit.Directives.TryGetValue("description", out var descriptionObj);
return new ElevatedConfigureUnitTaskResult
{
UnitName = unitResult.Unit.UnitName,
Id = unitResult.Unit.Identifier,
Description = descriptionObj?.ToString() ?? string.Empty,
Intent = unitResult.Unit.Intent.ToString(),
IsSkipped = unitResult.State == ConfigurationUnitState.Skipped,
HResult = unitResult.ResultInformation?.ResultCode?.HResult ?? HRESULT.S_OK,
};
}).ToList();

if (result.ResultException != null)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@ public class ConfigurationUnitResult
public ConfigurationUnitResult(ApplyConfigurationUnitResult result)
{
UnitName = result.Unit.UnitName;
Id = result.Unit.Identifier;
result.Unit.Directives.TryGetValue("description", out var descriptionObj);
Description = descriptionObj?.ToString() ?? string.Empty;
Intent = result.Unit.Intent.ToString();
IsSkipped = result.State == ConfigurationUnitState.Skipped;
HResult = result.ResultInformation?.ResultCode?.HResult ?? HRESULT.S_OK;
Expand All @@ -21,13 +24,19 @@ public ConfigurationUnitResult(ApplyConfigurationUnitResult result)
public ConfigurationUnitResult(ElevatedConfigureUnitTaskResult result)
{
UnitName = result.UnitName;
Id = result.Id;
Description = result.Description;
Intent = result.Intent;
IsSkipped = result.IsSkipped;
HResult = result.HResult;
}

public string UnitName { get; }

public string Id { get; }

public string Description { get; }

public string Intent { get; }

public bool IsSkipped { get; }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,10 @@ public static class StringResourceKey
public static readonly string ConfigurationUnitFailed = nameof(ConfigurationUnitFailed);
public static readonly string ConfigurationUnitSkipped = nameof(ConfigurationUnitSkipped);
public static readonly string ConfigurationUnitSuccess = nameof(ConfigurationUnitSuccess);
public static readonly string ConfigurationUnitSummary = nameof(ConfigurationUnitSummary);
public static readonly string ConfigurationUnitSummaryFull = nameof(ConfigurationUnitSummaryFull);
public static readonly string ConfigurationUnitSummaryMinimal = nameof(ConfigurationUnitSummaryMinimal);
public static readonly string ConfigurationUnitSummaryNoDescription = nameof(ConfigurationUnitSummaryNoDescription);
public static readonly string ConfigurationUnitSummaryNoId = nameof(ConfigurationUnitSummaryNoId);
public static readonly string ConfigurationUnitStats = nameof(ConfigurationUnitStats);
public static readonly string ConfigurationViewTitle = nameof(ConfigurationViewTitle);
public static readonly string DevDriveReviewTitle = nameof(DevDriveReviewTitle);
Expand Down
16 changes: 14 additions & 2 deletions tools/SetupFlow/DevHome.SetupFlow/Strings/en-us/Resources.resw
Original file line number Diff line number Diff line change
Expand Up @@ -221,9 +221,21 @@
<value>Configuration successfully applied</value>
<comment>Message displayed when applying a configuration unit succeeds.</comment>
</data>
<data name="ConfigurationUnitSummary" xml:space="preserve">
<data name="ConfigurationUnitSummaryFull" xml:space="preserve">
<value>{0} : {3} [{1} {2}]</value>
<comment>{Locked="{0}","{1}","{2}","{3}"}Summary text for a configuration unit. {0} is replaced by the configuration unit intent (e.g. Assert, Inform, Apply). {1} is replaced by the configuration unit name. {2} is replaced by the configuration unit id. {3} is replaced by the configuration unit description. A string with all values replaced could look like "Apply : Install VS [WinGetPackage vspackage]"</comment>
</data>
<data name="ConfigurationUnitSummaryMinimal" xml:space="preserve">
<value>{0} : {1}</value>
<comment>{Locked="{0}","{1}"}Summary text for a configuration unit. {0} is replaced by the configuration unit intent (e.g. Assert, Inform, Apply). {1} is replaced by the configuration unit name.</comment>
<comment>{Locked="{0}","{1}"}Summary text for a configuration unit. {0} is replaced by the configuration unit intent (e.g. Assert, Inform, Apply). {1} is replaced by the configuration unit name. A string with all values replaced could look like "Apply : WinGetPackage"</comment>
</data>
<data name="ConfigurationUnitSummaryNoDescription" xml:space="preserve">
<value>{0} : {1} [{2}]</value>
Comment on lines +232 to +233
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need all of these variants to be localized? I'm a bit concerned that we may have more combinations we want to be able to handle and that's going to grow too much.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I just followed the current style because I have no much context on why we are using a localized string for this, but folks, if you want I'm good with removing this strings.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't remember getting guidance specifically about this. When I've added strings like these to localization it is because I'm not sure if other locales would use the same characters.
For example, I know for quotes some languages use 「these」 and some others use „these“. Not sure if that applies in this case, particularly considering the audience here is developers.

If we're keeping your current formatting, I think it's okay to localize these. IIRC my comment was thinking of adding the components to the string one by one always in the same order, instead of the current formatting where things change places depending on which ones are available.

<comment>{Locked="{0}","{1}","{2}"}Summary text for a configuration unit. {0} is replaced by the configuration unit intent (e.g. Assert, Inform, Apply). {1} is replaced by the configuration unit name. {2} is replaced by the configuration unit id. A string with all values replaced could look like "Apply : WinGetPackage [vspackage]"</comment>
</data>
<data name="ConfigurationUnitSummaryNoId" xml:space="preserve">
<value>{0} : {2} [{1}]</value>
<comment>{Locked="{0}","{1}","{2}"}Summary text for a configuration unit. {0} is replaced by the configuration unit intent (e.g. Assert, Inform, Apply). {1} is replaced by the configuration unit name. {2} is replaced by the configuration unit description. A string with all values replaced could look like "Apply : Install VS [WinGetPackage]"</comment>
</data>
<data name="ConfigurationUnitStats" xml:space="preserve">
<value>Succeeded: {0} | Failed: {1} | Skipped: {2}</value>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ public ConfigurationUnitResultViewModel(ISetupFlowStringResource stringResource,
_unitResult = unitResult;
}

public string Title => _stringResource.GetLocalized(StringResourceKey.ConfigurationUnitSummary, _unitResult.Intent, _unitResult.UnitName);
public string Title => BuildTitle();

public string ApplyResult => GetApplyResult();

Expand All @@ -54,4 +54,24 @@ private string GetApplyResult()

return _stringResource.GetLocalized(StringResourceKey.ConfigurationUnitSuccess);
}

private string BuildTitle()
{
if (string.IsNullOrEmpty(_unitResult.Id) && string.IsNullOrEmpty(_unitResult.Description))
{
return _stringResource.GetLocalized(StringResourceKey.ConfigurationUnitSummaryMinimal, _unitResult.Intent, _unitResult.UnitName);
}

if (string.IsNullOrEmpty(_unitResult.Id))
{
return _stringResource.GetLocalized(StringResourceKey.ConfigurationUnitSummaryNoId, _unitResult.Intent, _unitResult.UnitName, _unitResult.Description);
}

if (string.IsNullOrEmpty(_unitResult.Description))
{
return _stringResource.GetLocalized(StringResourceKey.ConfigurationUnitSummaryNoDescription, _unitResult.Intent, _unitResult.UnitName, _unitResult.Id);
}

return _stringResource.GetLocalized(StringResourceKey.ConfigurationUnitSummaryFull, _unitResult.Intent, _unitResult.UnitName, _unitResult.Id, _unitResult.Description);
Comment on lines +60 to +75
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: It bothers me a bit to have all the repetition of GetLocalized. I wonder if it could make sense to do something like

var resourceKey = StringResourceKey.ConfigurationUnitSummaryFull;
if (condition1) resourceKey = [another string]
else if (condition2) resourceKey = [another string]

return _stringResource.GetLocalized(resourceKey, _unitResult.Intent, _unitResult.UnitName, ...);

Though this may be abusing the GetLocalized function since it may not be intended to get more replacements than placeholders there are

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is a corner case that break the simplicity of this solution: if the unit ID is missing the description should be the thrid param. Because of this the resulting code looks worse (even assuming the repetition of return _stringResource.GetLocalized(...)) to me because hide its intention:

private string BuildTitle()
{
    var missingId = string.IsNullOrEmpty(_unitResult.Id);
    var missingDescription = string.IsNullOrEmpty(_unitResult.Description);
    var summaryResourceKey = StringResourceKey.ConfigurationUnitSummaryFull;
    object[] localizedParams = { _unitResult.Intent, _unitResult.UnitName, _unitResult.Id, _unitResult.Description };

    if (missingId && missingDescription)
    {
        summaryResourceKey = StringResourceKey.ConfigurationUnitSummaryMinimal;
    }
    else if (missingId)
    {
        summaryResourceKey = StringResourceKey.ConfigurationUnitSummaryNoId;

        // for this variant of the string template the description is the thrid param
        localizedParams[2] = _unitResult.Description;
    }
    else if (missingDescription)
    {
        summaryResourceKey = StringResourceKey.ConfigurationUnitSummaryNoDescription;
    }

    return _stringResource.GetLocalized(summaryResourceKey, localizedParams);
}

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if the unit ID is missing the description should be the thrid param

This may be a Bad Idea® but... This could probably be avoided by having that string skip the replacement {2} so it would be like {0} : {3} [{1}]
Unless something is checking that the numbers used are contiguous.

Anyways, what I'm suggesting would be adding complexity in the strings to get some simplicity here, so it may not be worth it.

}
}