Update: Disco ICT Online Services - Plugin Library

Migrate plugin library to https://services.discoict.com.au
This commit is contained in:
Gary Sharp
2014-07-28 15:02:33 +10:00
parent 1cc7e94646
commit 3358d9e320
37 changed files with 729 additions and 763 deletions
@@ -1,16 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Disco.Models.BI.Interop.Community
{
public class PluginLibraryCompatibilityItem
{
public string Id { get; set; }
public string Version { get; set; }
public bool Compatible { get; set; }
public string Reason { get; set; }
}
}
@@ -1,14 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Disco.Models.BI.Interop.Community
{
public class PluginLibraryCompatibilityRequest
{
public string HostVersion { get; set; }
public string DeploymentId { get; set; }
}
}
@@ -1,15 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Disco.Models.BI.Interop.Community
{
public class PluginLibraryCompatibilityResponse
{
public string HostVersion { get; set; }
public DateTime ResponseTimestamp { get; set; }
public List<PluginLibraryCompatibilityItem> Plugins { get; set; }
}
}
@@ -1,23 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Disco.Models.BI.Interop.Community
{
public class PluginLibraryItem
{
public string Id { get; set; }
public string Name { get; set; }
public string Author { get; set; }
public string Url { get; set; }
public string Blurb { get; set; }
public string LatestVersion { get; set; }
public string LatestChangeLog { get; set; }
public string LatestHostVersionMin { get; set; }
public string LatestHostVersionMax { get; set; }
public string LatestDownloadUrl { get; set; }
}
}
@@ -1,14 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Disco.Models.BI.Interop.Community
{
public class PluginLibraryUpdateRequest
{
public string HostVersion { get; set; }
public string DeploymentId { get; set; }
}
}
@@ -1,14 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Disco.Models.BI.Interop.Community
{
public class PluginLibraryUpdateResponse
{
public DateTime ResponseTimestamp { get; set; }
public List<PluginLibraryItem> Plugins { get; set; }
}
}
+4 -7
View File
@@ -57,12 +57,6 @@
<Compile Include="BI\Device\ImportDeviceSession.cs" /> <Compile Include="BI\Device\ImportDeviceSession.cs" />
<Compile Include="BI\DocumentTemplate\DocumentState.cs" /> <Compile Include="BI\DocumentTemplate\DocumentState.cs" />
<Compile Include="BI\Expressions\IImageExpressionResult.cs" /> <Compile Include="BI\Expressions\IImageExpressionResult.cs" />
<Compile Include="BI\Interop\Community\PluginLibraryCompatibilityItem.cs" />
<Compile Include="BI\Interop\Community\PluginLibraryCompatibilityResponse.cs" />
<Compile Include="BI\Interop\Community\PluginLibraryCompatibilityRequest.cs" />
<Compile Include="BI\Interop\Community\PluginLibraryItem.cs" />
<Compile Include="BI\Interop\Community\PluginLibraryUpdateRequest.cs" />
<Compile Include="BI\Interop\Community\PluginLibraryUpdateResponse.cs" />
<Compile Include="BI\Job\Statistics\DailyOpenedClosedItem.cs" /> <Compile Include="BI\Job\Statistics\DailyOpenedClosedItem.cs" />
<Compile Include="ClientServices\EnrolResponse.cs" /> <Compile Include="ClientServices\EnrolResponse.cs" />
<Compile Include="ClientServices\MacEnrol.cs" /> <Compile Include="ClientServices\MacEnrol.cs" />
@@ -109,6 +103,9 @@
<Compile Include="Services\Devices\Importing\IDeviceImportContext.cs" /> <Compile Include="Services\Devices\Importing\IDeviceImportContext.cs" />
<Compile Include="Services\Devices\Importing\IDeviceImportField.cs" /> <Compile Include="Services\Devices\Importing\IDeviceImportField.cs" />
<Compile Include="Services\Interop\ActiveDirectory\ADManagedGroupConfiguration.cs" /> <Compile Include="Services\Interop\ActiveDirectory\ADManagedGroupConfiguration.cs" />
<Compile Include="Services\Interop\DiscoServices\PluginIncompatibility.cs" />
<Compile Include="Services\Interop\DiscoServices\PluginLibraryIncompatibility.cs" />
<Compile Include="Services\Interop\DiscoServices\PluginLibraryManifestV2.cs" />
<Compile Include="Services\Interop\DiscoServices\PublishJobResult.cs" /> <Compile Include="Services\Interop\DiscoServices\PublishJobResult.cs" />
<Compile Include="Services\Interop\DiscoServices\UpdateRequestV2.cs" /> <Compile Include="Services\Interop\DiscoServices\UpdateRequestV2.cs" />
<Compile Include="Services\Interop\DiscoServices\UpdateResponseV2.cs" /> <Compile Include="Services\Interop\DiscoServices\UpdateResponseV2.cs" />
@@ -182,7 +179,7 @@
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<ProjectExtensions> <ProjectExtensions>
<VisualStudio> <VisualStudio>
<UserProperties BuildVersion_UpdateFileVersion="True" BuildVersion_UpdateAssemblyVersion="True" BuildVersion_BuildVersioningStyle="None.DeltaBaseYear.MonthAndDayStamp.TimeStamp" BuildVersion_StartDate="2014/6/1" BuildVersion_DetectChanges="False" BuildVersion_UseGlobalSettings="False" BuildVersion_BuildAction="Both" /> <UserProperties BuildVersion_BuildAction="Both" BuildVersion_UseGlobalSettings="False" BuildVersion_DetectChanges="False" BuildVersion_StartDate="2014/6/1" BuildVersion_BuildVersioningStyle="None.DeltaBaseYear.MonthAndDayStamp.TimeStamp" BuildVersion_UpdateAssemblyVersion="True" BuildVersion_UpdateFileVersion="True" />
</VisualStudio> </VisualStudio>
</ProjectExtensions> </ProjectExtensions>
<PropertyGroup> <PropertyGroup>
@@ -0,0 +1,12 @@
using System;
namespace Disco.Models.Services.Interop.DiscoServices
{
public class PluginIncompatibility
{
public string PluginId { get; set; }
public Version Version { get; set; }
public string Reason { get; set; }
}
}
@@ -0,0 +1,11 @@
using System.Collections.Generic;
namespace Disco.Models.Services.Interop.DiscoServices
{
public class PluginLibraryIncompatibility
{
public List<PluginIncompatibility> IncompatiblePlugins { get; set; }
}
}
@@ -0,0 +1,41 @@
using System;
using System.Collections.Generic;
namespace Disco.Models.Services.Interop.DiscoServices
{
public class PluginLibraryManifestV2
{
public DateTime ManifestDate { get; set; }
public List<PluginLibraryItemV2> Plugins { get; set; }
}
public class PluginLibraryItemV2
{
public string Id { get; set; }
public string Name { get; set; }
public string Author { get; set; }
public string InformationUrl { get; set; }
public string PrimaryFeatureCategory { get; set; }
public string Description { get; set; }
public List<PluginLibraryItemReleaseV2> Releases { get; set; }
}
public class PluginLibraryItemReleaseV2
{
public string PluginId { get; set; }
public string Version { get; set; }
public string HostMinVersion { get; set; }
public string HostMaxVersion { get; set; }
public bool Blocked { get; set; }
public string Description { get; set; }
public string DownloadUrl { get; set; }
}
}
+3 -2
View File
@@ -248,6 +248,8 @@
<Compile Include="Interop\ActiveDirectory\IADObject.cs" /> <Compile Include="Interop\ActiveDirectory\IADObject.cs" />
<Compile Include="Interop\DiscoServices\DiscoServiceHelpers.cs" /> <Compile Include="Interop\DiscoServices\DiscoServiceHelpers.cs" />
<Compile Include="Interop\DiscoServices\Jobs.cs" /> <Compile Include="Interop\DiscoServices\Jobs.cs" />
<Compile Include="Interop\DiscoServices\PluginLibrary.cs" />
<Compile Include="Interop\DiscoServices\PluginLibraryUpdateTask.cs" />
<Compile Include="Interop\VicEduDept\VicSmart.cs" /> <Compile Include="Interop\VicEduDept\VicSmart.cs" />
<Compile Include="Interop\DiscoServices\UpdateQuery.cs" /> <Compile Include="Interop\DiscoServices\UpdateQuery.cs" />
<Compile Include="Interop\DiscoServices\UpdateQueryTask.cs" /> <Compile Include="Interop\DiscoServices\UpdateQueryTask.cs" />
@@ -275,7 +277,6 @@
<Compile Include="Logging\Persistance\LogPersistContext.cs" /> <Compile Include="Logging\Persistance\LogPersistContext.cs" />
<Compile Include="Logging\Persistance\LogPersistContextInitializer.cs" /> <Compile Include="Logging\Persistance\LogPersistContextInitializer.cs" />
<Compile Include="Logging\Utilities.cs" /> <Compile Include="Logging\Utilities.cs" />
<Compile Include="Plugins\CommunityInterop\PluginLibraryUpdateTask.cs" />
<Compile Include="Plugins\Features\RepairProvider\RepairProviderFeature.cs" /> <Compile Include="Plugins\Features\RepairProvider\RepairProviderFeature.cs" />
<Compile Include="Plugins\Features\RepairProvider\RepairProviderSubmitJobException.cs" /> <Compile Include="Plugins\Features\RepairProvider\RepairProviderSubmitJobException.cs" />
<Compile Include="Plugins\Features\UIExtension\Results\LiteralResult.cs" /> <Compile Include="Plugins\Features\UIExtension\Results\LiteralResult.cs" />
@@ -379,7 +380,7 @@
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<ProjectExtensions> <ProjectExtensions>
<VisualStudio> <VisualStudio>
<UserProperties BuildVersion_UpdateFileVersion="True" BuildVersion_UpdateAssemblyVersion="True" BuildVersion_BuildVersioningStyle="None.DeltaBaseYear.MonthAndDayStamp.TimeStamp" BuildVersion_StartDate="2014/6/1" BuildVersion_BuildAction="Both" BuildVersion_DetectChanges="False" BuildVersion_UseGlobalSettings="False" /> <UserProperties BuildVersion_UseGlobalSettings="False" BuildVersion_DetectChanges="False" BuildVersion_BuildAction="Both" BuildVersion_StartDate="2014/6/1" BuildVersion_BuildVersioningStyle="None.DeltaBaseYear.MonthAndDayStamp.TimeStamp" BuildVersion_UpdateAssemblyVersion="True" BuildVersion_UpdateFileVersion="True" />
</VisualStudio> </VisualStudio>
</ProjectExtensions> </ProjectExtensions>
<PropertyGroup> <PropertyGroup>
@@ -0,0 +1,149 @@
using Disco.Data.Repository;
using Disco.Models.Services.Interop.DiscoServices;
using Disco.Services.Tasks;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net.Http;
using System.Web;
namespace Disco.Services.Interop.DiscoServices
{
public static class PluginLibrary
{
private static string UpdateUrl()
{
return string.Concat(DiscoServiceHelpers.ServicesUrl, "API/Plugins/Library/V2");
}
public static string InitialManifestFilename()
{
return HttpContext.Current.Server.MapPath("~/ClientBin/DiscoServices.InitialPluginLibraryManifest.json");
}
public static string ManifestFilename(DiscoDataContext Database)
{
return Path.Combine(Database.DiscoConfiguration.PluginPackagesLocation, "LibraryManifest.json");
}
public static PluginLibraryManifestV2 LoadManifest(DiscoDataContext Database)
{
var manifestFile = ManifestFilename(Database);
if (File.Exists(manifestFile))
{
return JsonConvert.DeserializeObject<PluginLibraryManifestV2>(File.ReadAllText(manifestFile));
}
else
{
// Use Initial Plugin Library Manifest
manifestFile = InitialManifestFilename();
if (File.Exists(manifestFile))
return JsonConvert.DeserializeObject<PluginLibraryManifestV2>(File.ReadAllText(manifestFile));
throw new FileNotFoundException("No plugin library manifest file was found", manifestFile);
}
}
public static PluginLibraryIncompatibility LoadIncompatibilityData(this PluginLibraryManifestV2 LibraryManifest)
{
var pluginAssembly = typeof(PluginLibrary).Assembly;
Version hostVersion = pluginAssembly.GetName().Version;
return new PluginLibraryIncompatibility()
{
IncompatiblePlugins = LibraryManifest.Plugins.SelectMany(p => p.Releases, (p, r) =>
{
var rVersion = Version.Parse(r.Version);
if (r.Blocked)
return new PluginIncompatibility() { PluginId = r.PluginId, Version = rVersion, Reason = "This plugin release is blocked by Disco ICT Online Services" };
if (r.HostMinVersion != null && hostVersion < Version.Parse(r.HostMinVersion))
return new PluginIncompatibility() { PluginId = r.PluginId, Version = rVersion, Reason = string.Format("This plugin requires v{0} or newer", r.HostMinVersion) };
if (r.HostMaxVersion != null && hostVersion > Version.Parse(r.HostMaxVersion))
return new PluginIncompatibility() { PluginId = r.PluginId, Version = rVersion, Reason = string.Format("This plugin requires v{0} or older", r.HostMaxVersion) };
return null;
}).Where(i => i != null).ToList()
};
}
public static PluginLibraryManifestV2 UpdateManifest(DiscoDataContext Database, IScheduledTaskStatus Status)
{
Status.UpdateStatus(10, "Sending Request");
PluginLibraryManifestV2 result;
var discoVersion = UpdateQuery.CurrentDiscoVersionFormatted();
var url = UpdateUrl();
using (var httpClient = new HttpClient())
{
using (var formData = new FormUrlEncodedContent(new KeyValuePair<string, string>[] {
new KeyValuePair<string, string>("DeploymentId", Database.DiscoConfiguration.DeploymentId),
new KeyValuePair<string, string>("DiscoVersion", discoVersion)
}))
{
var response = httpClient.PostAsync(url, formData).Result;
response.EnsureSuccessStatusCode();
Status.UpdateStatus(50, "Waiting for Response");
var resultJson = response.Content.ReadAsStringAsync().Result;
Status.UpdateStatus(90, "Processing Response");
result = JsonConvert.DeserializeObject<PluginLibraryManifestV2>(resultJson);
}
}
var manifestJson = JsonConvert.SerializeObject(result);
var manifestFile = PluginLibrary.ManifestFilename(Database);
if (!Directory.Exists(Path.GetDirectoryName(manifestFile)))
Directory.CreateDirectory(Path.GetDirectoryName(manifestFile));
File.WriteAllText(manifestFile, manifestJson);
return result;
}
public static PluginLibraryItemReleaseV2 LatestCompatibleRelease(this PluginLibraryItemV2 LibraryItem, PluginLibraryIncompatibility Incompatibility)
{
return LibraryItem.Releases.OrderByDescending(r => Version.Parse(r.Version)).FirstOrDefault(r => Incompatibility.IsCompatible(r));
}
public static bool IsCompatible(this PluginLibraryIncompatibility IncompatibilityLibrary, PluginLibraryItemReleaseV2 Release)
{
PluginIncompatibility incompatibility;
return IsCompatible(IncompatibilityLibrary, Release, out incompatibility);
}
public static bool IsCompatible(this PluginLibraryIncompatibility IncompatibilityLibrary, PluginLibraryItemReleaseV2 Release, out PluginIncompatibility Incompatibility)
{
return IsCompatible(IncompatibilityLibrary, Release.PluginId, Version.Parse(Release.Version), out Incompatibility);
}
public static bool IsCompatible(this PluginLibraryIncompatibility IncompatibilityLibrary, string PluginId, Version Version)
{
PluginIncompatibility incompatibility;
return IsCompatible(IncompatibilityLibrary, PluginId, Version, out incompatibility);
}
public static bool IsCompatible(this PluginLibraryIncompatibility IncompatibilityLibrary, string PluginId, Version Version, out PluginIncompatibility Incompatibility)
{
Incompatibility = IncompatibilityLibrary.IncompatiblePlugins.FirstOrDefault(i => i.PluginId.Equals(PluginId, StringComparison.OrdinalIgnoreCase) && i.Version == Version);
return Incompatibility == null;
}
}
}
@@ -0,0 +1,63 @@
using Disco.Data.Repository;
using Disco.Services.Tasks;
using Newtonsoft.Json;
using Quartz;
using System;
using System.IO;
using System.Linq;
namespace Disco.Services.Interop.DiscoServices
{
public class PluginLibraryUpdateTask : ScheduledTask
{
public override string TaskName { get { return "Disco ICT - Update Plugin Library"; } }
public override bool SingleInstanceTask { get { return true; } }
public override bool CancelInitiallySupported { get { return false; } }
public override void InitalizeScheduledTask(DiscoDataContext Database)
{
// Random time between midday and midnight.
var rnd = new Random();
var rndHour = rnd.Next(12, 23);
var rndMinute = rnd.Next(0, 59);
TriggerBuilder triggerBuilder = TriggerBuilder.Create().
WithSchedule(CronScheduleBuilder.DailyAtHourAndMinute(rndHour, rndMinute));
this.ScheduleTask(triggerBuilder);
}
protected override void ExecuteTask()
{
using (DiscoDataContext database = new DiscoDataContext())
{
Status.UpdateStatus(1, "Updating Plugin Library Manifest", "Initializing");
var manifest = PluginLibrary.UpdateManifest(database, this.Status);
Status.SetFinishedMessage("The Plugin Library Manifest was updated successfully");
}
}
public static ScheduledTaskStatus ScheduleNow()
{
var taskStatus = RunningStatus;
if (taskStatus != null)
return taskStatus;
else
{
var task = new PluginLibraryUpdateTask();
return task.ScheduleTask();
}
}
public static ScheduledTaskStatus RunningStatus
{
get
{
return ScheduledTasks.GetTaskStatuses(typeof(PluginLibraryUpdateTask)).Where(ts => ts.IsRunning).FirstOrDefault();
}
}
}
}
@@ -1,218 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Disco.Data.Repository;
using Disco.Services.Plugins;
using Disco.Services.Tasks;
using Disco.Models.BI.Interop.Community;
using System.Net;
using System.Xml.Serialization;
using System.IO;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
using Quartz;
using Disco.Services.Interop.DiscoServices;
namespace Disco.Services.Plugins.CommunityInterop
{
public class PluginLibraryUpdateTask : ScheduledTask
{
public override string TaskName { get { return "Disco Community - Update Plugin Library"; } }
public static string CurrentDiscoVersion()
{
var AssemblyVersion = typeof(PluginLibraryUpdateTask).Assembly.GetName().Version;
return string.Format("{0}.{1}.{2:0000}.{3:0000}", AssemblyVersion.Major, AssemblyVersion.Minor, AssemblyVersion.Build, AssemblyVersion.Revision);
}
protected override void ExecuteTask()
{
ExecuteTaskInternal(this.Status);
Status.SetFinishedMessage("The Plugin Library Catalogue was updated.");
}
internal static void ExecuteTaskInternal(ScheduledTaskStatus Status)
{
PluginLibraryUpdateRequest updateRequestBody;
PluginLibraryUpdateResponse updateResult;
string catalogueFile;
PluginLibraryCompatibilityRequest compatRequestBody;
PluginLibraryCompatibilityResponse compatResult;
string compatibilityFile;
var DiscoBIVersion = CurrentDiscoVersion();
HttpWebRequest webRequest;
#region Update
Status.UpdateStatus(1, "Updating Plugin Library Catalogue", "Building Request");
using (DiscoDataContext database = new DiscoDataContext())
{
catalogueFile = Plugins.CatalogueFile(database);
updateRequestBody = new PluginLibraryUpdateRequest()
{
DeploymentId = database.DiscoConfiguration.DeploymentId,
HostVersion = typeof(Plugins).Assembly.GetName().Version.ToString(4)
};
}
Status.UpdateStatus(10, "Sending Request");
webRequest = (HttpWebRequest)HttpWebRequest.Create(PluginLibraryUpdateUrl());
webRequest.KeepAlive = false;
webRequest.ContentType = "application/xml";
webRequest.Method = WebRequestMethods.Http.Post;
webRequest.UserAgent = string.Format("Disco/{0} (PluginLibrary)", DiscoBIVersion);
using (var wrStream = webRequest.GetRequestStream())
{
XmlSerializer xml = new XmlSerializer(typeof(PluginLibraryUpdateRequest));
xml.Serialize(wrStream, updateRequestBody);
}
Status.UpdateStatus(20, "Waiting for Response");
using (HttpWebResponse webResponse = (HttpWebResponse)webRequest.GetResponse())
{
if (webResponse.StatusCode == HttpStatusCode.OK)
{
Status.UpdateStatus(45, "Reading Response");
using (var wResStream = webResponse.GetResponseStream())
{
XmlSerializer xml = new XmlSerializer(typeof(PluginLibraryUpdateResponse));
updateResult = (PluginLibraryUpdateResponse)xml.Deserialize(wResStream);
}
}
else
{
Status.SetTaskException(new WebException(string.Format("Server responded with: [{0}] {1}", webResponse.StatusCode, webResponse.StatusDescription)));
return;
}
}
if (!Directory.Exists(Path.GetDirectoryName(catalogueFile)))
Directory.CreateDirectory(Path.GetDirectoryName(catalogueFile));
using (FileStream fs = new FileStream(catalogueFile, FileMode.Create, FileAccess.Write, FileShare.None))
{
using (StreamWriter fsWriter = new StreamWriter(fs))
{
fsWriter.Write(JsonConvert.SerializeObject(updateResult));
fsWriter.Flush();
}
}
#endregion
#region Compatibility
Status.UpdateStatus(50, "Updating Plugin Library Compatibility", "Building Request");
using (DiscoDataContext database = new DiscoDataContext())
{
compatibilityFile = Plugins.CompatibilityFile(database);
compatRequestBody = new PluginLibraryCompatibilityRequest()
{
DeploymentId = database.DiscoConfiguration.DeploymentId,
HostVersion = typeof(Plugins).Assembly.GetName().Version.ToString(4)
};
}
Status.UpdateStatus(60, "Sending Request");
webRequest = (HttpWebRequest)HttpWebRequest.Create(PluginLibraryCompatibilityUrl());
webRequest.KeepAlive = false;
webRequest.ContentType = "application/json";
webRequest.Method = WebRequestMethods.Http.Post;
webRequest.UserAgent = string.Format("Disco/{0} (PluginLibrary)", DiscoBIVersion);
using (var wrStream = webRequest.GetRequestStream())
{
XmlSerializer xml = new XmlSerializer(typeof(PluginLibraryCompatibilityRequest));
xml.Serialize(wrStream, compatRequestBody);
}
Status.UpdateStatus(70, "Waiting for Response");
using (HttpWebResponse webResponse = (HttpWebResponse)webRequest.GetResponse())
{
if (webResponse.StatusCode == HttpStatusCode.OK)
{
Status.UpdateStatus(95, "Reading Response");
using (var wResStream = webResponse.GetResponseStream())
{
XmlSerializer xml = new XmlSerializer(typeof(PluginLibraryCompatibilityResponse));
compatResult = (PluginLibraryCompatibilityResponse)xml.Deserialize(wResStream);
}
}
else
{
Status.SetTaskException(new WebException(string.Format("Server responded with: [{0}] {1}", webResponse.StatusCode, webResponse.StatusDescription)));
return;
}
}
if (!Directory.Exists(Path.GetDirectoryName(compatibilityFile)))
Directory.CreateDirectory(Path.GetDirectoryName(compatibilityFile));
using (FileStream fs = new FileStream(compatibilityFile, FileMode.Create, FileAccess.Write, FileShare.None))
{
using (StreamWriter fsWriter = new StreamWriter(fs))
{
fsWriter.Write(JsonConvert.SerializeObject(compatResult));
fsWriter.Flush();
}
}
#endregion
}
private static string PluginLibraryUpdateUrl()
{
return string.Concat(DiscoServiceHelpers.CommunityUrl(), "DiscoPluginLibrary/V1");
}
private static string PluginLibraryCompatibilityUrl()
{
return string.Concat(DiscoServiceHelpers.CommunityUrl(), "DiscoPluginLibrary/CompatibilityV1");
}
public static ScheduledTaskStatus ScheduleNow()
{
var taskStatus = ScheduledTasks.GetTaskStatuses(typeof(PluginLibraryUpdateTask)).Where(ts => ts.IsRunning).FirstOrDefault();
if (taskStatus != null)
return taskStatus;
else
{
var t = new PluginLibraryUpdateTask();
return t.ScheduleTask();
}
}
public static ScheduledTaskStatus RunningStatus
{
get
{
return ScheduledTasks.GetTaskStatuses(typeof(PluginLibraryUpdateTask)).Where(ts => ts.IsRunning).FirstOrDefault();
}
}
public override void InitalizeScheduledTask(DiscoDataContext Database)
{
// Random time between midday and midnight.
var rnd = new Random();
var rndHour = rnd.Next(12, 23);
var rndMinute = rnd.Next(0, 59);
TriggerBuilder triggerBuilder = TriggerBuilder.Create().
WithSchedule(CronScheduleBuilder.DailyAtHourAndMinute(rndHour, rndMinute));
this.ScheduleTask(triggerBuilder);
}
}
}
+13 -25
View File
@@ -1,11 +1,13 @@
using Disco.Data.Repository; using Disco.Data.Repository;
using Disco.Models.Services.Interop.DiscoServices;
using Disco.Services.Interop.DiscoServices;
using Disco.Services.Tasks; using Disco.Services.Tasks;
using Quartz; using Quartz;
using System; using System;
using System.IO; using System.IO;
using System.IO.Compression; using System.IO.Compression;
using System.Linq; using System.Linq;
using System.Net; using System.Net.Http;
namespace Disco.Services.Plugins namespace Disco.Services.Plugins
{ {
@@ -33,31 +35,17 @@ namespace Disco.Services.Plugins
Directory.CreateDirectory(Path.GetDirectoryName(packageFilePath)); Directory.CreateDirectory(Path.GetDirectoryName(packageFilePath));
// Need to Download the Package // Need to Download the Package
HttpWebRequest webRequest = (HttpWebRequest)HttpWebRequest.Create(packageUrlPath); using (HttpClient httpClient = new HttpClient())
webRequest.KeepAlive = false;
webRequest.ContentType = "application/xml";
webRequest.Method = WebRequestMethods.Http.Get;
webRequest.UserAgent = string.Format("Disco/{0} (PluginLibrary)", Disco.Services.Plugins.CommunityInterop.PluginLibraryUpdateTask.CurrentDiscoVersion());
using (HttpWebResponse webResponse = (HttpWebResponse)webRequest.GetResponse())
{ {
if (webResponse.StatusCode == HttpStatusCode.OK) using (var httpResponse = httpClient.GetAsync(packageUrlPath).Result)
{ {
Status.UpdateStatus(0, "Downloading..."); httpResponse.EnsureSuccessStatusCode();
using (var wResStream = webResponse.GetResponseStream())
using (FileStream fsOut = new FileStream(packageFilePath, FileMode.Create, FileAccess.Write, FileShare.None))
{ {
using (FileStream fsOut = new FileStream(packageFilePath, FileMode.Create, FileAccess.Write, FileShare.None)) httpResponse.Content.ReadAsStreamAsync().Result.CopyTo(fsOut);
{
wResStream.CopyTo(fsOut);
}
} }
} }
else
{
Status.SetTaskException(new WebException(string.Format("Server responded with: [{0}] {1}", webResponse.StatusCode, webResponse.StatusDescription)));
return;
}
} }
} }
@@ -97,10 +85,10 @@ namespace Disco.Services.Plugins
string packagePath = Path.Combine(database.DiscoConfiguration.PluginsLocation, packageManifest.Id); string packagePath = Path.Combine(database.DiscoConfiguration.PluginsLocation, packageManifest.Id);
// Check for Compatibility // Check for Compatibility
var compatibilityData = Plugins.LoadCompatibilityData(database); var libraryIncompatibility = PluginLibrary.LoadManifest(database).LoadIncompatibilityData();
var pluginCompatibility = compatibilityData.Plugins.FirstOrDefault(i => i.Id.Equals(packageManifest.Id, StringComparison.OrdinalIgnoreCase) && packageManifest.Version == Version.Parse(i.Version)); PluginIncompatibility incompatibility;
if (pluginCompatibility != null && !pluginCompatibility.Compatible) if (!libraryIncompatibility.IsCompatible(packageManifest.Id, packageManifest.Version, out incompatibility))
throw new InvalidOperationException(string.Format("The plugin [{0} v{1}] is not compatible: {2}", packageManifest.Id, packageManifest.VersionFormatted, pluginCompatibility.Reason)); throw new InvalidOperationException(string.Format("The plugin [{0} v{1}] is not compatible: {2}", packageManifest.Id, packageManifest.VersionFormatted, incompatibility.Reason));
// Force Delete of Existing Folder // Force Delete of Existing Folder
if (Directory.Exists(packagePath)) if (Directory.Exists(packagePath))
+14 -88
View File
@@ -1,5 +1,6 @@
using Disco.Data.Repository; using Disco.Data.Repository;
using Disco.Models.BI.Interop.Community; using Disco.Models.Services.Interop.DiscoServices;
using Disco.Services.Interop.DiscoServices;
using Newtonsoft.Json; using Newtonsoft.Json;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
@@ -248,81 +249,6 @@ namespace Disco.Services.Plugins
throw new InvalidOperationException(string.Format("Unknown Plugin Feature Category Type: [{0}]", FeatureCategoryType.Name)); throw new InvalidOperationException(string.Format("Unknown Plugin Feature Category Type: [{0}]", FeatureCategoryType.Name));
} }
public static string CatalogueFile(DiscoDataContext Database)
{
return Path.Combine(Database.DiscoConfiguration.PluginPackagesLocation, "Catalogue.json");
}
public static string CompatibilityFile(DiscoDataContext Database)
{
return Path.Combine(Database.DiscoConfiguration.PluginPackagesLocation, "Compatibility.json");
}
public static PluginLibraryUpdateResponse LoadCatalogue(DiscoDataContext Database)
{
var catalogueFile = CatalogueFile(Database);
if (!File.Exists(catalogueFile))
return null;
return JsonConvert.DeserializeObject<PluginLibraryUpdateResponse>(File.ReadAllText(catalogueFile));
}
public static PluginLibraryCompatibilityResponse LoadCompatibilityData(DiscoDataContext Database)
{
var pluginAssembly = typeof(Plugins).Assembly;
Version hostVersion = pluginAssembly.GetName().Version;
PluginLibraryCompatibilityResponse Data = null;
var localCompatFile = Path.Combine(Path.GetDirectoryName(pluginAssembly.Location), "ReleasePluginCompatibility.json");
var serverCompatFile = CompatibilityFile(Database);
if (File.Exists(localCompatFile))
{
Data = JsonConvert.DeserializeObject<PluginLibraryCompatibilityResponse>(File.ReadAllText(localCompatFile));
Data.HostVersion = hostVersion.ToString(4);
}
if (File.Exists(serverCompatFile))
{
var serverData = JsonConvert.DeserializeObject<PluginLibraryCompatibilityResponse>(File.ReadAllText(serverCompatFile));
if (Version.Parse(serverData.HostVersion) == hostVersion)
{
if (Data == null)
{
// No Local Compatibility File
Data = serverData;
}
else
{
// Join Compatibility Files
var localItems = Data.Plugins;
var localItemVersions = localItems.ToDictionary(i => i, i => Version.Parse(i.Version));
var joinedItems = localItems.ToList();
Data.ResponseTimestamp = serverData.ResponseTimestamp;
foreach (var serverItem in serverData.Plugins)
{
var serverItemVersion = Version.Parse(serverItem.Version);
var localItem = localItems.FirstOrDefault(i => i.Id.Equals(serverItem.Id, StringComparison.OrdinalIgnoreCase) && serverItemVersion == localItemVersions[i]);
if (localItem != null)
joinedItems.Remove(localItem);
joinedItems.Add(serverItem);
}
Data.Plugins = joinedItems;
}
}
}
if (Data == null)
{
Data = new PluginLibraryCompatibilityResponse()
{
HostVersion = hostVersion.ToString(4),
Plugins = new List<PluginLibraryCompatibilityItem>(),
ResponseTimestamp = new DateTime(2011, 7, 1)
};
}
return Data;
}
public static void InitalizePlugins(DiscoDataContext Database) public static void InitalizePlugins(DiscoDataContext Database)
{ {
if (_PluginManifests == null) if (_PluginManifests == null)
@@ -332,7 +258,7 @@ namespace Disco.Services.Plugins
if (_PluginManifests == null) if (_PluginManifests == null)
{ {
Version hostVersion = typeof(Plugins).Assembly.GetName().Version; Version hostVersion = typeof(Plugins).Assembly.GetName().Version;
var compatibilityData = new Lazy<PluginLibraryCompatibilityResponse>(() => LoadCompatibilityData(Database)); var compatibilityData = new Lazy<PluginLibraryIncompatibility>(() => PluginLibrary.LoadManifest(Database).LoadIncompatibilityData());
Dictionary<string, PluginManifest> loadedPlugins = new Dictionary<string, PluginManifest>(); Dictionary<string, PluginManifest> loadedPlugins = new Dictionary<string, PluginManifest>();
PluginPath = Database.DiscoConfiguration.PluginsLocation; PluginPath = Database.DiscoConfiguration.PluginsLocation;
@@ -371,9 +297,9 @@ namespace Disco.Services.Plugins
if (pluginManifest != null) if (pluginManifest != null)
{ {
// Check Version Compatibility // Check Version Compatibility
var pluginCompatibility = compatibilityData.Value.Plugins.FirstOrDefault(i => i.Id.Equals(pluginManifest.Id, StringComparison.OrdinalIgnoreCase) && pluginManifest.Version == Version.Parse(i.Version)); var pluginIncompatible = compatibilityData.Value.IncompatiblePlugins.FirstOrDefault(i => i.PluginId.Equals(pluginManifest.Id, StringComparison.OrdinalIgnoreCase) && pluginManifest.Version == i.Version);
if (pluginCompatibility != null && !pluginCompatibility.Compatible) if (pluginIncompatible != null)
throw new InvalidOperationException(string.Format("The plugin [{0} v{1}] is not compatible: {2}", pluginManifest.Id, pluginManifest.VersionFormatted, pluginCompatibility.Reason)); throw new InvalidOperationException(string.Format("The plugin [{0} v{1}] is not compatible: {2}", pluginManifest.Id, pluginManifest.VersionFormatted, pluginIncompatible.Reason));
if (pluginManifest.HostVersionMin != null && pluginManifest.HostVersionMin > hostVersion) if (pluginManifest.HostVersionMin != null && pluginManifest.HostVersionMin > hostVersion)
throw new InvalidOperationException(string.Format("The plugin [{0} v{1}] does not support this version of Disco (Requires v{2} or greater)", pluginManifest.Id, pluginManifest.VersionFormatted, pluginManifest.HostVersionMin.ToString())); throw new InvalidOperationException(string.Format("The plugin [{0} v{1}] does not support this version of Disco (Requires v{2} or greater)", pluginManifest.Id, pluginManifest.VersionFormatted, pluginManifest.HostVersionMin.ToString()));
@@ -441,13 +367,13 @@ namespace Disco.Services.Plugins
_PluginAssemblyManifests = _PluginManifests.Values.ToDictionary(p => p.PluginAssembly, p => p); _PluginAssemblyManifests = _PluginManifests.Values.ToDictionary(p => p.PluginAssembly, p => p);
} }
public static PluginManifest UpdatePlugin(DiscoDataContext Database, PluginManifest ExistingManifest, String UpdatePluginPackageFilePath, PluginLibraryCompatibilityResponse CompatibilityData = null) public static PluginManifest UpdatePlugin(DiscoDataContext Database, PluginManifest ExistingManifest, String UpdatePluginPackageFilePath, PluginLibraryIncompatibility PluginLibraryIncompatibility = null)
{ {
PluginManifest updatedManifest; PluginManifest updatedManifest;
using (var packageStream = File.OpenRead(UpdatePluginPackageFilePath)) using (var packageStream = File.OpenRead(UpdatePluginPackageFilePath))
{ {
updatedManifest = UpdatePlugin(Database, ExistingManifest, packageStream, CompatibilityData); updatedManifest = UpdatePlugin(Database, ExistingManifest, packageStream, PluginLibraryIncompatibility);
} }
// Remove Update after processing // Remove Update after processing
@@ -456,7 +382,7 @@ namespace Disco.Services.Plugins
return updatedManifest; return updatedManifest;
} }
public static PluginManifest UpdatePlugin(DiscoDataContext Database, PluginManifest ExistingManifest, Stream UpdatePluginPackage, PluginLibraryCompatibilityResponse CompatibilityData = null) public static PluginManifest UpdatePlugin(DiscoDataContext Database, PluginManifest ExistingManifest, Stream UpdatePluginPackage, PluginLibraryIncompatibility PluginLibraryIncompatibility = null)
{ {
using (MemoryStream packageStream = new MemoryStream()) using (MemoryStream packageStream = new MemoryStream())
{ {
@@ -486,11 +412,11 @@ namespace Disco.Services.Plugins
} }
// Check Compatibility // Check Compatibility
if (CompatibilityData == null) if (PluginLibraryIncompatibility == null)
CompatibilityData = LoadCompatibilityData(Database); PluginLibraryIncompatibility = PluginLibrary.LoadManifest(Database).LoadIncompatibilityData();
var pluginCompatibility = CompatibilityData.Plugins.FirstOrDefault(i => i.Id.Equals(packageManifest.Id, StringComparison.OrdinalIgnoreCase) && packageManifest.Version == Version.Parse(i.Version)); var pluginIncompatibility = PluginLibraryIncompatibility.IncompatiblePlugins.FirstOrDefault(i => i.PluginId.Equals(packageManifest.Id, StringComparison.OrdinalIgnoreCase) && packageManifest.Version == i.Version);
if (pluginCompatibility != null && !pluginCompatibility.Compatible) if (pluginIncompatibility != null)
throw new InvalidOperationException(string.Format("The plugin [{0} v{1}] is not compatible: {2}", packageManifest.Id, packageManifest.VersionFormatted, pluginCompatibility.Reason)); throw new InvalidOperationException(string.Format("The plugin [{0} v{1}] is not compatible: {2}", packageManifest.Id, packageManifest.VersionFormatted, pluginIncompatibility.Reason));
string packagePath = Path.Combine(Database.DiscoConfiguration.PluginsLocation, packageManifest.Id); string packagePath = Path.Combine(Database.DiscoConfiguration.PluginsLocation, packageManifest.Id);
+68 -60
View File
@@ -1,17 +1,14 @@
using System; using Disco.Data.Repository;
using Disco.Models.Services.Interop.DiscoServices;
using Disco.Services.Interop.DiscoServices;
using Disco.Services.Tasks;
using Quartz;
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.IO.Compression; using System.IO.Compression;
using System.Linq; using System.Linq;
using System.Net; using System.Net.Http;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Web;
using Disco.Data.Repository;
using Disco.Models.BI.Interop.Community;
using Disco.Services.Tasks;
using Quartz;
namespace Disco.Services.Plugins namespace Disco.Services.Plugins
{ {
@@ -24,17 +21,19 @@ namespace Disco.Services.Plugins
string pluginId = (string)this.ExecutionContext.JobDetail.JobDataMap["PluginId"]; string pluginId = (string)this.ExecutionContext.JobDetail.JobDataMap["PluginId"];
string packageFilePath = (string)this.ExecutionContext.JobDetail.JobDataMap["PackageFilePath"]; string packageFilePath = (string)this.ExecutionContext.JobDetail.JobDataMap["PackageFilePath"];
PluginLibraryUpdateResponse catalogue; PluginLibraryManifestV2 libraryManifest;
PluginLibraryIncompatibility libraryIncompatibility;
string pluginPackagesLocation; string pluginPackagesLocation;
if (!Plugins.PluginsLoaded) if (!Plugins.PluginsLoaded)
throw new InvalidOperationException("Plugins have not been initialized"); throw new InvalidOperationException("Plugins have not been initialized");
List<Tuple<PluginManifest, string, PluginLibraryItem>> updatePlugins; List<Tuple<PluginManifest, string, PluginLibraryItemV2, PluginLibraryItemReleaseV2>> updatePlugins;
using (DiscoDataContext database = new DiscoDataContext()) using (DiscoDataContext database = new DiscoDataContext())
{ {
catalogue = Plugins.LoadCatalogue(database); libraryManifest = PluginLibrary.LoadManifest(database);
libraryIncompatibility = libraryManifest.LoadIncompatibilityData();
pluginPackagesLocation = database.DiscoConfiguration.PluginPackagesLocation; pluginPackagesLocation = database.DiscoConfiguration.PluginPackagesLocation;
} }
@@ -44,30 +43,41 @@ namespace Disco.Services.Plugins
{ {
// Update Single from Catalogue // Update Single from Catalogue
PluginManifest existingManifest = Plugins.GetPlugin(pluginId); PluginManifest existingManifest = Plugins.GetPlugin(pluginId);
var catalogueItem = catalogue.Plugins.FirstOrDefault(p => p.Id == existingManifest.Id); var libraryItem = libraryManifest.Plugins.FirstOrDefault(p => p.Id == existingManifest.Id);
if (catalogueItem == null) if (libraryItem == null)
throw new InvalidOperationException("No updates are available for this Plugin"); throw new InvalidOperationException("This item isn't in the plugin library manifest");
if (Version.Parse(catalogueItem.LatestVersion) <= existingManifest.Version)
var libraryItemRelease = libraryItem.LatestCompatibleRelease(libraryIncompatibility);
if (Version.Parse(libraryItemRelease.Version) <= existingManifest.Version)
throw new InvalidOperationException("Only newer versions can be used to update a plugin"); throw new InvalidOperationException("Only newer versions can be used to update a plugin");
updatePlugins = new List<Tuple<PluginManifest, string, PluginLibraryItem>>() { updatePlugins = new List<Tuple<PluginManifest, string, PluginLibraryItemV2, PluginLibraryItemReleaseV2>>() {
new Tuple<PluginManifest,string,PluginLibraryItem>(existingManifest, null, catalogueItem) Tuple.Create(existingManifest, (string)null, libraryItem, libraryItemRelease)
}; };
} }
else else
{ {
// Update Single from Local // Update Single from Local
PluginManifest existingManifest = Plugins.GetPlugin(pluginId); PluginManifest existingManifest = Plugins.GetPlugin(pluginId);
updatePlugins = new List<Tuple<PluginManifest, string, PluginLibraryItem>>() { updatePlugins = new List<Tuple<PluginManifest, string, PluginLibraryItemV2, PluginLibraryItemReleaseV2>>() {
new Tuple<PluginManifest,string,PluginLibraryItem>(existingManifest, packageFilePath, null) Tuple.Create(existingManifest, packageFilePath, (PluginLibraryItemV2)null, (PluginLibraryItemReleaseV2)null)
}; };
} }
} }
else else
{ {
// Update All // Update All
updatePlugins = Plugins.GetPlugins().Join((IEnumerable<PluginLibraryItem>)catalogue.Plugins, manifest => manifest.Id, update => update.Id, (manifest, update) => new Tuple<PluginManifest, string, PluginLibraryItem>(manifest, null, update)).Where(i => Version.Parse(i.Item3.LatestVersion) > i.Item1.Version).ToList(); updatePlugins = Plugins.GetPlugins()
.Join(
libraryManifest.Plugins,
manifest => manifest.Id,
libraryItem => libraryItem.Id,
(manifest, libraryItem) => Tuple.Create(manifest, (string)null, libraryItem, libraryItem.LatestCompatibleRelease(libraryIncompatibility)),
StringComparer.OrdinalIgnoreCase)
.Where(i => Version.Parse(i.Item4.Version) > i.Item1.Version)
.ToList();
} }
if (updatePlugins == null || updatePlugins.Count == 0) if (updatePlugins == null || updatePlugins.Count == 0)
@@ -115,31 +125,40 @@ namespace Disco.Services.Plugins
internal static void UpdateOffline(ScheduledTaskStatus Status) internal static void UpdateOffline(ScheduledTaskStatus Status)
{ {
PluginLibraryUpdateResponse pluginCatalogue = null; PluginLibraryManifestV2 libraryManifest = null;
PluginLibraryIncompatibility libraryIncompatibility = null;
List<PluginManifest> installedPluginManifests; List<PluginManifest> installedPluginManifests;
string pluginPackagesLocation; string pluginPackagesLocation;
List<Tuple<PluginManifest, string, PluginLibraryItem>> updatePlugins = new List<Tuple<PluginManifest, string, PluginLibraryItem>>(); List<Tuple<PluginManifest, string, PluginLibraryItemV2, PluginLibraryItemReleaseV2>> updatePlugins =
new List<Tuple<PluginManifest, string, PluginLibraryItemV2, PluginLibraryItemReleaseV2>>();
using (DiscoDataContext database = new DiscoDataContext()) using (DiscoDataContext database = new DiscoDataContext())
{ {
pluginPackagesLocation = database.DiscoConfiguration.PluginPackagesLocation; pluginPackagesLocation = database.DiscoConfiguration.PluginPackagesLocation;
installedPluginManifests = OfflineInstalledPlugins(database); installedPluginManifests = OfflineInstalledPlugins(database);
if (installedPluginManifests.Count > 0) if (installedPluginManifests.Count > 0){
pluginCatalogue = Plugins.LoadCatalogue(database); libraryManifest = PluginLibrary.LoadManifest(database);
libraryIncompatibility = libraryManifest.LoadIncompatibilityData();
}
} }
if (pluginCatalogue != null && installedPluginManifests.Count > 0) if (libraryManifest != null && installedPluginManifests.Count > 0)
{ {
foreach (var pluginManifest in installedPluginManifests) foreach (var pluginManifest in installedPluginManifests)
{ {
// Check for Update // Check for Update
var catalogueItem = pluginCatalogue.Plugins.FirstOrDefault(i => i.Id == pluginManifest.Id && Version.Parse(i.LatestVersion) > pluginManifest.Version); var libraryItem = libraryManifest.Plugins.FirstOrDefault(i => i.Id == pluginManifest.Id);
if (catalogueItem != null) if (libraryItem != null)
{ // Update Available {
updatePlugins.Add(new Tuple<PluginManifest, string, PluginLibraryItem>(pluginManifest, null, catalogueItem)); var libraryItemRelease = libraryItem.LatestCompatibleRelease(libraryIncompatibility);
if (libraryItemRelease != null && Version.Parse(libraryItemRelease.Version) > pluginManifest.Version)
{ // Update Available
updatePlugins.Add(Tuple.Create(pluginManifest, (string)null, libraryItem, libraryItemRelease));
}
} }
} }
} }
@@ -150,18 +169,19 @@ namespace Disco.Services.Plugins
} }
} }
internal static void ExecuteTaskInternal(ScheduledTaskStatus Status, string pluginPackagesLocation, List<Tuple<PluginManifest, string, PluginLibraryItem>> UpdatePlugins) internal static void ExecuteTaskInternal(ScheduledTaskStatus Status, string pluginPackagesLocation, List<Tuple<PluginManifest, string, PluginLibraryItemV2, PluginLibraryItemReleaseV2>> UpdatePlugins)
{ {
while (UpdatePlugins.Count > 0) while (UpdatePlugins.Count > 0)
{ {
var updatePlugin = UpdatePlugins[0]; var updatePlugin = UpdatePlugins[0];
var existingManifest = updatePlugin.Item1; var existingManifest = updatePlugin.Item1;
var packageTempFilePath = updatePlugin.Item2; var packageTempFilePath = updatePlugin.Item2;
var catalogueItem = updatePlugin.Item3; var libraryItem = updatePlugin.Item3;
var libraryItemRelease = updatePlugin.Item4;
UpdatePlugins.Remove(updatePlugin); UpdatePlugins.Remove(updatePlugin);
var pluginId = existingManifest != null ? existingManifest.Id : catalogueItem.Id; var pluginId = existingManifest != null ? existingManifest.Id : libraryItemRelease.PluginId;
var pluginName = existingManifest != null ? existingManifest.Name : catalogueItem.Name; var pluginName = existingManifest != null ? existingManifest.Name : libraryItem.Name;
if (string.IsNullOrEmpty(packageTempFilePath)) if (string.IsNullOrEmpty(packageTempFilePath))
{ {
@@ -176,31 +196,19 @@ namespace Disco.Services.Plugins
Directory.CreateDirectory(Path.GetDirectoryName(packageTempFilePath)); Directory.CreateDirectory(Path.GetDirectoryName(packageTempFilePath));
// Need to Download the Package // Need to Download the Package
HttpWebRequest webRequest = (HttpWebRequest)HttpWebRequest.Create(catalogueItem.LatestDownloadUrl); using (HttpClient httpClient = new HttpClient())
webRequest.KeepAlive = false;
webRequest.ContentType = "application/xml";
webRequest.Method = WebRequestMethods.Http.Get;
webRequest.UserAgent = string.Format("Disco/{0} (PluginLibrary)", Disco.Services.Plugins.CommunityInterop.PluginLibraryUpdateTask.CurrentDiscoVersion());
using (HttpWebResponse webResponse = (HttpWebResponse)webRequest.GetResponse())
{ {
if (webResponse.StatusCode == HttpStatusCode.OK) Status.UpdateStatus(0, "Downloading...");
using (var httpResponse = httpClient.GetAsync(libraryItemRelease.DownloadUrl).Result)
{ {
Status.UpdateStatus(0, "Downloading..."); httpResponse.EnsureSuccessStatusCode();
using (var wResStream = webResponse.GetResponseStream())
using (FileStream fsOut = new FileStream(packageTempFilePath, FileMode.Create, FileAccess.Write, FileShare.None))
{ {
using (FileStream fsOut = new FileStream(packageTempFilePath, FileMode.Create, FileAccess.Write, FileShare.None)) httpResponse.Content.ReadAsStreamAsync().Result.CopyTo(fsOut);
{
wResStream.CopyTo(fsOut);
}
} }
} }
else
{
Status.SetTaskException(new WebException(string.Format("Server responded with: [{0}] {1}", webResponse.StatusCode, webResponse.StatusDescription)));
return;
}
} }
} }
@@ -234,10 +242,10 @@ namespace Disco.Services.Plugins
using (DiscoDataContext database = new DiscoDataContext()) using (DiscoDataContext database = new DiscoDataContext())
{ {
// Check for Compatibility // Check for Compatibility
var compatibilityData = Plugins.LoadCompatibilityData(database); var incompatibilityLibrary = PluginLibrary.LoadManifest(database).LoadIncompatibilityData();
var pluginCompatibility = compatibilityData.Plugins.FirstOrDefault(i => i.Id.Equals(updateManifest.Id, StringComparison.OrdinalIgnoreCase) && updateManifest.Version == Version.Parse(i.Version)); PluginIncompatibility incompatibility;
if (pluginCompatibility != null && !pluginCompatibility.Compatible) if (!incompatibilityLibrary.IsCompatible(updateManifest.Id, updateManifest.Version, out incompatibility))
throw new InvalidOperationException(string.Format("The plugin [{0} v{1}] is not compatible: {2}", updateManifest.Id, updateManifest.VersionFormatted, pluginCompatibility.Reason)); throw new InvalidOperationException(string.Format("The plugin [{0} v{1}] is not compatible: {2}", updateManifest.Id, updateManifest.VersionFormatted, incompatibility.Reason));
var updatePluginPath = Path.Combine(database.DiscoConfiguration.PluginsLocation, string.Format("{0}.discoPlugin", updateManifest.Id)); var updatePluginPath = Path.Combine(database.DiscoConfiguration.PluginsLocation, string.Format("{0}.discoPlugin", updateManifest.Id));
File.Move(packageTempFilePath, updatePluginPath); File.Move(packageTempFilePath, updatePluginPath);
@@ -1,9 +1,8 @@
using System; using Disco.Data.Repository;
using System.Collections.Generic; using Disco.Services.Interop.DiscoServices;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Disco.Services.Tasks; using Disco.Services.Tasks;
using System;
using System.Linq;
namespace Disco.Services.Plugins namespace Disco.Services.Plugins
{ {
@@ -20,12 +19,15 @@ namespace Disco.Services.Plugins
// Wait for App to Load (10 Seconds) // Wait for App to Load (10 Seconds)
for (int i = 0; i < 10; i++) for (int i = 0; i < 10; i++)
{ {
this.Status.UpdateStatus(10 * i); this.Status.UpdateStatus(10 * i);
System.Threading.Thread.Sleep(1000); System.Threading.Thread.Sleep(1000);
} }
// Update Catalogue // Update Catalogue
CommunityInterop.PluginLibraryUpdateTask.ExecuteTaskInternal(this.Status); using (DiscoDataContext database = new DiscoDataContext())
{
PluginLibrary.UpdateManifest(database, this.Status);
}
// Update all Plugins // Update all Plugins
UpdatePluginTask.UpdateOffline(this.Status); UpdatePluginTask.UpdateOffline(this.Status);
@@ -1,6 +1,6 @@
using Disco.Services.Authorization; using Disco.Services.Authorization;
using Disco.Services.Interop.DiscoServices;
using Disco.Services.Plugins; using Disco.Services.Plugins;
using Disco.Services.Plugins.CommunityInterop;
using Disco.Services.Tasks; using Disco.Services.Tasks;
using Disco.Services.Web; using Disco.Services.Web;
using System; using System;
@@ -15,7 +15,7 @@ namespace Disco.Web.Areas.API.Controllers
public partial class PluginController : AuthorizedDatabaseController public partial class PluginController : AuthorizedDatabaseController
{ {
[DiscoAuthorize(Claims.Config.Plugin.Install)] [DiscoAuthorize(Claims.Config.Plugin.Install)]
public virtual ActionResult UpdateLibraryCatalogue(bool TryWaitingForCompletion = false) public virtual ActionResult UpdateLibraryManifest(bool TryWaitingForCompletion = false)
{ {
var status = PluginLibraryUpdateTask.ScheduleNow(); var status = PluginLibraryUpdateTask.ScheduleNow();
@@ -93,19 +93,25 @@ namespace Disco.Web.Areas.API.Controllers
if (string.IsNullOrEmpty(PluginId)) if (string.IsNullOrEmpty(PluginId))
throw new ArgumentNullException("PluginId", "A PluginId must be supplied"); throw new ArgumentNullException("PluginId", "A PluginId must be supplied");
var catalogue = Plugins.LoadCatalogue(Database); var library = PluginLibrary.LoadManifest(Database);
var plugin = catalogue.Plugins.FirstOrDefault(p => p.Id.Equals(PluginId)); var libraryIncompatibility = library.LoadIncompatibilityData();
var libraryItem = library.Plugins.FirstOrDefault(p => p.Id.Equals(PluginId));
if (plugin == null) if (libraryItem == null)
throw new ArgumentNullException("PluginId", "Plugin not found in catalogue"); throw new ArgumentNullException("PluginId", "Plugin not found in library");
var libraryItemRelease = libraryItem.LatestCompatibleRelease(libraryIncompatibility);
if (libraryItemRelease == null)
throw new ArgumentNullException("PluginId", "No compatibility releases were found in library");
// Already Installed? // Already Installed?
if (Plugins.PluginInstalled(plugin.Id)) if (Plugins.PluginInstalled(libraryItem.Id))
throw new InvalidOperationException("This plugin is already installed"); throw new InvalidOperationException("This plugin is already installed");
var tempPluginLocation = Path.Combine(Database.DiscoConfiguration.PluginPackagesLocation, string.Format("{0}.discoPlugin", plugin.Id)); var tempPluginLocation = Path.Combine(Database.DiscoConfiguration.PluginPackagesLocation, string.Format("{0}.discoPlugin", libraryItem.Id));
var status = InstallPluginTask.InstallPlugin(plugin.LatestDownloadUrl, tempPluginLocation, true); var status = InstallPluginTask.InstallPlugin(libraryItem.LatestCompatibleRelease(libraryIncompatibility).DownloadUrl, tempPluginLocation, true);
return RedirectToAction(MVC.Config.Logging.TaskStatus(status.SessionId)); return RedirectToAction(MVC.Config.Logging.TaskStatus(status.SessionId));
} }
@@ -1,4 +1,5 @@
using Disco.Services.Authorization; using Disco.Services.Authorization;
using Disco.Services.Interop.DiscoServices;
using Disco.Services.Plugins; using Disco.Services.Plugins;
using Disco.Services.Users; using Disco.Services.Users;
using Disco.Services.Web; using Disco.Services.Web;
@@ -16,7 +17,7 @@ namespace Disco.Web.Areas.Config.Controllers
Models.Plugins.IndexViewModel vm = new Models.Plugins.IndexViewModel() Models.Plugins.IndexViewModel vm = new Models.Plugins.IndexViewModel()
{ {
PluginManifests = Plugins.GetPlugins(), PluginManifests = Plugins.GetPlugins(),
Catalogue = Plugins.LoadCatalogue(Database) PluginLibrary = PluginLibrary.LoadManifest(Database)
}; };
return View(vm); return View(vm);
} }
@@ -70,18 +71,18 @@ namespace Disco.Web.Areas.Config.Controllers
public virtual ActionResult Install() public virtual ActionResult Install()
{ {
// Check for recent catalogue // Check for recent catalogue
var catalogue = Plugins.LoadCatalogue(Database); var library = PluginLibrary.LoadManifest(Database);
if (catalogue == null || catalogue.ResponseTimestamp < DateTime.Now.AddHours(-1)) if (library == null || library.ManifestDate < DateTime.Now.AddHours(-1))
{ {
// Need to Update Catalogue (over 1 hour old) // Need to Update Catalogue (over 1 hour old)
return RedirectToAction(MVC.API.Plugin.UpdateLibraryCatalogue(true)); return RedirectToAction(MVC.API.Plugin.UpdateLibraryManifest(true));
} }
else else
{ {
var model = new Models.Plugins.InstallModel() var model = new Models.Plugins.InstallModel()
{ {
Catalogue = catalogue Library = library
}; };
return View(model); return View(model);
@@ -1,33 +1,43 @@
using System; using Disco.Models.Services.Interop.DiscoServices;
using System.Collections.Generic; using Disco.Services.Interop.DiscoServices;
using System.Linq;
using System.Web;
using Disco.Models.BI.Interop.Community;
using Disco.Services.Plugins; using Disco.Services.Plugins;
using Disco.Services.Plugins.Features.Other; using Disco.Services.Plugins.Features.Other;
using System;
using System.Collections.Generic;
using System.Linq;
namespace Disco.Web.Areas.Config.Models.Plugins namespace Disco.Web.Areas.Config.Models.Plugins
{ {
public class IndexViewModel public class IndexViewModel
{ {
public List<PluginManifest> PluginManifests { get; set; } public List<PluginManifest> PluginManifests { get; set; }
public PluginLibraryUpdateResponse Catalogue { get; set; } public PluginLibraryManifestV2 PluginLibrary { get; set; }
private Dictionary<PluginManifest, PluginLibraryItem> _PluginUpdates; private Dictionary<PluginManifest, Tuple<PluginLibraryItemV2, PluginLibraryItemReleaseV2>> _PluginUpdates;
public Dictionary<PluginManifest, PluginLibraryItem> PluginUpdates public Dictionary<PluginManifest, Tuple<PluginLibraryItemV2, PluginLibraryItemReleaseV2>> PluginUpdates
{ {
get get
{ {
if (_PluginUpdates == null) if (_PluginUpdates == null)
{ {
if (Catalogue == null || Catalogue.Plugins == null || Catalogue.Plugins.Count == 0 || if (PluginLibrary == null || PluginLibrary.Plugins == null || PluginLibrary.Plugins.Count == 0 ||
PluginManifests == null || PluginManifests.Count == 0) PluginManifests == null || PluginManifests.Count == 0)
{ {
_PluginUpdates = new Dictionary<PluginManifest, PluginLibraryItem>(); // No Updates _PluginUpdates = new Dictionary<PluginManifest,Tuple<PluginLibraryItemV2,PluginLibraryItemReleaseV2>>(); // No Updates
} }
else else
{ {
_PluginUpdates = PluginManifests.Join((IEnumerable<PluginLibraryItem>)Catalogue.Plugins, manifest => manifest.Id, update => update.Id, (manifest, update) => new Tuple<PluginManifest, PluginLibraryItem>(manifest, update)).Where(i => Version.Parse(i.Item2.LatestVersion) > i.Item1.Version).ToDictionary(i => i.Item1, i => i.Item2); var libraryIncompatibility = PluginLibrary.LoadIncompatibilityData();
_PluginUpdates = PluginManifests
.Join(
PluginLibrary.Plugins,
manifest => manifest.Id,
libraryItem => libraryItem.Id,
(manifest, libraryItem) => Tuple.Create(manifest, libraryItem, libraryItem.LatestCompatibleRelease(libraryIncompatibility)),
StringComparer.OrdinalIgnoreCase)
.Where(i => i.Item3 != null && Version.Parse(i.Item3.Version) > i.Item1.Version)
.ToDictionary(i => i.Item1, i => Tuple.Create(i.Item2, i.Item3));
} }
} }
return _PluginUpdates; return _PluginUpdates;
@@ -1,13 +1,29 @@
using System; using Disco.Models.Services.Interop.DiscoServices;
using Disco.Services.Interop.DiscoServices;
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Web;
using Disco.Models.BI.Interop.Community;
namespace Disco.Web.Areas.Config.Models.Plugins namespace Disco.Web.Areas.Config.Models.Plugins
{ {
public class InstallModel public class InstallModel
{ {
public PluginLibraryUpdateResponse Catalogue { get; set; } public PluginLibraryManifestV2 Library { get; set; }
public List<Tuple<string, List<Tuple<PluginLibraryItemV2, PluginLibraryItemReleaseV2>>>> AvailablePlugins
{
get
{
var incompatibility = Library.LoadIncompatibilityData();
return Library.Plugins
.Select(p => Tuple.Create(p, p.LatestCompatibleRelease(incompatibility)))
.Where(p => p.Item2 != null)
.GroupBy(p => p.Item1.PrimaryFeatureCategory)
.Select(p => Tuple.Create(p.Key, p.OrderBy(r => r.Item1.Name).ToList()))
.OrderBy(g => g.Item1)
.ToList();
}
}
} }
} }
@@ -1,8 +1,5 @@
using System; using Disco.Services.Plugins;
using System.Collections.Generic; using System;
using System.Linq;
using System.Web;
using Disco.Services.Plugins;
namespace Disco.Web.Areas.Config.Models.Plugins namespace Disco.Web.Areas.Config.Models.Plugins
{ {
@@ -7,10 +7,9 @@
ViewBag.Title = Html.ToBreadcrumb("Configuration", MVC.Config.Config.Index(), "Plugins", MVC.Config.Plugins.Index(), "Install Plugin"); ViewBag.Title = Html.ToBreadcrumb("Configuration", MVC.Config.Config.Index(), "Plugins", MVC.Config.Plugins.Index(), "Install Plugin");
} }
<div id="pluginCatalog"> <div id="pluginLibrary">
<h4 id="pluginCatalogHeading">The plugin catalogue [<a href="https://discoict.com.au/">https://discoict.com.au</a>] was last updated @CommonHelpers.FriendlyDate((Model.Catalogue.ResponseTimestamp > DateTime.Now ? DateTime.Now : Model.Catalogue.ResponseTimestamp)) <h4 id="pluginLibraryHeading">The plugin library [<a href="https://discoict.com.au/">https://discoict.com.au</a>] was last updated @CommonHelpers.FriendlyDate((Model.Library.ManifestDate > DateTime.Now ? DateTime.Now : Model.Library.ManifestDate))</h4>
</h4> @if (Model.Library.Plugins.Count == 0)
@if (Model.Catalogue.Plugins.Count == 0)
{ {
<div class="form" style="width: 450px; padding: 100px 0;"> <div class="form" style="width: 450px; padding: 100px 0;">
<h2>No Plugins are Available</h2> <h2>No Plugins are Available</h2>
@@ -18,50 +17,50 @@
} }
else else
{ {
var plugins = Model.Catalogue.Plugins; var pluginGroups = Model.AvailablePlugins;
int itemsPerColumn = plugins.Count / 3;
var itemNextId = 0; <div id="pluginLibraryGroups">
<table id="pageMenu"> @foreach (var pluginGroup in pluginGroups)
<tr> {
@for (int i = 0; i < 3; i++) <div class="form">
{ <h2>@pluginGroup.Item1</h2>
<td> <table>
@{ @foreach (var plugin in pluginGroup.Item2)
int itemsForThisColumn = itemsPerColumn + (plugins.Count % 3 > i ? 1 : 0); {
for (int i2 = 0; i2 < itemsForThisColumn && itemNextId < plugins.Count; i2++) var installedPlugin = Plugins.PluginInstalled(plugin.Item1.Id) ? Plugins.GetPlugin(plugin.Item1.Id) : null;
{ <tr>
var plugin = plugins[itemNextId]; <td>
itemNextId++; <div class="pluginItem@(installedPlugin != null ? " pluginInstalled" : string.Empty)">
var installedPlugin = Plugins.PluginInstalled(plugin.Id) ? Plugins.GetPlugin(plugin.Id) : null; <h2 class="pluginName"><i class="fa fa-cogs"></i>@plugin.Item1.Name
<div class="pageMenuArea pluginItem@(installedPlugin != null ? " pluginInstalled" : string.Empty)"> @if (installedPlugin == null)
<h2 class="pluginName"><i class="fa fa-cogs"></i>@plugin.Name {
@if (installedPlugin == null) <a class="pluginInstallLink button" href="@(Url.Action(MVC.API.Plugin.Install(plugin.Item1.Id)))">Install</a>
{ }
<a class="pluginInstallLink button" href="@(Url.Action(MVC.API.Plugin.Install(plugin.Id)))">Install</a> else
} {
else if (Version.Parse(plugin.Item2.Version) > installedPlugin.Version)
{ {
if (Version.Parse(plugin.LatestVersion) > installedPlugin.Version) <a class="pluginUpdateLink button" href="@(Url.Action(MVC.API.Plugin.Update(plugin.Item1.Id)))">Update</a>
{ }
<a class="pluginUpdateLink button" href="@(Url.Action(MVC.API.Plugin.Update(plugin.Id)))">Update</a> else
} {
else <a class="pluginInstalledLink button disabled" href="#">Installed</a>
{ }
<a class="pluginInstalledLink button disabled" href="#">Installed</a> }
} </h2>
} <div class="pluginItemBlurb">@(new HtmlString(plugin.Item1.Description))</div>
</h2> <div class="pageMenuBlurb">
<div class="pluginItemBlurb">@(new HtmlString(plugin.Blurb))</div> <span class="pluginId">@plugin.Item1.Id</span> | <span class="pluginVersion">v@(plugin.Item2.Version)</span> | @plugin.Item1.Author | <a href="@plugin.Item1.InformationUrl" title="More Information" target="_blank"><i class="fa fa-external-link"></i></a>
<div class="pageMenuBlurb"> </div>
<span class="pluginId">@plugin.Id</span> | <span class="pluginVersion">v@(plugin.LatestVersion)</span> | @plugin.Author | <a href="@plugin.Url" title="More Information" target="_blank"><i class="fa fa-external-link"></i></a> </div>
</div> </td>
</div> </tr>
}
} }
</td> </table>
} </div>
</tr> }
</table> </div>
} }
</div> </div>
<div id="dialogInstallPlugin" title="Install this Plugin?"> <div id="dialogInstallPlugin" title="Install this Plugin?">
@@ -98,6 +97,8 @@
var $selectedPlugin; var $selectedPlugin;
var $selectedPluginUrl; var $selectedPluginUrl;
$('#pluginLibraryHeading').appendTo('#layout_PageHeading');
// Install // Install
var $dialogInstall = $('#dialogInstallPlugin').dialog({ var $dialogInstall = $('#dialogInstallPlugin').dialog({
resizable: false, resizable: false,
@@ -120,7 +121,7 @@
} }
} }
}); });
$('#pageMenu').find('a.pluginInstallLink').click(function () { $('#pluginLibraryGroups').find('a.pluginInstallLink').click(function () {
$this = $(this); $this = $(this);
$selectedPlugin = $this.closest('.pluginItem'); $selectedPlugin = $this.closest('.pluginItem');
@@ -134,7 +135,7 @@
return false; return false;
}); });
$('#pageMenu').find('a.pluginUpdateLink').click(function () { $('#pluginLibraryGroups').find('a.pluginUpdateLink').click(function () {
$this = $(this); $this = $(this);
$selectedPlugin = $this.closest('.pluginItem'); $selectedPlugin = $this.closest('.pluginItem');
@@ -180,7 +181,7 @@
}); });
</script> </script>
<div class="actionBar"> <div class="actionBar">
@Html.ActionLinkButton("Update Catalogue", MVC.API.Plugin.UpdateLibraryCatalogue()) @Html.ActionLinkButton("Update Plugin Library", MVC.API.Plugin.UpdateLibraryManifest())
@if (canInstallLocal) @if (canInstallLocal)
{ {
@Html.ActionLinkButton("Install Plugin Package", MVC.API.Plugin.InstallLocal(), "buttonUpload") @Html.ActionLinkButton("Install Plugin Package", MVC.API.Plugin.InstallLocal(), "buttonUpload")
@@ -64,13 +64,13 @@ namespace Disco.Web.Areas.Config.Views.Plugins
#line hidden #line hidden
WriteLiteral("\r\n<div"); WriteLiteral("\r\n<div");
WriteLiteral(" id=\"pluginCatalog\""); WriteLiteral(" id=\"pluginLibrary\"");
WriteLiteral(">\r\n <h4"); WriteLiteral(">\r\n <h4");
WriteLiteral(" id=\"pluginCatalogHeading\""); WriteLiteral(" id=\"pluginLibraryHeading\"");
WriteLiteral(">The plugin catalogue [<a"); WriteLiteral(">The plugin library [<a");
WriteLiteral(" href=\"https://discoict.com.au/\""); WriteLiteral(" href=\"https://discoict.com.au/\"");
@@ -78,22 +78,22 @@ WriteLiteral(">https://discoict.com.au</a>] was last updated ");
#line 11 "..\..\Areas\Config\Views\Plugins\Install.cshtml" #line 11 "..\..\Areas\Config\Views\Plugins\Install.cshtml"
Write(CommonHelpers.FriendlyDate((Model.Catalogue.ResponseTimestamp > DateTime.Now ? DateTime.Now : Model.Catalogue.ResponseTimestamp))); Write(CommonHelpers.FriendlyDate((Model.Library.ManifestDate > DateTime.Now ? DateTime.Now : Model.Library.ManifestDate)));
#line default #line default
#line hidden #line hidden
WriteLiteral("\r\n </h4>\r\n"); WriteLiteral("</h4>\r\n");
#line 13 "..\..\Areas\Config\Views\Plugins\Install.cshtml" #line 12 "..\..\Areas\Config\Views\Plugins\Install.cshtml"
#line default #line default
#line hidden #line hidden
#line 13 "..\..\Areas\Config\Views\Plugins\Install.cshtml" #line 12 "..\..\Areas\Config\Views\Plugins\Install.cshtml"
if (Model.Catalogue.Plugins.Count == 0) if (Model.Library.Plugins.Count == 0)
{ {
@@ -108,73 +108,81 @@ WriteLiteral(" style=\"width: 450px; padding: 100px 0;\"");
WriteLiteral(">\r\n <h2>No Plugins are Available</h2>\r\n </div> \r\n"); WriteLiteral(">\r\n <h2>No Plugins are Available</h2>\r\n </div> \r\n");
#line 18 "..\..\Areas\Config\Views\Plugins\Install.cshtml" #line 17 "..\..\Areas\Config\Views\Plugins\Install.cshtml"
} }
else else
{ {
var plugins = Model.Catalogue.Plugins; var pluginGroups = Model.AvailablePlugins;
int itemsPerColumn = plugins.Count / 3;
var itemNextId = 0;
#line default #line default
#line hidden #line hidden
WriteLiteral(" <table"); WriteLiteral(" <div");
WriteLiteral(" id=\"pageMenu\""); WriteLiteral(" id=\"pluginLibraryGroups\"");
WriteLiteral(">\r\n <tr>\r\n"); WriteLiteral(">\r\n");
#line 23 "..\..\Areas\Config\Views\Plugins\Install.cshtml"
#line default
#line hidden
#line 23 "..\..\Areas\Config\Views\Plugins\Install.cshtml"
foreach (var pluginGroup in pluginGroups)
{
#line default
#line hidden
WriteLiteral(" <div");
WriteLiteral(" class=\"form\"");
WriteLiteral(">\r\n <h2>");
#line 26 "..\..\Areas\Config\Views\Plugins\Install.cshtml" #line 26 "..\..\Areas\Config\Views\Plugins\Install.cshtml"
Write(pluginGroup.Item1);
#line default
#line hidden
#line 26 "..\..\Areas\Config\Views\Plugins\Install.cshtml"
for (int i = 0; i < 3; i++)
{
#line default #line default
#line hidden #line hidden
WriteLiteral(" <td>\r\n"); WriteLiteral("</h2>\r\n <table>\r\n");
#line 29 "..\..\Areas\Config\Views\Plugins\Install.cshtml" #line 28 "..\..\Areas\Config\Views\Plugins\Install.cshtml"
#line default #line default
#line hidden #line hidden
#line 29 "..\..\Areas\Config\Views\Plugins\Install.cshtml" #line 28 "..\..\Areas\Config\Views\Plugins\Install.cshtml"
foreach (var plugin in pluginGroup.Item2)
int itemsForThisColumn = itemsPerColumn + (plugins.Count % 3 > i ? 1 : 0); {
for (int i2 = 0; i2 < itemsForThisColumn && itemNextId < plugins.Count; i2++) var installedPlugin = Plugins.PluginInstalled(plugin.Item1.Id) ? Plugins.GetPlugin(plugin.Item1.Id) : null;
{
var plugin = plugins[itemNextId];
itemNextId++;
var installedPlugin = Plugins.PluginInstalled(plugin.Id) ? Plugins.GetPlugin(plugin.Id) : null;
#line default #line default
#line hidden #line hidden
WriteLiteral(" <div"); WriteLiteral(" <tr>\r\n <td>\r\n " +
" <div");
WriteAttribute("class", Tuple.Create(" class=\"", 1662), Tuple.Create("\"", 1755) WriteAttribute("class", Tuple.Create(" class=\"", 1506), Tuple.Create("\"", 1586)
, Tuple.Create(Tuple.Create("", 1670), Tuple.Create("pageMenuArea", 1670), true) , Tuple.Create(Tuple.Create("", 1514), Tuple.Create("pluginItem", 1514), true)
, Tuple.Create(Tuple.Create(" ", 1682), Tuple.Create("pluginItem", 1683), true)
#line 36 "..\..\Areas\Config\Views\Plugins\Install.cshtml" #line 33 "..\..\Areas\Config\Views\Plugins\Install.cshtml"
, Tuple.Create(Tuple.Create("", 1693), Tuple.Create<System.Object, System.Int32>(installedPlugin != null ? " pluginInstalled" : string.Empty , Tuple.Create(Tuple.Create("", 1524), Tuple.Create<System.Object, System.Int32>(installedPlugin != null ? " pluginInstalled" : string.Empty
#line default #line default
#line hidden #line hidden
, 1693), false) , 1524), false)
); );
WriteLiteral(">\r\n <h2"); WriteLiteral(">\r\n <h2");
WriteLiteral(" class=\"pluginName\""); WriteLiteral(" class=\"pluginName\"");
@@ -185,8 +193,8 @@ WriteLiteral(" class=\"fa fa-cogs\"");
WriteLiteral("></i>"); WriteLiteral("></i>");
#line 37 "..\..\Areas\Config\Views\Plugins\Install.cshtml" #line 34 "..\..\Areas\Config\Views\Plugins\Install.cshtml"
Write(plugin.Name); Write(plugin.Item1.Name);
#line default #line default
@@ -194,72 +202,72 @@ WriteLiteral("></i>");
WriteLiteral("\r\n"); WriteLiteral("\r\n");
#line 38 "..\..\Areas\Config\Views\Plugins\Install.cshtml" #line 35 "..\..\Areas\Config\Views\Plugins\Install.cshtml"
#line default #line default
#line hidden #line hidden
#line 38 "..\..\Areas\Config\Views\Plugins\Install.cshtml" #line 35 "..\..\Areas\Config\Views\Plugins\Install.cshtml"
if (installedPlugin == null) if (installedPlugin == null)
{ {
#line default #line default
#line hidden #line hidden
WriteLiteral(" <a"); WriteLiteral(" <a");
WriteLiteral(" class=\"pluginInstallLink button\""); WriteLiteral(" class=\"pluginInstallLink button\"");
WriteAttribute("href", Tuple.Create(" href=\"", 2035), Tuple.Create("\"", 2090) WriteAttribute("href", Tuple.Create(" href=\"", 1904), Tuple.Create("\"", 1965)
#line 40 "..\..\Areas\Config\Views\Plugins\Install.cshtml" #line 37 "..\..\Areas\Config\Views\Plugins\Install.cshtml"
, Tuple.Create(Tuple.Create("", 2042), Tuple.Create<System.Object, System.Int32>(Url.Action(MVC.API.Plugin.Install(plugin.Id)) , Tuple.Create(Tuple.Create("", 1911), Tuple.Create<System.Object, System.Int32>(Url.Action(MVC.API.Plugin.Install(plugin.Item1.Id))
#line default #line default
#line hidden #line hidden
, 2042), false) , 1911), false)
); );
WriteLiteral(">Install</a>\r\n"); WriteLiteral(">Install</a>\r\n");
#line 41 "..\..\Areas\Config\Views\Plugins\Install.cshtml" #line 38 "..\..\Areas\Config\Views\Plugins\Install.cshtml"
} }
else else
{ {
if (Version.Parse(plugin.LatestVersion) > installedPlugin.Version) if (Version.Parse(plugin.Item2.Version) > installedPlugin.Version)
{ {
#line default #line default
#line hidden #line hidden
WriteLiteral(" <a"); WriteLiteral(" <a");
WriteLiteral(" class=\"pluginUpdateLink button\""); WriteLiteral(" class=\"pluginUpdateLink button\"");
WriteAttribute("href", Tuple.Create(" href=\"", 2450), Tuple.Create("\"", 2504) WriteAttribute("href", Tuple.Create(" href=\"", 2373), Tuple.Create("\"", 2433)
#line 46 "..\..\Areas\Config\Views\Plugins\Install.cshtml" #line 43 "..\..\Areas\Config\Views\Plugins\Install.cshtml"
, Tuple.Create(Tuple.Create("", 2457), Tuple.Create<System.Object, System.Int32>(Url.Action(MVC.API.Plugin.Update(plugin.Id)) , Tuple.Create(Tuple.Create("", 2380), Tuple.Create<System.Object, System.Int32>(Url.Action(MVC.API.Plugin.Update(plugin.Item1.Id))
#line default #line default
#line hidden #line hidden
, 2457), false) , 2380), false)
); );
WriteLiteral(">Update</a> \r\n"); WriteLiteral(">Update</a> \r\n");
#line 47 "..\..\Areas\Config\Views\Plugins\Install.cshtml" #line 44 "..\..\Areas\Config\Views\Plugins\Install.cshtml"
} }
else else
{ {
#line default #line default
#line hidden #line hidden
WriteLiteral(" <a"); WriteLiteral(" <a");
WriteLiteral(" class=\"pluginInstalledLink button disabled\""); WriteLiteral(" class=\"pluginInstalledLink button disabled\"");
@@ -268,39 +276,40 @@ WriteLiteral(" href=\"#\"");
WriteLiteral(">Installed</a> \r\n"); WriteLiteral(">Installed</a> \r\n");
#line 51 "..\..\Areas\Config\Views\Plugins\Install.cshtml" #line 48 "..\..\Areas\Config\Views\Plugins\Install.cshtml"
} }
} }
#line default #line default
#line hidden #line hidden
WriteLiteral(" </h2>\r\n <div"); WriteLiteral(" </h2>\r\n " +
" <div");
WriteLiteral(" class=\"pluginItemBlurb\""); WriteLiteral(" class=\"pluginItemBlurb\"");
WriteLiteral(">"); WriteLiteral(">");
#line 54 "..\..\Areas\Config\Views\Plugins\Install.cshtml" #line 51 "..\..\Areas\Config\Views\Plugins\Install.cshtml"
Write(new HtmlString(plugin.Blurb)); Write(new HtmlString(plugin.Item1.Description));
#line default #line default
#line hidden #line hidden
WriteLiteral("</div>\r\n <div"); WriteLiteral("</div>\r\n <div");
WriteLiteral(" class=\"pageMenuBlurb\""); WriteLiteral(" class=\"pageMenuBlurb\"");
WriteLiteral(">\r\n <span"); WriteLiteral(">\r\n <span");
WriteLiteral(" class=\"pluginId\""); WriteLiteral(" class=\"pluginId\"");
WriteLiteral(">"); WriteLiteral(">");
#line 56 "..\..\Areas\Config\Views\Plugins\Install.cshtml" #line 53 "..\..\Areas\Config\Views\Plugins\Install.cshtml"
Write(plugin.Id); Write(plugin.Item1.Id);
#line default #line default
@@ -312,8 +321,8 @@ WriteLiteral(" class=\"pluginVersion\"");
WriteLiteral(">v"); WriteLiteral(">v");
#line 56 "..\..\Areas\Config\Views\Plugins\Install.cshtml" #line 53 "..\..\Areas\Config\Views\Plugins\Install.cshtml"
Write(plugin.LatestVersion); Write(plugin.Item2.Version);
#line default #line default
@@ -321,22 +330,22 @@ WriteLiteral(">v");
WriteLiteral("</span> | "); WriteLiteral("</span> | ");
#line 56 "..\..\Areas\Config\Views\Plugins\Install.cshtml" #line 53 "..\..\Areas\Config\Views\Plugins\Install.cshtml"
Write(plugin.Author); Write(plugin.Item1.Author);
#line default #line default
#line hidden #line hidden
WriteLiteral(" | <a"); WriteLiteral(" | <a");
WriteAttribute("href", Tuple.Create(" href=\"", 3211), Tuple.Create("\"", 3229) WriteAttribute("href", Tuple.Create(" href=\"", 3244), Tuple.Create("\"", 3279)
#line 56 "..\..\Areas\Config\Views\Plugins\Install.cshtml" #line 53 "..\..\Areas\Config\Views\Plugins\Install.cshtml"
, Tuple.Create(Tuple.Create("", 3218), Tuple.Create<System.Object, System.Int32>(plugin.Url , Tuple.Create(Tuple.Create("", 3251), Tuple.Create<System.Object, System.Int32>(plugin.Item1.InformationUrl
#line default #line default
#line hidden #line hidden
, 3218), false) , 3251), false)
); );
WriteLiteral(" title=\"More Information\""); WriteLiteral(" title=\"More Information\"");
@@ -347,29 +356,31 @@ WriteLiteral("><i");
WriteLiteral(" class=\"fa fa-external-link\""); WriteLiteral(" class=\"fa fa-external-link\"");
WriteLiteral("></i></a>\r\n </div>\r\n </" + WriteLiteral("></i></a>\r\n </div>\r\n " +
"div>\r\n"); " </div>\r\n </td>\r\n " +
" </tr> \r\n");
#line 59 "..\..\Areas\Config\Views\Plugins\Install.cshtml" #line 58 "..\..\Areas\Config\Views\Plugins\Install.cshtml"
} }
#line default
#line hidden
WriteLiteral("\r\n </td>\r\n");
#line 62 "..\..\Areas\Config\Views\Plugins\Install.cshtml"
}
#line default #line default
#line hidden #line hidden
WriteLiteral(" </tr>\r\n </table>\r\n"); WriteLiteral(" </table>\r\n </div>\r\n");
#line 65 "..\..\Areas\Config\Views\Plugins\Install.cshtml" #line 61 "..\..\Areas\Config\Views\Plugins\Install.cshtml"
}
#line default
#line hidden
WriteLiteral(" </div>\r\n");
#line 63 "..\..\Areas\Config\Views\Plugins\Install.cshtml"
} }
@@ -406,7 +417,7 @@ WriteLiteral("></i><strong>Warning:</strong> All plugins run with the same level
"om a trusted source.</strong>\r\n </p>\r\n </div>\r\n</div>\r\n"); "om a trusted source.</strong>\r\n </p>\r\n </div>\r\n</div>\r\n");
#line 78 "..\..\Areas\Config\Views\Plugins\Install.cshtml" #line 77 "..\..\Areas\Config\Views\Plugins\Install.cshtml"
if (canInstallLocal) if (canInstallLocal)
{ {
@@ -426,13 +437,13 @@ WriteLiteral(" style=\"padding-bottom: 10px;\"");
WriteLiteral(">\r\n"); WriteLiteral(">\r\n");
#line 82 "..\..\Areas\Config\Views\Plugins\Install.cshtml" #line 81 "..\..\Areas\Config\Views\Plugins\Install.cshtml"
#line default #line default
#line hidden #line hidden
#line 82 "..\..\Areas\Config\Views\Plugins\Install.cshtml" #line 81 "..\..\Areas\Config\Views\Plugins\Install.cshtml"
using (Html.BeginForm(MVC.API.Plugin.InstallLocal(), FormMethod.Post, new { enctype = "multipart/form-data" })) using (Html.BeginForm(MVC.API.Plugin.InstallLocal(), FormMethod.Post, new { enctype = "multipart/form-data" }))
{ {
@@ -456,7 +467,7 @@ WriteLiteral(" type=\"file\"");
WriteLiteral(" />\r\n"); WriteLiteral(" />\r\n");
#line 86 "..\..\Areas\Config\Views\Plugins\Install.cshtml" #line 85 "..\..\Areas\Config\Views\Plugins\Install.cshtml"
} }
@@ -480,48 +491,49 @@ WriteLiteral("></i><strong>Warning:</strong> All plugins run with the same level
"\n"); "\n");
#line 95 "..\..\Areas\Config\Views\Plugins\Install.cshtml" #line 94 "..\..\Areas\Config\Views\Plugins\Install.cshtml"
} }
#line default #line default
#line hidden #line hidden
WriteLiteral("<script>\r\n $(function () {\r\n var $selectedPlugin;\r\n var $selecte" + WriteLiteral("<script>\r\n $(function () {\r\n var $selectedPlugin;\r\n var $selecte" +
"dPluginUrl;\r\n\r\n // Install\r\n var $dialogInstall = $(\'#dialogInstal" + "dPluginUrl;\r\n\r\n $(\'#pluginLibraryHeading\').appendTo(\'#layout_PageHeading\'" +
"lPlugin\').dialog({\r\n resizable: false,\r\n modal: true,\r\n " + ");\r\n\r\n // Install\r\n var $dialogInstall = $(\'#dialogInstallPlugin\')" +
" width: 350,\r\n autoOpen: false,\r\n buttons: {\r\n " + ".dialog({\r\n resizable: false,\r\n modal: true,\r\n " +
" \"Install\": function () {\r\n if ($selectedPlugin ==" + "width: 350,\r\n autoOpen: false,\r\n buttons: {\r\n " +
" null || !$selectedPluginUrl) {\r\n $(this).dialog(\"close\")" + " \"Install\": function () {\r\n if ($selectedPlugin == null || " +
";\r\n return;\r\n }\r\n $" + "!$selectedPluginUrl) {\r\n $(this).dialog(\"close\");\r\n " +
"(this).dialog(\"disable\");\r\n\r\n window.location.href = $selecte" + " return;\r\n }\r\n $(this).di" +
"dPluginUrl;\r\n },\r\n Cancel: function () {\r\n " + "alog(\"disable\");\r\n\r\n window.location.href = $selectedPluginUr" +
" $selectedPlugin = null;\r\n $(this).dialog(\"close\")" + "l;\r\n },\r\n Cancel: function () {\r\n " +
";\r\n }\r\n }\r\n });\r\n $(\'#pageMenu\').find(\'a" + " $selectedPlugin = null;\r\n $(this).dialog(\"close\");\r\n " +
".pluginInstallLink\').click(function () {\r\n $this = $(this);\r\n\r\n " + " }\r\n }\r\n });\r\n $(\'#pluginLibraryGroups\').find(" +
" $selectedPlugin = $this.closest(\'.pluginItem\');\r\n $selectedPlug" + "\'a.pluginInstallLink\').click(function () {\r\n $this = $(this);\r\n\r\n " +
"inUrl = $this.attr(\'href\');\r\n\r\n $(\'#dialogInstallPluginName\').text($s" + " $selectedPlugin = $this.closest(\'.pluginItem\');\r\n $selectedPl" +
"electedPlugin.find(\'.pluginName\').text());\r\n $(\'#dialogInstallPluginD" + "uginUrl = $this.attr(\'href\');\r\n\r\n $(\'#dialogInstallPluginName\').text(" +
"etails\').text($selectedPlugin.find(\'.pluginId\').text() + \' | \' + $selectedPlugin" + "$selectedPlugin.find(\'.pluginName\').text());\r\n $(\'#dialogInstallPlugi" +
".find(\'.pluginVersion\').text());\r\n\r\n $dialogInstall.dialog(\'option\', " + "nDetails\').text($selectedPlugin.find(\'.pluginId\').text() + \' | \' + $selectedPlug" +
"\'title\', \'Install this Plugin?\');\r\n $dialogInstall.dialog(\'open\');\r\n\r" + "in.find(\'.pluginVersion\').text());\r\n\r\n $dialogInstall.dialog(\'option\'" +
"\n return false;\r\n });\r\n $(\'#pageMenu\').find(\'a.pluginUp" + ", \'title\', \'Install this Plugin?\');\r\n $dialogInstall.dialog(\'open\');\r" +
"dateLink\').click(function () {\r\n $this = $(this);\r\n\r\n $sel" + "\n\r\n return false;\r\n });\r\n $(\'#pluginLibraryGroups\').fin" +
"ectedPlugin = $this.closest(\'.pluginItem\');\r\n $selectedPluginUrl = $t" + "d(\'a.pluginUpdateLink\').click(function () {\r\n $this = $(this);\r\n\r\n " +
"his.attr(\'href\');\r\n\r\n $(\'#dialogInstallPluginName\').text($selectedPlu" + " $selectedPlugin = $this.closest(\'.pluginItem\');\r\n $selectedP" +
"gin.find(\'.pluginName\').text());\r\n $(\'#dialogInstallPluginDetails\').t" + "luginUrl = $this.attr(\'href\');\r\n\r\n $(\'#dialogInstallPluginName\').text" +
"ext($selectedPlugin.find(\'.pluginId\').text() + \' | \' + $selectedPlugin.find(\'.pl" + "($selectedPlugin.find(\'.pluginName\').text());\r\n $(\'#dialogInstallPlug" +
"uginVersion\').text());\r\n\r\n $dialogInstall.dialog(\'option\', \'title\', \'" + "inDetails\').text($selectedPlugin.find(\'.pluginId\').text() + \' | \' + $selectedPlu" +
"Update this Plugin?\');\r\n $dialogInstall.dialog(\'open\');\r\n\r\n " + "gin.find(\'.pluginVersion\').text());\r\n\r\n $dialogInstall.dialog(\'option" +
" return false;\r\n });\r\n\r\n"); "\', \'title\', \'Update this Plugin?\');\r\n $dialogInstall.dialog(\'open\');\r" +
"\n\r\n return false;\r\n });\r\n\r\n");
#line 152 "..\..\Areas\Config\Views\Plugins\Install.cshtml" #line 153 "..\..\Areas\Config\Views\Plugins\Install.cshtml"
#line default #line default
#line hidden #line hidden
#line 152 "..\..\Areas\Config\Views\Plugins\Install.cshtml" #line 153 "..\..\Areas\Config\Views\Plugins\Install.cshtml"
if (canInstallLocal) if (canInstallLocal)
{ {
@@ -556,7 +568,7 @@ WriteLiteral(@"
"); ");
#line 179 "..\..\Areas\Config\Views\Plugins\Install.cshtml" #line 180 "..\..\Areas\Config\Views\Plugins\Install.cshtml"
} }
@@ -571,8 +583,8 @@ WriteLiteral(">\r\n");
WriteLiteral(" "); WriteLiteral(" ");
#line 183 "..\..\Areas\Config\Views\Plugins\Install.cshtml" #line 184 "..\..\Areas\Config\Views\Plugins\Install.cshtml"
Write(Html.ActionLinkButton("Update Catalogue", MVC.API.Plugin.UpdateLibraryCatalogue())); Write(Html.ActionLinkButton("Update Plugin Library", MVC.API.Plugin.UpdateLibraryManifest()));
#line default #line default
@@ -580,13 +592,13 @@ Write(Html.ActionLinkButton("Update Catalogue", MVC.API.Plugin.UpdateLibraryCata
WriteLiteral("\r\n"); WriteLiteral("\r\n");
#line 184 "..\..\Areas\Config\Views\Plugins\Install.cshtml" #line 185 "..\..\Areas\Config\Views\Plugins\Install.cshtml"
#line default #line default
#line hidden #line hidden
#line 184 "..\..\Areas\Config\Views\Plugins\Install.cshtml" #line 185 "..\..\Areas\Config\Views\Plugins\Install.cshtml"
if (canInstallLocal) if (canInstallLocal)
{ {
@@ -594,14 +606,14 @@ WriteLiteral("\r\n");
#line default #line default
#line hidden #line hidden
#line 186 "..\..\Areas\Config\Views\Plugins\Install.cshtml" #line 187 "..\..\Areas\Config\Views\Plugins\Install.cshtml"
Write(Html.ActionLinkButton("Install Plugin Package", MVC.API.Plugin.InstallLocal(), "buttonUpload")); Write(Html.ActionLinkButton("Install Plugin Package", MVC.API.Plugin.InstallLocal(), "buttonUpload"));
#line default #line default
#line hidden #line hidden
#line 186 "..\..\Areas\Config\Views\Plugins\Install.cshtml" #line 187 "..\..\Areas\Config\Views\Plugins\Install.cshtml"
} }
+2 -1
View File
@@ -1,4 +1,5 @@
# Include all Resources # Include all Resources
!* !*
Disco.ClientBootstrapper.exe Disco.ClientBootstrapper.exe
PreparationClient.zip PreparationClient.zip
DiscoServices.InitialPluginLibraryManifest.json
@@ -4144,6 +4144,7 @@ div.actionBar {
border-top: 1px solid #d1d1d1; border-top: 1px solid #d1d1d1;
text-align: right; text-align: right;
background-color: #f2f2f2; background-color: #f2f2f2;
clear: both;
} }
div.actionBar:not(:first-child) { div.actionBar:not(:first-child) {
margin-top: 10px; margin-top: 10px;
File diff suppressed because one or more lines are too long
+22 -11
View File
@@ -946,31 +946,42 @@ div.logEventsViewport table.logEventsViewport > tbody > tr > td.eventType {
#dialogUninstallPluginConfirm #uninstallPluginDataConfirm { #dialogUninstallPluginConfirm #uninstallPluginDataConfirm {
margin-top: 1em; margin-top: 1em;
} }
#pluginCatalog #pluginCatalogHeading { #pluginLibraryHeading {
margin-bottom: 20px; float: right;
text-align: right;
} }
#pluginCatalog .pluginItem .pluginItemBlurb { #pluginLibrary #pluginLibraryGroups {
margin: 4px 0 4px 2px; width: 900px;
margin: 0 auto;
}
#pluginLibrary #pluginLibraryGroups > div.form {
width: 50%;
float: left;
}
#pluginLibrary #pluginLibraryGroups > div.form > table {
margin: 0 10px 10px 4px;
width: calc(100% - 14px);
}
#pluginLibrary .pluginItem .pluginItemBlurb {
margin: 8px 0 8px 2px;
padding: 0 4px; padding: 0 4px;
border-left: 4px solid #f4f4f4; border-left: 4px solid #d1d1d1;
} }
#pluginCatalog .pluginItem .pluginItemBlurb * { #pluginLibrary .pluginItem .pluginItemBlurb * {
padding: 0; padding: 0;
margin: 0; margin: 0;
} }
#pluginCatalog .pluginItem .pageMenuBlurb i { #pluginLibrary .pluginItem .pageMenuBlurb i {
font-size: .9em; font-size: .9em;
} }
#pluginCatalog .pluginItem > h2:first-child { #pluginLibrary .pluginItem > h2:first-child {
min-height: 22px; min-height: 22px;
} }
#pluginCatalog .pluginItem > h2:first-child i { #pluginLibrary .pluginItem > h2:first-child i {
font-size: .9em; font-size: .9em;
padding-right: 4px; padding-right: 4px;
color: #333333; color: #333333;
} }
#pluginCatalog .pluginItem > h2:first-child a { #pluginLibrary .pluginItem > h2:first-child a {
float: right; float: right;
font-size: 12px; font-size: 12px;
} }
+32 -10
View File
@@ -671,11 +671,13 @@ div.logEventsViewport {
margin-top: 4px; margin-top: 4px;
} }
} }
#Config_DocumentTemplates_Scope_Dialog { #Config_DocumentTemplates_Scope_Dialog {
div.input { div.input {
margin: 14px 10px 20px; margin: 14px 10px 20px;
} }
} }
#Config_DocumentTemplates_TemplatePdf_Dialog { #Config_DocumentTemplates_TemplatePdf_Dialog {
div { div {
text-align: center; text-align: center;
@@ -1066,34 +1068,53 @@ div.logEventsViewport {
} }
#dialogUninstallPlugins { #dialogUninstallPlugins {
#uninstallPlugin{ #uninstallPlugin {
margin: .5em 0; margin: .5em 0;
} }
#uninstallPluginData{
#uninstallPluginData {
margin: .5em 0; margin: .5em 0;
} }
} }
#dialogUninstallPluginConfirm { #dialogUninstallPluginConfirm {
#uninstallPluginConfirm { #uninstallPluginConfirm {
text-align: center; text-align: center;
margin: 1em 0 0.5em 0; margin: 1em 0 0.5em 0;
} }
#uninstallPluginDataConfirm{
#uninstallPluginDataConfirm {
margin-top: 1em; margin-top: 1em;
} }
} }
#pluginCatalog { #pluginLibraryHeading {
#pluginCatalogHeading { float: right;
margin-bottom: 20px; }
text-align: right;
#pluginLibrary {
#pluginLibraryGroups {
width: 900px;
margin: 0 auto;
& > div.form {
width: 50%;
float: left;
& > table {
margin: 0 10px 10px 4px;
width: calc(~"100% - 14px");
}
}
} }
.pluginItem { .pluginItem {
.pluginItemBlurb { .pluginItemBlurb {
margin: 4px 0 4px 2px; margin: 8px 0 8px 2px;
padding: 0 4px; padding: 0 4px;
border-left: 4px solid @TableDataBorderColour; border-left: 4px solid @BackgroundColour;
* { * {
padding: 0; padding: 0;
@@ -1129,6 +1150,7 @@ div.logEventsViewport {
margin-top: 1em; margin-top: 1em;
} }
} }
#dialogUploadPlugin { #dialogUploadPlugin {
#pluginFile { #pluginFile {
margin: 1em 0 1em 6px; margin: 1em 0 1em 6px;
@@ -1625,4 +1647,4 @@ div.logEventsViewport {
display: none; display: none;
} }
} }
} }
File diff suppressed because one or more lines are too long
+1
View File
@@ -483,6 +483,7 @@ div.actionBar {
border-top: 1px solid #d1d1d1; border-top: 1px solid #d1d1d1;
text-align: right; text-align: right;
background-color: #f2f2f2; background-color: #f2f2f2;
clear: both;
} }
div.actionBar:not(:first-child) { div.actionBar:not(:first-child) {
margin-top: 10px; margin-top: 10px;
+1
View File
@@ -434,6 +434,7 @@ div.actionBar {
border-top: 1px solid @ActionBarBorder; border-top: 1px solid @ActionBarBorder;
text-align: right; text-align: right;
background-color: @ActionBarBackgound; background-color: @ActionBarBackgound;
clear: both;
&:not(:first-child) { &:not(:first-child) {
margin-top: 10px; margin-top: 10px;
File diff suppressed because one or more lines are too long
+1
View File
@@ -1227,6 +1227,7 @@
<Generator>RazorGenerator</Generator> <Generator>RazorGenerator</Generator>
<LastGenOutput>Noticeboard.generated.cs</LastGenOutput> <LastGenOutput>Noticeboard.generated.cs</LastGenOutput>
</None> </None>
<Content Include="ClientBin\DiscoServices.InitialPluginLibraryManifest.json" />
<None Include="ClientSource\Scripts\Core.min.js.map"> <None Include="ClientSource\Scripts\Core.min.js.map">
<DependentUpon>Core.js.bundle</DependentUpon> <DependentUpon>Core.js.bundle</DependentUpon>
</None> </None>
@@ -103,7 +103,7 @@ namespace Disco.Web.Areas.API.Controllers
[GeneratedCode("T4MVC", "2.0"), DebuggerNonUserCode] [GeneratedCode("T4MVC", "2.0"), DebuggerNonUserCode]
public class ActionNamesClass public class ActionNamesClass
{ {
public readonly string UpdateLibraryCatalogue = "UpdateLibraryCatalogue"; public readonly string UpdateLibraryManifest = "UpdateLibraryManifest";
public readonly string UpdateAll = "UpdateAll"; public readonly string UpdateAll = "UpdateAll";
public readonly string Update = "Update"; public readonly string Update = "Update";
public readonly string UpdateLocal = "UpdateLocal"; public readonly string UpdateLocal = "UpdateLocal";
@@ -115,7 +115,7 @@ namespace Disco.Web.Areas.API.Controllers
[GeneratedCode("T4MVC", "2.0"), DebuggerNonUserCode] [GeneratedCode("T4MVC", "2.0"), DebuggerNonUserCode]
public class ActionNameConstants public class ActionNameConstants
{ {
public const string UpdateLibraryCatalogue = "UpdateLibraryCatalogue"; public const string UpdateLibraryManifest = "UpdateLibraryManifest";
public const string UpdateAll = "UpdateAll"; public const string UpdateAll = "UpdateAll";
public const string Update = "Update"; public const string Update = "Update";
public const string UpdateLocal = "UpdateLocal"; public const string UpdateLocal = "UpdateLocal";
@@ -125,11 +125,11 @@ namespace Disco.Web.Areas.API.Controllers
} }
static readonly ActionParamsClass_UpdateLibraryCatalogue s_params_UpdateLibraryCatalogue = new ActionParamsClass_UpdateLibraryCatalogue(); static readonly ActionParamsClass_UpdateLibraryManifest s_params_UpdateLibraryManifest = new ActionParamsClass_UpdateLibraryManifest();
[GeneratedCode("T4MVC", "2.0"), DebuggerNonUserCode] [GeneratedCode("T4MVC", "2.0"), DebuggerNonUserCode]
public ActionParamsClass_UpdateLibraryCatalogue UpdateLibraryCatalogueParams { get { return s_params_UpdateLibraryCatalogue; } } public ActionParamsClass_UpdateLibraryManifest UpdateLibraryManifestParams { get { return s_params_UpdateLibraryManifest; } }
[GeneratedCode("T4MVC", "2.0"), DebuggerNonUserCode] [GeneratedCode("T4MVC", "2.0"), DebuggerNonUserCode]
public class ActionParamsClass_UpdateLibraryCatalogue public class ActionParamsClass_UpdateLibraryManifest
{ {
public readonly string TryWaitingForCompletion = "TryWaitingForCompletion"; public readonly string TryWaitingForCompletion = "TryWaitingForCompletion";
} }
@@ -195,14 +195,14 @@ namespace Disco.Web.Areas.API.Controllers
public T4MVC_PluginController() : base(Dummy.Instance) { } public T4MVC_PluginController() : base(Dummy.Instance) { }
[NonAction] [NonAction]
partial void UpdateLibraryCatalogueOverride(T4MVC_System_Web_Mvc_ActionResult callInfo, bool TryWaitingForCompletion); partial void UpdateLibraryManifestOverride(T4MVC_System_Web_Mvc_ActionResult callInfo, bool TryWaitingForCompletion);
[NonAction] [NonAction]
public override System.Web.Mvc.ActionResult UpdateLibraryCatalogue(bool TryWaitingForCompletion) public override System.Web.Mvc.ActionResult UpdateLibraryManifest(bool TryWaitingForCompletion)
{ {
var callInfo = new T4MVC_System_Web_Mvc_ActionResult(Area, Name, ActionNames.UpdateLibraryCatalogue); var callInfo = new T4MVC_System_Web_Mvc_ActionResult(Area, Name, ActionNames.UpdateLibraryManifest);
ModelUnbinderHelpers.AddRouteValues(callInfo.RouteValueDictionary, "TryWaitingForCompletion", TryWaitingForCompletion); ModelUnbinderHelpers.AddRouteValues(callInfo.RouteValueDictionary, "TryWaitingForCompletion", TryWaitingForCompletion);
UpdateLibraryCatalogueOverride(callInfo, TryWaitingForCompletion); UpdateLibraryManifestOverride(callInfo, TryWaitingForCompletion);
return callInfo; return callInfo;
} }
+1
View File
@@ -873,6 +873,7 @@ namespace Links
public static string Url() { return T4MVCHelpers.ProcessVirtualPath(URLPATH); } public static string Url() { return T4MVCHelpers.ProcessVirtualPath(URLPATH); }
public static string Url(string fileName) { return T4MVCHelpers.ProcessVirtualPath(URLPATH + "/" + fileName); } public static string Url(string fileName) { return T4MVCHelpers.ProcessVirtualPath(URLPATH + "/" + fileName); }
public static readonly string Disco_ClientBootstrapper_exe = Url("Disco.ClientBootstrapper.exe"); public static readonly string Disco_ClientBootstrapper_exe = Url("Disco.ClientBootstrapper.exe");
public static readonly string DiscoServices_InitialPluginLibraryManifest_json = Url("DiscoServices.InitialPluginLibraryManifest.json");
public static readonly string PreparationClient_zip = Url("PreparationClient.zip"); public static readonly string PreparationClient_zip = Url("PreparationClient.zip");
} }