diff --git a/src/PKSim.Core/CoreConstants.cs b/src/PKSim.Core/CoreConstants.cs
index 867ca4173..0dd9733ed 100644
--- a/src/PKSim.Core/CoreConstants.cs
+++ b/src/PKSim.Core/CoreConstants.cs
@@ -80,11 +80,13 @@ public static class Filter
public static readonly string TEMPLATE_USER_DATABASE_TEMPLATE = "PKSimTemplateDBUser.template";
public static readonly string REMOTE_TEMPLATE_SUMMARY = "templates.json";
public const string PRODUCT_NAME = "PK-Sim";
+ public const string TEMPLATES_PRODUCT_NAME = "BuildingBlockTemplates";
public static readonly string PRODUCT_NAME_WITH_TRADEMARK = "PK-SimĀ®";
public static readonly string DEFAULT_SKIN = "Office 2013 Light Gray";
public static readonly string VALUE_PROPERTY_NAME = "Value";
public static readonly string PROJECT_UNDEFINED = "Undefined";
public static readonly string VERSION_FILE_URL = "https://raw.githubusercontent.com/Open-Systems-Pharmacology/Suite/master/versions.json";
+ public static readonly string REMOTE_TEMPLATE_FILE_URL = "https://raw.githubusercontent.com/Open-Systems-Pharmacology/OSPSuite.BuildingBlockTemplates/main/templates.json";
public static readonly string ISSUE_TRACKER_URL = "https://github.com/open-systems-pharmacology/pk-sim/issues";
public static readonly string TEMPLATE_DATABASE_CONVERSION_WIKI_URL =
@@ -92,7 +94,7 @@ public static class Filter
public const string APPLICATION_NAME_TEMPLATE = "Application_";
- //tolerated precision to relativtely compare to double values
+ //tolerated precision to relatively compare to double values
public const double DOUBLE_RELATIVE_EPSILON = 1e-2;
public const char COMPOSITE_SEPARATOR = '-';
diff --git a/src/PKSim.Core/IPKSimConfiguration.cs b/src/PKSim.Core/IPKSimConfiguration.cs
index 41a577cf0..4500be0d8 100644
--- a/src/PKSim.Core/IPKSimConfiguration.cs
+++ b/src/PKSim.Core/IPKSimConfiguration.cs
@@ -34,6 +34,9 @@ public interface IPKSimConfiguration : IApplicationConfiguration
///
string RemoteTemplateSummaryPath { get; }
+ ///
+ /// Folder path where templates will be downloaded
+ ///
string RemoteTemplateFolderPath { get; }
}
diff --git a/src/PKSim.Core/Repositories/IRemoteTemplateRepository.cs b/src/PKSim.Core/Repositories/IRemoteTemplateRepository.cs
index 9bbfc5992..32207f1a4 100644
--- a/src/PKSim.Core/Repositories/IRemoteTemplateRepository.cs
+++ b/src/PKSim.Core/Repositories/IRemoteTemplateRepository.cs
@@ -12,5 +12,6 @@ public interface IRemoteTemplateRepository : IStartableRepository LoadTemplateAsync(RemoteTemplate remoteTemplate);
IReadOnlyList AllReferenceTemplatesFor(RemoteTemplate remoteTemplate, T loadedTemplate);
+ Task UpdateLocalTemplateSummaryFile();
}
}
\ No newline at end of file
diff --git a/src/PKSim.Core/Services/IVersionChecker.cs b/src/PKSim.Core/Services/IVersionChecker.cs
index 6b73def3c..e9852b009 100644
--- a/src/PKSim.Core/Services/IVersionChecker.cs
+++ b/src/PKSim.Core/Services/IVersionChecker.cs
@@ -24,9 +24,24 @@ public interface IVersionChecker
///
VersionInfo LatestVersion { get; }
+ ///
+ /// Returns the latest version available for the product named
+ ///
+ VersionInfo LatestVersionFor(string productName);
+
+ ///
+ /// Downloads the latest version available for our software products
+ ///
+ Task DownloadLatestVersionInfoAsync();
+
///
/// Returns true if a new version was found otherwise false. The latest version can be retrieved from LatestVersion
///
- Task NewVersionIsAvailableAsync();
+ bool NewVersionIsAvailable { get; }
+
+ ///
+ /// Returns true if a new version was found for product named otherwise false.
+ ///
+ bool NewVersionIsAvailableFor(string productName, string currentVersion);
}
}
\ No newline at end of file
diff --git a/src/PKSim.Infrastructure/ORM/Repositories/RemoteTemplateRepository.cs b/src/PKSim.Infrastructure/ORM/Repositories/RemoteTemplateRepository.cs
index 656dd08f4..8d14c0cdd 100644
--- a/src/PKSim.Infrastructure/ORM/Repositories/RemoteTemplateRepository.cs
+++ b/src/PKSim.Infrastructure/ORM/Repositories/RemoteTemplateRepository.cs
@@ -69,6 +69,20 @@ public IReadOnlyList AllReferenceTemplatesFor(RemoteTemplate
}
}
+ public async Task UpdateLocalTemplateSummaryFile()
+ {
+ var tempFile = FileHelper.GenerateTemporaryFileName();
+ try
+ {
+ await downloadRemoteFile(CoreConstants.REMOTE_TEMPLATE_FILE_URL, tempFile);
+ FileHelper.Copy(tempFile, _configuration.RemoteTemplateSummaryPath);
+ }
+ catch (Exception)
+ {
+ //could not download the file. Do nothing
+ }
+ }
+
private IReadOnlyList expressionProfileFor(RemoteTemplate remoteTemplate, ISimulationSubject simulationSubject)
{
//TODO Not implemented yet. It will be done with the profile defined for individual as separate building block
diff --git a/src/PKSim.Infrastructure/Services/VersionChecker.cs b/src/PKSim.Infrastructure/Services/VersionChecker.cs
index fb5ed2cce..642d783d6 100644
--- a/src/PKSim.Infrastructure/Services/VersionChecker.cs
+++ b/src/PKSim.Infrastructure/Services/VersionChecker.cs
@@ -3,7 +3,6 @@
using System.Net;
using System.Threading.Tasks;
using OSPSuite.Core.Domain;
-using OSPSuite.Utility.Exceptions;
using PKSim.Core.Services;
namespace PKSim.Infrastructure.Services
@@ -11,57 +10,46 @@ namespace PKSim.Infrastructure.Services
public class VersionChecker : IVersionChecker
{
private readonly IJsonSerializer _jsonSerializer;
+ private IReadOnlyList _allVersions = new List();
public string ProductName { get; set; }
public string CurrentVersion { get; set; }
public string VersionFileUrl { get; set; }
- public VersionInfo LatestVersion { get; private set; }
public VersionChecker(IJsonSerializer jsonSerializer)
{
_jsonSerializer = jsonSerializer;
}
- public async Task NewVersionIsAvailableAsync()
+ public VersionInfo LatestVersion => LatestVersionFor(ProductName);
+
+ public VersionInfo LatestVersionFor(string productName) => _allVersions.FindByName(productName);
+
+ public async Task DownloadLatestVersionInfoAsync()
{
try
{
- await retrieveLatestVersion();
- return newVersionIsAvailable();
-
+ using (var wc = new WebClient())
+ {
+ var jsonContent = await wc.DownloadStringTaskAsync(VersionFileUrl);
+ _allVersions = await _jsonSerializer.DeserializeAsArrayFromString(jsonContent);
+ }
}
catch (Exception)
{
- return false;
+ //we do nothing if we cannot download the file
}
}
- private async Task retrieveLatestVersion()
- {
- using (var wc = new WebClient())
- {
- var jsonContent = await wc.DownloadStringTaskAsync(VersionFileUrl);
- var versions = await _jsonSerializer.DeserializeAsArrayFromString(jsonContent);
- LatestVersion = retrieveVersionFrom(versions);
- }
- }
+ public bool NewVersionIsAvailable => NewVersionIsAvailableFor(ProductName, CurrentVersion);
- private bool newVersionIsAvailable()
+ public bool NewVersionIsAvailableFor(string productName, string currentVersion)
{
- if (LatestVersion == null)
+ var latestVersion = LatestVersionFor(productName);
+ if (latestVersion == null)
return false;
- var curVersion = new Version(CurrentVersion);
- return curVersion.CompareTo(new Version(LatestVersion.Version)) < 0;
- }
-
-
- private VersionInfo retrieveVersionFrom(IEnumerable allVersionInfos)
- {
- var versionInfo = allVersionInfos.FindByName(ProductName);
- if (versionInfo == null)
- throw new OSPSuiteException($"{ProductName} node not available");
-
- return versionInfo;
+ var curVersion = new Version(currentVersion);
+ return curVersion.CompareTo(new Version(latestVersion.Version)) < 0;
}
}
}
\ No newline at end of file
diff --git a/src/PKSim.Presentation/Presenters/AboutPresenter.cs b/src/PKSim.Presentation/Presenters/AboutPresenter.cs
index 5dd42f4e9..58d24133d 100644
--- a/src/PKSim.Presentation/Presenters/AboutPresenter.cs
+++ b/src/PKSim.Presentation/Presenters/AboutPresenter.cs
@@ -12,7 +12,7 @@ namespace PKSim.Presentation.Presenters
{
public interface IAboutPresenter : IDisposablePresenter
{
- Task CheckForUpdate();
+ void CheckForUpdate();
}
public class AboutPresenter : AbstractDisposablePresenter, IAboutPresenter
@@ -36,9 +36,9 @@ public override void Initialize()
_view.Display();
}
- public async Task CheckForUpdate()
+ public void CheckForUpdate()
{
- var newVersionAvailable = await _versionChecker.NewVersionIsAvailableAsync();
+ var newVersionAvailable = _versionChecker.NewVersionIsAvailable;
if (newVersionAvailable)
_dialogCreator.MessageBoxInfo(PKSimConstants.Information.NewVersionIsAvailable(_versionChecker.LatestVersion, Constants.PRODUCT_SITE_DOWNLOAD).RemoveHtml());
diff --git a/src/PKSim.Presentation/Services/PostLaunchChecker.cs b/src/PKSim.Presentation/Services/PostLaunchChecker.cs
index 6b66f6b4b..c213a5435 100644
--- a/src/PKSim.Presentation/Services/PostLaunchChecker.cs
+++ b/src/PKSim.Presentation/Services/PostLaunchChecker.cs
@@ -4,6 +4,8 @@
using OSPSuite.Core.Services;
using OSPSuite.Utility.Events;
using PKSim.Assets;
+using PKSim.Core;
+using PKSim.Core.Repositories;
using PKSim.Core.Services;
using PKSim.Presentation.Events;
@@ -16,24 +18,29 @@ public class PostLaunchChecker : IPostLaunchChecker
private readonly ITemplateDatabaseCreator _templateDatabaseCreator;
private readonly IEventPublisher _eventPublisher;
private readonly IUserSettings _userSettings;
+ private readonly IRemoteTemplateRepository _remoteTemplateRepository;
public PostLaunchChecker(
IVersionChecker versionChecker,
IWatermarkStatusChecker watermarkStatusChecker,
ITemplateDatabaseCreator templateDatabaseCreator,
IEventPublisher eventPublisher,
- IUserSettings userSettings)
+ IUserSettings userSettings,
+ IRemoteTemplateRepository remoteTemplateRepository)
{
_versionChecker = versionChecker;
_watermarkStatusChecker = watermarkStatusChecker;
_templateDatabaseCreator = templateDatabaseCreator;
_eventPublisher = eventPublisher;
_userSettings = userSettings;
+ _remoteTemplateRepository = remoteTemplateRepository;
}
public async Task PerformPostLaunchCheckAsync()
{
- await checkForNewVersionAsync();
+ await checkForNewSoftwareVersionAsync();
+
+ await checkForNewTemplateVersionAsync();
_watermarkStatusChecker.CheckWatermarkStatus();
@@ -41,14 +48,34 @@ public async Task PerformPostLaunchCheckAsync()
}
- private async Task checkForNewVersionAsync()
+ private async Task checkForNewTemplateVersionAsync()
+ {
+ try
+ {
+ await _versionChecker.DownloadLatestVersionInfoAsync();
+ var hasNewVersion = _versionChecker.NewVersionIsAvailableFor(CoreConstants.TEMPLATES_PRODUCT_NAME, _remoteTemplateRepository.Version);
+ if (!hasNewVersion)
+ return;
+
+ await _remoteTemplateRepository.UpdateLocalTemplateSummaryFile();
+ }
+ catch (Exception)
+ {
+ //no need to do anything if version cannot be returned
+ return;
+ }
+
+
+ }
+ private async Task checkForNewSoftwareVersionAsync()
{
if (!_userSettings.ShowUpdateNotification)
return;
try
{
- var hasNewVersion = await _versionChecker.NewVersionIsAvailableAsync();
+ await _versionChecker.DownloadLatestVersionInfoAsync();
+ var hasNewVersion = _versionChecker.NewVersionIsAvailable;
if (!hasNewVersion) return;
}
catch (Exception)
diff --git a/templates b/templates
index b7e74ee68..5678c8eec 160000
--- a/templates
+++ b/templates
@@ -1 +1 @@
-Subproject commit b7e74ee687f0ae1c701e6a4d85e10bf27c28fd56
+Subproject commit 5678c8eec95b7fbf0904b474feb56d5b70e62bc2
diff --git a/tests/PKSim.Tests/Infrastructure/VersionCheckerSpecs.cs b/tests/PKSim.Tests/Infrastructure/VersionCheckerSpecs.cs
index de5fea920..635d847c5 100644
--- a/tests/PKSim.Tests/Infrastructure/VersionCheckerSpecs.cs
+++ b/tests/PKSim.Tests/Infrastructure/VersionCheckerSpecs.cs
@@ -31,7 +31,8 @@ protected override async Task Context()
protected override async Task Because()
{
- _result = await sut.NewVersionIsAvailableAsync();
+ await sut.DownloadLatestVersionInfoAsync();
+ _result = sut.NewVersionIsAvailable;
}
[Observation]
@@ -61,7 +62,8 @@ protected override async Task Context()
protected override async Task Because()
{
- _result = await sut.NewVersionIsAvailableAsync();
+ await sut.DownloadLatestVersionInfoAsync();
+ _result = sut.NewVersionIsAvailable;
}
[Observation]
@@ -85,7 +87,8 @@ protected override async Task Context()
protected override async Task Because()
{
- _result = await sut.NewVersionIsAvailableAsync();
+ await sut.DownloadLatestVersionInfoAsync();
+ _result = sut.NewVersionIsAvailable;
}
[Observation]
@@ -107,7 +110,7 @@ protected override async Task Context()
protected override async Task Because()
{
- await sut.NewVersionIsAvailableAsync();
+ await sut.DownloadLatestVersionInfoAsync();
}
[Observation]
diff --git a/tests/PKSim.Tests/Presentation/PostLaunchCheckerSpecs.cs b/tests/PKSim.Tests/Presentation/PostLaunchCheckerSpecs.cs
index ba625db19..fc8f11633 100644
--- a/tests/PKSim.Tests/Presentation/PostLaunchCheckerSpecs.cs
+++ b/tests/PKSim.Tests/Presentation/PostLaunchCheckerSpecs.cs
@@ -6,11 +6,12 @@
using OSPSuite.Core.Services;
using OSPSuite.Utility.Events;
using PKSim.Assets;
+using PKSim.Core;
+using PKSim.Core.Repositories;
using PKSim.Core.Services;
using PKSim.Presentation.Events;
using PKSim.Presentation.Services;
-
namespace PKSim.Presentation
{
public abstract class concern_for_PostLaunchChecker : ContextSpecificationAsync
@@ -20,6 +21,7 @@ public abstract class concern_for_PostLaunchChecker : ContextSpecificationAsync<
protected ITemplateDatabaseCreator TemplateDatabaseCreator;
protected IUserSettings _userSettings;
protected IEventPublisher _eventPublisher;
+ protected IRemoteTemplateRepository _remoteTemplateRepository;
protected override Task Context()
{
@@ -28,8 +30,15 @@ protected override Task Context()
TemplateDatabaseCreator = A.Fake();
_userSettings = A.Fake();
_eventPublisher = A.Fake();
+ _remoteTemplateRepository = A.Fake();
- sut = new PostLaunchChecker(_versionChecker, _watermarkStatusChecker, TemplateDatabaseCreator, _eventPublisher, _userSettings);
+ sut = new PostLaunchChecker(
+ _versionChecker,
+ _watermarkStatusChecker,
+ TemplateDatabaseCreator,
+ _eventPublisher,
+ _userSettings,
+ _remoteTemplateRepository);
return _completed;
}
@@ -53,9 +62,15 @@ public void should_verify_the_watermark_status()
{
A.CallTo(() => _watermarkStatusChecker.CheckWatermarkStatus()).MustHaveHappened();
}
+
+ [Observation]
+ public void should_check_if_a_new_version_of_the_template_repository_file_is_available()
+ {
+ A.CallTo(() => _versionChecker.NewVersionIsAvailableFor(CoreConstants.TEMPLATES_PRODUCT_NAME, _remoteTemplateRepository.Version)).MustHaveHappened();
+ }
}
- public class When_starting_the_post_launch_check_and_the_user_does_not_want_to_be_notifed_of_new_version_of_the_app : concern_for_PostLaunchChecker
+ public class When_starting_the_post_launch_check_and_the_user_does_not_want_to_be_notified_of_new_version_of_the_app : concern_for_PostLaunchChecker
{
protected override async Task Context()
{
@@ -71,11 +86,11 @@ protected override async Task Because()
[Observation]
public void should_not_check_for_a_new_version()
{
- A.CallTo(() => _versionChecker.NewVersionIsAvailableAsync()).MustNotHaveHappened();
+ A.CallTo(() => _versionChecker.NewVersionIsAvailable).MustNotHaveHappened();
}
}
- public class When_starting_the_post_launch_check_and_the_user_wants_to_be_notifed_of_new_version_of_the_app_and_a_new_version_is_available : concern_for_PostLaunchChecker
+ public class When_starting_the_post_launch_check_and_the_user_wants_to_be_notified_of_new_version_of_the_app_and_a_new_version_is_available : concern_for_PostLaunchChecker
{
private readonly VersionInfo _newVersion = new VersionInfo {Version = "1.2.3"};
private ShowNotificationEvent _event;
@@ -84,12 +99,11 @@ protected override async Task Context()
{
await base.Context();
_userSettings.ShowUpdateNotification = true;
- A.CallTo(() => _versionChecker.NewVersionIsAvailableAsync()).Returns(true);
+ A.CallTo(() => _versionChecker.NewVersionIsAvailable).Returns(true);
A.CallTo(() => _versionChecker.LatestVersion).Returns(_newVersion);
A.CallTo(() => _eventPublisher.PublishEvent(A._))
.Invokes(x => _event = x.GetArgument(0));
-
}
protected override async Task Because()
@@ -107,15 +121,15 @@ public void should_publish_a_new_version_notification()
}
}
- public class When_starting_the_post_launch_check_and_the_user_wants_to_be_notifed_of_new_version_of_the_app_and_a_new_version_is_available_but_the_check_was_already_dismissed_by_user : concern_for_PostLaunchChecker
+ public class When_starting_the_post_launch_check_and_the_user_wants_to_be_notified_of_new_version_of_the_app_and_a_new_version_is_available_but_the_check_was_already_dismissed_by_user : concern_for_PostLaunchChecker
{
- private readonly VersionInfo _newVersion = new VersionInfo { Version = "1.2.3" };
+ private readonly VersionInfo _newVersion = new VersionInfo {Version = "1.2.3"};
protected override async Task Context()
{
await base.Context();
_userSettings.ShowUpdateNotification = true;
- A.CallTo(() => _versionChecker.NewVersionIsAvailableAsync()).Returns(true);
+ A.CallTo(() => _versionChecker.NewVersionIsAvailable).Returns(true);
A.CallTo(() => _versionChecker.LatestVersion).Returns(_newVersion);
A.CallTo(() => _userSettings.LastIgnoredVersion).Returns(_newVersion.Version);
}
@@ -132,4 +146,44 @@ public void should_not_publish_a_new_version_notification()
}
}
+ public class When_starting_the_post_launch_check_and_a_new_template_version_is_available : concern_for_PostLaunchChecker
+ {
+ protected override async Task Context()
+ {
+ await base.Context();
+ A.CallTo(() => _versionChecker.NewVersionIsAvailableFor(CoreConstants.TEMPLATES_PRODUCT_NAME, _remoteTemplateRepository.Version)).Returns(true);
+ }
+
+ protected override async Task Because()
+ {
+ await sut.PerformPostLaunchCheckAsync();
+ }
+
+ [Observation]
+ public void should_update_the_summary_file()
+ {
+ A.CallTo(() => _remoteTemplateRepository.UpdateLocalTemplateSummaryFile()).MustHaveHappened();
+ }
+ }
+
+
+ public class When_starting_the_post_launch_check_and_no_new_template_version_is_available : concern_for_PostLaunchChecker
+ {
+ protected override async Task Context()
+ {
+ await base.Context();
+ A.CallTo(() => _versionChecker.NewVersionIsAvailableFor(CoreConstants.TEMPLATES_PRODUCT_NAME, _remoteTemplateRepository.Version)).Returns(false);
+ }
+
+ protected override async Task Because()
+ {
+ await sut.PerformPostLaunchCheckAsync();
+ }
+
+ [Observation]
+ public void should_update_the_summary_file()
+ {
+ A.CallTo(() => _remoteTemplateRepository.UpdateLocalTemplateSummaryFile()).MustNotHaveHappened();
+ }
+ }
}
\ No newline at end of file