Update: Plugin Updating

Updating plugins from the plugin catalogue, and automatic updating of
plugins after a newer version of Disco is installed.
This commit is contained in:
Gary Sharp committed 2013-02-14 19:00:01 +11:00
1 parent 734b02fa1d
commit 8f769809c2
53 files changed
+3795 -2975

No files matched your search

+13 -9
View File
@@ -18,13 +18,17 @@ namespace Disco.BI.Interop.Community
{ {
private static string UpdateUrl() private static string UpdateUrl()
{ {
return string.Concat(CommunityHelpers.CommunityUrl(), "DiscoUpdate/V1"); return string.Concat(Disco.Data.Configuration.CommunityHelpers.CommunityUrl(), "DiscoUpdate/V1");
} }
public static string CurrentDiscoVersion() public static Version CurrentDiscoVersion()
{ {
var AssemblyVersion = typeof(UpdateCheck).Assembly.GetName().Version; return typeof(UpdateCheck).Assembly.GetName().Version;
return string.Format("{0}.{1}.{2:0000}.{3:0000}", AssemblyVersion.Major, AssemblyVersion.Minor, AssemblyVersion.Build, AssemblyVersion.Revision); }
public static string CurrentDiscoVersionFormatted()
{
var v = CurrentDiscoVersion();
return string.Format("{0}.{1}.{2:0000}.{3:0000}", v.Major, v.Minor, v.Build, v.Revision);
} }
public static UpdateResponse Check(DiscoDataContext db, bool UseProxy, ScheduledTaskStatus status = null) public static UpdateResponse Check(DiscoDataContext db, bool UseProxy, ScheduledTaskStatus status = null)
@@ -38,7 +42,7 @@ namespace Disco.BI.Interop.Community
if (status != null) if (status != null)
status.UpdateStatus(40, "Sending Request"); status.UpdateStatus(40, "Sending Request");
var DiscoBIVersion = CurrentDiscoVersion(); var DiscoBIVersion = CurrentDiscoVersionFormatted();
HttpWebRequest webRequest = (HttpWebRequest)HttpWebRequest.Create(UpdateUrl()); HttpWebRequest webRequest = (HttpWebRequest)HttpWebRequest.Create(UpdateUrl());
@@ -49,7 +53,7 @@ namespace Disco.BI.Interop.Community
if (!UseProxy) if (!UseProxy)
webRequest.Proxy = new WebProxy(); webRequest.Proxy = new WebProxy();
webRequest.ContentType = "application/json"; webRequest.ContentType = "application/json";
webRequest.Method = WebRequestMethods.Http.Post; webRequest.Method = WebRequestMethods.Http.Post;
webRequest.UserAgent = string.Format("Disco/{0} (Update)", DiscoBIVersion); webRequest.UserAgent = string.Format("Disco/{0} (Update)", DiscoBIVersion);
@@ -78,7 +82,7 @@ namespace Disco.BI.Interop.Community
db.SaveChanges(); db.SaveChanges();
status.SetFinishedMessage(string.Format("The update server reported Version {0} is the latest.", result.Version)); status.SetFinishedMessage(string.Format("The update server reported Version {0} is the latest.", result.Version));
return result; return result;
} }
else else
@@ -96,7 +100,7 @@ namespace Disco.BI.Interop.Community
m.DeploymentId = db.DiscoConfiguration.DeploymentId; m.DeploymentId = db.DiscoConfiguration.DeploymentId;
m.CurrentDiscoVersion = CurrentDiscoVersion(); m.CurrentDiscoVersion = CurrentDiscoVersionFormatted();
m.OrganisationName = db.DiscoConfiguration.OrganisationName; m.OrganisationName = db.DiscoConfiguration.OrganisationName;
m.BroadbandDoeWanId = GetBroadbandDoeWanId(); m.BroadbandDoeWanId = GetBroadbandDoeWanId();
@@ -144,7 +148,7 @@ namespace Disco.BI.Interop.Community
{ {
try try
{ {
var DiscoBIVersion = CurrentDiscoVersion(); var DiscoBIVersion = CurrentDiscoVersionFormatted();
HttpWebRequest wReq = (HttpWebRequest)HttpWebRequest.Create("http://broadband.doe.wan/ipsearch/showresult.php"); HttpWebRequest wReq = (HttpWebRequest)HttpWebRequest.Create("http://broadband.doe.wan/ipsearch/showresult.php");
// Added: 2013-02-08 G# // Added: 2013-02-08 G#
@@ -55,7 +55,7 @@ namespace Disco.BI.Interop.Community
public override void InitalizeScheduledTask(Data.Repository.DiscoDataContext dbContext) public override void InitalizeScheduledTask(Data.Repository.DiscoDataContext dbContext)
{ {
// ActiveDirectoryUpdateLastNetworkLogonDateJob @ 11:30pm // Random time between midday and midnight.
var rnd = new Random(); var rnd = new Random();
var rndHour = rnd.Next(12, 23); var rndHour = rnd.Next(12, 23);
+1 -3
View File
@@ -149,8 +149,6 @@
<Compile Include="BI\Interop\ActiveDirectory\ActiveDirectoryUpdateLastNetworkLogonDateJob.cs" /> <Compile Include="BI\Interop\ActiveDirectory\ActiveDirectoryUpdateLastNetworkLogonDateJob.cs" />
<Compile Include="BI\Interop\ActiveDirectory\ActiveDirectoryUserAccountExtensions.cs" /> <Compile Include="BI\Interop\ActiveDirectory\ActiveDirectoryUserAccountExtensions.cs" />
<Compile Include="BI\Expressions\ExpressionCache.cs" /> <Compile Include="BI\Expressions\ExpressionCache.cs" />
<Compile Include="BI\Interop\Community\CommunityHelpers.cs" />
<Compile Include="BI\Interop\Community\PluginLibraryUpdateTask.cs" />
<Compile Include="BI\Interop\Community\UpdateCheck.cs" /> <Compile Include="BI\Interop\Community\UpdateCheck.cs" />
<Compile Include="BI\Interop\Community\UpdateCheckTask.cs" /> <Compile Include="BI\Interop\Community\UpdateCheckTask.cs" />
<Compile Include="BI\Interop\MimeTypes.cs" /> <Compile Include="BI\Interop\MimeTypes.cs" />
@@ -221,7 +219,7 @@
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<ProjectExtensions> <ProjectExtensions>
<VisualStudio> <VisualStudio>
<UserProperties BuildVersion_StartDate="2001/1/1" BuildVersion_BuildAction="ReBuild" BuildVersion_DetectChanges="False" BuildVersion_UseGlobalSettings="True" /> <UserProperties BuildVersion_UseGlobalSettings="True" BuildVersion_DetectChanges="False" BuildVersion_BuildAction="ReBuild" BuildVersion_StartDate="2001/1/1" />
</VisualStudio> </VisualStudio>
</ProjectExtensions> </ProjectExtensions>
<Import Project="$(SolutionDir)\.nuget\nuget.targets" /> <Import Project="$(SolutionDir)\.nuget\nuget.targets" />
+2 -2
View File
@@ -32,5 +32,5 @@ using System.Runtime.InteropServices;
// You can specify all the values or you can default the Build and Revision Numbers // You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below: // by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")] // [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.2.0212.1702")] [assembly: AssemblyVersion("1.2.0214.1848")]
[assembly: AssemblyFileVersion("1.2.0212.1702")] [assembly: AssemblyFileVersion("1.2.0214.1848")]
Binary file not shown.
+2 -2
View File
@@ -32,5 +32,5 @@ using System.Runtime.InteropServices;
// You can specify all the values or you can default the Build and Revision Numbers // You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below: // by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")] // [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.2.0212.1702")] [assembly: AssemblyVersion("1.2.0214.1848")]
[assembly: AssemblyFileVersion("1.2.0212.1702")] [assembly: AssemblyFileVersion("1.2.0214.1848")]
@@ -32,5 +32,5 @@ using System.Runtime.InteropServices;
// You can specify all the values or you can default the Build and Revision Numbers // You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below: // by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")] // [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.2.0212.1702")] [assembly: AssemblyVersion("1.2.0214.1848")]
[assembly: AssemblyFileVersion("1.2.0212.1702")] [assembly: AssemblyFileVersion("1.2.0214.1848")]
@@ -5,7 +5,7 @@ using System.Net;
using System.Text; using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
namespace Disco.BI.Interop.Community namespace Disco.Data.Configuration
{ {
public static class CommunityHelpers public static class CommunityHelpers
{ {
@@ -460,15 +460,19 @@ namespace Disco.Data.Configuration
return this.GetConfigurationValue<bool>(this.Scope, "UpdateBetaDeployment", false); return this.GetConfigurationValue<bool>(this.Scope, "UpdateBetaDeployment", false);
} }
} }
public string InstalledDatabaseVersion public Version InstalledDatabaseVersion
{ {
get get
{ {
return this.GetConfigurationValue<string>(this.Scope, "InstalledDatabaseVersion", null); var versionString = this.GetConfigurationValue<string>(this.Scope, "InstalledDatabaseVersion", null);
if (string.IsNullOrEmpty(versionString))
return null;
else
return Version.Parse(versionString);
} }
set set
{ {
this.SetConfigurationValue<string>(this.Scope, "InstalledDatabaseVersion", value); this.SetConfigurationValue<string>(this.Scope, "InstalledDatabaseVersion", value.ToString(4));
} }
} }
#endregion #endregion
+150 -149
View File
@@ -1,150 +1,151 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup> <PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform> <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProductVersion>8.0.30703</ProductVersion> <ProductVersion>8.0.30703</ProductVersion>
<SchemaVersion>2.0</SchemaVersion> <SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>{85A6BD19-2C64-4746-8F2C-A68A86E8C2D7}</ProjectGuid> <ProjectGuid>{85A6BD19-2C64-4746-8F2C-A68A86E8C2D7}</ProjectGuid>
<OutputType>Library</OutputType> <OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder> <AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>Disco.Data</RootNamespace> <RootNamespace>Disco.Data</RootNamespace>
<AssemblyName>Disco.Data</AssemblyName> <AssemblyName>Disco.Data</AssemblyName>
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion> <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment> <FileAlignment>512</FileAlignment>
<TargetFrameworkProfile /> <TargetFrameworkProfile />
<SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\</SolutionDir> <SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\</SolutionDir>
<RestorePackages>true</RestorePackages> <RestorePackages>true</RestorePackages>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols> <DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType> <DebugType>full</DebugType>
<Optimize>false</Optimize> <Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath> <OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants> <DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport> <ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel> <WarningLevel>4</WarningLevel>
<Prefer32Bit>false</Prefer32Bit> <Prefer32Bit>false</Prefer32Bit>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "> <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType> <DebugType>pdbonly</DebugType>
<Optimize>true</Optimize> <Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath> <OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants> <DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport> <ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel> <WarningLevel>4</WarningLevel>
<Prefer32Bit>false</Prefer32Bit> <Prefer32Bit>false</Prefer32Bit>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<Reference Include="EntityFramework, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089, processorArchitecture=MSIL"> <Reference Include="EntityFramework, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion> <SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\EntityFramework.5.0.0\lib\net45\EntityFramework.dll</HintPath> <HintPath>..\packages\EntityFramework.5.0.0\lib\net45\EntityFramework.dll</HintPath>
</Reference> </Reference>
<Reference Include="Newtonsoft.Json, Version=4.5.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL"> <Reference Include="Newtonsoft.Json, Version=4.5.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion> <SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\Newtonsoft.Json.4.5.11\lib\net40\Newtonsoft.Json.dll</HintPath> <HintPath>..\packages\Newtonsoft.Json.4.5.11\lib\net40\Newtonsoft.Json.dll</HintPath>
</Reference> </Reference>
<Reference Include="System" /> <Reference Include="System" />
<Reference Include="System.ComponentModel.DataAnnotations" /> <Reference Include="System.ComponentModel.DataAnnotations" />
<Reference Include="System.Core" /> <Reference Include="System.Core" />
<Reference Include="System.Data.Entity" /> <Reference Include="System.Data.Entity" />
<Reference Include="System.Drawing" /> <Reference Include="System.Drawing" />
<Reference Include="System.Web" /> <Reference Include="System.Web" />
<Reference Include="System.Xml.Linq" /> <Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" /> <Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" /> <Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" /> <Reference Include="System.Data" />
<Reference Include="System.Xml" /> <Reference Include="System.Xml" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Compile Include="Configuration\ConfigurationBase.cs" /> <Compile Include="Configuration\CommunityHelpers.cs" />
<Compile Include="Configuration\ConfigurationContext.cs" /> <Compile Include="Configuration\ConfigurationBase.cs" />
<Compile Include="Configuration\Modules\BootstrapperConfiguration.cs" /> <Compile Include="Configuration\ConfigurationContext.cs" />
<Compile Include="Configuration\Modules\DeviceProfileConfiguration.cs" /> <Compile Include="Configuration\Modules\BootstrapperConfiguration.cs" />
<Compile Include="Configuration\Modules\DeviceProfilesConfiguration.cs" /> <Compile Include="Configuration\Modules\DeviceProfileConfiguration.cs" />
<Compile Include="Configuration\Modules\OrganisationAddressesConfiguration.cs" /> <Compile Include="Configuration\Modules\DeviceProfilesConfiguration.cs" />
<Compile Include="Configuration\Modules\WirelessConfiguration.cs" /> <Compile Include="Configuration\Modules\OrganisationAddressesConfiguration.cs" />
<Compile Include="Migrations\201204250418485_DBv0.cs" /> <Compile Include="Configuration\Modules\WirelessConfiguration.cs" />
<Compile Include="Migrations\201204250418485_DBv0.Designer.cs"> <Compile Include="Migrations\201204250418485_DBv0.cs" />
<DependentUpon>201204250418485_DBv0.cs</DependentUpon> <Compile Include="Migrations\201204250418485_DBv0.Designer.cs">
</Compile> <DependentUpon>201204250418485_DBv0.cs</DependentUpon>
<Compile Include="Migrations\201205100307196_DBv1.cs" /> </Compile>
<Compile Include="Migrations\201205100307196_DBv1.Designer.cs"> <Compile Include="Migrations\201205100307196_DBv1.cs" />
<DependentUpon>201205100307196_DBv1.cs</DependentUpon> <Compile Include="Migrations\201205100307196_DBv1.Designer.cs">
</Compile> <DependentUpon>201205100307196_DBv1.cs</DependentUpon>
<Compile Include="Migrations\201205290205162_DBv2.cs" /> </Compile>
<Compile Include="Migrations\201205290205162_DBv2.Designer.cs"> <Compile Include="Migrations\201205290205162_DBv2.cs" />
<DependentUpon>201205290205162_DBv2.cs</DependentUpon> <Compile Include="Migrations\201205290205162_DBv2.Designer.cs">
</Compile> <DependentUpon>201205290205162_DBv2.cs</DependentUpon>
<Compile Include="Migrations\201206140712161_DBv3.cs" /> </Compile>
<Compile Include="Migrations\201206140712161_DBv3.Designer.cs"> <Compile Include="Migrations\201206140712161_DBv3.cs" />
<DependentUpon>201206140712161_DBv3.cs</DependentUpon> <Compile Include="Migrations\201206140712161_DBv3.Designer.cs">
</Compile> <DependentUpon>201206140712161_DBv3.cs</DependentUpon>
<Compile Include="Migrations\201206280337277_DBv4.cs" /> </Compile>
<Compile Include="Migrations\201206280337277_DBv4.Designer.cs"> <Compile Include="Migrations\201206280337277_DBv4.cs" />
<DependentUpon>201206280337277_DBv4.cs</DependentUpon> <Compile Include="Migrations\201206280337277_DBv4.Designer.cs">
</Compile> <DependentUpon>201206280337277_DBv4.cs</DependentUpon>
<Compile Include="Migrations\201211090325116_DBv5.cs" /> </Compile>
<Compile Include="Migrations\201211090325116_DBv5.Designer.cs"> <Compile Include="Migrations\201211090325116_DBv5.cs" />
<DependentUpon>201211090325116_DBv5.cs</DependentUpon> <Compile Include="Migrations\201211090325116_DBv5.Designer.cs">
</Compile> <DependentUpon>201211090325116_DBv5.cs</DependentUpon>
<Compile Include="Migrations\201301150107063_DBv6.cs" /> </Compile>
<Compile Include="Migrations\201301150107063_DBv6.Designer.cs"> <Compile Include="Migrations\201301150107063_DBv6.cs" />
<DependentUpon>201301150107063_DBv6.cs</DependentUpon> <Compile Include="Migrations\201301150107063_DBv6.Designer.cs">
</Compile> <DependentUpon>201301150107063_DBv6.cs</DependentUpon>
<Compile Include="Migrations\Configuration.cs" /> </Compile>
<Compile Include="Migrations\DiscoDataMigrator.cs" /> <Compile Include="Migrations\Configuration.cs" />
<Compile Include="Properties\AssemblyInfo.cs" /> <Compile Include="Migrations\DiscoDataMigrator.cs" />
<Compile Include="Properties\Resources.Designer.cs"> <Compile Include="Properties\AssemblyInfo.cs" />
<AutoGen>True</AutoGen> <Compile Include="Properties\Resources.Designer.cs">
<DesignTime>True</DesignTime> <AutoGen>True</AutoGen>
<DependentUpon>Resources.resx</DependentUpon> <DesignTime>True</DesignTime>
</Compile> <DependentUpon>Resources.resx</DependentUpon>
<Compile Include="Repository\DiscoDatabaseConnectionFactory.cs" /> </Compile>
<Compile Include="Repository\DiscoDataContext.cs" /> <Compile Include="Repository\DiscoDatabaseConnectionFactory.cs" />
<Compile Include="Repository\DiscoDataContextInitializer.cs" /> <Compile Include="Repository\DiscoDataContext.cs" />
<Compile Include="Repository\DiscoDataSeeder.cs" /> <Compile Include="Repository\DiscoDataContextInitializer.cs" />
</ItemGroup> <Compile Include="Repository\DiscoDataSeeder.cs" />
<ItemGroup> </ItemGroup>
<None Include="App.config"> <ItemGroup>
<SubType>Designer</SubType> <None Include="App.config">
</None> <SubType>Designer</SubType>
</ItemGroup> </None>
<ItemGroup> </ItemGroup>
<ProjectReference Include="..\Disco.Models\Disco.Models.csproj"> <ItemGroup>
<Project>{FBC05512-FCCA-4B16-9E76-8C413C5DE6C9}</Project> <ProjectReference Include="..\Disco.Models\Disco.Models.csproj">
<Name>Disco.Models</Name> <Project>{FBC05512-FCCA-4B16-9E76-8C413C5DE6C9}</Project>
</ProjectReference> <Name>Disco.Models</Name>
</ItemGroup> </ProjectReference>
<ItemGroup> </ItemGroup>
<EmbeddedResource Include="Migrations\201211090325116_DBv5.resx"> <ItemGroup>
<DependentUpon>201211090325116_DBv5.cs</DependentUpon> <EmbeddedResource Include="Migrations\201211090325116_DBv5.resx">
</EmbeddedResource> <DependentUpon>201211090325116_DBv5.cs</DependentUpon>
<EmbeddedResource Include="Migrations\201301150107063_DBv6.resx"> </EmbeddedResource>
<DependentUpon>201301150107063_DBv6.cs</DependentUpon> <EmbeddedResource Include="Migrations\201301150107063_DBv6.resx">
</EmbeddedResource> <DependentUpon>201301150107063_DBv6.cs</DependentUpon>
<EmbeddedResource Include="Properties\Resources.resx"> </EmbeddedResource>
<Generator>ResXFileCodeGenerator</Generator> <EmbeddedResource Include="Properties\Resources.resx">
<LastGenOutput>Resources.Designer.cs</LastGenOutput> <Generator>ResXFileCodeGenerator</Generator>
<SubType>Designer</SubType> <LastGenOutput>Resources.Designer.cs</LastGenOutput>
</EmbeddedResource> <SubType>Designer</SubType>
</ItemGroup> </EmbeddedResource>
<ItemGroup> </ItemGroup>
<None Include="packages.config" /> <ItemGroup>
<None Include="Resources\EmptyLogo.png" /> <None Include="packages.config" />
</ItemGroup> <None Include="Resources\EmptyLogo.png" />
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> </ItemGroup>
<ProjectExtensions> <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<VisualStudio> <ProjectExtensions>
<UserProperties BuildVersion_BuildAction="ReBuild" BuildVersion_UseGlobalSettings="True" BuildVersion_DetectChanges="False" BuildVersion_StartDate="2001/1/1" /> <VisualStudio>
</VisualStudio> <UserProperties BuildVersion_StartDate="2001/1/1" BuildVersion_DetectChanges="False" BuildVersion_UseGlobalSettings="True" BuildVersion_BuildAction="ReBuild" />
</ProjectExtensions> </VisualStudio>
<Import Project="$(SolutionDir)\.nuget\nuget.targets" /> </ProjectExtensions>
<!-- To modify your build process, add your task inside one of the targets below and uncomment it. <Import Project="$(SolutionDir)\.nuget\nuget.targets" />
Other similar extension points exist, see Microsoft.Common.targets. <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
<Target Name="BeforeBuild"> Other similar extension points exist, see Microsoft.Common.targets.
</Target> <Target Name="BeforeBuild">
<Target Name="AfterBuild"> </Target>
</Target> <Target Name="AfterBuild">
--> </Target>
-->
</Project> </Project>
+2 -2
View File
@@ -32,5 +32,5 @@ using System.Runtime.InteropServices;
// You can specify all the values or you can default the Build and Revision Numbers // You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below: // by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")] // [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.2.0212.1702")] [assembly: AssemblyVersion("1.2.0214.1848")]
[assembly: AssemblyFileVersion("1.2.0212.1702")] [assembly: AssemblyFileVersion("1.2.0214.1848")]
+2 -2
View File
@@ -32,5 +32,5 @@ using System.Runtime.InteropServices;
// You can specify all the values or you can default the Build and Revision Numbers // You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below: // by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")] // [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.2.0212.1702")] [assembly: AssemblyVersion("1.2.0214.1848")]
[assembly: AssemblyFileVersion("1.2.0212.1702")] [assembly: AssemblyFileVersion("1.2.0214.1848")]
+3 -1
View File
@@ -101,6 +101,9 @@
<Compile Include="Logging\Targets\LogLiveContext.cs" /> <Compile Include="Logging\Targets\LogLiveContext.cs" />
<Compile Include="Logging\Targets\LogPersistContext.cs" /> <Compile Include="Logging\Targets\LogPersistContext.cs" />
<Compile Include="Logging\Utilities.cs" /> <Compile Include="Logging\Utilities.cs" />
<Compile Include="Plugins\CommunityInterop\PluginLibraryUpdateTask.cs" />
<Compile Include="Plugins\UpdatePluginsAfterDiscoUpdateTask.cs" />
<Compile Include="Plugins\UpdatePluginTask.cs" />
<Compile Include="Plugins\InstallPluginTask.cs" /> <Compile Include="Plugins\InstallPluginTask.cs" />
<Compile Include="Plugins\PluginAttribute.cs" /> <Compile Include="Plugins\PluginAttribute.cs" />
<Compile Include="Plugins\PluginExtensions.cs" /> <Compile Include="Plugins\PluginExtensions.cs" />
@@ -126,7 +129,6 @@
<Compile Include="Plugins\UnknownPluginException.cs" /> <Compile Include="Plugins\UnknownPluginException.cs" />
<Compile Include="Properties\AssemblyInfo.cs" /> <Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Tasks\ScheduledTask.cs" /> <Compile Include="Tasks\ScheduledTask.cs" />
<Compile Include="Tasks\ScheduledTaskCleanup.cs" />
<Compile Include="Tasks\ScheduledTasks.cs" /> <Compile Include="Tasks\ScheduledTasks.cs" />
<Compile Include="Tasks\ScheduledTasksLog.cs" /> <Compile Include="Tasks\ScheduledTasksLog.cs" />
<Compile Include="Tasks\ScheduledTaskStatus.cs" /> <Compile Include="Tasks\ScheduledTaskStatus.cs" />
@@ -12,14 +12,27 @@ using System.Xml.Serialization;
using System.IO; using System.IO;
using Newtonsoft.Json; using Newtonsoft.Json;
using Newtonsoft.Json.Converters; using Newtonsoft.Json.Converters;
using Quartz;
namespace Disco.BI.Interop.Community namespace Disco.Services.Plugins.CommunityInterop
{ {
public class PluginLibraryUpdateTask : ScheduledTask public class PluginLibraryUpdateTask : ScheduledTask
{ {
public override string TaskName { get { return "Disco Community - Update Plugin Library"; } } 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() protected override void ExecuteTask()
{
ExecuteTaskInternal(this.Status);
Status.SetFinishedMessage("The Plugin Library Catalogue was updated.");
}
internal static void ExecuteTaskInternal(ScheduledTaskStatus Status)
{ {
PluginLibraryUpdateRequest updateRequestBody; PluginLibraryUpdateRequest updateRequestBody;
PluginLibraryUpdateResponse updateResult; PluginLibraryUpdateResponse updateResult;
@@ -28,13 +41,13 @@ namespace Disco.BI.Interop.Community
PluginLibraryCompatibilityResponse compatResult; PluginLibraryCompatibilityResponse compatResult;
string compatibilityFile; string compatibilityFile;
var DiscoBIVersion = UpdateCheck.CurrentDiscoVersion(); var DiscoBIVersion = CurrentDiscoVersion();
HttpWebRequest webRequest; HttpWebRequest webRequest;
#region Update #region Update
Status.UpdateStatus(1, "Updating Plugin Library Catalogue", "Building Request"); Status.UpdateStatus(1, "Updating Plugin Library Catalogue", "Building Request");
using (DiscoDataContext dbContext = new DiscoDataContext()) using (DiscoDataContext dbContext = new DiscoDataContext())
{ {
catalogueFile = Plugins.CatalogueFile(dbContext); catalogueFile = Plugins.CatalogueFile(dbContext);
@@ -156,20 +169,15 @@ namespace Disco.BI.Interop.Community
} }
} }
#endregion #endregion
Status.SetFinishedMessage("The Plugin Library Catalogue was updated.");
} }
private static string PluginLibraryUpdateUrl() private static string PluginLibraryUpdateUrl()
{ {
return string.Concat(CommunityHelpers.CommunityUrl(), "DiscoPluginLibrary/V1"); return string.Concat(Disco.Data.Configuration.CommunityHelpers.CommunityUrl(), "DiscoPluginLibrary/V1");
} }
private static string PluginLibraryCompatibilityUrl() private static string PluginLibraryCompatibilityUrl()
{ {
return string.Concat(CommunityHelpers.CommunityUrl(), "DiscoPluginLibrary/CompatibilityV1"); return string.Concat(Disco.Data.Configuration.CommunityHelpers.CommunityUrl(), "DiscoPluginLibrary/CompatibilityV1");
} }
public static ScheduledTaskStatus ScheduleNow() public static ScheduledTaskStatus ScheduleNow()
@@ -191,5 +199,19 @@ namespace Disco.BI.Interop.Community
return ScheduledTasks.GetTaskStatuses(typeof(PluginLibraryUpdateTask)).Where(ts => ts.IsRunning).FirstOrDefault(); return ScheduledTasks.GetTaskStatuses(typeof(PluginLibraryUpdateTask)).Where(ts => ts.IsRunning).FirstOrDefault();
} }
} }
public override void InitalizeScheduledTask(DiscoDataContext dbContext)
{
// 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);
}
} }
} }
@@ -158,6 +158,10 @@ namespace Disco.Services.Plugins
{ {
if (ScheduledTasks.GetTaskStatuses(typeof(InstallPluginTask)).Where(s => s.IsRunning).Count() > 0) if (ScheduledTasks.GetTaskStatuses(typeof(InstallPluginTask)).Where(s => s.IsRunning).Count() > 0)
throw new InvalidOperationException("A plugin is already being Installed"); throw new InvalidOperationException("A plugin is already being Installed");
if (ScheduledTasks.GetTaskStatuses(typeof(UpdatePluginTask)).Where(s => s.IsRunning).Count() > 0)
throw new InvalidOperationException("A plugin is being Updated");
if (ScheduledTasks.GetTaskStatuses(typeof(UninstallPluginTask)).Where(s => s.IsRunning).Count() > 0)
throw new InvalidOperationException("A plugin is being Uninstalled");
JobDataMap taskData = new JobDataMap() { { "PackageUrl", PackageUrl }, { "PackageFilePath", PackageFilePath }, { "DeletePackageAfterInstall", DeletePackageAfterInstall } }; JobDataMap taskData = new JobDataMap() { { "PackageUrl", PackageUrl }, { "PackageFilePath", PackageFilePath }, { "DeletePackageAfterInstall", DeletePackageAfterInstall } };
+16
View File
@@ -348,6 +348,14 @@ namespace Disco.Services.Plugins
return handler; return handler;
} }
[JsonIgnore] [JsonIgnore]
public string ConfigurationUrl
{
get
{
return string.Format("/Config/Plugins/{0}", HttpUtility.UrlEncode(this.Id));
}
}
[JsonIgnore]
public bool HasWebHandler public bool HasWebHandler
{ {
get get
@@ -371,6 +379,14 @@ namespace Disco.Services.Plugins
return handler; return handler;
} }
[JsonIgnore]
public string WebHandlerUrl
{
get
{
return string.Format("/Plugin/{0}", HttpUtility.UrlEncode(this.Id));
}
}
public Tuple<string, string> WebResourcePath(string Resource) public Tuple<string, string> WebResourcePath(string Resource)
{ {
+22
View File
@@ -10,6 +10,7 @@ using System.IO.Compression;
using Disco.Models.BI.Interop.Community; using Disco.Models.BI.Interop.Community;
using System.Web; using System.Web;
using Newtonsoft.Json; using Newtonsoft.Json;
using System.Threading;
namespace Disco.Services.Plugins namespace Disco.Services.Plugins
{ {
@@ -477,6 +478,27 @@ namespace Disco.Services.Plugins
return categoryDisplayNames; return categoryDisplayNames;
} }
#region Restart App
private static object _restartTimerLock = new object();
private static Timer _restartTimer;
internal static void RestartApp(int DelayMilliseconds)
{
lock (_restartTimerLock)
{
if (_restartTimer != null)
{
_restartTimer.Dispose();
}
_restartTimer = new Timer((state) =>
{
HttpRuntime.UnloadAppDomain();
//AppDomain.Unload(AppDomain.CurrentDomain);
}, null, DelayMilliseconds, Timeout.Infinite);
}
}
#endregion
#region Plugin Referenced Assemblies Resolving #region Plugin Referenced Assemblies Resolving
public static Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args) public static Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args)
+5 -22
View File
@@ -45,13 +45,17 @@ namespace Disco.Services.Plugins
} }
this.Status.Finished("Restarting Disco, please wait...", "/Config/Plugins"); this.Status.Finished("Restarting Disco, please wait...", "/Config/Plugins");
RestartApp(1500); Plugins.RestartApp(1500);
} }
public static ScheduledTaskStatus UninstallPlugin(PluginManifest Manifest, bool UninstallData) public static ScheduledTaskStatus UninstallPlugin(PluginManifest Manifest, bool UninstallData)
{ {
if (ScheduledTasks.GetTaskStatuses(typeof(InstallPluginTask)).Where(s => s.IsRunning).Count() > 0) if (ScheduledTasks.GetTaskStatuses(typeof(InstallPluginTask)).Where(s => s.IsRunning).Count() > 0)
throw new InvalidOperationException("A plugin is already being Uninstalled"); throw new InvalidOperationException("A plugin is already being Uninstalled");
if (ScheduledTasks.GetTaskStatuses(typeof(UpdatePluginTask)).Where(s => s.IsRunning).Count() > 0)
throw new InvalidOperationException("A plugin is being Updated");
if (ScheduledTasks.GetTaskStatuses(typeof(InstallPluginTask)).Where(s => s.IsRunning).Count() > 0)
throw new InvalidOperationException("A plugin is being Installed");
JobDataMap taskData = new JobDataMap() { { "PluginManifest", Manifest }, { "UninstallData", UninstallData } }; JobDataMap taskData = new JobDataMap() { { "PluginManifest", Manifest }, { "UninstallData", UninstallData } };
@@ -59,26 +63,5 @@ namespace Disco.Services.Plugins
return instance.ScheduleTask(taskData); return instance.ScheduleTask(taskData);
} }
#region Restart App
private static object _restartTimerLock = new object();
private static Timer _restartTimer;
private void RestartApp(int DelayMilliseconds)
{
lock (_restartTimerLock)
{
if (_restartTimer != null)
{
_restartTimer.Dispose();
}
_restartTimer = new Timer((state) =>
{
HttpRuntime.UnloadAppDomain();
//AppDomain.Unload(AppDomain.CurrentDomain);
}, null, DelayMilliseconds, Timeout.Infinite);
}
}
#endregion
} }
} }
+252
View File
@@ -0,0 +1,252 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Net;
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
{
public class UpdatePluginTask : ScheduledTask
{
public override string TaskName { get { return "Updating Plugin/s"; } }
protected override void ExecuteTask()
{
string pluginId = (string)this.ExecutionContext.JobDetail.JobDataMap["PluginId"];
string packageFilePath = (string)this.ExecutionContext.JobDetail.JobDataMap["PackageFilePath"];
PluginLibraryUpdateResponse catalogue;
string pluginPackagesLocation;
if (!Plugins.PluginsLoaded)
throw new InvalidOperationException("Plugins have not been initialized");
List<Tuple<PluginManifest, string, PluginLibraryItem>> updatePlugins;
using (DiscoDataContext dbContext = new DiscoDataContext())
{
catalogue = Plugins.LoadCatalogue(dbContext);
pluginPackagesLocation = dbContext.DiscoConfiguration.PluginPackagesLocation;
}
if (!string.IsNullOrEmpty(pluginId))
{
if (string.IsNullOrEmpty(packageFilePath))
{
// Update Single from Catalogue
PluginManifest existingManifest = Plugins.GetPlugin(pluginId);
var catalogueItem = catalogue.Plugins.FirstOrDefault(p => p.Id == existingManifest.Id);
if (catalogueItem == null)
throw new InvalidOperationException("No updates are available for this Plugin");
if (Version.Parse(catalogueItem.LatestVersion) <= existingManifest.Version)
throw new InvalidOperationException("Only newer versions can be used to update a plugin");
updatePlugins = new List<Tuple<PluginManifest, string, PluginLibraryItem>>() {
new Tuple<PluginManifest,string,PluginLibraryItem>(existingManifest, null, catalogueItem)
};
}
else
{
// Update Single from Local
PluginManifest existingManifest = Plugins.GetPlugin(pluginId);
updatePlugins = new List<Tuple<PluginManifest, string, PluginLibraryItem>>() {
new Tuple<PluginManifest,string,PluginLibraryItem>(existingManifest, packageFilePath, null)
};
}
}
else
{
// 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();
}
if (updatePlugins == null || updatePlugins.Count == 0)
{
this.Status.Finished("No plugins to update...", "/Config/Plugins");
return;
}
ExecuteTaskInternal(this.Status, pluginPackagesLocation, updatePlugins);
this.Status.Finished("Restarting Disco, please wait...", "/Config/Plugins");
Plugins.RestartApp(1500);
}
internal static void UpdateOffline(ScheduledTaskStatus Status)
{
string pluginsLocation;
string pluginPackagesLocation;
PluginLibraryUpdateResponse pluginCatalogue;
List<Tuple<PluginManifest, string, PluginLibraryItem>> UpdatePlugins = new List<Tuple<PluginManifest, string, PluginLibraryItem>>();
using (DiscoDataContext dbContext = new DiscoDataContext())
{
pluginCatalogue = Plugins.LoadCatalogue(dbContext);
pluginsLocation = dbContext.DiscoConfiguration.PluginsLocation;
pluginPackagesLocation = dbContext.DiscoConfiguration.PluginPackagesLocation;
}
DirectoryInfo pluginDirectoryRoot = new DirectoryInfo(pluginsLocation);
if (pluginDirectoryRoot.Exists)
{
foreach (DirectoryInfo pluginDirectory in pluginDirectoryRoot.EnumerateDirectories())
{
string pluginManifestFilename = Path.Combine(pluginDirectory.FullName, "manifest.json");
if (File.Exists(pluginManifestFilename))
{
PluginManifest pluginManifest = null;
try
{
pluginManifest = PluginManifest.FromPluginManifestFile(pluginManifestFilename);
}
catch (Exception) { }
if (pluginManifest != null)
{
// Check for Update
var catalogueItem = pluginCatalogue.Plugins.FirstOrDefault(i => i.Id == pluginManifest.Id && Version.Parse(i.LatestVersion) > pluginManifest.Version);
if (catalogueItem != null)
{ // Update Available
UpdatePlugins.Add(new Tuple<PluginManifest, string, PluginLibraryItem>(pluginManifest, null, catalogueItem));
}
}
}
}
}
if (UpdatePlugins.Count > 0)
{
ExecuteTaskInternal(Status, pluginPackagesLocation, UpdatePlugins);
}
}
internal static void ExecuteTaskInternal(ScheduledTaskStatus Status, string pluginPackagesLocation, List<Tuple<PluginManifest, string, PluginLibraryItem>> UpdatePlugins)
{
while (UpdatePlugins.Count > 0)
{
var updatePlugin = UpdatePlugins[0];
var existingManifest = updatePlugin.Item1;
var packageTempFilePath = updatePlugin.Item2;
var catalogueItem = updatePlugin.Item3;
UpdatePlugins.Remove(updatePlugin);
var pluginId = existingManifest != null ? existingManifest.Id : catalogueItem.Id;
var pluginName = existingManifest != null ? existingManifest.Name : catalogueItem.Name;
if (string.IsNullOrEmpty(packageTempFilePath))
{
// Download Update
Status.UpdateStatus(0, string.Format("Downloading Plugin Package: {0}", pluginName), "Connecting...");
packageTempFilePath = Path.Combine(pluginPackagesLocation, string.Format("{0}.discoPlugin", pluginId));
if (File.Exists(packageTempFilePath))
File.Delete(packageTempFilePath);
if (!Directory.Exists(Path.GetDirectoryName(packageTempFilePath)))
Directory.CreateDirectory(Path.GetDirectoryName(packageTempFilePath));
// Need to Download the Package
WebClient downloader = new WebClient();
DateTime progressExpires = DateTime.Now;
downloader.DownloadProgressChanged += (sender, e) =>
{
Console.WriteLine(e.ProgressPercentage);
if (progressExpires <= DateTime.Now)
{
Status.UpdateStatus(e.ProgressPercentage, string.Format("{0} of {1} KB downloaded", e.BytesReceived / 1024, e.TotalBytesToReceive / 1024));
// Throttle Updates for SignalR
progressExpires = DateTime.Now.AddMilliseconds(250);
}
};
downloader.DownloadFileTaskAsync(new Uri(catalogueItem.LatestDownloadUrl), packageTempFilePath).Wait();
}
Status.UpdateStatus(10, "Opening Plugin Package", Path.GetFileName(packageTempFilePath));
PluginManifest updateManifest;
using (var packageStream = File.OpenRead(packageTempFilePath))
{
using (ZipArchive packageArchive = new ZipArchive(packageStream, ZipArchiveMode.Read, false))
{
ZipArchiveEntry packageManifestEntry = packageArchive.GetEntry("manifest.json");
if (packageManifestEntry == null)
throw new InvalidDataException("The plugin package does not contain the 'manifest.json' entry");
using (Stream packageManifestStream = packageManifestEntry.Open())
{
updateManifest = PluginManifest.FromPluginManifestFile(packageManifestStream);
}
}
}
// Ensure not already installed
if (existingManifest != null)
if (updateManifest.Version <= existingManifest.Version)
throw new InvalidOperationException("Only newer versions can be used to update a plugin");
Status.UpdateStatus(20, string.Format("{0} [{1} v{2}] by {3}", updateManifest.Name, updateManifest.Id, updateManifest.Version.ToString(4), updateManifest.Author), "Initializing Update Environment");
using (DiscoDataContext dbContext = new DiscoDataContext())
{
// Check for Compatibility
var compatibilityData = Plugins.LoadCompatibilityData(dbContext);
var pluginCompatibility = compatibilityData.Plugins.FirstOrDefault(i => i.Id.Equals(updateManifest.Id, StringComparison.InvariantCultureIgnoreCase) && updateManifest.Version == Version.Parse(i.Version));
if (pluginCompatibility != null && !pluginCompatibility.Compatible)
throw new InvalidOperationException(string.Format("The plugin [{0} v{1}] is not compatible: {2}", updateManifest.Id, updateManifest.VersionFormatted, pluginCompatibility.Reason));
var updatePluginPath = Path.Combine(dbContext.DiscoConfiguration.PluginsLocation, string.Format("{0}.discoPlugin", updateManifest.Id));
File.Move(packageTempFilePath, updatePluginPath);
if (existingManifest != null && Plugins.PluginsLoaded)
{
PluginsLog.LogBeforeUpdate(existingManifest, updateManifest);
existingManifest.BeforePluginUpdate(dbContext, updateManifest, Status);
}
}
}
}
private static ScheduledTaskStatus UpdateHelper(string PluginId = null, string PackageFilePath = null)
{
if (ScheduledTasks.GetTaskStatuses(typeof(UpdatePluginTask)).Where(s => s.IsRunning).Count() > 0)
throw new InvalidOperationException("A plugin is already being Updated");
if (ScheduledTasks.GetTaskStatuses(typeof(UninstallPluginTask)).Where(s => s.IsRunning).Count() > 0)
throw new InvalidOperationException("A plugin is being Uninstalled");
if (ScheduledTasks.GetTaskStatuses(typeof(InstallPluginTask)).Where(s => s.IsRunning).Count() > 0)
throw new InvalidOperationException("A plugin is being Installed");
JobDataMap taskData = new JobDataMap() { { "PluginId", PluginId }, { "PackageFilePath", PackageFilePath } };
var instance = new UpdatePluginTask();
return instance.ScheduleTask(taskData);
}
public static ScheduledTaskStatus UpdateLocalPlugin(string PluginId, string PackageFilePath)
{
return UpdateHelper(PluginId, PackageFilePath);
}
public static ScheduledTaskStatus UpdatePlugin(string PluginId)
{
return UpdateHelper(PluginId);
}
public static ScheduledTaskStatus UpdateAllPlugins()
{
return UpdateHelper();
}
}
}
@@ -0,0 +1,77 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Disco.Services.Tasks;
namespace Disco.Services.Plugins
{
public class UpdatePluginsAfterDiscoUpdateTask : ScheduledTask
{
private static object _startLock = new object();
public override string TaskName { get { return "Updating Disco Plugins"; } }
protected override void ExecuteTask()
{
this.Status.UpdateStatus(0, "Updating plugins after Disco update", "Starting, please wait...");
// Wait for App to Load (6 Seconds)
for (int i = 0; i < 10; i++)
{
this.Status.UpdateStatus(10 * i);
System.Threading.Thread.Sleep(600);
}
// Update Catalogue
CommunityInterop.PluginLibraryUpdateTask.ExecuteTaskInternal(this.Status);
// Update all Plugins
UpdatePluginTask.UpdateOffline(this.Status);
// Restart
this.Status.Finished("Restarting Disco, please wait...", "/");
Plugins.RestartApp(1500);
}
public static ScheduledTaskStatus UpdateDiscoPlugins(bool ReturnExistingStatusIfRunning)
{
if (ScheduledTasks.GetTaskStatuses(typeof(UpdatePluginTask)).Where(s => s.IsRunning).Count() > 0)
throw new InvalidOperationException("A plugin is already being Updated");
if (ScheduledTasks.GetTaskStatuses(typeof(UninstallPluginTask)).Where(s => s.IsRunning).Count() > 0)
throw new InvalidOperationException("A plugin is being Uninstalled");
if (ScheduledTasks.GetTaskStatuses(typeof(InstallPluginTask)).Where(s => s.IsRunning).Count() > 0)
throw new InvalidOperationException("A plugin is being Installed");
var existingTask = ScheduledTasks.GetTaskStatuses(typeof(UpdatePluginsAfterDiscoUpdateTask)).Where(s => s.IsRunning).FirstOrDefault();
if (existingTask != null)
{
if (ReturnExistingStatusIfRunning)
return existingTask;
else
throw new InvalidOperationException("Plugins are already being updated");
}
lock (_startLock)
{
existingTask = ScheduledTasks.GetTaskStatuses(typeof(UpdatePluginsAfterDiscoUpdateTask)).Where(s => s.IsRunning).FirstOrDefault();
if (existingTask != null)
{
if (ReturnExistingStatusIfRunning)
return existingTask;
else
throw new InvalidOperationException("Plugins are already being updated");
}
var instance = new UpdatePluginsAfterDiscoUpdateTask();
var status = instance.ScheduleTask();
// Give the scheduler a chance to start the task
System.Threading.Thread.Sleep(150);
return status;
}
}
}
}
+2 -2
View File
@@ -32,5 +32,5 @@ using System.Runtime.InteropServices;
// You can specify all the values or you can default the Build and Revision Numbers // You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below: // by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")] // [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.2.0212.1702")] [assembly: AssemblyVersion("1.2.0214.1848")]
[assembly: AssemblyFileVersion("1.2.0212.1702")] [assembly: AssemblyFileVersion("1.2.0214.1848")]
@@ -1,10 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Quartz;
namespace Disco.Services.Tasks
{
}
+193 -190
View File
@@ -1,190 +1,193 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
using Quartz; using Quartz;
using Quartz.Impl; using Quartz.Impl;
using Disco.Data.Repository; using Disco.Data.Repository;
namespace Disco.Services.Tasks namespace Disco.Services.Tasks
{ {
public static class ScheduledTasks public static class ScheduledTasks
{ {
internal const string SchedulerGroupName = "DiscoScheduledTasks"; internal const string SchedulerGroupName = "DiscoScheduledTasks";
private static IScheduler _TaskScheduler; private static IScheduler _TaskScheduler;
private static object _RunningTasksLock = new object(); private static object _RunningTasksLock = new object();
private static List<ScheduledTaskStatus> _RunningTasks = new List<ScheduledTaskStatus>(); private static List<ScheduledTaskStatus> _RunningTasks = new List<ScheduledTaskStatus>();
public static void InitalizeScheduledTasks(DiscoDataContext dbContext, ISchedulerFactory SchedulerFactory) public static void InitalizeScheduledTasks(DiscoDataContext dbContext, ISchedulerFactory SchedulerFactory, bool InitiallySchedule)
{ {
ScheduledTasksLog.LogInitializingScheduledTasks(); ScheduledTasksLog.LogInitializingScheduledTasks();
try try
{ {
_TaskScheduler = SchedulerFactory.GetScheduler(); _TaskScheduler = SchedulerFactory.GetScheduler();
_TaskScheduler.Start(); _TaskScheduler.Start();
// Scheduled Cleanup // Scheduled Cleanup
ScheduledTaskCleanup.Schedule(_TaskScheduler); ScheduledTaskCleanup.Schedule(_TaskScheduler);
// Discover DiscoScheduledTask if (InitiallySchedule)
var appDomain = AppDomain.CurrentDomain; {
// Discover DiscoScheduledTask
var scheduledTaskTypes = (from a in appDomain.GetAssemblies() var appDomain = AppDomain.CurrentDomain;
where !a.GlobalAssemblyCache && !a.IsDynamic
from type in a.GetTypes() var scheduledTaskTypes = (from a in appDomain.GetAssemblies()
where typeof(ScheduledTask).IsAssignableFrom(type) && !type.IsAbstract where !a.GlobalAssemblyCache && !a.IsDynamic
select type); from type in a.GetTypes()
foreach (Type scheduledTaskType in scheduledTaskTypes) where typeof(ScheduledTask).IsAssignableFrom(type) && !type.IsAbstract
{ select type);
ScheduledTask instance = (ScheduledTask)Activator.CreateInstance(scheduledTaskType); foreach (Type scheduledTaskType in scheduledTaskTypes)
try {
{ ScheduledTask instance = (ScheduledTask)Activator.CreateInstance(scheduledTaskType);
instance.InitalizeScheduledTask(dbContext); try
} {
catch (Exception ex) instance.InitalizeScheduledTask(dbContext);
{ }
ScheduledTasksLog.LogInitializeException(ex, scheduledTaskType); catch (Exception ex)
} {
} ScheduledTasksLog.LogInitializeException(ex, scheduledTaskType);
} }
catch (Exception ex) }
{ }
ScheduledTasksLog.LogInitializeException(ex); }
} catch (Exception ex)
{
} ScheduledTasksLog.LogInitializeException(ex);
}
public static ScheduledTaskStatus GetTaskStatus(string TaskSessionId)
{ }
return _RunningTasks.Where(t => t.SessionId == TaskSessionId).FirstOrDefault();
} public static ScheduledTaskStatus GetTaskStatus(string TaskSessionId)
public static List<ScheduledTaskStatus> GetTaskStatuses(Type TaskType) {
{ return _RunningTasks.Where(t => t.SessionId == TaskSessionId).FirstOrDefault();
return _RunningTasks.Where(t => t.TaskType == TaskType).ToList(); }
} public static List<ScheduledTaskStatus> GetTaskStatuses(Type TaskType)
public static List<ScheduledTaskStatus> GetTaskStatuses() {
{ return _RunningTasks.Where(t => t.TaskType == TaskType).ToList();
return _RunningTasks.ToList(); }
} public static List<ScheduledTaskStatus> GetTaskStatuses()
{
public static ScheduledTaskStatus RegisterTask(ScheduledTask Task) return _RunningTasks.ToList();
{ }
return RegisterTask(Task, null);
} public static ScheduledTaskStatus RegisterTask(ScheduledTask Task)
public static ScheduledTaskStatus RegisterTask(ScheduledTask Task, TriggerBuilder TaskBuilder) {
{ return RegisterTask(Task, null);
var sessionId = Guid.NewGuid().ToString("D"); }
var triggerKey = GenerateTriggerKey(); public static ScheduledTaskStatus RegisterTask(ScheduledTask Task, TriggerBuilder TaskBuilder)
var taskType = Task.GetType(); {
var sessionId = Guid.NewGuid().ToString("D");
var taskStatus = new ScheduledTaskStatus(Task, sessionId, triggerKey.Name); var triggerKey = GenerateTriggerKey();
var taskType = Task.GetType();
lock (_RunningTasksLock)
{ var taskStatus = new ScheduledTaskStatus(Task, sessionId, triggerKey.Name);
if (Task.SingleInstanceTask)
{ lock (_RunningTasksLock)
var existingGuid = _RunningTasks.Where(t => t.IsRunning && t.TaskType == taskType).Select(t => t.SessionId).FirstOrDefault(); {
if (existingGuid != null) if (Task.SingleInstanceTask)
throw new InvalidOperationException(string.Format("This Single-Instance Task is already running, SessionId: {0}", existingGuid)); {
} var existingGuid = _RunningTasks.Where(t => t.IsRunning && t.TaskType == taskType).Select(t => t.SessionId).FirstOrDefault();
_RunningTasks.Add(taskStatus); if (existingGuid != null)
} throw new InvalidOperationException(string.Format("This Single-Instance Task is already running, SessionId: {0}", existingGuid));
}
if (TaskBuilder != null) _RunningTasks.Add(taskStatus);
{ }
ITrigger trigger = TaskBuilder.WithIdentity(triggerKey).Build();
IJobDetail jobDetails = new JobDetailImpl(sessionId, taskType) if (TaskBuilder != null)
{ {
Description = Task.TaskName, ITrigger trigger = TaskBuilder.WithIdentity(triggerKey).Build();
JobDataMap = trigger.JobDataMap IJobDetail jobDetails = new JobDetailImpl(sessionId, taskType)
}; {
Description = Task.TaskName,
_TaskScheduler.ScheduleJob(jobDetails, trigger); JobDataMap = trigger.JobDataMap
};
var nextTriggerTime = trigger.GetNextFireTimeUtc();
if (nextTriggerTime.HasValue) _TaskScheduler.ScheduleJob(jobDetails, trigger);
taskStatus.SetNextScheduledTimestamp(nextTriggerTime.Value.LocalDateTime);
} var nextTriggerTime = trigger.GetNextFireTimeUtc();
if (nextTriggerTime.HasValue)
return taskStatus; taskStatus.SetNextScheduledTimestamp(nextTriggerTime.Value.LocalDateTime);
} }
public static bool UnregisterTask(this ScheduledTask Task)
{ return taskStatus;
lock (_RunningTasksLock) }
{ public static bool UnregisterTask(this ScheduledTask Task)
if (_RunningTasks.Contains(Task.Status)) {
{ lock (_RunningTasksLock)
//_RunningTasks.Remove(Task.Status); {
_TaskScheduler.UnscheduleJob(Task.ExecutionContext.Trigger.Key); if (_RunningTasks.Contains(Task.Status))
return true; {
} //_RunningTasks.Remove(Task.Status);
} _TaskScheduler.UnscheduleJob(Task.ExecutionContext.Trigger.Key);
return false; return true;
} }
public static bool UnregisterTask(this ScheduledTaskStatus TaskStatus) }
{ return false;
lock (_RunningTasksLock) }
{ public static bool UnregisterTask(this ScheduledTaskStatus TaskStatus)
if (_RunningTasks.Contains(TaskStatus)) {
{ lock (_RunningTasksLock)
//_RunningTasks.Remove(Task.Status); {
_TaskScheduler.UnscheduleJob(new TriggerKey(TaskStatus.TriggerKey, SchedulerGroupName)); if (_RunningTasks.Contains(TaskStatus))
return true; {
} //_RunningTasks.Remove(Task.Status);
} _TaskScheduler.UnscheduleJob(new TriggerKey(TaskStatus.TriggerKey, SchedulerGroupName));
return false; return true;
} }
}
public static TriggerKey GenerateTriggerKey() return false;
{ }
return new TriggerKey(Guid.NewGuid().ToString("D"), SchedulerGroupName);
} public static TriggerKey GenerateTriggerKey()
{
public static ScheduledTaskStatus GetDiscoScheduledTaskStatus(this IJobExecutionContext context) return new TriggerKey(Guid.NewGuid().ToString("D"), SchedulerGroupName);
{ }
return GetTaskStatus(context.JobDetail.Key.Name);
} public static ScheduledTaskStatus GetDiscoScheduledTaskStatus(this IJobExecutionContext context)
{
private class ScheduledTaskCleanup : IJob return GetTaskStatus(context.JobDetail.Key.Name);
{ }
public void Execute(IJobExecutionContext context)
{ private class ScheduledTaskCleanup : IJob
lock (ScheduledTasks._RunningTasksLock) {
{ public void Execute(IJobExecutionContext context)
// Lifetime = 5mins {
var expiredTime = DateTime.Now.AddMinutes(-1); lock (ScheduledTasks._RunningTasksLock)
var expiredTasks = ScheduledTasks._RunningTasks.Where( {
t => !t.IsRunning && // Lifetime = 5mins
!t.NextScheduledTimestamp.HasValue && var expiredTime = DateTime.Now.AddMinutes(-1);
t.FinishedTimestamp < expiredTime var expiredTasks = ScheduledTasks._RunningTasks.Where(
).ToArray(); t => !t.IsRunning &&
!t.NextScheduledTimestamp.HasValue &&
foreach (var expiredTask in expiredTasks) t.FinishedTimestamp < expiredTime
ScheduledTasks._RunningTasks.Remove(expiredTask); ).ToArray();
}
} foreach (var expiredTask in expiredTasks)
public static void Schedule(IScheduler TaskScheduler) ScheduledTasks._RunningTasks.Remove(expiredTask);
{ }
// Next 10min interval }
DateTime now = DateTime.Now; public static void Schedule(IScheduler TaskScheduler)
int mins = (10 - (now.Minute % 10)); {
if (mins < 2) // Next 10min interval
mins += 10; DateTime now = DateTime.Now;
DateTimeOffset startAt = new DateTimeOffset(now).AddMinutes(mins).AddSeconds(now.Second * -1).AddMilliseconds(now.Millisecond * -1); int mins = (10 - (now.Minute % 10));
ITrigger trigger = TriggerBuilder.Create() if (mins < 2)
.StartAt(startAt) mins += 10;
.WithSchedule(SimpleScheduleBuilder.RepeatMinutelyForever(10)) DateTimeOffset startAt = new DateTimeOffset(now).AddMinutes(mins).AddSeconds(now.Second * -1).AddMilliseconds(now.Millisecond * -1);
.WithIdentity("ScheduledTaskCleanupTrigger", ScheduledTasks.SchedulerGroupName + "_System") ITrigger trigger = TriggerBuilder.Create()
.Build(); .StartAt(startAt)
.WithSchedule(SimpleScheduleBuilder.RepeatMinutelyForever(10))
IJobDetail job = JobBuilder.Create<ScheduledTaskCleanup>() .WithIdentity("ScheduledTaskCleanupTrigger", ScheduledTasks.SchedulerGroupName + "_System")
.WithIdentity("ScheduledTaskCleanupJob", ScheduledTasks.SchedulerGroupName + "_System") .Build();
.Build();
IJobDetail job = JobBuilder.Create<ScheduledTaskCleanup>()
_TaskScheduler.ScheduleJob(job, trigger); .WithIdentity("ScheduledTaskCleanupJob", ScheduledTasks.SchedulerGroupName + "_System")
} .Build();
}
} _TaskScheduler.ScheduleJob(job, trigger);
} }
}
}
}
@@ -1,134 +1,135 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Security.Cryptography; using System.Security.Cryptography;
using System.Text; using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
using System.Web; using System.Web;
namespace Disco.Web.Extensions.MvcExtensions.Bundles namespace Disco.Web.Extensions.MvcExtensions.Bundles
{ {
public class Bundle public class Bundle
{ {
private DateTime? _FileLastModified { get; set; } private DateTime? _FileLastModified { get; set; }
private string _FileHash { get; set; } private string _FileHash { get; set; }
private string _VersionUrl { get; set; } private string _VersionUrl { get; set; }
public string Url { get; private set; } public string Url { get; private set; }
public string File { get; private set; } public string File { get; private set; }
public string FileHash public string FileHash
{ {
get get
{ {
#if DEBUG #if DEBUG
UpdateFileHash(); UpdateFileHash();
#endif #endif
return _FileHash; return _FileHash;
} }
} }
public string ContentType { get; private set; } public string ContentType { get; private set; }
public string VersionUrl public string VersionUrl
{ {
get get
{ {
#if DEBUG #if DEBUG
return string.Format("{0}?v={1}", this.Url, this.FileHash); return string.Format("{0}?v={1}", this.Url, this.FileHash);
#else #else
return _VersionUrl; return _VersionUrl;
#endif #endif
} }
} }
public Bundle(string Url, string File) public Bundle(string Url, string File)
{ {
if (string.IsNullOrWhiteSpace(Url)) if (string.IsNullOrWhiteSpace(Url))
throw new ArgumentNullException("Url"); throw new ArgumentNullException("Url");
if (string.IsNullOrWhiteSpace(File)) if (string.IsNullOrWhiteSpace(File))
throw new ArgumentNullException("File"); throw new ArgumentNullException("File");
Uri fileUri; Uri fileUri;
if (!Uri.TryCreate(File, UriKind.Absolute, out fileUri)) if (!Uri.TryCreate(File, UriKind.Absolute, out fileUri))
{ {
File = HttpContext.Current.Server.MapPath(File); File = HttpContext.Current.Server.MapPath(File);
} }
var fileInfo = new FileInfo(File); var fileInfo = new FileInfo(File);
if (!fileInfo.Exists) if (!fileInfo.Exists)
throw new FileNotFoundException(string.Format("Not Found: {0}", File), File); throw new FileNotFoundException(string.Format("Not Found: {0}", File), File);
this.Url = Url; this.Url = Url;
this.File = File; this.File = File;
switch (fileInfo.Extension.ToLower()) switch (fileInfo.Extension.ToLower())
{ {
case ".css": case ".css":
this.ContentType = "text/css"; this.ContentType = "text/css";
break; break;
case ".js": case ".js":
this.ContentType = "text/javascript"; this.ContentType = "text/javascript";
break; break;
default: default:
throw new ArgumentException("Unsupported Bundle File Extension"); throw new ArgumentException("Unsupported Bundle File Extension");
} }
// Write File Hash // Write File Hash
if (fileInfo.Length > 0) if (fileInfo.Length > 0)
UpdateFileHash(); UpdateFileHash();
else else
this._FileHash = string.Empty; this._FileHash = string.Empty;
//this.Version = fileInfo.LastWriteTimeUtc.Ticks; //this.Version = fileInfo.LastWriteTimeUtc.Ticks;
this._VersionUrl = string.Format("{0}?v={1}", this.Url, this.FileHash); this._VersionUrl = string.Format("{0}?v={1}", this.Url, this.FileHash);
} }
private void UpdateFileHash() private void UpdateFileHash()
{ {
if (System.IO.File.Exists(this.File)) if (System.IO.File.Exists(this.File))
{ {
var fileLastModified = System.IO.File.GetLastWriteTimeUtc(this.File); var fileLastModified = System.IO.File.GetLastWriteTimeUtc(this.File);
if (!this._FileLastModified.HasValue || this._FileLastModified.Value != fileLastModified) if (!this._FileLastModified.HasValue || this._FileLastModified.Value != fileLastModified)
{ {
this._FileLastModified = fileLastModified; this._FileLastModified = fileLastModified;
var fileBytes = System.IO.File.ReadAllBytes(this.File); var fileBytes = System.IO.File.ReadAllBytes(this.File);
if (fileBytes.Length > 0) if (fileBytes.Length > 0)
{ {
using (SHA256 sha = SHA256.Create()) using (SHA256 sha = SHA256.Create())
{ {
byte[] hash = sha.ComputeHash(fileBytes); byte[] hash = sha.ComputeHash(fileBytes);
this._FileHash = HttpServerUtility.UrlTokenEncode(hash); this._FileHash = HttpServerUtility.UrlTokenEncode(hash);
return; return;
} }
} }
} }
else else
{ {
// Already Updated // Already Updated
return; return;
} }
} }
this._FileHash = string.Empty; this._FileHash = string.Empty;
} }
internal void ProcessRequest(HttpContext context) internal void ProcessRequest(HttpContext context)
{ {
// Write Content Type // Write Content Type
context.Response.ContentType = this.ContentType; context.Response.ContentType = this.ContentType;
// Write Headers // Write Headers
var cache = context.Response.Cache; var cache = context.Response.Cache;
cache.SetCacheability(HttpCacheability.Public); cache.SetCacheability(HttpCacheability.Public);
cache.SetOmitVaryStar(true); cache.SetOmitVaryStar(true);
cache.SetExpires(DateTime.Now.AddYears(1)); cache.SetExpires(DateTime.Now.AddYears(1));
cache.SetValidUntilExpires(true); cache.SetValidUntilExpires(true);
cache.SetLastModified(DateTime.Now); cache.SetMaxAge(TimeSpan.FromDays(365));
cache.VaryByHeaders["User-Agent"] = true; cache.SetLastModified(DateTime.Now);
cache.VaryByHeaders["User-Agent"] = true;
// Write File
context.Response.WriteFile(this.File); // Write File
} context.Response.WriteFile(this.File);
} }
} }
}
@@ -1,52 +1,52 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
using System.Web; using System.Web;
namespace Disco.Web.Extensions.MvcExtensions.Bundles namespace Disco.Web.Extensions.MvcExtensions.Bundles
{ {
internal sealed class BundleHandler : IHttpHandler internal sealed class BundleHandler : IHttpHandler
{ {
public Bundle RequestBundle { get; private set; } public Bundle RequestBundle { get; private set; }
public string BundleVirtualPath { get; private set; } public string BundleVirtualPath { get; private set; }
public BundleHandler(Bundle requestBundle, string bundleVirtualPath) public BundleHandler(Bundle requestBundle, string bundleVirtualPath)
{ {
this.RequestBundle = requestBundle; this.RequestBundle = requestBundle;
this.BundleVirtualPath = bundleVirtualPath; this.BundleVirtualPath = bundleVirtualPath;
} }
public bool IsReusable public bool IsReusable
{ {
get { return false; } get { return false; }
} }
public void ProcessRequest(HttpContext context) public void ProcessRequest(HttpContext context)
{ {
context.Response.Clear(); context.Response.Clear();
if (!string.IsNullOrEmpty(context.Request.Headers["If-Modified-Since"])) if (!string.IsNullOrEmpty(context.Request.Headers["If-Modified-Since"]))
context.Response.StatusCode = 0x130; context.Response.StatusCode = 304;
else else
this.RequestBundle.ProcessRequest(context); this.RequestBundle.ProcessRequest(context);
} }
internal static bool RemapHandlerForBundleRequests(HttpApplication app) internal static bool RemapHandlerForBundleRequests(HttpApplication app)
{ {
var context = app.Context; var context = app.Context;
string bundleUrlFromContext = context.Request.AppRelativeCurrentExecutionFilePath + context.Request.PathInfo; string bundleUrlFromContext = context.Request.AppRelativeCurrentExecutionFilePath + context.Request.PathInfo;
var bundle = BundleTable.GetBundleFor(bundleUrlFromContext); var bundle = BundleTable.GetBundleFor(bundleUrlFromContext);
if (bundle != null) if (bundle != null)
{ {
context.RemapHandler(new BundleHandler(bundle, bundleUrlFromContext)); context.RemapHandler(new BundleHandler(bundle, bundleUrlFromContext));
return true; return true;
} }
return false; return false;
} }
} }
} }
@@ -32,5 +32,5 @@ using System.Runtime.InteropServices;
// You can specify all the values or you can default the Build and Revision Numbers // You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below: // by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")] // [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.2.0212.1702")] [assembly: AssemblyVersion("1.2.0214.1848")]
[assembly: AssemblyFileVersion("1.2.0212.1702")] [assembly: AssemblyFileVersion("1.2.0214.1848")]
+105 -88
View File
@@ -1,89 +1,106 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Web; using System.Web;
using Disco.Data.Repository; using Disco.Data.Repository;
namespace Disco.Web namespace Disco.Web
{ {
public static class AppConfig public static class AppConfig
{ {
public static bool InitializeDatabase() public static bool InitializeDatabase()
{ {
// Modified Connection Factory // Modified Connection Factory
System.Data.Entity.Database.DefaultConnectionFactory = new DiscoDatabaseConnectionFactory(System.Data.Entity.Database.DefaultConnectionFactory); System.Data.Entity.Database.DefaultConnectionFactory = new DiscoDatabaseConnectionFactory(System.Data.Entity.Database.DefaultConnectionFactory);
if (Disco.Data.Repository.DiscoDatabaseConnectionFactory.DiscoDataContextConnectionString == null) if (Disco.Data.Repository.DiscoDatabaseConnectionFactory.DiscoDataContextConnectionString == null)
{ {
// Database Connection String not configured - Trigger 'Install' // Database Connection String not configured - Trigger 'Install'
return false; return false;
} }
// Migrate Database // Migrate Database
Disco.Data.Migrations.DiscoDataMigrator.MigrateLatest(true); Disco.Data.Migrations.DiscoDataMigrator.MigrateLatest(true);
return true; return true;
} }
public static void InitalizeEnvironment() public static void InitalizeEnvironment()
{ {
using (var dbContext = new DiscoDataContext()) using (var dbContext = new DiscoDataContext())
{ {
// Initialize Logging // Initialize Logging
Disco.Services.Logging.LogContext.Initalize(dbContext, DiscoApplication.SchedulerFactory); Disco.Services.Logging.LogContext.Initalize(dbContext, DiscoApplication.SchedulerFactory);
// Load Organisation Name // Load Organisation Name
DiscoApplication.OrganisationName = dbContext.DiscoConfiguration.OrganisationName; DiscoApplication.OrganisationName = dbContext.DiscoConfiguration.OrganisationName;
DiscoApplication.MultiSiteMode = dbContext.DiscoConfiguration.MultiSiteMode; DiscoApplication.MultiSiteMode = dbContext.DiscoConfiguration.MultiSiteMode;
// Setup Global Proxy // Setup Global Proxy
DiscoApplication.SetGlobalProxy(dbContext.DiscoConfiguration.ProxyAddress, DiscoApplication.SetGlobalProxy(dbContext.DiscoConfiguration.ProxyAddress,
dbContext.DiscoConfiguration.ProxyPort, dbContext.DiscoConfiguration.ProxyPort,
dbContext.DiscoConfiguration.ProxyUsername, dbContext.DiscoConfiguration.ProxyUsername,
dbContext.DiscoConfiguration.ProxyPassword); dbContext.DiscoConfiguration.ProxyPassword);
// Initialize Expressions // Initialize Expressions
BI.Expressions.Expression.InitializeExpressions(); BI.Expressions.Expression.InitializeExpressions();
// Initialize Warranty Providers Plugins // Initialize Warranty Providers Plugins
Disco.Services.Plugins.Plugins.InitalizePlugins(dbContext); Disco.Services.Plugins.Plugins.InitalizePlugins(dbContext);
// Initialize Scheduled Tasks // Initialize Scheduled Tasks
Disco.Services.Tasks.ScheduledTasks.InitalizeScheduledTasks(dbContext, DiscoApplication.SchedulerFactory); Disco.Services.Tasks.ScheduledTasks.InitalizeScheduledTasks(dbContext, DiscoApplication.SchedulerFactory, true);
// Schedule Immediate Check for Update (if a new version was installed, never updated, last updated over 2 days ago) // Schedule Immediate Check for Update (if never updated, or last updated over 2 days ago)
var currentVersion = Disco.BI.Interop.Community.UpdateCheck.CurrentDiscoVersion(); if (dbContext.DiscoConfiguration.UpdateLastCheck == null ||
if (dbContext.DiscoConfiguration.InstalledDatabaseVersion == null || dbContext.DiscoConfiguration.UpdateLastCheck.ResponseTimestamp < DateTime.Now.AddDays(-2))
dbContext.DiscoConfiguration.InstalledDatabaseVersion != currentVersion || {
dbContext.DiscoConfiguration.UpdateLastCheck == null || Disco.BI.Interop.Community.UpdateCheckTask.ScheduleNow();
dbContext.DiscoConfiguration.UpdateLastCheck.ResponseTimestamp < DateTime.Now.AddDays(-2)) }
{
Disco.BI.Interop.Community.UpdateCheckTask.ScheduleNow(); // Setup Attachment Monitor
dbContext.DiscoConfiguration.InstalledDatabaseVersion = currentVersion; DiscoApplication.DocumentDropBoxMonitor = new BI.DocumentTemplateBI.Importer.DocumentDropBoxMonitor(dbContext, DiscoApplication.SchedulerFactory, HttpContext.Current.Cache);
dbContext.SaveChanges(); }
} DiscoApplication.DocumentDropBoxMonitor.StartWatching();
DiscoApplication.DocumentDropBoxMonitor.ScheduleCurrentFiles(10);
// Setup Attachment Monitor }
DiscoApplication.DocumentDropBoxMonitor = new BI.DocumentTemplateBI.Importer.DocumentDropBoxMonitor(dbContext, DiscoApplication.SchedulerFactory, HttpContext.Current.Cache);
} public static void InitializeUpdateEnvironment()
DiscoApplication.DocumentDropBoxMonitor.StartWatching(); {
DiscoApplication.DocumentDropBoxMonitor.ScheduleCurrentFiles(10); using (var dbContext = new DiscoDataContext())
} {
// Initialize Logging
public static void DisposeEnvironment() Disco.Services.Logging.LogContext.Initalize(dbContext, DiscoApplication.SchedulerFactory);
{
if (DiscoApplication.DocumentDropBoxMonitor != null) // Load Organisation Name
DiscoApplication.DocumentDropBoxMonitor.Dispose(); DiscoApplication.OrganisationName = dbContext.DiscoConfiguration.OrganisationName;
DiscoApplication.MultiSiteMode = dbContext.DiscoConfiguration.MultiSiteMode;
if (DiscoApplication.SchedulerFactory != null)
{ // Setup Global Proxy
foreach (var item in DiscoApplication.SchedulerFactory.AllSchedulers.ToArray()) DiscoApplication.SetGlobalProxy(dbContext.DiscoConfiguration.ProxyAddress,
{ dbContext.DiscoConfiguration.ProxyPort,
item.Shutdown(false); dbContext.DiscoConfiguration.ProxyUsername,
} dbContext.DiscoConfiguration.ProxyPassword);
}
// Initialize Scheduled Tasks
Disco.Services.Logging.SystemLog.LogUninitialized(); Disco.Services.Tasks.ScheduledTasks.InitalizeScheduledTasks(dbContext, DiscoApplication.SchedulerFactory, true);
} }
} }
public static void DisposeEnvironment()
{
if (DiscoApplication.DocumentDropBoxMonitor != null)
DiscoApplication.DocumentDropBoxMonitor.Dispose();
if (DiscoApplication.SchedulerFactory != null)
{
foreach (var item in DiscoApplication.SchedulerFactory.AllSchedulers.ToArray())
{
item.Shutdown(false);
}
}
Disco.Services.Logging.SystemLog.LogUninitialized();
}
}
} }
+82 -71
View File
@@ -1,72 +1,83 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Web; using System.Web;
using System.Web.Mvc; using System.Web.Mvc;
using System.Web.Routing; using System.Web.Routing;
namespace Disco.Web namespace Disco.Web
{ {
public class RouteConfig public class RouteConfig
{ {
public static void RegisterInstallRoutes(RouteCollection routes) public static void RegisterInstallRoutes(RouteCollection routes)
{ {
// Install Route // Install Route
routes.MapRoute( routes.MapRoute(
name: "InitialConfig", // Route name name: "InitialConfig", // Route name
url: "{controller}/{action}/{id}", // URL with parameters url: "{controller}/{action}/{id}", // URL with parameters
defaults: new { controller = "InitialConfig", action = "Index", id = UrlParameter.Optional }, // Parameter defaults defaults: new { controller = "InitialConfig", action = "Index", id = UrlParameter.Optional }, // Parameter defaults
namespaces: new string[] { "Disco.Web.Controllers" } // Controllers Namespace Only namespaces: new string[] { "Disco.Web.Controllers" } // Controllers Namespace Only
); );
} }
public static void RegisterRoutes(RouteCollection routes) public static void RegisterRoutes(RouteCollection routes)
{ {
routes.IgnoreRoute("{resource}.axd/{*pathInfo}"); routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
// Device Route // Device Route
routes.MapRoute( routes.MapRoute(
name: "Device", // Route name name: "Device", // Route name
url: "Device/{action}/{id}", // URL with parameters url: "Device/{action}/{id}", // URL with parameters
defaults: new { controller = "Device", action = "Index", id = UrlParameter.Optional }, // Parameter defaults defaults: new { controller = "Device", action = "Index", id = UrlParameter.Optional }, // Parameter defaults
namespaces: new string[] { "Disco.Web.Controllers" } // Controllers Namespace Only namespaces: new string[] { "Disco.Web.Controllers" } // Controllers Namespace Only
); );
// Search Route // Search Route
routes.MapRoute( routes.MapRoute(
name: "SearchQuery", name: "SearchQuery",
url: "Search/Query/{SearchQuery}", url: "Search/Query/{SearchQuery}",
defaults: new { controller = "Search", action = "Query", SearchQuery = UrlParameter.Optional } defaults: new { controller = "Search", action = "Query", SearchQuery = UrlParameter.Optional }
); );
// User Route // User Route
routes.MapRoute( routes.MapRoute(
name: "User", // Route name name: "User", // Route name
url: "User/{action}/{id}", // URL with parameters url: "User/{action}/{id}", // URL with parameters
defaults: new { controller = "User", action = "Index", id = UrlParameter.Optional }, // Parameter defaults defaults: new { controller = "User", action = "Index", id = UrlParameter.Optional }, // Parameter defaults
namespaces: new string[] { "Disco.Web.Controllers" } // Controllers Namespace Only namespaces: new string[] { "Disco.Web.Controllers" } // Controllers Namespace Only
); );
// Plugin Resources Route // Plugin Resources Route
routes.MapRoute( routes.MapRoute(
name: "Plugin_Resources", // Route name name: "Plugin_Resources", // Route name
url: "Plugin/{PluginId}/Resources/{*res}", // URL with parameters url: "Plugin/{PluginId}/Resources/{*res}", // URL with parameters
defaults: new { controller = "PluginWebHandler", action = "Resource" }, // Parameter defaults defaults: new { controller = "PluginWebHandler", action = "Resource" }, // Parameter defaults
namespaces: new string[] { "Disco.Web.Controllers" } // Controllers Namespace Only namespaces: new string[] { "Disco.Web.Controllers" } // Controllers Namespace Only
); );
// Plugin Route // Plugin Route
routes.MapRoute( routes.MapRoute(
name: "Plugin", // Route name name: "Plugin", // Route name
url: "Plugin/{PluginId}/{PluginAction}", // URL with parameters url: "Plugin/{PluginId}/{PluginAction}", // URL with parameters
defaults: new { controller = "PluginWebHandler", action = "Index" }, // Parameter defaults defaults: new { controller = "PluginWebHandler", action = "Index" }, // Parameter defaults
namespaces: new string[] { "Disco.Web.Controllers" } // Controllers Namespace Only namespaces: new string[] { "Disco.Web.Controllers" } // Controllers Namespace Only
); );
// Job Route // Job Route
routes.MapRoute( routes.MapRoute(
name: "Job", // Route name name: "Job", // Route name
url: "{controller}/{action}/{id}", // URL with parameters url: "{controller}/{action}/{id}", // URL with parameters
defaults: new { controller = "Job", action = "Index", id = UrlParameter.Optional }, // Parameter defaults defaults: new { controller = "Job", action = "Index", id = UrlParameter.Optional }, // Parameter defaults
namespaces: new string[] { "Disco.Web.Controllers" } // Controllers Namespace Only namespaces: new string[] { "Disco.Web.Controllers" } // Controllers Namespace Only
); );
} }
}
public static void RegisterUpdateRoutes(RouteCollection routes)
{
// Update Route
routes.MapRoute(
name: "Update", // Route name
url: "{controller}/{action}/{id}", // URL with parameters
defaults: new { controller = "Update", action = "Index", id = UrlParameter.Optional }, // Parameter defaults
namespaces: new string[] { "Disco.Web.Controllers" } // Controllers Namespace Only
);
}
}
} }
@@ -4,8 +4,8 @@ using System.IO;
using System.Linq; using System.Linq;
using System.Web; using System.Web;
using System.Web.Mvc; using System.Web.Mvc;
using Disco.BI.Interop.Community;
using Disco.Services.Plugins; using Disco.Services.Plugins;
using Disco.Services.Plugins.CommunityInterop;
namespace Disco.Web.Areas.API.Controllers namespace Disco.Web.Areas.API.Controllers
{ {
@@ -20,6 +20,46 @@ namespace Disco.Web.Areas.API.Controllers
return RedirectToAction(MVC.Config.Logging.TaskStatus(status.SessionId)); return RedirectToAction(MVC.Config.Logging.TaskStatus(status.SessionId));
} }
public virtual ActionResult UpdateAll()
{
var status = UpdatePluginTask.UpdateAllPlugins();
return RedirectToAction(MVC.Config.Logging.TaskStatus(status.SessionId));
}
public virtual ActionResult Update(string PluginId)
{
if (string.IsNullOrEmpty(PluginId))
throw new ArgumentNullException("PluginId");
var status = UpdatePluginTask.UpdatePlugin(PluginId);
return RedirectToAction(MVC.Config.Logging.TaskStatus(status.SessionId));
}
public virtual ActionResult UpdateLocal(string PluginId, HttpPostedFileBase Plugin)
{
if (string.IsNullOrEmpty(PluginId))
throw new ArgumentNullException("PluginId");
if (Plugin == null || Plugin.ContentLength <= 0 || string.IsNullOrWhiteSpace(Plugin.FileName))
throw new ArgumentException("A discoPlugin file must be uploaded", "Plugin");
var tempPluginLocation = Path.Combine(dbContext.DiscoConfiguration.PluginPackagesLocation, Path.GetFileName(Plugin.FileName));
if (!Directory.Exists(dbContext.DiscoConfiguration.PluginPackagesLocation))
Directory.CreateDirectory(dbContext.DiscoConfiguration.PluginPackagesLocation);
if (System.IO.File.Exists(tempPluginLocation))
System.IO.File.Delete(tempPluginLocation);
Plugin.SaveAs(tempPluginLocation);
var status = UpdatePluginTask.UpdateLocalPlugin(PluginId, tempPluginLocation);
return RedirectToAction(MVC.Config.Logging.TaskStatus(status.SessionId));
}
public virtual ActionResult Uninstall(string id, bool UninstallData) public virtual ActionResult Uninstall(string id, bool UninstallData)
{ {
if (string.IsNullOrEmpty(id)) if (string.IsNullOrEmpty(id))
@@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Web; using System.Web;
using System.Web.Mvc; using System.Web.Mvc;
using Disco.Models.BI.Interop.Community;
using Disco.Services.Plugins; using Disco.Services.Plugins;
using Disco.Services.Tasks; using Disco.Services.Tasks;
using Disco.Web.Areas.Config.Models.Plugins; using Disco.Web.Areas.Config.Models.Plugins;
@@ -16,7 +17,8 @@ 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(dbContext)
}; };
return View(vm); return View(vm);
} }
@@ -72,9 +74,9 @@ namespace Disco.Web.Areas.Config.Controllers
var catalogue = Plugins.LoadCatalogue(dbContext); var catalogue = Plugins.LoadCatalogue(dbContext);
if (catalogue == null || catalogue.ResponseTimestamp < DateTime.Now.AddMinutes(-15)) if (catalogue == null || catalogue.ResponseTimestamp < DateTime.Now.AddHours(-1))
{ {
// Need to Update Catalogue // Need to Update Catalogue (over 1 hour old)
return RedirectToAction(MVC.API.Plugin.UpdateLibraryCatalogue()); return RedirectToAction(MVC.API.Plugin.UpdateLibraryCatalogue());
} }
else else
@@ -1,52 +1,75 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Web; using System.Web;
using Disco.Services.Plugins; using Disco.Models.BI.Interop.Community;
using Disco.Services.Plugins.Features.Other; using Disco.Services.Plugins;
using Disco.Services.Plugins.Features.Other;
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 List<Tuple<Type, List<PluginManifest>>> PluginManifestsByType public PluginLibraryUpdateResponse Catalogue { get; set; }
{
get private Dictionary<PluginManifest, PluginLibraryItem> _PluginUpdates;
{ public Dictionary<PluginManifest, PluginLibraryItem> PluginUpdates
if (PluginManifests.Count == 0) {
return new List<Tuple<Type, List<PluginManifest>>>(); get
{
var categorisedManifests = PluginManifests.SelectMany(pm => pm.Features) if (_PluginUpdates == null)
.GroupBy(fm => fm.CategoryType) {
.Select(g => new Tuple<Type, List<PluginManifest>>(g.Key, g.Select(fm => fm.PluginManifest).Distinct().OrderBy(fm => fm.Name).ToList())).ToList(); if (Catalogue == null || Catalogue.Plugins == null || Catalogue.Plugins.Count == 0 ||
PluginManifests == null || PluginManifests.Count == 0)
// Ensure all plugins are represented {
var allCategorisedManifests = categorisedManifests.SelectMany(g => g.Item2).ToList(); _PluginUpdates = new Dictionary<PluginManifest, PluginLibraryItem>(); // No Updates
}
var unrepresentedPlugins = PluginManifests.Where(m => !allCategorisedManifests.Contains(m)).ToList(); else
if (unrepresentedPlugins.Count > 0) {
{ _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);
Tuple<Type, List<PluginManifest>> otherCategory = null; }
foreach (var category in categorisedManifests) }
{ return _PluginUpdates;
if (category.Item1 == typeof(OtherFeature)) }
{ }
otherCategory = category;
} public List<Tuple<Type, List<PluginManifest>>> PluginManifestsByType
} {
if (otherCategory == null) get
{ {
otherCategory = new Tuple<Type, List<PluginManifest>>(typeof(OtherFeature), new List<PluginManifest>()); if (PluginManifests.Count == 0)
categorisedManifests.Add(otherCategory); return new List<Tuple<Type, List<PluginManifest>>>();
}
foreach (var pluginManifest in unrepresentedPlugins) var categorisedManifests = PluginManifests.SelectMany(pm => pm.Features)
otherCategory.Item2.Add(pluginManifest); .GroupBy(fm => fm.CategoryType)
} .Select(g => new Tuple<Type, List<PluginManifest>>(g.Key, g.Select(fm => fm.PluginManifest).Distinct().OrderBy(fm => fm.Name).ToList())).ToList();
return categorisedManifests; // Ensure all plugins are represented
} var allCategorisedManifests = categorisedManifests.SelectMany(g => g.Item2).ToList();
}
} var unrepresentedPlugins = PluginManifests.Where(m => !allCategorisedManifests.Contains(m)).ToList();
if (unrepresentedPlugins.Count > 0)
{
Tuple<Type, List<PluginManifest>> otherCategory = null;
foreach (var category in categorisedManifests)
{
if (category.Item1 == typeof(OtherFeature))
{
otherCategory = category;
}
}
if (otherCategory == null)
{
otherCategory = new Tuple<Type, List<PluginManifest>>(typeof(OtherFeature), new List<PluginManifest>());
categorisedManifests.Add(otherCategory);
}
foreach (var pluginManifest in unrepresentedPlugins)
otherCategory.Item2.Add(pluginManifest);
}
return categorisedManifests;
}
}
}
} }
@@ -1,260 +1,256 @@
@model Disco.Web.Areas.Config.Models.Logging.TaskStatusModel @model Disco.Web.Areas.Config.Models.Logging.TaskStatusModel
@{ @{
ViewBag.Title = Html.ToBreadcrumb("Configuration", MVC.Config.Config.Index(), "Logging", MVC.Config.Logging.Index(), "Task Status"); ViewBag.Title = Html.ToBreadcrumb("Configuration", MVC.Config.Config.Index(), "Logging", MVC.Config.Logging.Index(), "Task Status");
Html.BundleDeferred("~/ClientScripts/Modules/Knockout"); Html.BundleDeferred("~/ClientScripts/Modules/Knockout");
Html.BundleDeferred("~/ClientScripts/Modules/jQuery-SignalR"); Html.BundleDeferred("~/ClientScripts/Modules/jQuery-SignalR");
} }
<div style="min-height: 300px;"> <div style="min-height: 300px;">
<div id="scheduledTaskStatus" class="form" style="width: 520px;" data-bind="visible: Initialized"> <div id="scheduledTaskStatus" class="form" style="width: 520px;" data-bind="visible: Initialized">
<h2 data-bind="text: TaskName"> <h2 data-bind="text: TaskName">&nbsp;</h2>
&nbsp;</h2> <table>
<table> <tr data-bind="visible: IsRunning">
<tr data-bind="visible: IsRunning"> <th class="process" data-bind="text: CurrentProcess">&nbsp;
<th class="process" data-bind="text: CurrentProcess"> </th>
&nbsp; </tr>
</th> <tr data-bind="visible: IsRunning">
</tr> <td class="description" data-bind="text: CurrentDescription">&nbsp;
<tr data-bind="visible: IsRunning"> </td>
<td class="description" data-bind="text: CurrentDescription"> </tr>
&nbsp; <tr data-bind="visible: IsRunning">
</td> <td class="progress">
</tr> <div data-bind="progressValue: Progress">
<tr data-bind="visible: IsRunning"> </div>
<td class="progress"> </td>
<div data-bind="progressValue: Progress"> </tr>
</div> <tr data-bind="visible: FinishedTimestamp">
</td> <td class="finishedTimestamp">
</tr> <h3>Finished: <span data-bind="text: FinishedTimestampFormatted"></span>
<tr data-bind="visible: FinishedTimestamp"> </h3>
<td class="finishedTimestamp"> </td>
<h3> </tr>
Finished: <span data-bind="text: FinishedTimestampFormatted"></span> <tr data-bind="visible: FinishedTimestamp() && !TaskExceptionMessage()">
</h3> <td class="finishedMessage" data-bind="css: {finishedRedirect: FinishedUrl}">
</td> <span data-bind="text: FinishedMessage"></span>
</tr> </td>
<tr data-bind="visible: FinishedTimestamp() && !TaskExceptionMessage()"> </tr>
<td class="finishedMessage" data-bind="css: {finishedRedirect: FinishedUrl}"> <tr data-bind="visible: TaskExceptionMessage">
<span data-bind="text: FinishedMessage"></span> <td class="exception">Last Error:
</td> <div class="code" data-bind="text: TaskExceptionMessage">
</tr> </div>
<tr data-bind="visible: TaskExceptionMessage"> </td>
<td class="exception"> </tr>
Last Error: <tr data-bind="visible: NextScheduledTimestamp">
<div class="code" data-bind="text: TaskExceptionMessage"> <td class="nextScheduledTimestamp">Next Scheduled: <span data-bind="text: NextScheduledTimestampFormatted"></span>
</div> </td>
</td> </tr>
</tr> </table>
<tr data-bind="visible: NextScheduledTimestamp"> </div>
<td class="nextScheduledTimestamp"> </div>
Next Scheduled: <span data-bind="text: NextScheduledTimestampFormatted"></span> <script type="text/javascript">
</td> ko.bindingHandlers.progressValue = {
</tr> init: function (element, valueAccessor, allBindingsAccessor, viewModel) {
</table> var $element = $(element);
</div> if (!$element.is('.ui-progressbar'))
</div> $element.progressbar();
<script type="text/javascript"> },
ko.bindingHandlers.progressValue = { update: function (element, valueAccessor, allBindingsAccessor, viewModel) {
init: function (element, valueAccessor, allBindingsAccessor, viewModel) { var v = ko.utils.unwrapObservable(valueAccessor());
var $element = $(element); var vInt = parseInt(v);
if (!$element.is('.ui-progressbar')) if (vInt >= 0) {
$element.progressbar(); $(element).progressbar('option', 'value', vInt);
}, }
update: function (element, valueAccessor, allBindingsAccessor, viewModel) { }
var v = ko.utils.unwrapObservable(valueAccessor()); };
var vInt = parseInt(v); //* http://webcloud.se/log/JavaScript-and-ISO-8601/
if (vInt >= 0) { Date.prototype.setISO8601 = function (string) {
$(element).progressbar('option', 'value', vInt); var regexp = "([0-9]{4})(-([0-9]{2})(-([0-9]{2})" +
} "(T([0-9]{2}):([0-9]{2})(:([0-9]{2})(\.([0-9]+))?)?" +
} "(Z|(([-+])([0-9]{2}):([0-9]{2})))?)?)?)?";
}; var d = string.match(new RegExp(regexp));
//* http://webcloud.se/log/JavaScript-and-ISO-8601/
Date.prototype.setISO8601 = function (string) { var offset = 0;
var regexp = "([0-9]{4})(-([0-9]{2})(-([0-9]{2})" + var date = new Date(d[1], 0, 1);
"(T([0-9]{2}):([0-9]{2})(:([0-9]{2})(\.([0-9]+))?)?" +
"(Z|(([-+])([0-9]{2}):([0-9]{2})))?)?)?)?"; if (d[3]) { date.setMonth(d[3] - 1); }
var d = string.match(new RegExp(regexp)); if (d[5]) { date.setDate(d[5]); }
if (d[7]) { date.setHours(d[7]); }
var offset = 0; if (d[8]) { date.setMinutes(d[8]); }
var date = new Date(d[1], 0, 1); if (d[10]) { date.setSeconds(d[10]); }
if (d[12]) { date.setMilliseconds(Number("0." + d[12]) * 1000); }
if (d[3]) { date.setMonth(d[3] - 1); } if (d[14]) {
if (d[5]) { date.setDate(d[5]); } offset = (Number(d[16]) * 60) + Number(d[17]);
if (d[7]) { date.setHours(d[7]); } offset *= ((d[15] == '-') ? 1 : -1);
if (d[8]) { date.setMinutes(d[8]); } }
if (d[10]) { date.setSeconds(d[10]); }
if (d[12]) { date.setMilliseconds(Number("0." + d[12]) * 1000); } offset -= date.getTimezoneOffset();
if (d[14]) { time = (Number(date) + (offset * 60 * 1000));
offset = (Number(d[16]) * 60) + Number(d[17]); this.setTime(Number(time));
offset *= ((d[15] == '-') ? 1 : -1); return this;
} }
</script>
offset -= date.getTimezoneOffset(); <script type="text/javascript">
time = (Number(date) + (offset * 60 * 1000)); $(function () {
this.setTime(Number(time)); var sessionId = '@(Model.SessionId)';
return this; var sessionStatusUrl = '@(Url.Action(MVC.API.Logging.ScheduledTaskStatus(Model.SessionId)))';
}
</script> var view = $('#scheduledTaskStatus');
<script type="text/javascript"> var vm = null;
$(function () {
var sessionId = '@(Model.SessionId)'; var liveConnection = null;
var sessionStatusUrl = '@(Url.Action(MVC.API.Logging.ScheduledTaskStatus(Model.SessionId)))';
var statusViewModel = function (sessionId) {
var view = $('#scheduledTaskStatus'); var self = this;
var vm = null;
self.Initialized = ko.observable(false);
var liveConnection = null;
self.TimestampParse = function (timestamp) {
var statusViewModel = function (sessionId) { if (timestamp) {
var self = this; if (timestamp.indexOf("\/Date(") == 0)
return new Date(parseInt(timestamp.substr(6)));
self.Initialized = ko.observable(false); else
return (new Date()).setISO8601(timestamp);
self.TimestampParse = function (timestamp) { }
if (timestamp) { return new Date();
if (timestamp.indexOf("\/Date(") == 0) }
return new Date(parseInt(timestamp.substr(6))); self.TimestampFormat = function (timestamp) {
else var addZero = function (v) { v = v + ''; if (v.length == 1) v = '0' + v; return v; }
return (new Date()).setISO8601(timestamp); return timestamp.getFullYear() + '/' + addZero((1 + timestamp.getMonth())) + '/' + addZero(timestamp.getDate()) + ' ' + addZero(timestamp.getHours()) + ':' + addZero(timestamp.getMinutes()) + ':' + addZero(timestamp.getSeconds());
} }
return new Date();
} self.SessionId = sessionId;
self.TimestampFormat = function (timestamp) { self.TaskName = ko.observable(null);
var addZero = function (v) { v = v + ''; if (v.length == 1) v = '0' + v; return v; } self.StatusVersion = -1;
return timestamp.getFullYear() + '/' + addZero((1 + timestamp.getMonth())) + '/' + addZero(timestamp.getDate()) + ' ' + addZero(timestamp.getHours()) + ':' + addZero(timestamp.getMinutes()) + ':' + addZero(timestamp.getSeconds());
} self.Progress = ko.observable(0);
self.CurrentProcess = ko.observable(null);
self.SessionId = sessionId; self.CurrentDescription = ko.observable(null);
self.TaskName = ko.observable(null);
self.StatusVersion = -1; self.IsRunning = ko.observable(null);
self.Progress = ko.observable(0); self.TaskExceptionMessage = ko.observable(null);
self.CurrentProcess = ko.observable(null);
self.CurrentDescription = ko.observable(null); self.FinishedTimestamp = ko.observable(null);
self.NextScheduledTimestamp = ko.observable(null)
self.IsRunning = ko.observable(null);
self.NextScheduledTimestampFormatted = ko.computed(function () {
self.TaskExceptionMessage = ko.observable(null); return self.TimestampFormat(self.TimestampParse(self.NextScheduledTimestamp()));
});
self.FinishedTimestamp = ko.observable(null); self.FinishedTimestampFormatted = ko.computed(function () {
self.NextScheduledTimestamp = ko.observable(null) return self.TimestampFormat(self.TimestampParse(self.FinishedTimestamp()));
});
self.NextScheduledTimestampFormatted = ko.computed(function () {
return self.TimestampFormat(self.TimestampParse(self.NextScheduledTimestamp())); self.FinishedUrl = ko.observable(null);
}); self.FinishedMessage = ko.observable(null);
self.FinishedTimestampFormatted = ko.computed(function () {
return self.TimestampFormat(self.TimestampParse(self.FinishedTimestamp())); self.Finished = function () {
}); if (self.FinishedTimestamp()) {
if (self.FinishedUrl() && !self.TaskExceptionMessage()) {
self.FinishedUrl = ko.observable(null); if (self.FinishedMessage())
self.FinishedMessage = ko.observable(null); window.setTimeout(function () { window.location.href = self.FinishedUrl(); }, 3000);
else
self.Finished = function () { window.location.href = self.FinishedUrl();
if (self.FinishedTimestamp()) { }
if (self.FinishedUrl() && !self.TaskExceptionMessage()) { }
if (self.FinishedMessage()) }
window.setTimeout(function () { window.location.href = self.FinishedUrl(); }, 3000);
else self.Initialize = function (taskStatus) {
window.location.href = self.FinishedUrl(); self.TaskName(taskStatus.TaskName);
} self.FinishedUrl(taskStatus.FinishedUrl);
}
} self.Progress(taskStatus.Progress);
self.CurrentProcess(taskStatus.CurrentProcess);
self.Initialize = function (taskStatus) { self.CurrentDescription(taskStatus.CurrentDescription);
self.TaskName(taskStatus.TaskName);
self.FinishedUrl(taskStatus.FinishedUrl); self.IsRunning(taskStatus.IsRunning);
self.Progress(taskStatus.Progress); self.TaskExceptionMessage(taskStatus.TaskExceptionMessage);
self.CurrentProcess(taskStatus.CurrentProcess);
self.CurrentDescription(taskStatus.CurrentDescription); self.FinishedTimestamp(taskStatus.FinishedTimestamp);
self.NextScheduledTimestamp(taskStatus.NextScheduledTimestamp);
self.IsRunning(taskStatus.IsRunning);
self.FinishedMessage(taskStatus.FinishedMessage);
self.TaskExceptionMessage(taskStatus.TaskExceptionMessage);
self.Initialized(true);
self.FinishedTimestamp(taskStatus.FinishedTimestamp);
self.NextScheduledTimestamp(taskStatus.NextScheduledTimestamp); self.Finished();
}
self.FinishedMessage(taskStatus.FinishedMessage); self.Update = function (taskStatus) {
if (!self.Initialized())
self.Initialized(true); return self.Initialize(taskStatus);
self.Finished(); if (taskStatus.StatusVersion < self.StatusVersion)
} return; // Have Newer Status Update
self.Update = function (taskStatus) { self.StatusVersion = taskStatus.StatusVersion;
if (!self.Initialized())
return self.Initialize(taskStatus); if (taskStatus.ChangedProperties) {
for (var changedPropertyIndex = 0; changedPropertyIndex < taskStatus.ChangedProperties.length; changedPropertyIndex++) {
if (taskStatus.StatusVersion < self.StatusVersion) switch (taskStatus.ChangedProperties[changedPropertyIndex]) {
return; // Have Newer Status Update case 'Progress':
self.StatusVersion = taskStatus.StatusVersion; self.Progress(taskStatus.Progress);
break;
for (var changedPropertyIndex = 0; changedPropertyIndex < taskStatus.ChangedProperties.length; changedPropertyIndex++) { case 'CurrentProcess':
switch (taskStatus.ChangedProperties[changedPropertyIndex]) { self.CurrentProcess(taskStatus.CurrentProcess);
case 'Progress': break;
self.Progress(taskStatus.Progress); case 'CurrentDescription':
break; self.CurrentDescription(taskStatus.CurrentDescription);
case 'CurrentProcess': break;
self.CurrentProcess(taskStatus.CurrentProcess); case 'IsRunning':
break; self.IsRunning(taskStatus.IsRunning);
case 'CurrentDescription': break;
self.CurrentDescription(taskStatus.CurrentDescription); case 'TaskException':
break; self.TaskExceptionMessage(taskStatus.TaskExceptionMessage);
case 'IsRunning': break;
self.IsRunning(taskStatus.IsRunning); case 'NextScheduledTimestamp':
break; self.NextScheduledTimestamp(taskStatus.NextScheduledTimestamp);
case 'TaskException': break;
self.TaskExceptionMessage(taskStatus.TaskExceptionMessage); case 'FinishedUrl':
break; self.FinishedUrl(taskStatus.FinishedUrl);
case 'NextScheduledTimestamp': break;
self.NextScheduledTimestamp(taskStatus.NextScheduledTimestamp); case 'FinishedMessage':
break; self.FinishedMessage(taskStatus.FinishedMessage);
case 'FinishedUrl': break;
self.FinishedUrl(taskStatus.FinishedUrl); case 'FinishedTimestamp':
break; self.FinishedTimestamp(taskStatus.FinishedTimestamp);
case 'FinishedMessage': window.setTimeout(self.Finished, 1);
self.FinishedMessage(taskStatus.FinishedMessage); break;
break; default:
case 'FinishedTimestamp': // Ignore
self.FinishedTimestamp(taskStatus.FinishedTimestamp); }
window.setTimeout(self.Finished, 1); }
break; }
default: }
// Ignore }
}
} vm = new statusViewModel(sessionId);
} ko.applyBindings(vm, view[0]);
}
// Start Live Connection
vm = new statusViewModel(sessionId); updateWithLive();
ko.applyBindings(vm, view[0]);
function updateWithAjax(onSuccess) {
// Start Live Connection $.ajax({
updateWithLive(); url: sessionStatusUrl,
dataType: 'json',
function updateWithAjax(onSuccess) { type: 'POST',
$.ajax({ traditional: true,
url: sessionStatusUrl, success: update_Received,
dataType: 'json', error: function (jqXHR, textStatus, errorThrown) {
type: 'POST', alert('Unable to load Session: ' + errorThrown);
traditional: true, }
success: update_Received, });
error: function (jqXHR, textStatus, errorThrown) { }
alert('Unable to load Session: ' + errorThrown); function updateWithLive() {
} liveConnection = $.connection('@(Url.Content("~/API/Logging/TaskStatusNotifications"))');
}); liveConnection.received(update_Received);
} liveConnection.error(function (e) { alert('Live-Status Error: ' + e) });
function updateWithLive() { liveConnection.start(function () {
liveConnection = $.connection('@(Url.Content("~/API/Logging/TaskStatusNotifications"))'); liveConnection.send('/addToGroups:' + sessionId);
liveConnection.received(update_Received); updateWithAjax();
liveConnection.error(function (e) { alert('Live-Status Error: ' + e) }); });
liveConnection.start(function () { }
liveConnection.send('/addToGroups:' + sessionId); function update_Received(taskStatus) {
updateWithAjax(); vm.Update(taskStatus);
}); }
}
function update_Received(taskStatus) { });
vm.Update(taskStatus); </script>
}
});
</script>
@@ -1,314 +1,314 @@
#pragma warning disable 1591 #pragma warning disable 1591
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// <auto-generated> // <auto-generated>
// This code was generated by a tool. // This code was generated by a tool.
// Runtime Version:4.0.30319.17929 // Runtime Version:4.0.30319.17929
// //
// Changes to this file may cause incorrect behavior and will be lost if // Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated. // the code is regenerated.
// </auto-generated> // </auto-generated>
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
namespace Disco.Web.Areas.Config.Views.Logging namespace Disco.Web.Areas.Config.Views.Logging
{ {
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Net; using System.Net;
using System.Text; using System.Text;
using System.Web; using System.Web;
using System.Web.Helpers; using System.Web.Helpers;
using System.Web.Mvc; using System.Web.Mvc;
using System.Web.Mvc.Ajax; using System.Web.Mvc.Ajax;
using System.Web.Mvc.Html; using System.Web.Mvc.Html;
using System.Web.Routing; using System.Web.Routing;
using System.Web.Security; using System.Web.Security;
using System.Web.UI; using System.Web.UI;
using System.Web.WebPages; using System.Web.WebPages;
using Disco.BI.Extensions; using Disco.BI.Extensions;
using Disco.Models.Repository; using Disco.Models.Repository;
using Disco.Web; using Disco.Web;
using Disco.Web.Extensions; using Disco.Web.Extensions;
[System.CodeDom.Compiler.GeneratedCodeAttribute("RazorGenerator", "1.5.0.0")] [System.CodeDom.Compiler.GeneratedCodeAttribute("RazorGenerator", "1.5.0.0")]
[System.Web.WebPages.PageVirtualPathAttribute("~/Areas/Config/Views/Logging/TaskStatus.cshtml")] [System.Web.WebPages.PageVirtualPathAttribute("~/Areas/Config/Views/Logging/TaskStatus.cshtml")]
public class TaskStatus : System.Web.Mvc.WebViewPage<Disco.Web.Areas.Config.Models.Logging.TaskStatusModel> public class TaskStatus : System.Web.Mvc.WebViewPage<Disco.Web.Areas.Config.Models.Logging.TaskStatusModel>
{ {
public TaskStatus() public TaskStatus()
{ {
} }
public override void Execute() public override void Execute()
{ {
#line 2 "..\..\Areas\Config\Views\Logging\TaskStatus.cshtml" #line 2 "..\..\Areas\Config\Views\Logging\TaskStatus.cshtml"
ViewBag.Title = Html.ToBreadcrumb("Configuration", MVC.Config.Config.Index(), "Logging", MVC.Config.Logging.Index(), "Task Status"); ViewBag.Title = Html.ToBreadcrumb("Configuration", MVC.Config.Config.Index(), "Logging", MVC.Config.Logging.Index(), "Task Status");
Html.BundleDeferred("~/ClientScripts/Modules/Knockout"); Html.BundleDeferred("~/ClientScripts/Modules/Knockout");
Html.BundleDeferred("~/ClientScripts/Modules/jQuery-SignalR"); Html.BundleDeferred("~/ClientScripts/Modules/jQuery-SignalR");
#line default #line default
#line hidden #line hidden
WriteLiteral("\r\n<div"); WriteLiteral("\r\n<div");
WriteLiteral(" style=\"min-height: 300px;\""); WriteLiteral(" style=\"min-height: 300px;\"");
WriteLiteral(">\r\n <div"); WriteLiteral(">\r\n <div");
WriteLiteral(" id=\"scheduledTaskStatus\""); WriteLiteral(" id=\"scheduledTaskStatus\"");
WriteLiteral(" class=\"form\""); WriteLiteral(" class=\"form\"");
WriteLiteral(" style=\"width: 520px;\""); WriteLiteral(" style=\"width: 520px;\"");
WriteLiteral(" data-bind=\"visible: Initialized\""); WriteLiteral(" data-bind=\"visible: Initialized\"");
WriteLiteral(">\r\n <h2"); WriteLiteral(">\r\n <h2");
WriteLiteral(" data-bind=\"text: TaskName\""); WriteLiteral(" data-bind=\"text: TaskName\"");
WriteLiteral(">\r\n &nbsp;</h2>\r\n <table>\r\n <tr"); WriteLiteral(">&nbsp;</h2>\r\n <table>\r\n <tr");
WriteLiteral(" data-bind=\"visible: IsRunning\""); WriteLiteral(" data-bind=\"visible: IsRunning\"");
WriteLiteral(">\r\n <th"); WriteLiteral(">\r\n <th");
WriteLiteral(" class=\"process\""); WriteLiteral(" class=\"process\"");
WriteLiteral(" data-bind=\"text: CurrentProcess\""); WriteLiteral(" data-bind=\"text: CurrentProcess\"");
WriteLiteral(">\r\n &nbsp;\r\n </th>\r\n </tr>\r\n " + WriteLiteral(">&nbsp;\r\n </th>\r\n </tr>\r\n <tr");
" <tr");
WriteLiteral(" data-bind=\"visible: IsRunning\"");
WriteLiteral(" data-bind=\"visible: IsRunning\"");
WriteLiteral(">\r\n <td");
WriteLiteral(">\r\n <td");
WriteLiteral(" class=\"description\"");
WriteLiteral(" class=\"description\"");
WriteLiteral(" data-bind=\"text: CurrentDescription\"");
WriteLiteral(" data-bind=\"text: CurrentDescription\"");
WriteLiteral(">&nbsp;\r\n </td>\r\n </tr>\r\n <tr");
WriteLiteral(">\r\n &nbsp;\r\n </td>\r\n </tr>\r\n " +
" <tr"); WriteLiteral(" data-bind=\"visible: IsRunning\"");
WriteLiteral(" data-bind=\"visible: IsRunning\""); WriteLiteral(">\r\n <td");
WriteLiteral(">\r\n <td"); WriteLiteral(" class=\"progress\"");
WriteLiteral(" class=\"progress\""); WriteLiteral(">\r\n <div");
WriteLiteral(">\r\n <div"); WriteLiteral(" data-bind=\"progressValue: Progress\"");
WriteLiteral(" data-bind=\"progressValue: Progress\""); WriteLiteral(">\r\n </div>\r\n </td>\r\n </tr>\r\n " +
" <tr");
WriteLiteral(">\r\n </div>\r\n </td>\r\n </tr>\r\n " +
" <tr"); WriteLiteral(" data-bind=\"visible: FinishedTimestamp\"");
WriteLiteral(" data-bind=\"visible: FinishedTimestamp\""); WriteLiteral(">\r\n <td");
WriteLiteral(">\r\n <td"); WriteLiteral(" class=\"finishedTimestamp\"");
WriteLiteral(" class=\"finishedTimestamp\""); WriteLiteral(">\r\n <h3>Finished: <span");
WriteLiteral(">\r\n <h3>\r\n Finished: <span"); WriteLiteral(" data-bind=\"text: FinishedTimestampFormatted\"");
WriteLiteral(" data-bind=\"text: FinishedTimestampFormatted\""); WriteLiteral("></span>\r\n </h3>\r\n </td>\r\n </tr>\r\n " +
" <tr");
WriteLiteral("></span>\r\n </h3>\r\n </td>\r\n </tr>\r\n " +
" <tr"); WriteLiteral(" data-bind=\"visible: FinishedTimestamp() && !TaskExceptionMessage()\"");
WriteLiteral(" data-bind=\"visible: FinishedTimestamp() && !TaskExceptionMessage()\""); WriteLiteral(">\r\n <td");
WriteLiteral(">\r\n <td"); WriteLiteral(" class=\"finishedMessage\"");
WriteLiteral(" class=\"finishedMessage\""); WriteLiteral(" data-bind=\"css: {finishedRedirect: FinishedUrl}\"");
WriteLiteral(" data-bind=\"css: {finishedRedirect: FinishedUrl}\""); WriteLiteral(">\r\n <span");
WriteLiteral(">\r\n <span"); WriteLiteral(" data-bind=\"text: FinishedMessage\"");
WriteLiteral(" data-bind=\"text: FinishedMessage\""); WriteLiteral("></span>\r\n </td>\r\n </tr>\r\n <tr");
WriteLiteral("></span>\r\n </td>\r\n </tr>\r\n <tr"); WriteLiteral(" data-bind=\"visible: TaskExceptionMessage\"");
WriteLiteral(" data-bind=\"visible: TaskExceptionMessage\""); WriteLiteral(">\r\n <td");
WriteLiteral(">\r\n <td"); WriteLiteral(" class=\"exception\"");
WriteLiteral(" class=\"exception\""); WriteLiteral(">Last Error:\r\n <div");
WriteLiteral(">\r\n Last Error:\r\n <div"); WriteLiteral(" class=\"code\"");
WriteLiteral(" class=\"code\""); WriteLiteral(" data-bind=\"text: TaskExceptionMessage\"");
WriteLiteral(" data-bind=\"text: TaskExceptionMessage\""); WriteLiteral(">\r\n </div>\r\n </td>\r\n </tr>\r\n " +
" <tr");
WriteLiteral(">\r\n </div>\r\n </td>\r\n </tr>\r\n " +
" <tr"); WriteLiteral(" data-bind=\"visible: NextScheduledTimestamp\"");
WriteLiteral(" data-bind=\"visible: NextScheduledTimestamp\""); WriteLiteral(">\r\n <td");
WriteLiteral(">\r\n <td"); WriteLiteral(" class=\"nextScheduledTimestamp\"");
WriteLiteral(" class=\"nextScheduledTimestamp\""); WriteLiteral(">Next Scheduled: <span");
WriteLiteral(">\r\n Next Scheduled: <span"); WriteLiteral(" data-bind=\"text: NextScheduledTimestampFormatted\"");
WriteLiteral(" data-bind=\"text: NextScheduledTimestampFormatted\""); WriteLiteral("></span>\r\n </td>\r\n </tr>\r\n </table>\r\n </div>\r" +
"\n</div>\r\n<script");
WriteLiteral("></span>\r\n </td>\r\n </tr>\r\n </table>\r\n </div>\r" +
"\n</div>\r\n<script"); WriteLiteral(" type=\"text/javascript\"");
WriteLiteral(" type=\"text/javascript\""); WriteLiteral(">\r\n ko.bindingHandlers.progressValue = {\r\n init: function (element, val" +
"ueAccessor, allBindingsAccessor, viewModel) {\r\n var $element = $(elem" +
WriteLiteral(">\r\n ko.bindingHandlers.progressValue = {\r\n init: function (element, val" + "ent);\r\n if (!$element.is(\'.ui-progressbar\'))\r\n $elemen" +
"ueAccessor, allBindingsAccessor, viewModel) {\r\n var $element = $(elem" + "t.progressbar();\r\n },\r\n update: function (element, valueAccessor, " +
"ent);\r\n if (!$element.is(\'.ui-progressbar\'))\r\n $elemen" + "allBindingsAccessor, viewModel) {\r\n var v = ko.utils.unwrapObservable" +
"t.progressbar();\r\n },\r\n update: function (element, valueAccessor, " + "(valueAccessor());\r\n var vInt = parseInt(v);\r\n if (vInt >=" +
"allBindingsAccessor, viewModel) {\r\n var v = ko.utils.unwrapObservable" + " 0) {\r\n $(element).progressbar(\'option\', \'value\', vInt);\r\n " +
"(valueAccessor());\r\n var vInt = parseInt(v);\r\n if (vInt >=" + " }\r\n }\r\n };\r\n //* http://webcloud.se/log/JavaScript-and-ISO-860" +
" 0) {\r\n $(element).progressbar(\'option\', \'value\', vInt);\r\n " + "1/\r\n Date.prototype.setISO8601 = function (string) {\r\n var regexp = \"(" +
" }\r\n }\r\n };\r\n //* http://webcloud.se/log/JavaScript-and-ISO-860" + "[0-9]{4})(-([0-9]{2})(-([0-9]{2})\" +\r\n \"(T([0-9]{2}):([0-9]{2})(:([0-9]{2" +
"1/\r\n Date.prototype.setISO8601 = function (string) {\r\n var regexp = \"(" + "})(\\.([0-9]+))?)?\" +\r\n \"(Z|(([-+])([0-9]{2}):([0-9]{2})))?)?)?)?\";\r\n " +
"[0-9]{4})(-([0-9]{2})(-([0-9]{2})\" +\r\n \"(T([0-9]{2}):([0-9]{2})(:([0-9]{2" + " var d = string.match(new RegExp(regexp));\r\n\r\n var offset = 0;\r\n " +
"})(\\.([0-9]+))?)?\" +\r\n \"(Z|(([-+])([0-9]{2}):([0-9]{2})))?)?)?)?\";\r\n " + " var date = new Date(d[1], 0, 1);\r\n\r\n if (d[3]) { date.setMonth(d[3] - 1)" +
" var d = string.match(new RegExp(regexp));\r\n\r\n var offset = 0;\r\n " + "; }\r\n if (d[5]) { date.setDate(d[5]); }\r\n if (d[7]) { date.setHour" +
" var date = new Date(d[1], 0, 1);\r\n\r\n if (d[3]) { date.setMonth(d[3] - 1)" + "s(d[7]); }\r\n if (d[8]) { date.setMinutes(d[8]); }\r\n if (d[10]) { d" +
"; }\r\n if (d[5]) { date.setDate(d[5]); }\r\n if (d[7]) { date.setHour" + "ate.setSeconds(d[10]); }\r\n if (d[12]) { date.setMilliseconds(Number(\"0.\" " +
"s(d[7]); }\r\n if (d[8]) { date.setMinutes(d[8]); }\r\n if (d[10]) { d" + "+ d[12]) * 1000); }\r\n if (d[14]) {\r\n offset = (Number(d[16]) *" +
"ate.setSeconds(d[10]); }\r\n if (d[12]) { date.setMilliseconds(Number(\"0.\" " + " 60) + Number(d[17]);\r\n offset *= ((d[15] == \'-\') ? 1 : -1);\r\n " +
"+ d[12]) * 1000); }\r\n if (d[14]) {\r\n offset = (Number(d[16]) *" + " }\r\n\r\n offset -= date.getTimezoneOffset();\r\n time = (Number(date) " +
" 60) + Number(d[17]);\r\n offset *= ((d[15] == \'-\') ? 1 : -1);\r\n " + "+ (offset * 60 * 1000));\r\n this.setTime(Number(time));\r\n return th" +
" }\r\n\r\n offset -= date.getTimezoneOffset();\r\n time = (Number(date) " + "is;\r\n }\r\n</script>\r\n<script");
"+ (offset * 60 * 1000));\r\n this.setTime(Number(time));\r\n return th" +
"is;\r\n }\r\n</script>\r\n<script"); WriteLiteral(" type=\"text/javascript\"");
WriteLiteral(" type=\"text/javascript\""); WriteLiteral(">\r\n $(function () {\r\n var sessionId = \'");
WriteLiteral(">\r\n $(function () {\r\n var sessionId = \'");
#line 93 "..\..\Areas\Config\Views\Logging\TaskStatus.cshtml"
Write(Model.SessionId);
#line 99 "..\..\Areas\Config\Views\Logging\TaskStatus.cshtml"
Write(Model.SessionId);
#line default
#line hidden
#line default WriteLiteral("\';\r\n var sessionStatusUrl = \'");
#line hidden
WriteLiteral("\';\r\n var sessionStatusUrl = \'");
#line 94 "..\..\Areas\Config\Views\Logging\TaskStatus.cshtml"
Write(Url.Action(MVC.API.Logging.ScheduledTaskStatus(Model.SessionId)));
#line 100 "..\..\Areas\Config\Views\Logging\TaskStatus.cshtml"
Write(Url.Action(MVC.API.Logging.ScheduledTaskStatus(Model.SessionId)));
#line default
#line hidden
#line default WriteLiteral("\';\r\n\r\n var view = $(\'#scheduledTaskStatus\');\r\n var vm = null;\r\n\r\n " +
#line hidden " var liveConnection = null;\r\n\r\n var statusViewModel = function (sess" +
WriteLiteral("\';\r\n\r\n var view = $(\'#scheduledTaskStatus\');\r\n var vm = null;\r\n\r\n " + "ionId) {\r\n var self = this;\r\n\r\n self.Initialized = ko.obse" +
" var liveConnection = null;\r\n\r\n var statusViewModel = function (sess" + "rvable(false);\r\n\r\n self.TimestampParse = function (timestamp) {\r\n " +
"ionId) {\r\n var self = this;\r\n\r\n self.Initialized = ko.obse" + " if (timestamp) {\r\n if (timestamp.indexOf(\"\\/Date(" +
"rvable(false);\r\n\r\n self.TimestampParse = function (timestamp) {\r\n " + "\") == 0)\r\n return new Date(parseInt(timestamp.substr(6)))" +
" if (timestamp) {\r\n if (timestamp.indexOf(\"\\/Date(" + ";\r\n else\r\n return (new Date()).setISO8" +
"\") == 0)\r\n return new Date(parseInt(timestamp.substr(6)))" + "601(timestamp);\r\n }\r\n return new Date();\r\n " +
";\r\n else\r\n return (new Date()).setISO8" + " }\r\n self.TimestampFormat = function (timestamp) {\r\n " +
"601(timestamp);\r\n }\r\n return new Date();\r\n " + " var addZero = function (v) { v = v + \'\'; if (v.length == 1) v = \'0\' + v; retur" +
" }\r\n self.TimestampFormat = function (timestamp) {\r\n " + "n v; }\r\n return timestamp.getFullYear() + \'/\' + addZero((1 + time" +
" var addZero = function (v) { v = v + \'\'; if (v.length == 1) v = \'0\' + v; retur" + "stamp.getMonth())) + \'/\' + addZero(timestamp.getDate()) + \' \' + addZero(timestam" +
"n v; }\r\n return timestamp.getFullYear() + \'/\' + addZero((1 + time" + "p.getHours()) + \':\' + addZero(timestamp.getMinutes()) + \':\' + addZero(timestamp." +
"stamp.getMonth())) + \'/\' + addZero(timestamp.getDate()) + \' \' + addZero(timestam" + "getSeconds());\r\n }\r\n\r\n self.SessionId = sessionId;\r\n " +
"p.getHours()) + \':\' + addZero(timestamp.getMinutes()) + \':\' + addZero(timestamp." + " self.TaskName = ko.observable(null);\r\n self.StatusVersion = -1;" +
"getSeconds());\r\n }\r\n\r\n self.SessionId = sessionId;\r\n " + "\r\n\r\n self.Progress = ko.observable(0);\r\n self.CurrentProce" +
" self.TaskName = ko.observable(null);\r\n self.StatusVersion = -1;" + "ss = ko.observable(null);\r\n self.CurrentDescription = ko.observable(n" +
"\r\n\r\n self.Progress = ko.observable(0);\r\n self.CurrentProce" + "ull);\r\n\r\n self.IsRunning = ko.observable(null);\r\n\r\n self.T" +
"ss = ko.observable(null);\r\n self.CurrentDescription = ko.observable(n" + "askExceptionMessage = ko.observable(null);\r\n\r\n self.FinishedTimestamp" +
"ull);\r\n\r\n self.IsRunning = ko.observable(null);\r\n\r\n self.T" + " = ko.observable(null);\r\n self.NextScheduledTimestamp = ko.observable" +
"askExceptionMessage = ko.observable(null);\r\n\r\n self.FinishedTimestamp" + "(null)\r\n\r\n self.NextScheduledTimestampFormatted = ko.computed(functio" +
" = ko.observable(null);\r\n self.NextScheduledTimestamp = ko.observable" + "n () {\r\n return self.TimestampFormat(self.TimestampParse(self.Nex" +
"(null)\r\n\r\n self.NextScheduledTimestampFormatted = ko.computed(functio" + "tScheduledTimestamp()));\r\n });\r\n self.FinishedTimestampFor" +
"n () {\r\n return self.TimestampFormat(self.TimestampParse(self.Nex" + "matted = ko.computed(function () {\r\n return self.TimestampFormat(" +
"tScheduledTimestamp()));\r\n });\r\n self.FinishedTimestampFor" + "self.TimestampParse(self.FinishedTimestamp()));\r\n });\r\n\r\n " +
"matted = ko.computed(function () {\r\n return self.TimestampFormat(" + "self.FinishedUrl = ko.observable(null);\r\n self.FinishedMessage = ko.o" +
"self.TimestampParse(self.FinishedTimestamp()));\r\n });\r\n\r\n " + "bservable(null);\r\n\r\n self.Finished = function () {\r\n i" +
"self.FinishedUrl = ko.observable(null);\r\n self.FinishedMessage = ko.o" + "f (self.FinishedTimestamp()) {\r\n if (self.FinishedUrl() && !s" +
"bservable(null);\r\n\r\n self.Finished = function () {\r\n i" + "elf.TaskExceptionMessage()) {\r\n if (self.FinishedMessage(" +
"f (self.FinishedTimestamp()) {\r\n if (self.FinishedUrl() && !s" + "))\r\n window.setTimeout(function () { window.location." +
"elf.TaskExceptionMessage()) {\r\n if (self.FinishedMessage(" + "href = self.FinishedUrl(); }, 3000);\r\n else\r\n " +
"))\r\n window.setTimeout(function () { window.location." + " window.location.href = self.FinishedUrl();\r\n " +
"href = self.FinishedUrl(); }, 3000);\r\n else\r\n " + "}\r\n }\r\n }\r\n\r\n self.Initialize = function (t" +
" window.location.href = self.FinishedUrl();\r\n " + "askStatus) {\r\n self.TaskName(taskStatus.TaskName);\r\n " +
"}\r\n }\r\n }\r\n\r\n self.Initialize = function (t" + " self.FinishedUrl(taskStatus.FinishedUrl);\r\n\r\n self.Progress(ta" +
"askStatus) {\r\n self.TaskName(taskStatus.TaskName);\r\n " + "skStatus.Progress);\r\n self.CurrentProcess(taskStatus.CurrentProce" +
" self.FinishedUrl(taskStatus.FinishedUrl);\r\n\r\n self.Progress(ta" + "ss);\r\n self.CurrentDescription(taskStatus.CurrentDescription);\r\n\r" +
"skStatus.Progress);\r\n self.CurrentProcess(taskStatus.CurrentProce" + "\n self.IsRunning(taskStatus.IsRunning);\r\n\r\n self.T" +
"ss);\r\n self.CurrentDescription(taskStatus.CurrentDescription);\r\n\r" + "askExceptionMessage(taskStatus.TaskExceptionMessage);\r\n\r\n self.Fi" +
"\n self.IsRunning(taskStatus.IsRunning);\r\n\r\n self.T" + "nishedTimestamp(taskStatus.FinishedTimestamp);\r\n self.NextSchedul" +
"askExceptionMessage(taskStatus.TaskExceptionMessage);\r\n\r\n self.Fi" + "edTimestamp(taskStatus.NextScheduledTimestamp);\r\n\r\n self.Finished" +
"nishedTimestamp(taskStatus.FinishedTimestamp);\r\n self.NextSchedul" + "Message(taskStatus.FinishedMessage);\r\n\r\n self.Initialized(true);\r" +
"edTimestamp(taskStatus.NextScheduledTimestamp);\r\n\r\n self.Finished" + "\n\r\n self.Finished();\r\n }\r\n self.Update = fu" +
"Message(taskStatus.FinishedMessage);\r\n\r\n self.Initialized(true);\r" + "nction (taskStatus) {\r\n if (!self.Initialized())\r\n " +
"\n\r\n self.Finished();\r\n }\r\n self.Update = fu" + " return self.Initialize(taskStatus);\r\n\r\n if (taskStatus.Statu" +
"nction (taskStatus) {\r\n if (!self.Initialized())\r\n " + "sVersion < self.StatusVersion)\r\n return; // Have Newer Status" +
" return self.Initialize(taskStatus);\r\n\r\n if (taskStatus.Statu" + " Update\r\n self.StatusVersion = taskStatus.StatusVersion;\r\n\r\n " +
"sVersion < self.StatusVersion)\r\n return; // Have Newer Status" + " if (taskStatus.ChangedProperties) {\r\n for (var cha" +
" Update\r\n self.StatusVersion = taskStatus.StatusVersion;\r\n\r\n " + "ngedPropertyIndex = 0; changedPropertyIndex < taskStatus.ChangedProperties.lengt" +
" for (var changedPropertyIndex = 0; changedPropertyIndex < taskStatus." + "h; changedPropertyIndex++) {\r\n switch (taskStatus.Changed" +
"ChangedProperties.length; changedPropertyIndex++) {\r\n switch " + "Properties[changedPropertyIndex]) {\r\n case \'Progress\'" +
"(taskStatus.ChangedProperties[changedPropertyIndex]) {\r\n " + ":\r\n self.Progress(taskStatus.Progress);\r\n " +
"case \'Progress\':\r\n self.Progress(taskStatus.Progress)" + " break;\r\n case \'CurrentProcess" +
";\r\n break;\r\n case \'CurrentProc" + "\':\r\n self.CurrentProcess(taskStatus.CurrentProces" +
"ess\':\r\n self.CurrentProcess(taskStatus.CurrentProcess" + "s);\r\n break;\r\n case \'C" +
");\r\n break;\r\n case \'CurrentDes" + "urrentDescription\':\r\n self.CurrentDescription(tas" +
"cription\':\r\n self.CurrentDescription(taskStatus.Curre" + "kStatus.CurrentDescription);\r\n break;\r\n " +
"ntDescription);\r\n break;\r\n cas" + " case \'IsRunning\':\r\n self.IsRunn" +
"e \'IsRunning\':\r\n self.IsRunning(taskStatus.IsRunning)" + "ing(taskStatus.IsRunning);\r\n break;\r\n " +
";\r\n break;\r\n case \'TaskExcepti" + " case \'TaskException\':\r\n self.Task" +
"on\':\r\n self.TaskExceptionMessage(taskStatus.TaskExcep" + "ExceptionMessage(taskStatus.TaskExceptionMessage);\r\n " +
"tionMessage);\r\n break;\r\n case " + " break;\r\n case \'NextScheduledTimestamp\':\r\n " +
"\'NextScheduledTimestamp\':\r\n self.NextScheduledTimesta" + " self.NextScheduledTimestamp(taskStatus.NextScheduledTime" +
"mp(taskStatus.NextScheduledTimestamp);\r\n break;\r\n " + "stamp);\r\n break;\r\n cas" +
" case \'FinishedUrl\':\r\n self.Finish" + "e \'FinishedUrl\':\r\n self.FinishedUrl(taskStatus.Fi" +
"edUrl(taskStatus.FinishedUrl);\r\n break;\r\n " + "nishedUrl);\r\n break;\r\n " +
" case \'FinishedMessage\':\r\n self.FinishedMe" + " case \'FinishedMessage\':\r\n self.FinishedMessage(t" +
"ssage(taskStatus.FinishedMessage);\r\n break;\r\n " + "askStatus.FinishedMessage);\r\n break;\r\n " +
" case \'FinishedTimestamp\':\r\n self.Fini" + " case \'FinishedTimestamp\':\r\n self" +
"shedTimestamp(taskStatus.FinishedTimestamp);\r\n window" + ".FinishedTimestamp(taskStatus.FinishedTimestamp);\r\n " +
".setTimeout(self.Finished, 1);\r\n break;\r\n " + " window.setTimeout(self.Finished, 1);\r\n break;\r" +
" default:\r\n // Ignore\r\n " + "\n default:\r\n // Ignore" +
" }\r\n }\r\n }\r\n }\r\n\r\n vm = new statusViewMo" + "\r\n }\r\n }\r\n }\r\n " +
"del(sessionId);\r\n ko.applyBindings(vm, view[0]);\r\n\r\n // Start Live" + " }\r\n }\r\n\r\n vm = new statusViewModel(sessionId);\r\n ko.appl" +
" Connection\r\n updateWithLive();\r\n\r\n function updateWithAjax(onSucc" + "yBindings(vm, view[0]);\r\n\r\n // Start Live Connection\r\n updateWithL" +
"ess) {\r\n $.ajax({\r\n url: sessionStatusUrl,\r\n " + "ive();\r\n\r\n function updateWithAjax(onSuccess) {\r\n $.ajax({\r\n " +
" dataType: \'json\',\r\n type: \'POST\',\r\n traditio" + " url: sessionStatusUrl,\r\n dataType: \'json\',\r\n " +
"nal: true,\r\n success: update_Received,\r\n error: fu" + " type: \'POST\',\r\n traditional: true,\r\n succ" +
"nction (jqXHR, textStatus, errorThrown) {\r\n alert(\'Unable to " + "ess: update_Received,\r\n error: function (jqXHR, textStatus, error" +
"load Session: \' + errorThrown);\r\n }\r\n });\r\n }\r\n" + "Thrown) {\r\n alert(\'Unable to load Session: \' + errorThrown);\r" +
" function updateWithLive() {\r\n liveConnection = $.connection(\'" + "\n }\r\n });\r\n }\r\n function updateWithLive(" +
""); ") {\r\n liveConnection = $.connection(\'");
#line 247 "..\..\Areas\Config\Views\Logging\TaskStatus.cshtml" #line 243 "..\..\Areas\Config\Views\Logging\TaskStatus.cshtml"
Write(Url.Content("~/API/Logging/TaskStatusNotifications")); Write(Url.Content("~/API/Logging/TaskStatusNotifications"));
#line default #line default
#line hidden #line hidden
WriteLiteral(@"'); WriteLiteral(@"');
liveConnection.received(update_Received); liveConnection.received(update_Received);
liveConnection.error(function (e) { alert('Live-Status Error: ' + e) }); liveConnection.error(function (e) { alert('Live-Status Error: ' + e) });
liveConnection.start(function () { liveConnection.start(function () {
liveConnection.send('/addToGroups:' + sessionId); liveConnection.send('/addToGroups:' + sessionId);
updateWithAjax(); updateWithAjax();
}); });
} }
function update_Received(taskStatus) { function update_Received(taskStatus) {
vm.Update(taskStatus); vm.Update(taskStatus);
} }
}); });
</script> </script>
"); ");
} }
} }
} }
#pragma warning restore 1591 #pragma warning restore 1591
@@ -72,85 +72,102 @@
$(function () { $(function () {
// Uninstall // Uninstall
var uninstallUrl = '@(Url.Action(MVC.API.Plugin.Uninstall()))/'; var uninstallUrl = '@(Url.Action(MVC.API.Plugin.Uninstall()))/';
var uninstallPlugin, uninstallPluginData, $dialogConfirm, uninstallPluginConfirm, uninstallPluginDataConfirm; var uninstallPlugin, uninstallPluginData, $dialogConfirm, uninstallPluginConfirm, uninstallPluginDataConfirm;
var pluginId, pluginName, pluginUninstallData; var pluginId, pluginName, pluginUninstallData;
var $dialog = $('#dialogUninstallPlugins').dialog({ var $dialog = $('#dialogUninstallPlugins').dialog({
resizable: false, resizable: false,
modal: true, modal: true,
width: 350, width: 350,
autoOpen: false, autoOpen: false,
buttons: { buttons: {
"Uninstall": function () { "Uninstall": function () {
pluginId = uninstallPlugin.val(); pluginId = uninstallPlugin.val();
pluginName = uninstallPlugin.find('option:selected').text(); pluginName = uninstallPlugin.find('option:selected').text();
pluginUninstallData = uninstallPluginData.is(':checked'); pluginUninstallData = uninstallPluginData.is(':checked');
if (!pluginId) { if (!pluginId) {
alert('Select a plugin to uninstall'); alert('Select a plugin to uninstall');
} else { } else {
uninstallPluginConfirm.text(pluginName + ' [' + pluginId + ']'); uninstallPluginConfirm.text(pluginName + ' [' + pluginId + ']');
if (pluginUninstallData) if (pluginUninstallData)
uninstallPluginDataConfirm.show(); uninstallPluginDataConfirm.show();
else else
uninstallPluginDataConfirm.hide(); uninstallPluginDataConfirm.hide();
$dialogConfirm.dialog('open'); $dialogConfirm.dialog('open');
$(this).dialog("close");
}
},
Cancel: function () {
uninstallPluginData.removeAttr('checked');
$('#uninstallPluginDataAlert').hide();
$(this).dialog("close"); $(this).dialog("close");
} }
},
Cancel: function () {
uninstallPluginData.removeAttr('checked');
$('#uninstallPluginDataAlert').hide();
$(this).dialog("close");
} }
} });
});
$dialogConfirm = $('#dialogUninstallPluginConfirm').dialog({ $dialogConfirm = $('#dialogUninstallPluginConfirm').dialog({
resizable: false, resizable: false,
modal: true, modal: true,
width: 350, width: 350,
autoOpen: false, autoOpen: false,
buttons: { buttons: {
"Confirm Uninstall": function () { "Confirm Uninstall": function () {
var url = uninstallUrl + pluginId; var url = uninstallUrl + pluginId;
if (pluginUninstallData) if (pluginUninstallData)
url += '?UninstallData=true' url += '?UninstallData=true'
else else
url += '?UninstallData=false' url += '?UninstallData=false'
window.location.href = url; window.location.href = url;
$(this).dialog("disable"); $(this).dialog("disable");
}, },
Cancel: function () { Cancel: function () {
uninstallPluginData.removeAttr('checked'); uninstallPluginData.removeAttr('checked');
$('#uninstallPluginDataAlert').hide(); $('#uninstallPluginDataAlert').hide();
$(this).dialog("close"); $(this).dialog("close");
}
} }
} });
});
uninstallPlugin = $('#uninstallPlugin'); uninstallPlugin = $('#uninstallPlugin');
uninstallPluginData = $('#uninstallPluginData'); uninstallPluginData = $('#uninstallPluginData');
uninstallPluginConfirm = $('#uninstallPluginConfirm'); uninstallPluginConfirm = $('#uninstallPluginConfirm');
uninstallPluginDataConfirm = $('#uninstallPluginDataConfirm'); uninstallPluginDataConfirm = $('#uninstallPluginDataConfirm');
$('#buttonUninstall').click(function () { $('#buttonUninstall').click(function () {
$dialog.dialog('open'); $dialog.dialog('open');
return false; return false;
}); });
$('#uninstallPluginData').change(function () { $('#uninstallPluginData').change(function () {
if ($(this).is(':checked')) { if ($(this).is(':checked')) {
$('#uninstallPluginDataAlert').slideDown(); $('#uninstallPluginDataAlert').slideDown();
} else { } else {
$('#uninstallPluginDataAlert').slideUp(); $('#uninstallPluginDataAlert').slideUp();
} }
});
}); });
});
</script> </script>
if (Model.PluginUpdates.Count > 0)
{
<div id="updateAvailableContainer">
<div>@(Model.PluginUpdates.Count) plugin update@(Model.PluginUpdates.Count == 1 ? " is" : "s are") available</div>
@Html.ActionLinkButton("Update Now", MVC.API.Plugin.UpdateAll())
</div>
<script>
(function () {
$(function () {
var layout_PageHeading = $('#layout_PageHeading').height(80);
var updateAvailableContainer = $('#updateAvailableContainer');
updateAvailableContainer.appendTo(layout_PageHeading);
});
})();
</script>
}
} }
} }
</div> </div>
@@ -365,51 +365,110 @@ WriteLiteral(" <script>\r\n $(function () {\r\n
#line default #line default
#line hidden #line hidden
WriteLiteral("/\';\r\n var uninstallPlugin, uninstallPluginData, $dialogConfirm, uninst" + WriteLiteral("/\';\r\n var uninstallPlugin, uninstallPluginData, $dialogConfirm, un" +
"allPluginConfirm, uninstallPluginDataConfirm;\r\n\r\n var pluginId, plugi" + "installPluginConfirm, uninstallPluginDataConfirm;\r\n\r\n var pluginI" +
"nName, pluginUninstallData;\r\n\r\n var $dialog = $(\'#dialogUninstallPlug" + "d, pluginName, pluginUninstallData;\r\n\r\n var $dialog = $(\'#dialogU" +
"ins\').dialog({\r\n resizable: false,\r\n modal: true,\r" + "ninstallPlugins\').dialog({\r\n resizable: false,\r\n " +
"\n width: 350,\r\n autoOpen: false,\r\n " + " modal: true,\r\n width: 350,\r\n autoOp" +
"buttons: {\r\n \"Uninstall\": function () {\r\n " + "en: false,\r\n buttons: {\r\n \"Uninstall\":" +
" pluginId = uninstallPlugin.val();\r\n pluginName = unin" + " function () {\r\n pluginId = uninstallPlugin.val();\r\n " +
"stallPlugin.find(\'option:selected\').text();\r\n pluginUnins" + " pluginName = uninstallPlugin.find(\'option:selected\')." +
"tallData = uninstallPluginData.is(\':checked\');\r\n\r\n if (!p" + "text();\r\n pluginUninstallData = uninstallPluginData.i" +
"luginId) {\r\n alert(\'Select a plugin to uninstall\');\r\n" + "s(\':checked\');\r\n\r\n if (!pluginId) {\r\n " +
" } else {\r\n uninstallPluginCon" + " alert(\'Select a plugin to uninstall\');\r\n " +
"firm.text(pluginName + \' [\' + pluginId + \']\');\r\n if (" + " } else {\r\n uninstallPluginConfirm.text(plugin" +
"pluginUninstallData)\r\n uninstallPluginDataConfirm" + "Name + \' [\' + pluginId + \']\');\r\n if (pluginUninst" +
".show();\r\n else\r\n unin" + "allData)\r\n uninstallPluginDataConfirm.show();" +
"stallPluginDataConfirm.hide();\r\n\r\n $dialogConfirm.dia" + "\r\n else\r\n unin" +
"log(\'open\');\r\n $(this).dialog(\"close\");\r\n " + "stallPluginDataConfirm.hide();\r\n\r\n $dialogConfirm" +
" }\r\n },\r\n Cancel: function () {" + ".dialog(\'open\');\r\n $(this).dialog(\"close\");\r\n " +
"\r\n uninstallPluginData.removeAttr(\'checked\');\r\n " + " }\r\n },\r\n C" +
" $(\'#uninstallPluginDataAlert\').hide();\r\n $(" + "ancel: function () {\r\n uninstallPluginData.removeAttr" +
"this).dialog(\"close\");\r\n }\r\n }\r\n })" + "(\'checked\');\r\n $(\'#uninstallPluginDataAlert\').hide();" +
";\r\n\r\n $dialogConfirm = $(\'#dialogUninstallPluginConfirm\').dialog({\r\n " + "\r\n $(this).dialog(\"close\");\r\n " +
" resizable: false,\r\n modal: true,\r\n " + "}\r\n }\r\n });\r\n\r\n $dialogConfirm " +
"width: 350,\r\n autoOpen: false,\r\n buttons: {\r\n " + "= $(\'#dialogUninstallPluginConfirm\').dialog({\r\n resizable: fa" +
" \"Confirm Uninstall\": function () {\r\n var u" + "lse,\r\n modal: true,\r\n width: 350,\r\n " +
"rl = uninstallUrl + pluginId;\r\n if (pluginUninstallData)\r" + " autoOpen: false,\r\n buttons: {\r\n " +
"\n url += \'?UninstallData=true\'\r\n " + " \"Confirm Uninstall\": function () {\r\n var url =" +
" else\r\n url += \'?UninstallData=false\'\r\n\r\n " + " uninstallUrl + pluginId;\r\n if (pluginUninstallData)\r" +
" window.location.href = url;\r\n $(this).dialo" + "\n url += \'?UninstallData=true\'\r\n " +
"g(\"disable\");\r\n },\r\n Cancel: function () {" + " else\r\n url += \'?UninstallData=false\'\r\n" +
"\r\n uninstallPluginData.removeAttr(\'checked\');\r\n " + "\r\n window.location.href = url;\r\n " +
" $(\'#uninstallPluginDataAlert\').hide();\r\n $(" + " $(this).dialog(\"disable\");\r\n },\r\n " +
"this).dialog(\"close\");\r\n }\r\n }\r\n })" + " Cancel: function () {\r\n uninstallPluginData.re" +
";\r\n\r\n uninstallPlugin = $(\'#uninstallPlugin\');\r\n uninstall" + "moveAttr(\'checked\');\r\n $(\'#uninstallPluginDataAlert\')" +
"PluginData = $(\'#uninstallPluginData\');\r\n uninstallPluginConfirm = $(" + ".hide();\r\n $(this).dialog(\"close\");\r\n " +
"\'#uninstallPluginConfirm\');\r\n uninstallPluginDataConfirm = $(\'#uninst" + " }\r\n }\r\n });\r\n\r\n uninsta" +
"allPluginDataConfirm\');\r\n\r\n $(\'#buttonUninstall\').click(function () {" + "llPlugin = $(\'#uninstallPlugin\');\r\n uninstallPluginData = $(\'#uni" +
"\r\n $dialog.dialog(\'open\');\r\n return false;\r\n " + "nstallPluginData\');\r\n uninstallPluginConfirm = $(\'#uninstallPlugi" +
" });\r\n\r\n $(\'#uninstallPluginData\').change(function () {\r\n " + "nConfirm\');\r\n uninstallPluginDataConfirm = $(\'#uninstallPluginDat" +
" if ($(this).is(\':checked\')) {\r\n $(\'#uninstallPluginD" + "aConfirm\');\r\n\r\n $(\'#buttonUninstall\').click(function () {\r\n " +
"ataAlert\').slideDown();\r\n } else {\r\n $(\'#unins" + " $dialog.dialog(\'open\');\r\n return false;\r\n " +
"tallPluginDataAlert\').slideUp();\r\n }\r\n });\r\n })" + " });\r\n\r\n $(\'#uninstallPluginData\').change(function () {\r" +
";\r\n </script>\r\n"); "\n if ($(this).is(\':checked\')) {\r\n $(\'#" +
"uninstallPluginDataAlert\').slideDown();\r\n } else {\r\n " +
" $(\'#uninstallPluginDataAlert\').slideUp();\r\n }\r" +
"\n });\r\n });\r\n </script>\r\n");
#line 154 "..\..\Areas\Config\Views\Plugins\Index.cshtml" #line 154 "..\..\Areas\Config\Views\Plugins\Index.cshtml"
if (Model.PluginUpdates.Count > 0)
{
#line default
#line hidden
WriteLiteral(" <div");
WriteLiteral(" id=\"updateAvailableContainer\"");
WriteLiteral(">\r\n <div>");
#line 158 "..\..\Areas\Config\Views\Plugins\Index.cshtml"
Write(Model.PluginUpdates.Count);
#line default
#line hidden
WriteLiteral(" plugin update");
#line 158 "..\..\Areas\Config\Views\Plugins\Index.cshtml"
Write(Model.PluginUpdates.Count == 1 ? " is" : "s are");
#line default
#line hidden
WriteLiteral(" available</div>\r\n");
WriteLiteral(" ");
#line 159 "..\..\Areas\Config\Views\Plugins\Index.cshtml"
Write(Html.ActionLinkButton("Update Now", MVC.API.Plugin.UpdateAll()));
#line default
#line hidden
WriteLiteral("\r\n </div>\r\n");
WriteLiteral(@" <script>
(function () {
$(function () {
var layout_PageHeading = $('#layout_PageHeading').height(80);
var updateAvailableContainer = $('#updateAvailableContainer');
updateAvailableContainer.appendTo(layout_PageHeading);
});
})();
</script>
");
#line 170 "..\..\Areas\Config\Views\Plugins\Index.cshtml"
}
} }
@@ -422,13 +481,13 @@ WriteLiteral(" class=\"actionBar\"");
WriteLiteral(">\r\n"); WriteLiteral(">\r\n");
#line 158 "..\..\Areas\Config\Views\Plugins\Index.cshtml" #line 175 "..\..\Areas\Config\Views\Plugins\Index.cshtml"
#line default #line default
#line hidden #line hidden
#line 158 "..\..\Areas\Config\Views\Plugins\Index.cshtml" #line 175 "..\..\Areas\Config\Views\Plugins\Index.cshtml"
if (Model.PluginManifests.Count > 0) if (Model.PluginManifests.Count > 0)
{ {
@@ -436,14 +495,14 @@ WriteLiteral(">\r\n");
#line default #line default
#line hidden #line hidden
#line 160 "..\..\Areas\Config\Views\Plugins\Index.cshtml" #line 177 "..\..\Areas\Config\Views\Plugins\Index.cshtml"
Write(Html.ActionLinkButton("Uninstall Plugins", MVC.Config.Plugins.Index(), "buttonUninstall")); Write(Html.ActionLinkButton("Uninstall Plugins", MVC.Config.Plugins.Index(), "buttonUninstall"));
#line default #line default
#line hidden #line hidden
#line 160 "..\..\Areas\Config\Views\Plugins\Index.cshtml" #line 177 "..\..\Areas\Config\Views\Plugins\Index.cshtml"
} }
@@ -453,7 +512,7 @@ WriteLiteral(">\r\n");
WriteLiteral(" "); WriteLiteral(" ");
#line 162 "..\..\Areas\Config\Views\Plugins\Index.cshtml" #line 179 "..\..\Areas\Config\Views\Plugins\Index.cshtml"
Write(Html.ActionLinkButton("Install Plugins", MVC.Config.Plugins.Install())); Write(Html.ActionLinkButton("Install Plugins", MVC.Config.Plugins.Install()));
@@ -28,10 +28,19 @@
{ {
var plugin = plugins[itemNextId]; var plugin = plugins[itemNextId];
itemNextId++; itemNextId++;
<div class="pageMenuArea pluginItem@(Plugins.PluginInstalled(plugin.Id) ? " pluginInstalled" : string.Empty)"> var installedPlugin = Plugins.PluginInstalled(plugin.Id) ? Plugins.GetPlugin(plugin.Id) : null;
<a class="pluginInstallLink" href="@(Url.Action(MVC.API.Plugin.Install(plugin.Id)))"> <div class="pageMenuArea pluginItem@(installedPlugin != null ? " pluginInstalled" : string.Empty)">
<h2 class="pluginName">@plugin.Name</h2> <h2 class="pluginName">@plugin.Name
</a> @if (installedPlugin == null){
<a class="pluginInstallLink button" href="@(Url.Action(MVC.API.Plugin.Install(plugin.Id)))">Install</a>
}else{
if (Version.Parse(plugin.LatestVersion) > installedPlugin.Version){
<a class="pluginUpdateLink button" href="@(Url.Action(MVC.API.Plugin.Update(plugin.Id)))">Update</a>
}else{
<a class="pluginInstalledLink button disabled" href="#">Installed</a>
}
}
</h2>
<div class="pluginItemBlurb">@(new HtmlString(plugin.Blurb))</div> <div class="pluginItemBlurb">@(new HtmlString(plugin.Blurb))</div>
<div class="pageMenuBlurb"> <div class="pageMenuBlurb">
<span class="pluginId">@plugin.Id</span> | <span class="pluginVersion">v@(plugin.LatestVersion)</span> | @plugin.Author | <a href="@plugin.Url" target="_blank">More Information</a> <span class="pluginId">@plugin.Id</span> | <span class="pluginVersion">v@(plugin.LatestVersion)</span> | @plugin.Author | <a href="@plugin.Url" target="_blank">More Information</a>
@@ -100,14 +109,26 @@
$selectedPlugin = $this.closest('.pluginItem'); $selectedPlugin = $this.closest('.pluginItem');
$selectedPluginUrl = $this.attr('href'); $selectedPluginUrl = $this.attr('href');
if ($selectedPlugin.is('.pluginInstalled')) { $('#dialogInstallPluginName').text($selectedPlugin.find('.pluginName').text());
alert('This plugin is already installed.'); $('#dialogInstallPluginDetails').text($selectedPlugin.find('.pluginId').text() + ' | ' + $selectedPlugin.find('.pluginVersion').text());
} else {
$('#dialogInstallPluginName').text($selectedPlugin.find('.pluginName').text()); $dialogInstall.dialog('option', 'title', 'Install this Plugin?');
$('#dialogInstallPluginDetails').text($selectedPlugin.find('.pluginId').text() + ' | ' + $selectedPlugin.find('.pluginVersion').text()); $dialogInstall.dialog('open');
return false;
});
$('#pageMenu').find('a.pluginUpdateLink').click(function () {
$this = $(this);
$selectedPlugin = $this.closest('.pluginItem');
$selectedPluginUrl = $this.attr('href');
$('#dialogInstallPluginName').text($selectedPlugin.find('.pluginName').text());
$('#dialogInstallPluginDetails').text($selectedPlugin.find('.pluginId').text() + ' | ' + $selectedPlugin.find('.pluginVersion').text());
$dialogInstall.dialog('option', 'title', 'Update this Plugin?');
$dialogInstall.dialog('open');
$dialogInstall.dialog('open');
}
return false; return false;
}); });
@@ -147,39 +147,26 @@ WriteLiteral(" <td>\r\n");
{ {
var plugin = plugins[itemNextId]; var plugin = plugins[itemNextId];
itemNextId++; itemNextId++;
var installedPlugin = Plugins.PluginInstalled(plugin.Id) ? Plugins.GetPlugin(plugin.Id) : null;
#line default #line default
#line hidden #line hidden
WriteLiteral(" <div"); WriteLiteral(" <div");
WriteAttribute("class", Tuple.Create(" class=\"", 1328), Tuple.Create("\"", 1432) WriteAttribute("class", Tuple.Create(" class=\"", 1449), Tuple.Create("\"", 1542)
, Tuple.Create(Tuple.Create("", 1336), Tuple.Create("pageMenuArea", 1336), true) , Tuple.Create(Tuple.Create("", 1457), Tuple.Create("pageMenuArea", 1457), true)
, Tuple.Create(Tuple.Create(" ", 1348), Tuple.Create("pluginItem", 1349), true) , Tuple.Create(Tuple.Create(" ", 1469), Tuple.Create("pluginItem", 1470), true)
#line 31 "..\..\Areas\Config\Views\Plugins\Install.cshtml"
, Tuple.Create(Tuple.Create("", 1359), Tuple.Create<System.Object, System.Int32>(Plugins.PluginInstalled(plugin.Id) ? " pluginInstalled" : string.Empty
#line default
#line hidden
, 1359), false)
);
WriteLiteral(">\r\n <a");
WriteLiteral(" class=\"pluginInstallLink\"");
WriteAttribute("href", Tuple.Create(" href=\"", 1496), Tuple.Create("\"", 1551)
#line 32 "..\..\Areas\Config\Views\Plugins\Install.cshtml" #line 32 "..\..\Areas\Config\Views\Plugins\Install.cshtml"
, Tuple.Create(Tuple.Create("", 1503), Tuple.Create<System.Object, System.Int32>(Url.Action(MVC.API.Plugin.Install(plugin.Id)) , Tuple.Create(Tuple.Create("", 1480), Tuple.Create<System.Object, System.Int32>(installedPlugin != null ? " pluginInstalled" : string.Empty
#line default #line default
#line hidden #line hidden
, 1503), false) , 1480), false)
); );
WriteLiteral(">\r\n <h2"); WriteLiteral(">\r\n <h2");
WriteLiteral(" class=\"pluginName\""); WriteLiteral(" class=\"pluginName\"");
@@ -187,20 +174,97 @@ WriteLiteral(">");
#line 33 "..\..\Areas\Config\Views\Plugins\Install.cshtml" #line 33 "..\..\Areas\Config\Views\Plugins\Install.cshtml"
Write(plugin.Name); Write(plugin.Name);
#line default #line default
#line hidden #line hidden
WriteLiteral("</h2>\r\n </a>\r\n <div" + WriteLiteral("\r\n");
"");
#line 34 "..\..\Areas\Config\Views\Plugins\Install.cshtml"
#line default
#line hidden
#line 34 "..\..\Areas\Config\Views\Plugins\Install.cshtml"
if (installedPlugin == null){
#line default
#line hidden
WriteLiteral(" <a");
WriteLiteral(" class=\"pluginInstallLink button\"");
WriteAttribute("href", Tuple.Create(" href=\"", 1754), Tuple.Create("\"", 1809)
#line 35 "..\..\Areas\Config\Views\Plugins\Install.cshtml"
, Tuple.Create(Tuple.Create("", 1761), Tuple.Create<System.Object, System.Int32>(Url.Action(MVC.API.Plugin.Install(plugin.Id))
#line default
#line hidden
, 1761), false)
);
WriteLiteral(">Install</a>\r\n");
#line 36 "..\..\Areas\Config\Views\Plugins\Install.cshtml"
}else{
if (Version.Parse(plugin.LatestVersion) > installedPlugin.Version){
#line default
#line hidden
WriteLiteral(" <a");
WriteLiteral(" class=\"pluginUpdateLink button\"");
WriteAttribute("href", Tuple.Create(" href=\"", 2047), Tuple.Create("\"", 2101)
#line 38 "..\..\Areas\Config\Views\Plugins\Install.cshtml"
, Tuple.Create(Tuple.Create("", 2054), Tuple.Create<System.Object, System.Int32>(Url.Action(MVC.API.Plugin.Update(plugin.Id))
#line default
#line hidden
, 2054), false)
);
WriteLiteral(">Update</a> \r\n");
#line 39 "..\..\Areas\Config\Views\Plugins\Install.cshtml"
}else{
#line default
#line hidden
WriteLiteral(" <a");
WriteLiteral(" class=\"pluginInstalledLink button disabled\"");
WriteLiteral(" href=\"#\"");
WriteLiteral(">Installed</a> \r\n");
#line 41 "..\..\Areas\Config\Views\Plugins\Install.cshtml"
}
}
#line default
#line hidden
WriteLiteral(" </h2>\r\n <div");
WriteLiteral(" class=\"pluginItemBlurb\""); WriteLiteral(" class=\"pluginItemBlurb\"");
WriteLiteral(">"); WriteLiteral(">");
#line 35 "..\..\Areas\Config\Views\Plugins\Install.cshtml" #line 44 "..\..\Areas\Config\Views\Plugins\Install.cshtml"
Write(new HtmlString(plugin.Blurb)); Write(new HtmlString(plugin.Blurb));
@@ -217,7 +281,7 @@ WriteLiteral(" class=\"pluginId\"");
WriteLiteral(">"); WriteLiteral(">");
#line 37 "..\..\Areas\Config\Views\Plugins\Install.cshtml" #line 46 "..\..\Areas\Config\Views\Plugins\Install.cshtml"
Write(plugin.Id); Write(plugin.Id);
@@ -230,7 +294,7 @@ WriteLiteral(" class=\"pluginVersion\"");
WriteLiteral(">v"); WriteLiteral(">v");
#line 37 "..\..\Areas\Config\Views\Plugins\Install.cshtml" #line 46 "..\..\Areas\Config\Views\Plugins\Install.cshtml"
Write(plugin.LatestVersion); Write(plugin.LatestVersion);
@@ -239,7 +303,7 @@ WriteLiteral(">v");
WriteLiteral("</span> | "); WriteLiteral("</span> | ");
#line 37 "..\..\Areas\Config\Views\Plugins\Install.cshtml" #line 46 "..\..\Areas\Config\Views\Plugins\Install.cshtml"
Write(plugin.Author); Write(plugin.Author);
@@ -247,14 +311,14 @@ WriteLiteral("</span> | ");
#line hidden #line hidden
WriteLiteral(" | <a"); WriteLiteral(" | <a");
WriteAttribute("href", Tuple.Create(" href=\"", 1992), Tuple.Create("\"", 2010) WriteAttribute("href", Tuple.Create(" href=\"", 2716), Tuple.Create("\"", 2734)
#line 37 "..\..\Areas\Config\Views\Plugins\Install.cshtml" #line 46 "..\..\Areas\Config\Views\Plugins\Install.cshtml"
, Tuple.Create(Tuple.Create("", 1999), Tuple.Create<System.Object, System.Int32>(plugin.Url , Tuple.Create(Tuple.Create("", 2723), Tuple.Create<System.Object, System.Int32>(plugin.Url
#line default #line default
#line hidden #line hidden
, 1999), false) , 2723), false)
); );
WriteLiteral(" target=\"_blank\""); WriteLiteral(" target=\"_blank\"");
@@ -263,7 +327,7 @@ WriteLiteral(">More Information</a>\r\n </div>\r\
" </div>\r\n"); " </div>\r\n");
#line 40 "..\..\Areas\Config\Views\Plugins\Install.cshtml" #line 49 "..\..\Areas\Config\Views\Plugins\Install.cshtml"
} }
@@ -272,7 +336,7 @@ WriteLiteral(">More Information</a>\r\n </div>\r\
WriteLiteral("\r\n </td>\r\n"); WriteLiteral("\r\n </td>\r\n");
#line 43 "..\..\Areas\Config\Views\Plugins\Install.cshtml" #line 52 "..\..\Areas\Config\Views\Plugins\Install.cshtml"
} }
@@ -281,7 +345,7 @@ WriteLiteral("\r\n </td>\r\n");
WriteLiteral(" </tr>\r\n </table>\r\n"); WriteLiteral(" </tr>\r\n </table>\r\n");
#line 46 "..\..\Areas\Config\Views\Plugins\Install.cshtml" #line 55 "..\..\Areas\Config\Views\Plugins\Install.cshtml"
} }
@@ -328,13 +392,13 @@ WriteLiteral(" style=\"padding-bottom: 10px;\"");
WriteLiteral(">\r\n"); WriteLiteral(">\r\n");
#line 59 "..\..\Areas\Config\Views\Plugins\Install.cshtml" #line 68 "..\..\Areas\Config\Views\Plugins\Install.cshtml"
#line default #line default
#line hidden #line hidden
#line 59 "..\..\Areas\Config\Views\Plugins\Install.cshtml" #line 68 "..\..\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" }))
{ {
@@ -358,7 +422,7 @@ WriteLiteral(" type=\"file\"");
WriteLiteral(" />\r\n"); WriteLiteral(" />\r\n");
#line 63 "..\..\Areas\Config\Views\Plugins\Install.cshtml" #line 72 "..\..\Areas\Config\Views\Plugins\Install.cshtml"
} }
@@ -391,25 +455,32 @@ WriteLiteral("></span>Warning: All plugins run with the same level of network pr
" $(this).dialog(\"close\");\r\n }\r\n }\r\n }" + " $(this).dialog(\"close\");\r\n }\r\n }\r\n }" +
");\r\n $(\'#pageMenu\').find(\'a.pluginInstallLink\').click(function () {\r\n " + ");\r\n $(\'#pageMenu\').find(\'a.pluginInstallLink\').click(function () {\r\n " +
" $this = $(this);\r\n\r\n $selectedPlugin = $this.closest(\'.plugin" + " $this = $(this);\r\n\r\n $selectedPlugin = $this.closest(\'.plugin" +
"Item\');\r\n $selectedPluginUrl = $this.attr(\'href\');\r\n\r\n if " + "Item\');\r\n $selectedPluginUrl = $this.attr(\'href\');\r\n\r\n $(\'" +
"($selectedPlugin.is(\'.pluginInstalled\')) {\r\n alert(\'This plugin i" + "#dialogInstallPluginName\').text($selectedPlugin.find(\'.pluginName\').text());\r\n " +
"s already installed.\');\r\n } else {\r\n $(\'#dialogInstall" + " $(\'#dialogInstallPluginDetails\').text($selectedPlugin.find(\'.pluginId\'" +
"PluginName\').text($selectedPlugin.find(\'.pluginName\').text());\r\n " + ").text() + \' | \' + $selectedPlugin.find(\'.pluginVersion\').text());\r\n\r\n " +
" $dialogInstall.dialog(\'option\', \'title\', \'Install this Plugin?\');\r\n " +
" $dialogInstall.dialog(\'open\');\r\n\r\n return false;\r\n });\r\n " +
" $(\'#pageMenu\').find(\'a.pluginUpdateLink\').click(function () {\r\n $t" +
"his = $(this);\r\n\r\n $selectedPlugin = $this.closest(\'.pluginItem\');\r\n " +
" $selectedPluginUrl = $this.attr(\'href\');\r\n\r\n $(\'#dialogIns" +
"tallPluginName\').text($selectedPlugin.find(\'.pluginName\').text());\r\n " +
"$(\'#dialogInstallPluginDetails\').text($selectedPlugin.find(\'.pluginId\').text() +" + "$(\'#dialogInstallPluginDetails\').text($selectedPlugin.find(\'.pluginId\').text() +" +
" \' | \' + $selectedPlugin.find(\'.pluginVersion\').text());\r\n\r\n $dia" + " \' | \' + $selectedPlugin.find(\'.pluginVersion\').text());\r\n\r\n $dialogI" +
"logInstall.dialog(\'open\');\r\n }\r\n return false;\r\n })" + "nstall.dialog(\'option\', \'title\', \'Update this Plugin?\');\r\n $dialogIns" +
";\r\n\r\n // Upload\r\n var $dialogUpload = $(\'#dialogUploadPlugin\').dia" + "tall.dialog(\'open\');\r\n\r\n return false;\r\n });\r\n\r\n // Upl" +
"log({\r\n resizable: false,\r\n modal: true,\r\n widt" + "oad\r\n var $dialogUpload = $(\'#dialogUploadPlugin\').dialog({\r\n " +
"h: 350,\r\n autoOpen: false,\r\n buttons: {\r\n \"" + "resizable: false,\r\n modal: true,\r\n width: 350,\r\n " +
"Upload & Install\": function () {\r\n var pluginFile = $(\'#plugi" + " autoOpen: false,\r\n buttons: {\r\n \"Upload & Install\": " +
"nFile\');\r\n if (pluginFile.val()) {\r\n p" + "function () {\r\n var pluginFile = $(\'#pluginFile\');\r\n " +
"luginFile.closest(\'form\').submit();\r\n $(this).dialog(\'dis" + " if (pluginFile.val()) {\r\n pluginFile.closest(\'" +
"able\');\r\n } else {\r\n alert(\'Choose a P" + "form\').submit();\r\n $(this).dialog(\'disable\');\r\n " +
"lugin Package to Upload\');\r\n }\r\n },\r\n " + " } else {\r\n alert(\'Choose a Plugin Package to Up" +
" Cancel: function () {\r\n $(this).dialog(\"close\");\r\n " + "load\');\r\n }\r\n },\r\n Cancel: func" +
" }\r\n }\r\n });\r\n $(\'#buttonUpload\').click(func" + "tion () {\r\n $(this).dialog(\"close\");\r\n }\r\n " +
"tion () {\r\n $dialogUpload.dialog(\'open\');\r\n return false;\r" + " }\r\n });\r\n $(\'#buttonUpload\').click(function () {\r\n " +
"\n });\r\n });\r\n</script>\r\n<div"); " $dialogUpload.dialog(\'open\');\r\n return false;\r\n });\r\n }" +
");\r\n</script>\r\n<div");
WriteLiteral(" class=\"actionBar\""); WriteLiteral(" class=\"actionBar\"");
@@ -418,7 +489,7 @@ WriteLiteral(">\r\n");
WriteLiteral(" "); WriteLiteral(" ");
#line 142 "..\..\Areas\Config\Views\Plugins\Install.cshtml" #line 163 "..\..\Areas\Config\Views\Plugins\Install.cshtml"
Write(Html.ActionLinkButton("Update Catalogue", MVC.API.Plugin.UpdateLibraryCatalogue())); Write(Html.ActionLinkButton("Update Catalogue", MVC.API.Plugin.UpdateLibraryCatalogue()));
@@ -429,7 +500,7 @@ WriteLiteral("\r\n");
WriteLiteral(" "); WriteLiteral(" ");
#line 143 "..\..\Areas\Config\Views\Plugins\Install.cshtml" #line 164 "..\..\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"));
+9 -8
View File
@@ -1,4 +1,4 @@
/*#source /ClientSource/Style/jQueryUI/jquery-ui.css */ /*#source /ClientSource/Style/jQueryUI/jquery-ui.css */
/*! /*!
* jQuery UI CSS Framework 1.8.19 * jQuery UI CSS Framework 1.8.19
* *
@@ -563,8 +563,8 @@ button.ui-button::-moz-focus-inner { border: 0; padding: 0; } /* reset extra pad
* http://docs.jquery.com/UI/Progressbar#theming * http://docs.jquery.com/UI/Progressbar#theming
*/ */
.ui-progressbar { height:2em; text-align: left; overflow: hidden; } .ui-progressbar { height:2em; text-align: left; overflow: hidden; }
.ui-progressbar .ui-progressbar-value {margin: -1px; height:100%; } .ui-progressbar .ui-progressbar-value {margin: -1px; height:100%; }
/*#source /ClientSource/Style/Site.css */ /*#source /ClientSource/Style/Site.css */
.tableData { .tableData {
border: solid 1px #e8eef4; border: solid 1px #e8eef4;
border-collapse: collapse; border-collapse: collapse;
@@ -906,6 +906,7 @@ a:active {
color: #335a87; color: #335a87;
} }
a.button { a.button {
display: inline-block;
padding: 4px 10px; padding: 4px 10px;
margin: 2px; margin: 2px;
border: 1px solid #875a33; border: 1px solid #875a33;
@@ -914,11 +915,11 @@ a.button {
font-weight: bold; font-weight: bold;
text-transform: uppercase; text-transform: uppercase;
cursor: pointer; cursor: pointer;
line-height: 2.2em;
white-space: nowrap; white-space: nowrap;
text-decoration: none; text-decoration: none;
} }
a.button[disabled] { a.button[disabled],
a.button.disabled {
background: #9e9e9e; background: #9e9e9e;
border: 1px solid #696969; border: 1px solid #696969;
cursor: default; cursor: default;
@@ -1357,7 +1358,8 @@ input[type="submit"] {
padding: 5px; padding: 5px;
} }
input[type="submit"].button { input[type="submit"].button {
padding: 4px 10px; font-size: 12px;
padding: 6px 10px 4px 10px;
margin: 2px; margin: 2px;
border: 1px solid #875a33; border: 1px solid #875a33;
background: #db761d; background: #db761d;
@@ -1365,7 +1367,6 @@ input[type="submit"].button {
font-weight: bold; font-weight: bold;
text-transform: uppercase; text-transform: uppercase;
cursor: pointer; cursor: pointer;
line-height: 1.2em;
} }
input[type="submit"].button:hover { input[type="submit"].button:hover {
border: 1px solid #696969; border: 1px solid #696969;
@@ -1686,4 +1687,4 @@ textarea.block {
{ {
font-weight: bold; font-weight: bold;
}*/ }*/
+1 -1
View File
@@ -1 +1 @@
.ui-helper-hidden{display:none}.ui-helper-hidden-accessible{position:absolute!important;clip:rect(1px 1px 1px 1px);clip:rect(1px,1px,1px,1px)}.ui-helper-reset{margin:0;padding:0;border:0;outline:0;line-height:1.3;text-decoration:none;font-size:100%;list-style:none}.ui-helper-clearfix:before,.ui-helper-clearfix:after{content:"";display:table}.ui-helper-clearfix:after{clear:both}.ui-helper-clearfix{zoom:1}.ui-helper-zfix{width:100%;height:100%;top:0;left:0;position:absolute;opacity:0;filter:Alpha(Opacity=0)}.ui-state-disabled{cursor:default!important}.ui-icon{display:block;text-indent:-99999px;overflow:hidden;background-repeat:no-repeat}.ui-widget-overlay{position:absolute;top:0;left:0;width:100%;height:100%}.ui-widget{font-family:Trebuchet MS,Tahoma,Verdana,Arial,sans-serif;font-size:1.1em}.ui-widget .ui-widget{font-size:1em}.ui-widget input,.ui-widget select,.ui-widget textarea,.ui-widget button{font-family:Trebuchet MS,Tahoma,Verdana,Arial,sans-serif;font-size:1em}.ui-widget-content{border:1px solid #ddd;background:#eee url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAABkCAYAAABHLFpgAAAAIUlEQVQYlWP48ePHfyYGBgaGIUT8//8fO5cSFn6J4UQAAJSgIpAFCJPdAAAAAElFTkSuQmCC) 50% top repeat-x;color:#333}.ui-widget-content a{color:#333}.ui-widget-header{border:1px solid #e78f08;background:#f6a828 url(data:image/png;base64,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) 50% 50% repeat-x;color:#fff;font-weight:bold}.ui-widget-header a{color:#fff}.ui-state-default,.ui-widget-content .ui-state-default,.ui-widget-header .ui-Line truncated .ui-helper-hidden{display:none}.ui-helper-hidden-accessible{position:absolute!important;clip:rect(1px 1px 1px 1px);clip:rect(1px,1px,1px,1px)}.ui-helper-reset{margin:0;padding:0;border:0;outline:0;line-height:1.3;text-decoration:none;font-size:100%;list-style:none}.ui-helper-clearfix:before,.ui-helper-clearfix:after{content:"";display:table}.ui-helper-clearfix:after{clear:both}.ui-helper-clearfix{zoom:1}.ui-helper-zfix{width:100%;height:100%;top:0;left:0;position:absolute;opacity:0;filter:Alpha(Opacity=0)}.ui-state-disabled{cursor:default!important}.ui-icon{display:block;text-indent:-99999px;overflow:hidden;background-repeat:no-repeat}.ui-widget-overlay{position:absolute;top:0;left:0;width:100%;height:100%}.ui-widget{font-family:Trebuchet MS,Tahoma,Verdana,Arial,sans-serif;font-size:1.1em}.ui-widget .ui-widget{font-size:1em}.ui-widget input,.ui-widget select,.ui-widget textarea,.ui-widget button{font-family:Trebuchet MS,Tahoma,Verdana,Arial,sans-serif;font-size:1em}.ui-widget-content{border:1px solid #ddd;background:#eee url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAABkCAYAAABHLFpgAAAAIUlEQVQYlWP48ePHfyYGBgaGIUT8//8fO5cSFn6J4UQAAJSgIpAFCJPdAAAAAElFTkSuQmCC) 50% top repeat-x;color:#333}.ui-widget-content a{color:#333}.ui-widget-header{border:1px solid #e78f08;background:#f6a828 url(data:image/png;base64,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) 50% 50% repeat-x;color:#fff;font-weight:bold}.ui-widget-header a{color:#fff}.ui-state-default,.ui-widget-content .ui-state-default,.ui-widget-header .ui-Line truncated
+17 -24
View File
@@ -81,15 +81,18 @@
float: right; float: right;
border: 1px dashed #ddd; border: 1px dashed #ddd;
background-color: #fff; background-color: #fff;
line-height: 1.5em;
font-size: 0.6em; font-size: 0.6em;
padding: 4px 4px 4px 70px; line-height: 1em;
padding: 4px 10px 4px 70px;
text-align: right; text-align: right;
height: 64px; height: 64px;
background-image: url(data:image/png;base64,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 truncated background-image: url(data:image/png;base64,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 truncated
background-position: 10px center; background-position: 10px center;
background-repeat: no-repeat; background-repeat: no-repeat;
} }
#updateAvailableContainer a.button {
margin-top: 16px;
}
#expressionEditor #expressionEditorExceptionContainer { #expressionEditor #expressionEditorExceptionContainer {
display: none; display: none;
border: 1px dashed #FF9696; border: 1px dashed #FF9696;
@@ -728,15 +731,16 @@ div.logEventsViewport table.logEventsViewport > tbody > tr > td.eventType {
#plugins .pageMenuArea a > h3:hover { #plugins .pageMenuArea a > h3:hover {
color: #4f81bd; color: #4f81bd;
} }
#plugins #pageMenu td .pageMenuArea > a {
background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAAZiS0dEAP8A/wD/oL2nkwAAAAlwSFlzAAALEwAACxMBAJqcGAAAAAd0SU1FB90CDRcZMTlpMjsAAAKbSURBVDjLbZHBS2NHHMc/82ZeXpLaiNJHDylF6KEIGxFa0Jtdi4IFqfQq2P/As4f9D0rwplIwsDlZiofHStaTVQJCj+6a9SpKL3HhkTx5cZLMTA9uHov4Pf2Y33w/fL8z4vj4mHfv3vNUHz60ouXl5VmtNScnJ3eVmZkfn96ZqVRQj6P7HXj56VwAFAqFsenp6W+73S7NZjMRUH/iPwVqnwC8nJ2drU9NTb3I5XIDpVS6u7v7qlQqEQQBxWLxq83NzX+EEIUkSYJ8Pj+xs7Pz0+cAyuXyTqPR+F5KiTEGrTVCCHzfR2v99d7eXg3AGMPGxsZb4CPwWEEIAUC73ebm5gYhBKVSiTiOcc4RBAHn5+dYa9Fas76+nvXIEvi+jzEG5xyrq6vEcczV1RW+77O2tka73WZ/f58wDHHOZQBvNEgp6ff7hGHI4eEhSinOzs64uLjg+vqaWq3GYDBASom19vkEWmuMMYyPjxNFEUtLS1hrOTg4wBiD53k4554HeJ6H1pp+v59VaTQaWGuRUqKUYjAYADwPcM6Rpim9Xg9jDFJKgiBASokQAuccDw8P5PP5ZwHOOUe1WsU5hxACz/Oy3xlplCZJkmw3Apw2m81fx8bGEEJkFay12YuPDMPhkDiOvwP+/gwgXhtjTq21Yb/fTyuVysPt7e3PW1tbf/q+T7Va/U0p9b7VahW11vlOp3Pt53JtAOI4RimFUgohRG5+fv6Po6Ojf7e3twcLCwtucXHR1ev1NIqiN3Nzc6+klEUpJVJK7u/vEXEcE4YhgJBSfjE5OfnDysrKX4VC4ctSqdQCXKfTedHr9T5GUfRLmqb/DYfDBDB3d3ePgJGSJOHy8pJOt4vneQS5HABaa6xzfFMuUy6XmZiYyDz/AxHBRmZKLqH0AAAAAElFTkSuQmCC) /*Images/Actions/pluginDownloadIcon16.png*/;
}
#plugins #pageMenu td .pageMenuArea > a:hover {
background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAC4klEQVQ4jWWRTWhcVRTHf/fd+958JJMw+aDFaYNUtChNTDHYFBdNm4K0IEI3lW7ErZR2IWhKi0tba6gBMRAXhaYiiJskjRgENWlVEC3VJrGFgpaIaetMM515kzfzvu51kZmhxrM6i3N+nN//iLm5OW7eXGRznXfHpg8eGui/zwqLs4X8O9kTA5tn+np7UfX+dWB/vRcAyXSidXDHSz23dIrbqugCk5v254GLDcD+/v7dkzue3L4rpdJhlAi8qanZM52ZTp4xz5FN3u46efLN7xyTSJUqawk72ZL9eHx86HEAT+S2jU98fXenUAoT2sj1LSAiElKh11u3vDuxfNGXNVS0zsixga+AAlBXEGCwuPUwxa/l4ygrINWeYdW9x0rLHYK2R0z8+Qpx1EX64QHePrq76aEa0sqWRJHGijO8+Fobzqrk+z+uUWor0PeGQ3l1Owvvu2x19qGN3ggKsBokqRTVMKAnMcrVS6vca8/z48K3/H7jNx7cCVk4l0YXziNUhNGmeUETYCuFF2jKtQpdfMQvl6s8/fyz9HTs5OfxNXTpLVA+xoDWuvGs5huRlqTqx1RCTRz7BOWzXP9sFGMewPoEMuUTBxag6wD+C8Bo3GrEWk0QaMC2SIjTWEoiOkOMsfGqGidZxfwfIIw2mm/eO4g2gBBYlkCIRsQbzlqDY2mi8v2GQfOC+R+uXX01lWlHCIsojqDuqo0BDJbYiCsKA0rFwlPAF48DLsVxPG/FfnfoB15vX2/tr5WV4ZFTI5/Yymb0woUjtrIXl5cX0zU/TD4quXdtR/0DQLFYRCmFUgohhLN3cO8HV2a//Gnsw7FwaN+QGT4wbC5PfurNTM9cGdwzeEZKmZZSIqWkUqkgisUi3d3dAEJK2dLR0fHCy4cOf55OpTPtba3LgCmV3F1e1SvMTE8d9jzv7yiKXCDO5/MbgEa5rsvS0hKlchnLskg4DgC+76ONYVsuRy6XI5vNNnf+BS/0P9OBtw+RAAAAAElFTkSuQmCC) /*Images/Actions/pluginDownloadIconHover16.png*/;
}
#pluginCatalog #pluginCatalogHeading { #pluginCatalog #pluginCatalogHeading {
margin-bottom: 20px; margin-bottom: 20px;
text-align: right; text-align: right;
} }
#pluginCatalog .pluginItem.pluginInstalled > a:first-child h2:after {
content: ' [Installed]';
font-size: .8em;
font-weight: bold;
}
#pluginCatalog .pluginItem .pluginItemBlurb { #pluginCatalog .pluginItem .pluginItemBlurb {
margin: 4px 0 4px 2px; margin: 4px 0 4px 2px;
padding: 0 4px; padding: 0 4px;
@@ -746,25 +750,14 @@ div.logEventsViewport table.logEventsViewport > tbody > tr > td.eventType {
padding: 0; padding: 0;
margin: 0; margin: 0;
} }
#pluginCatalog .pluginItem > a:first-child { #pluginCatalog .pluginItem > h2:first-child {
padding-left: 30px; padding-left: 20px;
background-image: url(data:image/png;base64,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 truncated background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAC4klEQVQ4jWWRTWhcVRTHf/fd+958JJMw+aDFaYNUtChNTDHYFBdNm4K0IEI3lW7ErZR2IWhKi0tba6gBMRAXhaYiiJskjRgENWlVEC3VJrGFgpaIaetMM515kzfzvu51kZmhxrM6i3N+nN//iLm5OW7eXGRznXfHpg8eGui/zwqLs4X8O9kTA5tn+np7UfX+dWB/vRcAyXSidXDHSz23dIrbqugCk5v254GLDcD+/v7dkzue3L4rpdJhlAi8qanZM52ZTp4xz5FN3u46efLN7xyTSJUqawk72ZL9eHx86HEAT+S2jU98fXenUAoT2sj1LSAiElKh11u3vDuxfNGXNVS0zsixga+AAlBXEGCwuPUwxa/l4ygrINWeYdW9x0rLHYK2R0z8+Qpx1EX64QHePrq76aEa0sqWRJHGijO8+Fobzqrk+z+uUWor0PeGQ3l1Owvvu2x19qGN3ggKsBokqRTVMKAnMcrVS6vca8/z48K3/H7jNx7cCVk4l0YXziNUhNGmeUETYCuFF2jKtQpdfMQvl6s8/fyz9HTs5OfxNXTpLVA+xoDWuvGs5huRlqTqx1RCTRz7BOWzXP9sFGMewPoEMuUTBxag6wD+C8Bo3GrEWk0QaMC2SIjTWEoiOkOMsfGqGidZxfwfIIw2mm/eO4g2gBBYlkCIRsQbzlqDY2mi8v2GQfOC+R+uXX01lWlHCIsojqDuqo0BDJbYiCsKA0rFwlPAF48DLsVxPG/FfnfoB15vX2/tr5WV4ZFTI5/Yymb0woUjtrIXl5cX0zU/TD4quXdtR/0DQLFYRCmFUgohhLN3cO8HV2a//Gnsw7FwaN+QGT4wbC5PfurNTM9cGdwzeEZKmZZSIqWkUqkgisUi3d3dAEJK2dLR0fHCy4cOf55OpTPtba3LgCmV3F1e1SvMTE8d9jzv7yiKXCDO5/MbgEa5rsvS0hKlchnLskg4DgC+76ONYVsuRy6XI5vNNnf+BS/0P9OBtw+RAAAAAElFTkSuQmCC) /*Images/Actions/pluginDownloadIconHover16.png*/;
background-position: left center; background-position: left center;
background-repeat: no-repeat; background-repeat: no-repeat;
min-height: 22px; min-height: 22px;
} }
#pluginCatalog .pluginItem > a:first-child:hover { #pluginCatalog .pluginItem > h2:first-child a {
background-image: url(data:image/png;base64,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 truncated float: right;
} font-size: 12px;
#pluginCatalog .pluginItem > a:first-child h2 {
display: inline;
color: #335a87;
}
#pluginCatalog .pluginItem > a:first-child h2:hover {
color: #4f81bd;
}
#pluginCatalog .pluginItem:not(.pluginInstalled) > a:first-child h2:hover:after {
font-size: .8em;
font-weight: bold;
content: ' < Install';
} }
+23 -36
View File
@@ -16,14 +16,17 @@
float: right; float: right;
border: 1px dashed #ddd; border: 1px dashed #ddd;
background-color: #fff; background-color: #fff;
line-height: 1.5em;
font-size: 0.6em; font-size: 0.6em;
padding: 4px 4px 4px 70px; line-height: 1em;
padding: 4px 10px 4px 70px;
text-align: right; text-align: right;
height: 64px; height: 64px;
background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADEAAABACAYAAACz4p94AAAVPUlEQVRo3s2aWaxk13Wev7X3PkONd+6+PQ+cmoNItkha4iCYtBVLpGQ7MkQ78EMICBZt+EFAAENMgAAKkAQInYcEQR6Sl8AKHE1OBBkg2YJFKS0O8iCSgimymyLZTXY3e+471q1bVWfYKw/7nLrVDCkDQQNhNQ7OrdNVe69/Tf9aa5dwLV+P/ycOuE1z8fxZKaa2U4pQYkEBY0m3tZk79pKePXbc8/ZPrtm27pqscvfn4aWnYO+exq5WvqCptUOXMHAJmYkZFYpzMfO7usysnSnOvnnqIpB9tEC89BQArW5zenpK7ugPB+nQRLRtQm4tK3lJZCKmui1ttFt9Ytf76IGoXs00WUib9oHp6dlOZoyU4siNxY9KrHV0Gw1Va5dw9nVg9SMJIo3jxTSJPjnXbc8UYqWwjhzDMCmxxtFsNXQTvUDkvguc/kiCEGsX4ii6ud3tTJXGUIhjKJbesERcRLedMvB+Gmu713LfawoC9Q1nbDrTdHFpHKWxbIil5RTjItrNhEtIijWNjyyIIi8iI0g3TSisozQOVUPTCDZKaDYjBBVEoo8siOFoJKinncTk1lLaiEwtqXNESUI3teABMeYjC2IwGIovSpqxIzeO0jr6RKQupptEbIs8AmBEP7og+hv4vCB2DmsdhYtwGtHEMR8J2xyIEhj8IxvYvR5lNsIaQYxBjMFhaakw42C23k2uLYhr6ptcPJ8x3FQjghXBVEASK7Ss0A67KSvr2TW1xF9897uRM/aPW63mnla7U7Zb7bC5UN0FEETkqmfhOUglrBHDn3z32cM220yCpDJWuAGsASuQRK79L77y2Jef+Mf/40EFUdlaQyb2kbAZBkFRijwnyzLyoiDPMrJwRXme/5UzmEjEfBkxtwqCMeHaEnTr76ufT2wuAqIcmmlxYZDhvWppVEpVCpQcyD1kHk0i17hp1/bfCZKCqdarARgRMBPPjCAalBeAMt5bVVHV0llr1BjJjAhxHBEnCda6qzRvEMSAiA2LimDEhA3HloDIOWBEXnopjacsPUP19MXQK6HnEUWI4pi02awiPAgKEnxbggWlAmOqTxljq2ASvCp5ntcgCmeMwVpLmjb43z/8AUl+kZgMjEHiGfCKiWJwCUWRUSKIsYhmCAXYFCmGiHpeO9OnffAuhmVJQYliGPmCnhiuGEvHwWiwyQ/+15+z9uPv4FUxrS6MelDm+NYUuBhrLNYlaL+HZhkap2AU1ZCieyPLdTffwaFDN6GqODGVyQRmZ2f4/V/7OKkbgFho7YM8g7QFaYdvP3+MYxeWKLMR4kugBBOD5qhXfvOR69HWHFfyAu+FUmHolT5wxSSkubB9cZ5z76zyzsJ1eO+RRgufD1Atybylt3yFe67byR/93iOwdB42N6E9HfKoehDLL05c5u9PXkZV8ao4U7mGmOAew9GIxOeABzsMILBkuXDiSo+p3TsYnrpC7j02jiFK8HEoM664Kdpxh41hTmkVXyr9smCoJasopcbc8IV/ip69xFkxlB5GvmRQKFnpaS6f442Xv0e/P+IPP9cjGg7wg0GwtlPAIxjyLCQ3r4r3HmeMxRiDrYCIelCtcrkHLcF7sMqt844jr73JjGuSJjFeCzAxpYB3EecHOX60hroIb0vUejZKYVNzVD1FUdCLYpL5nSGuVJGywOQFjTyjf+Uktx7azx/efx2qHnwRLi2DTOpBlPAP1AdZnYihdiljBFGt4s2AKqIlqiWxFT51/SL9Qcb3//49ZrrTWCMwKiiTnCIuKKIUtQ51Bd6EewBhKIuCOI6JXMTAGkQMqp6yLMnzgrXXX2Hz2F/zxMO3cc/BBZy1qJbgC8SXiCe8F0UqylclxIQ1ghVDbZGAQBFAvQa03qOqzDQiHr59H14MT798km67SzYYoUlOkeRkcY6PEtRGqHV4F7Huoe+FIi/IRhkuclhjQcJOZVHgz7zN0k+e5muP3sdv3r6bTjPB4NEyWKPWuPgCjAvSA6o+xERdHhgTcrR6BTWoBMqiAmEq9DPtBv9ob4uffucob7UP0d2xj+EwI48ziiQjixt4F+NdALLuhb4asiQnsg7nHNYaFMEI2LMnOffUf+exqUt8dvYepjrN4DYo+BKKEqlAKFolFB3HhKrianIzxmBN4EcBVAXUI+pRDZZAFclHnDryHeZ+9gx24U3eKn+D0fwBhoMhWdQkS4ZkcUoRJahxbKqQiyXLIqIowloLYmhEFv/eScyrR/l3vzLPPadepX/0e8xddxDTmg7KrvYWLYPc3kPg1XFMqPdVTIgZ1znjCrOuNitLgIIovXff4vVn/idtX3JPcYKPXTjC98pfZ6W7n/5Gn1HcJItSRlGDzMXkJkKsJYoinHMYa2nGERvvnmbb8R/xz29u8pn778c2L/Pa0SPM/Opnmbr9vhDA9d61ArUSqr4pVYqtA9rUJYSOmTFovwwW8Qp5xuWXfsy5c6ssdKApBffl79BZfpav66/zdrSd9fWLAUCUkkUpGjeQOMFGCdZZEudILi6z+/izfDV7ns+4u2m8+HUuvPU6f3t6gH3+R9x+891InF4NwlfZqdawKr7ykBDYxmDFYoxMAg0vT3ApFJ8NeffFH2IdNGxYl7Lknuxd/NJf8d+mPs161mBpdQ1Nm5A0IWmgcYMiiilcxHZTMnv8R/yz/EXuO7SfSy8fZWW9x9sbsOzhF0d/yC2PfQUXdyu3ptoo+H8dqirUZQcOCT4aWHuiMq9X0OB3glIO+lx46xc0I2g76FT9gRYl97oLDDf/mj/vPoTPLRfWVyAeQtKAOEGilL3tBu2Tf8NX+Ts+dd0O+pfe4+JKj5UMBiU0Irhweo3i0llcZ1vwhIoTBII7iSKVbAEEwZ1sFdTGVOVzVUHWwQygYtDL77HZh2YKe5pw0/7dOOsYtOZJdx7kt1cvI8e+z9dbn6KUDku9Nfxwk7jZYrorTJ/8Gf9SfsoDu2fRfMTm5XN4hcgKC9Nt1i/3WPdQnH4Luf5uVEwo5KtqenyvalnvQ+A7I+aqnuCqORJVvaJlQN1bQQQSA7umGnQ+98ew5zYaS6cZPPtnxO8d4wsmY7q3yX9uPcRLMwsUxRBMzMGNd/hXzZ/zwO5FUE/vxHFSUXws7FpY5OIQTlzqgUC5ugRGtgBUZTvGjp/V+vV+HNhm3E7WDldXHrJlDET9OBaKtAtrl2DjOfzLT6MnjpMsLmLzAb+Rr9H0f8OT8X38ZPYG7hmd52sP/Ar3t28nOvkS2d/9JamWuIalZVOW1la5tDLEGkgt2FB8gzFQpeSKfSdA1O7kA9kZa6qmIxC61Ohr6av0ZtIW0xFk3RZrw4L2U/+FlgMtRkQJ2EEPmh0S5/mUDGjrq/zt5lnuu/sT3PHZLxCNNuC9nxMlCS2T0x8V9Df7bI6g8GGac10Lku5U3USAWMRU5CsGEUtojbTiL3C2ql7rahbxW75YVSlad3azO9g/b3i3gPcuLZGnsDOFqQiiNIYogqiBihDHKZ8g5xP2CuyegdVzaDaAPEPSNjZfxoliTLCsBzoWbu5CtLi/2tOCMShVS2wCEJXJmFDcOB5s3TsH9OOsVQWSKMjMAtv2HeSd197GGxiWMPAwLQIugbgRvrPtAOSDYP4dN8KZY/DecWRqO1w6ASgmirBFQeEhq1x2dwo7t7eR3TcEIcWi4pCq1gqEG+TyVWYKgW1sYOyatUWDK1Uto4oJ6BEkSmnf8QDzx95mrSrgRiUMSiX2HrERtKZh1yHozsPmGqxfhuVzUGZw4QTM7Ya1S6gYsjKk1rwM6fqm+YTGXZ+G9mzVtlrUukqxNQipKuzAE95r1ZdP1E8YC+IqdzJj5BgBF5Pefj/7Fzt0LURV0ig8+LIAsWiUQJzCtv0w6MHGCkRpeKYeXAx5Rj4aMSygLKDZbnHjwX3sWFzE3PMZ1MVVSrXBCvUlrpJHxgBUFWOrrKQVP9SaD0FlKi2YauphYM8hFj75aXY0AmsrMPIwynNYOR+aquVz8OK3YfVCXYBBkQcQvoS9t4W9puaZuvlOds9Ps0/WkRvvhv23gnWBl2qlmhDQwQrVPdQQISa8KuI96itKr0B5sePZT52rVUA688iv/j57zhzn0olfkKsGi3iPn9uDGfTgjRcgbYfL2gCgLGB+D9z6a5A0iRf2Y199Ed59ld3b52DXbegnfwvmdoVRp1QArNsKZuuoBjkhvVaWcHW+9eqr9GrQKkZU7ThTCYJi8V7ZWLwB//HPs1hkDC69ByK4zgzSX4Yyh0Yn3LNBCPYoCRqc2QmL1weXeuFbdPoXWTh4EOb2sLH3Dli8gZayxRFS7W9coAqtUr/ZiomrQKhqNRSzCBatSEXEosZUixl86Vm9ssQJWWD/3vs4MHcKVi9CfyWkw6iDRCl0F2B2V4gHY4NLrV+Gn/4l2miDNaQHPgadWc5Hc7yTd9i9tkE6u4B1QeO1JerArpU8SXbe+8qdKtMIEsxmzFZgm624UITSlww3NxmMCl5inivdNh9vzmI3V6HIYO/H4Pq7gwttLMOwH2Jjcx2KHN1YgmKITG8HhdcGKSdHKXFqGG4OKEvFuio2zURg1y1CVT/pJE+oV1Qqa0CVkydAyOQlGGNxcUKjkTJIUt4cGFbyOe7avshcp4MkLRhshIBuToVUO70tjH6yAZKPwMDKlSv89NQqy1OzNNoNGmlKlKSIDRylbHlBPczAlxX5CYrfak/r+sOrr0BuWQCVii1NVQ4aTGSYmp1hem6ebDREXM5wI+e1K2vs2eiza3aWOEqQRgcaXYga4DZgtIkay6i3xpmzFzi5OmSdJmm7Q6vdYGpmjqmZWZyLtvYzIR5CfNSyVSnWVzGB4upmw3tfpVE7zgKIBVvTfCAZYyzd6Vl27t0HKGurGxB5WiODFn2ypTPEvfPo3F5K0wijIgOycRmLine truncated background-image: url(data:image/png;base64,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 truncated
background-position: 10px center; background-position: 10px center;
background-repeat: no-repeat; background-repeat: no-repeat;
a.button {
margin-top: 16px;
}
} }
#expressionEditor #expressionEditor
@@ -953,7 +956,7 @@ div.logEventsViewport
#plugins #plugins
{ {
.pageMenuArea a > h3 .pageMenuArea a > h3
{ {
display: inline; display: inline;
color: @HyperLinkColour; color: @HyperLinkColour;
@@ -963,6 +966,17 @@ div.logEventsViewport
color: @HyperLinkHoverColour; color: @HyperLinkHoverColour;
} }
} }
#pageMenu td .pageMenuArea > a
{
background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAAZiS0dEAP8A/wD/oL2nkwAAAAlwSFlzAAALEwAACxMBAJqcGAAAAAd0SU1FB90CDRcZMTlpMjsAAAKbSURBVDjLbZHBS2NHHMc/82ZeXpLaiNJHDylF6KEIGxFa0Jtdi4IFqfQq2P/As4f9D0rwplIwsDlZiofHStaTVQJCj+6a9SpKL3HhkTx5cZLMTA9uHov4Pf2Y33w/fL8z4vj4mHfv3vNUHz60ouXl5VmtNScnJ3eVmZkfn96ZqVRQj6P7HXj56VwAFAqFsenp6W+73S7NZjMRUH/iPwVqnwC8nJ2drU9NTb3I5XIDpVS6u7v7qlQqEQQBxWLxq83NzX+EEIUkSYJ8Pj+xs7Pz0+cAyuXyTqPR+F5KiTEGrTVCCHzfR2v99d7eXg3AGMPGxsZb4CPwWEEIAUC73ebm5gYhBKVSiTiOcc4RBAHn5+dYa9Fas76+nvXIEvi+jzEG5xyrq6vEcczV1RW+77O2tka73WZ/f58wDHHOZQBvNEgp6ff7hGHI4eEhSinOzs64uLjg+vqaWq3GYDBASom19vkEWmuMMYyPjxNFEUtLS1hrOTg4wBiD53k4554HeJ6H1pp+v59VaTQaWGuRUqKUYjAYADwPcM6Rpim9Xg9jDFJKgiBASokQAuccDw8P5PP5ZwHOOUe1WsU5hxACz/Oy3xlplCZJkmw3Apw2m81fx8bGEEJkFay12YuPDMPhkDiOvwP+/gwgXhtjTq21Yb/fTyuVysPt7e3PW1tbf/q+T7Va/U0p9b7VahW11vlOp3Pt53JtAOI4RimFUgohRG5+fv6Po6Ojf7e3twcLCwtucXHR1ev1NIqiN3Nzc6+klEUpJVJK7u/vEXEcE4YhgJBSfjE5OfnDysrKX4VC4ctSqdQCXKfTedHr9T5GUfRLmqb/DYfDBDB3d3ePgJGSJOHy8pJOt4vneQS5HABaa6xzfFMuUy6XmZiYyDz/AxHBRmZKLqH0AAAAAElFTkSuQmCC) /*Images/Actions/pluginDownloadIcon16.png*/;
&:hover
{
background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAC4klEQVQ4jWWRTWhcVRTHf/fd+958JJMw+aDFaYNUtChNTDHYFBdNm4K0IEI3lW7ErZR2IWhKi0tba6gBMRAXhaYiiJskjRgENWlVEC3VJrGFgpaIaetMM515kzfzvu51kZmhxrM6i3N+nN//iLm5OW7eXGRznXfHpg8eGui/zwqLs4X8O9kTA5tn+np7UfX+dWB/vRcAyXSidXDHSz23dIrbqugCk5v254GLDcD+/v7dkzue3L4rpdJhlAi8qanZM52ZTp4xz5FN3u46efLN7xyTSJUqawk72ZL9eHx86HEAT+S2jU98fXenUAoT2sj1LSAiElKh11u3vDuxfNGXNVS0zsixga+AAlBXEGCwuPUwxa/l4ygrINWeYdW9x0rLHYK2R0z8+Qpx1EX64QHePrq76aEa0sqWRJHGijO8+Fobzqrk+z+uUWor0PeGQ3l1Owvvu2x19qGN3ggKsBokqRTVMKAnMcrVS6vca8/z48K3/H7jNx7cCVk4l0YXziNUhNGmeUETYCuFF2jKtQpdfMQvl6s8/fyz9HTs5OfxNXTpLVA+xoDWuvGs5huRlqTqx1RCTRz7BOWzXP9sFGMewPoEMuUTBxag6wD+C8Bo3GrEWk0QaMC2SIjTWEoiOkOMsfGqGidZxfwfIIw2mm/eO4g2gBBYlkCIRsQbzlqDY2mi8v2GQfOC+R+uXX01lWlHCIsojqDuqo0BDJbYiCsKA0rFwlPAF48DLsVxPG/FfnfoB15vX2/tr5WV4ZFTI5/Yymb0woUjtrIXl5cX0zU/TD4quXdtR/0DQLFYRCmFUgohhLN3cO8HV2a//Gnsw7FwaN+QGT4wbC5PfurNTM9cGdwzeEZKmZZSIqWkUqkgisUi3d3dAEJK2dLR0fHCy4cOf55OpTPtba3LgCmV3F1e1SvMTE8d9jzv7yiKXCDO5/MbgEa5rsvS0hKlchnLskg4DgC+76ONYVsuRy6XI5vNNnf+BS/0P9OBtw+RAAAAAElFTkSuQmCC) /*Images/Actions/pluginDownloadIconHover16.png*/;
}
}
} }
#pluginCatalog #pluginCatalog
@@ -975,13 +989,6 @@ div.logEventsViewport
.pluginItem .pluginItem
{ {
&.pluginInstalled > a:first-child h2:after
{
content: ' [Installed]';
font-size: .8em;
font-weight: bold;
}
.pluginItemBlurb .pluginItemBlurb
{ {
margin: 4px 0 4px 2px; margin: 4px 0 4px 2px;
@@ -995,38 +1002,18 @@ div.logEventsViewport
} }
} }
&>a:first-child &>h2:first-child
{ {
padding-left: 30px; padding-left: 20px;
background-image: url(data:image/png;base64,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 truncated background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAC4klEQVQ4jWWRTWhcVRTHf/fd+958JJMw+aDFaYNUtChNTDHYFBdNm4K0IEI3lW7ErZR2IWhKi0tba6gBMRAXhaYiiJskjRgENWlVEC3VJrGFgpaIaetMM515kzfzvu51kZmhxrM6i3N+nN//iLm5OW7eXGRznXfHpg8eGui/zwqLs4X8O9kTA5tn+np7UfX+dWB/vRcAyXSidXDHSz23dIrbqugCk5v254GLDcD+/v7dkzue3L4rpdJhlAi8qanZM52ZTp4xz5FN3u46efLN7xyTSJUqawk72ZL9eHx86HEAT+S2jU98fXenUAoT2sj1LSAiElKh11u3vDuxfNGXNVS0zsixga+AAlBXEGCwuPUwxa/l4ygrINWeYdW9x0rLHYK2R0z8+Qpx1EX64QHePrq76aEa0sqWRJHGijO8+Fobzqrk+z+uUWor0PeGQ3l1Owvvu2x19qGN3ggKsBokqRTVMKAnMcrVS6vca8/z48K3/H7jNx7cCVk4l0YXziNUhNGmeUETYCuFF2jKtQpdfMQvl6s8/fyz9HTs5OfxNXTpLVA+xoDWuvGs5huRlqTqx1RCTRz7BOWzXP9sFGMewPoEMuUTBxag6wD+C8Bo3GrEWk0QaMC2SIjTWEoiOkOMsfGqGidZxfwfIIw2mm/eO4g2gBBYlkCIRsQbzlqDY2mi8v2GQfOC+R+uXX01lWlHCIsojqDuqo0BDJbYiCsKA0rFwlPAF48DLsVxPG/FfnfoB15vX2/tr5WV4ZFTI5/Yymb0woUjtrIXl5cX0zU/TD4quXdtR/0DQLFYRCmFUgohhLN3cO8HV2a//Gnsw7FwaN+QGT4wbC5PfurNTM9cGdwzeEZKmZZSIqWkUqkgisUi3d3dAEJK2dLR0fHCy4cOf55OpTPtba3LgCmV3F1e1SvMTE8d9jzv7yiKXCDO5/MbgEa5rsvS0hKlchnLskg4DgC+76ONYVsuRy6XI5vNNnf+BS/0P9OBtw+RAAAAAElFTkSuQmCC) /*Images/Actions/pluginDownloadIconHover16.png*/;
background-position: left center; background-position: left center;
background-repeat: no-repeat; background-repeat: no-repeat;
min-height: 22px; min-height: 22px;
&:hover a
{ {
background-image: url(data:image/png;base64,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 truncated float: right;
} font-size: 12px;
h2
{
display: inline;
color: @HyperLinkColour;
&:hover
{
color: @HyperLinkHoverColour;
}
}
}
&:not(.pluginInstalled)
{
&>a:first-child h2:hover:after
{
font-size: .8em;
font-weight: bold;
content: ' < Install';
} }
} }
} }
+1 -1
View File
@@ -1 +1 @@
.tableData{border:solid 1px #e8eef4;border-collapse:collapse}.tableData>tbody>tr>td{border:solid 1px #e8eef4;background-color:#fff}.tableData>tbody>tr:nth-child(odd)>td{background-color:#fcfcfd}.tableData>thead>tr>th,.tableData>tbody>tr>th{background-color:#e8eef4;border:solid 1px #e8eef4}.tableData>tbody>tr:hover>td{background-color:#e8eef4}.tableDataDark{border:solid 1px #8db2d8;border-collapse:collapse}.tableDataDark td{border:solid 1px #8db2d8;background-color:#fff}.tableDataDark th{background-color:#8db2d8;border:solid 1px #8db2d8}.tableDataContainer{background-color:#fff}.tableDataVertical{border:solid 1px #e8eef4;border-collapse:collapse}.tableDataVertical>tbody>tr:nth-child(odd){background-color:#e8eef4;margin:0;padding:0}.tableDataVertical>tbody>tr>th.name{width:170px;text-align:right}.tableDataVertical table.sub>tbody>tr:not(:first-child)>th,.tableDataVertical table.sub>tbody>tr:not(:first-child)>td{border-top:1px dashed #aaa}.tableDataVertical table.sub>tbody>tr>th{font-weight:normal;text-align:right}.tableDataVertical table.sub>tbody>tr>th.name{text-align:right}.icon16{display:inline-block;height:16px;width:16px;margin-left:2px;cursor:pointer}.subtleUntilHover{-moz-opacity:.3;opacity:.3}.subtleUntilHover:hover{-moz-opacity:1;opacity:1}#pageMenu td .pageMenuArea>a.config{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAACsElEQVQ4y41T3UtTcRie3QaNRhKC/4SgN4KBeSGK4EAvuzChNZQSvJgXYldCV5tMiUzEDVuZ84M0P4OmpjO3lV+bs21nH2fnbGd69mFuMz/39DunFsUadODh/Hj5vc/zPu/7/iQAJP9CQ0NDrU6nO9Lr9YnS0tKqfPdyAoODg7daWlpuqFQqYyyeQDKVQmdnp6G9vf26RqO5nZfAYDC0vZ2ezuj0es5oHEuGuQhCYQ7RWAznFxeYmpo6fmkwcCaTKfO8v1/5F4FMJrv26vUIQ7MhxOJxEYc8DzrIgItEcHB4iONkEql0Gqdn5xgdHfXnVFBXV6cNkATK54M/QMNm+4yPq2vY3NqCl8QSR0ci0icnqK6ufppDoO3t3fSRROe+C/PzCyKJ3e64CjLslZC0tLyMyMHPSjQ9PZbfBEqlslar1fIut/uS8vpgtdoQCoVB/NJSqVReWFh4b2FxkY8SW0JVQl88FHXZ19fHl5eXV0kqK++qInwU+y43duwOrJnXQVE+1NfLn2RVHigUAx7KC/P6BulLEH6aJs2No6LiTpukrKzsEcOy2HN+xfbOLlbXzOCjMajV6vdZgiGd7oswlZnZOdj3nAjQhCQQQElJiUJCPmlTU9MsGR1H/GJre0ds1uTkJEZG3nwzGo3HY+Pj4jSsNhu8/gD0w8OskCPk/rl5z1LpE7DE/wfTkjjGXWLJQRRpovhuZgYO5z4pP4iamhp1zhS6u7u572dniCcScHs8sFisWN+w4NMvWIi6QB4ku9LV1RXKIVB1dJjJX1iiDNm+TJjjRL+CqrAfRDlDFusqHDlAa2vrSg6B4KexsXGiqKjofnFx8WNSxalfbBYNyutNkvhDElfI5fIJ4W7ex5TFi4EBF0umwzAMmpubV/77NWZRUFAgI52eE0DON/Pd+wH6O+vw3ozilAAAAABJRU5ErkJggg==)}#pageMenu td .pageMenuArea>a.config:hover{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAACiElEQVQ4y41Ta0iTYRQe/ShCTCpJiiRIKvtTiUE3+2VRiMR+JEk3ktKMslmGJZVEf1aZhpFFS/uRQ7Jcq2jVKvKCu2S66eZl05zu5qd9m+5i28TtO73njYXyNeiDw/dyOOc5z3me9xUAgOBfUXYgNUv3+JxH/0Q0lZ22MjNWHS/R9agwsfZU+hL5hZ0vAi4HhLwsKC5lSBuLtsepbx9MignQ/bRENCC7xekkRYyx4brf6zCB194Pv1gbhGeCMNAk9pEaZlgp4Tru5xXOA0hKWLSg59kVu8dqBJyK4R+3wJSlG3xOM/iZHxD0TEDI54LZ4DQYpFdHeAyK96+rxgb3YAdMDevBoZXDaHM9jH1/R3MBt5PGjH8SzmSmiHkAmru5Omz8aWyGwbf3KAijV0YIqwg2WT7XgW9siDJR38n59hdAcjI9S1NxiGX728M4ya5uAo+tF8i+1sT4hcLk5YuPDikesLgWskJdXCZNWFt1hM3ZtjpTcDxjTen0xAiwfW04EUZbpOA2a6Eka315dMrDE2kS0gTWtgaqC7JDcXN3JIsExOMinIjUGd1HCoCA7WLhpygAuQ9d6Ir5TRWM93yhABj7NiUVCMiXUHl4s4JYx6ALTNcHKlZf400w1Jd5Sd7X+/wGdcOueQWTQ52gry12YA/2zr15NWgTsiFeUxtxpQnDVzrNJK+gLPF8dm9KJc+FlvI9zGzAR++Aa0AFNtXLeYHTERxDeXm3kwfw+uIuFReJIABHBOJwZ9yXTv0jHEf+EczX5W9t5QHgPteEG2VrV8Tlpa6KP09YhKJiEVf8JH+a5AtKszfIsDbmY4pGZ02+mVImwlYf29L6369xDqNlROn3GOS8NFbdbzB85s9H8NGVAAAAAElFTkSuQmCC)}#updateAvailableContainer{float:right;border:1px dashed #ddd;background-color:#fff;line-height:1.5em;font-size:.6em;padding:4px 4px 4px 70px;text-align:right;height:64px;background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADEAAABACAYAAACz4p94AAAVPUlEQVRo3s2aWaxk13Wev7X3PkONd+6+PQ+cmoNItkha4iCYtBVLpGQ7MkQ78EMICBZt+EFAAENMgAAKkAQInYcEQR6Sl8AKHE1OBBkg2YJFKS0O8iCSgimymyLZTXY3e+471q1bVWfYKw/7nLrVDCkDQQNhNQ7OrdNVe69/Tf9aa5dwLV+P/ycOuE1z8fxZKaa2U4pQYkEBY0m3tZk79pKePXbc8/ZPrtm27pqscvfn4aWnYO+exq5WvqCptUOXMHAJmYkZFYpzMfO7usysnSnOvnnqIpB9tEC89BQArW5zenpK7ugPB+nQRLRtQm4tK3lJZCKmui1ttFt9Ytf76IGoXs00WUib9oHp6dlOZoyU4siNxY9KrHV0Gw1Va5dw9nVg9SMJIo3jxTSJPjnXbc8UYqWwjhzDMCmxxtFsNXQTvUDkvguc/kiCEGsX4ii6ud3tTJXGUIhjKJbesERcRLedMvB+Gmu713LfawoC9Q1nbDrTdHFpHKWxbIil5RTjItrNhEtIijWNjyyIIi8iI0g3TSisozQOVUPTCDZKaDYjBBVEoo8siOFoJKinncTk1lLaiEwtqXNESUI3teABMeYjC2IwGIovSpqxIzeO0jr6RKQupptEbIs8AmBEP7og+hv4vCB2DmsdhYtwGtHEMR8J2xyIEhj8IxvYvR5lNsIaQYxBjMFhaakw42C23k2uLYhr6ptcPJ8x3FQjghXBVEASK7Ss0A67KSvr2TW1xF9897uRM/aPW63mnla7U7Zb7bC5UN0FEETkqmfhOUglrBHDn3z32cM220yCpDJWuAGsASuQRK79L77y2Jef+Mf/40EFUdlaQyb2kbAZBkFRijwnyzLyoiDPMrJwRXme/5UzmEjEfBkxtwqCMeHaEnTr76ufT2wuAqIcmmlxYZDhvWppVEpVCpQcyD1kHk0i17hp1/bfCZKCqdarARgRMBPPjCAalBeAMt5bVVHV0llr1BjJjAhxHBEnCda6qzRvEMSAiA2LimDEhA3HloDIOWBEXnopjacsPUP19MXQK6HnEUWI4pi02awiPAgKEnxbggWlAmOqTxljq2ASvCp5ntcgCmeMwVpLmjb43z/8AUl+kZgMjEHiGfCKiWJwCUWRUSKIsYhmCAXYFCmGiHpeO9OnffAuhmVJQYliGPmCnhiuGEvHwWiwyQ/+15+z9uPv4FUxrS6MelDm+NYUuBhrLNYlaL+HZhkap2AU1ZCieyPLdTffwaFDN6GqODGVyQRmZ2f4/V/7OKkbgFho7YM8g7QFaYdvP3+MYxeWKLMR4kugBBOD5qhXfvOR69HWHFfyAu+FUmHolT5wxSSkubB9cZ5z76zyzsJ1eO+RRgufD1AtLine truncated .tableData{border:solid 1px #e8eef4;border-collapse:collapse}.tableData>tbody>tr>td{border:solid 1px #e8eef4;background-color:#fff}.tableData>tbody>tr:nth-child(odd)>td{background-color:#fcfcfd}.tableData>thead>tr>th,.tableData>tbody>tr>th{background-color:#e8eef4;border:solid 1px #e8eef4}.tableData>tbody>tr:hover>td{background-color:#e8eef4}.tableDataDark{border:solid 1px #8db2d8;border-collapse:collapse}.tableDataDark td{border:solid 1px #8db2d8;background-color:#fff}.tableDataDark th{background-color:#8db2d8;border:solid 1px #8db2d8}.tableDataContainer{background-color:#fff}.tableDataVertical{border:solid 1px #e8eef4;border-collapse:collapse}.tableDataVertical>tbody>tr:nth-child(odd){background-color:#e8eef4;margin:0;padding:0}.tableDataVertical>tbody>tr>th.name{width:170px;text-align:right}.tableDataVertical table.sub>tbody>tr:not(:first-child)>th,.tableDataVertical table.sub>tbody>tr:not(:first-child)>td{border-top:1px dashed #aaa}.tableDataVertical table.sub>tbody>tr>th{font-weight:normal;text-align:right}.tableDataVertical table.sub>tbody>tr>th.name{text-align:right}.icon16{display:inline-block;height:16px;width:16px;margin-left:2px;cursor:pointer}.subtleUntilHover{-moz-opacity:.3;opacity:.3}.subtleUntilHover:hover{-moz-opacity:1;opacity:1}#pageMenu td .pageMenuArea>a.config{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAACsElEQVQ4y41T3UtTcRie3QaNRhKC/4SgN4KBeSGK4EAvuzChNZQSvJgXYldCV5tMiUzEDVuZ84M0P4OmpjO3lV+bs21nH2fnbGd69mFuMz/39DunFsUadODh/Hj5vc/zPu/7/iQAJP9CQ0NDrU6nO9Lr9YnS0tKqfPdyAoODg7daWlpuqFQqYyyeQDKVQmdnp6G9vf26RqO5nZfAYDC0vZ2ezuj0es5oHEuGuQhCYQ7RWAznFxeYmpo6fmkwcCaTKfO8v1/5F4FMJrv26vUIQ7MhxOJxEYc8DzrIgItEcHB4iONkEql0Gqdn5xgdHfXnVFBXV6cNkATK54M/QMNm+4yPq2vY3NqCl8QSR0ci0icnqK6ufppDoO3t3fSRROe+C/PzCyKJ3e64CjLslZC0tLyMyMHPSjQ9PZbfBEqlslar1fIut/uS8vpgtdoQCoVB/NJSqVReWFh4b2FxkY8SW0JVQl88FHXZ19fHl5eXV0kqK++qInwU+y43duwOrJnXQVE+1NfLn2RVHigUAx7KC/P6BulLEH6aJs2No6LiTpukrKzsEcOy2HN+xfbOLlbXzOCjMajV6vdZgiGd7oswlZnZOdj3nAjQhCQQQElJiUJCPmlTU9MsGR1H/GJre0ds1uTkJEZG3nwzGo3HY+Pj4jSsNhu8/gD0w8OskCPk/rl5z1LpE7DE/wfTkjjGXWLJQRRpovhuZgYO5z4pP4iamhp1zhS6u7u572dniCcScHs8sFisWN+w4NMvWIi6QB4ku9LV1RXKIVB1dJjJX1iiDNm+TJjjRL+CqrAfRDlDFusqHDlAa2vrSg6B4KexsXGiqKjofnFx8WNSxalfbBYNyutNkvhDElfI5fIJ4W7ex5TFi4EBF0umwzAMmpubV/77NWZRUFAgI52eE0DON/Pd+wH6O+vw3ozilAAAAABJRU5ErkJggg==)}#pageMenu td .pageMenuArea>a.config:hover{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAACiElEQVQ4y41Ta0iTYRQe/ShCTCpJiiRIKvtTiUE3+2VRiMR+JEk3ktKMslmGJZVEf1aZhpFFS/uRQ7Jcq2jVKvKCu2S66eZl05zu5qd9m+5i28TtO73njYXyNeiDw/dyOOc5z3me9xUAgOBfUXYgNUv3+JxH/0Q0lZ22MjNWHS/R9agwsfZU+hL5hZ0vAi4HhLwsKC5lSBuLtsepbx9MignQ/bRENCC7xekkRYyx4brf6zCB194Pv1gbhGeCMNAk9pEaZlgp4Tru5xXOA0hKWLSg59kVu8dqBJyK4R+3wJSlG3xOM/iZHxD0TEDI54LZ4DQYpFdHeAyK96+rxgb3YAdMDevBoZXDaHM9jH1/R3MBt5PGjH8SzmSmiHkAmru5Omz8aWyGwbf3KAijV0YIqwg2WT7XgW9siDJR38n59hdAcjI9S1NxiGX728M4ya5uAo+tF8i+1sT4hcLk5YuPDikesLgWskJdXCZNWFt1hM3ZtjpTcDxjTen0xAiwfW04EUZbpOA2a6Eka315dMrDE2kS0gTWtgaqC7JDcXN3JIsExOMinIjUGd1HCoCA7WLhpygAuQ9d6Ir5TRWM93yhABj7NiUVCMiXUHl4s4JYx6ALTNcHKlZf400w1Jd5Sd7X+/wGdcOueQWTQ52gry12YA/2zr15NWgTsiFeUxtxpQnDVzrNJK+gLPF8dm9KJc+FlvI9zGzAR++Aa0AFNtXLeYHTERxDeXm3kwfw+uIuFReJIABHBOJwZ9yXTv0jHEf+EczX5W9t5QHgPteEG2VrV8Tlpa6KP09YhKJiEVf8JH+a5AtKszfIsDbmY4pGZ02+mVImwlYf29L6369xDqNlROn3GOS8NFbdbzB85s9H8NGVAAAAAElFTkSuQmCC)}#updateAvailableContainer{float:right;border:1px dashed #ddd;background-color:#fff;font-size:.6em;line-height:1em;padding:4px 10px 4px 70px;text-align:right;height:64px;background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADEAAABACAYAAACz4p94AAAVPUlEQVRo3s2aWaxk13Wev7X3PkONd+6+PQ+cmoNItkha4iCYtBVLpGQ7MkQ78EMICBZt+EFAAENMgAAKkAQInYcEQR6Sl8AKHE1OBBkg2YJFKS0O8iCSgimymyLZTXY3e+471q1bVWfYKw/7nLrVDCkDQQNhNQ7OrdNVe69/Tf9aa5dwLV+P/ycOuE1z8fxZKaa2U4pQYkEBY0m3tZk79pKePXbc8/ZPrtm27pqscvfn4aWnYO+exq5WvqCptUOXMHAJmYkZFYpzMfO7usysnSnOvnnqIpB9tEC89BQArW5zenpK7ugPB+nQRLRtQm4tK3lJZCKmui1ttFt9Ytf76IGoXs00WUib9oHp6dlOZoyU4siNxY9KrHV0Gw1Va5dw9nVg9SMJIo3jxTSJPjnXbc8UYqWwjhzDMCmxxtFsNXQTvUDkvguc/kiCEGsX4ii6ud3tTJXGUIhjKJbesERcRLedMvB+Gmu713LfawoC9Q1nbDrTdHFpHKWxbIil5RTjItrNhEtIijWNjyyIIi8iI0g3TSisozQOVUPTCDZKaDYjBBVEoo8siOFoJKinncTk1lLaiEwtqXNESUI3teABMeYjC2IwGIovSpqxIzeO0jr6RKQupptEbIs8AmBEP7og+hv4vCB2DmsdhYtwGtHEMR8J2xyIEhj8IxvYvR5lNsIaQYxBjMFhaakw42C23k2uLYhr6ptcPJ8x3FQjghXBVEASK7Ss0A67KSvr2TW1xF9897uRM/aPW63mnla7U7Zb7bC5UN0FEETkqmfhOUglrBHDn3z32cM220yCpDJWuAGsASuQRK79L77y2Jef+Mf/40EFUdlaQyb2kbAZBkFRijwnyzLyoiDPMrJwRXme/5UzmEjEfBkxtwqCMeHaEnTr76ufT2wuAqIcmmlxYZDhvWppVEpVCpQcyD1kHk0i17hp1/bfCZKCqdarARgRMBPPjCAalBeAMt5bVVHV0llr1BjJjAhxHBEnCda6qzRvEMSAiA2LimDEhA3HloDIOWBEXnopjacsPUP19MXQK6HnEUWI4pi02awiPAgKEnxbggWlAmOqTxljq2ASvCp5ntcgCmeMwVpLmjb43z/8AUl+kZgMjEHiGfCKiWJwCUWRUSKIsYhmCAXYFCmGiHpeO9OnffAuhmVJQYliGPmCnhiuGEvHwWiwyQ/+15+z9uPv4FUxrS6MelDm+NYUuBhrLNYlaL+HZhkap2AU1ZCieyPLdTffwaFDN6GqODGVyQRmZ2f4/V/7OKkbgFho7YM8g7QFaYdvP3+MYxeWKLMR4kugBBOD5qhXfvOR69HWHFfyAu+FUmHolT5wxSSkubB9cZ5z76zyzsJ1eO+RRgufD1AtyLine truncated
Binary file not shown.

After

Width:  |  Height:  |  Size: 795 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 795 B

+5 -4
View File
@@ -339,6 +339,7 @@ a:active {
color: #335a87; color: #335a87;
} }
a.button { a.button {
display: inline-block;
padding: 4px 10px; padding: 4px 10px;
margin: 2px; margin: 2px;
border: 1px solid #875a33; border: 1px solid #875a33;
@@ -347,11 +348,11 @@ a.button {
font-weight: bold; font-weight: bold;
text-transform: uppercase; text-transform: uppercase;
cursor: pointer; cursor: pointer;
line-height: 2.2em;
white-space: nowrap; white-space: nowrap;
text-decoration: none; text-decoration: none;
} }
a.button[disabled] { a.button[disabled],
a.button.disabled {
background: #9e9e9e; background: #9e9e9e;
border: 1px solid #696969; border: 1px solid #696969;
cursor: default; cursor: default;
@@ -790,7 +791,8 @@ input[type="submit"] {
padding: 5px; padding: 5px;
} }
input[type="submit"].button { input[type="submit"].button {
padding: 4px 10px; font-size: 12px;
padding: 6px 10px 4px 10px;
margin: 2px; margin: 2px;
border: 1px solid #875a33; border: 1px solid #875a33;
background: #db761d; background: #db761d;
@@ -798,7 +800,6 @@ input[type="submit"].button {
font-weight: bold; font-weight: bold;
text-transform: uppercase; text-transform: uppercase;
cursor: pointer; cursor: pointer;
line-height: 1.2em;
} }
input[type="submit"].button:hover { input[type="submit"].button:hover {
border: 1px solid #696969; border: 1px solid #696969;
File diff suppressed because it is too large. Load diff
+1 -1
View File
@@ -1 +1 @@
.tableData{border:solid 1px #e8eef4;border-collapse:collapse}.tableData>tbody>tr>td{border:solid 1px #e8eef4;background-color:#fff}.tableData>tbody>tr:nth-child(odd)>td{background-color:#fcfcfd}.tableData>thead>tr>th,.tableData>tbody>tr>th{background-color:#e8eef4;border:solid 1px #e8eef4}.tableData>tbody>tr:hover>td{background-color:#e8eef4}.tableDataDark{border:solid 1px #8db2d8;border-collapse:collapse}.tableDataDark td{border:solid 1px #8db2d8;background-color:#fff}.tableDataDark th{background-color:#8db2d8;border:solid 1px #8db2d8}.tableDataContainer{background-color:#fff}.tableDataVertical{border:solid 1px #e8eef4;border-collapse:collapse}.tableDataVertical>tbody>tr:nth-child(odd){background-color:#e8eef4;margin:0;padding:0}.tableDataVertical>tbody>tr>th.name{width:170px;text-align:right}.tableDataVertical table.sub>tbody>tr:not(:first-child)>th,.tableDataVertical table.sub>tbody>tr:not(:first-child)>td{border-top:1px dashed #aaa}.tableDataVertical table.sub>tbody>tr>th{font-weight:normal;text-align:right}.tableDataVertical table.sub>tbody>tr>th.name{text-align:right}.icon16{display:inline-block;height:16px;width:16px;margin-left:2px;cursor:pointer}.subtleUntilHover{-moz-opacity:.3;opacity:.3}.subtleUntilHover:hover{-moz-opacity:1;opacity:1}body{font-size:12px;font-family:"Segoe UI",Arial,Verdana,Tahoma,sans-serif;margin:0;padding:0 10px;color:#333}body.layout{background:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAFvCAMAAABEoqrSAAADAFBMVEVRUVFUVFRYWFhbW1tfX19iYmJmZmZpaWltbW1wcHB0dHR3d3d7e3t/f3/MzMzNzc3Ozs7Pz8/Q0NDR0dHS0tLT09PU1NTV1dXW1tbX19fY2NjZ2dna2trb29vc3Nzd3d3e3t7f39/g4ODh4eHi4uLj4+Pk5OTl5eXm5ubn5+fo6Ojp6enq6urr6+vs7Ozt7e3u7u7v7+/w8PDx8fHy8vLz8/P09PT19fX29vb39/f4+Pj5+fn6+vr7+/v8/Pz9/f3+/v4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD28iAmAAAAbklEQVRIx2NUZ4ABlv9kMZkYRrXhYUphMwzZXEYCogQV0FfbUHMOrSxGAoyMBEygM/M/zZnMjFiZDPQEjCYEsin2/EYKk6qGDTVzR7TnRwN1NFBHPT8aqKOBOur5Uc+PBip1zWVkYGCBCv2nhrkAr7hI+jpl4KUAAAAASUVORK5CYII=) left top repeat-x #d1d1d1}.page{max-width:1230px;min-width:750px;margin-left:auto;margin-right:auto}header,#header{position:relative;margin:0;padding:0;height:110px}header #headerMenu,#header #headerMenu{height:24px;padding:4px;line-height:22px;text-align:right}header #headerMenu a,#header #headerMenu a{color:#000;text-decoration:none}header #headerMenu a:hover,#header #headerMenu a:hover{text-decoration:underline}header #heading,#header #heading{float:left;height:75px}header #heading img,#header #heading img{height:75px;width:300px}header nav,#header nav{padding:0;margin:0;font-size:1.1em}header nav ul#menu,#header nav ul#menu{height:29px;padding:3px 6px;margin:0;list-style:none;z-index:100000}header nav ul#menu>li,#header nav ul#menu>li{display:inline-block;z-index:100000;margin-bottom:-4px}header nav ul#menu>li a,#header nav ul#menu>li a{padding:4px 10px;text-decoration:none;color:#fff;display:inline-block;height:21px}header nav ul#menu>li a:hover,#header nav ul#menu>li a:hover{color:#ffd5ba;text-decoration:none}header nav ul#menu>li a:active,#header nav ul#menu>li a:active{text-decoration:none}header nav ul#menu>li.sep,#header nav ul#menu>li.sep{margin-top:4px;height:21px;border-left:1px solid #777}header nav ul#menu>li.moveRight,#header nav ul#menu>li.moveRight{margin-left:40px}header nav ul#menu>li>ul,#header nav ul#menu>li>ul{z-index:100000;display:none;list-style:none;position:absolute;margin:2px 0 0 0;-moz-border-radius:0 0 0 0;-webkit-border-radius:0 0 0 0;border-radius:0 0 0 0;border-left:1px solid #ecab72;border-bottom:2px solid #ecab72;border-right:1px solid #ecab72;padding:0;min-width:180px}header nav ul#menu>li>ul li,#header nav ul#menu>li>ul li{position:relative;background-color:rgba(242,242,242,.9);background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAAUCAYAAABMDlehAAAAIUlEQVQI12NgYGBQYGJgYPgLJ/6gciEEMwMDAyMzA1kAAB/mByD2JQzYAAAAAElFTkSuQmCC);background-position:top;background-repeat:repeat-x}header nav ul#menu>li>ul li:hover,#header nav ul#menu>li>ul li:hover{background-color:rgba(249,228,210,.75)}header nav ul#menu>li>ul li.hasSubmenu,#header nav ul#menu>li>ul li.hasSubmenu{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAANCAYAAACgu+4kAAAAa0lEQVQoz2NgGBRg8uTJO4BYhxIDVgPxHyCeDcQS5BpiAcSHgfgzENcBMRe5BgUC8Line truncated .tableData{border:solid 1px #e8eef4;border-collapse:collapse}.tableData>tbody>tr>td{border:solid 1px #e8eef4;background-color:#fff}.tableData>tbody>tr:nth-child(odd)>td{background-color:#fcfcfd}.tableData>thead>tr>th,.tableData>tbody>tr>th{background-color:#e8eef4;border:solid 1px #e8eef4}.tableData>tbody>tr:hover>td{background-color:#e8eef4}.tableDataDark{border:solid 1px #8db2d8;border-collapse:collapse}.tableDataDark td{border:solid 1px #8db2d8;background-color:#fff}.tableDataDark th{background-color:#8db2d8;border:solid 1px #8db2d8}.tableDataContainer{background-color:#fff}.tableDataVertical{border:solid 1px #e8eef4;border-collapse:collapse}.tableDataVertical>tbody>tr:nth-child(odd){background-color:#e8eef4;margin:0;padding:0}.tableDataVertical>tbody>tr>th.name{width:170px;text-align:right}.tableDataVertical table.sub>tbody>tr:not(:first-child)>th,.tableDataVertical table.sub>tbody>tr:not(:first-child)>td{border-top:1px dashed #aaa}.tableDataVertical table.sub>tbody>tr>th{font-weight:normal;text-align:right}.tableDataVertical table.sub>tbody>tr>th.name{text-align:right}.icon16{display:inline-block;height:16px;width:16px;margin-left:2px;cursor:pointer}.subtleUntilHover{-moz-opacity:.3;opacity:.3}.subtleUntilHover:hover{-moz-opacity:1;opacity:1}body{font-size:12px;font-family:"Segoe UI",Arial,Verdana,Tahoma,sans-serif;margin:0;padding:0 10px;color:#333}body.layout{background:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAFvCAMAAABEoqrSAAADAFBMVEVRUVFUVFRYWFhbW1tfX19iYmJmZmZpaWltbW1wcHB0dHR3d3d7e3t/f3/MzMzNzc3Ozs7Pz8/Q0NDR0dHS0tLT09PU1NTV1dXW1tbX19fY2NjZ2dna2trb29vc3Nzd3d3e3t7f39/g4ODh4eHi4uLj4+Pk5OTl5eXm5ubn5+fo6Ojp6enq6urr6+vs7Ozt7e3u7u7v7+/w8PDx8fHy8vLz8/P09PT19fX29vb39/f4+Pj5+fn6+vr7+/v8/Pz9/f3+/v4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD28iAmAAAAbklEQVRIx2NUZ4ABlv9kMZkYRrXhYUphMwzZXEYCogQV0FfbUHMOrSxGAoyMBEygM/M/zZnMjFiZDPQEjCYEsin2/EYKk6qGDTVzR7TnRwN1NFBHPT8aqKOBOur5Uc+PBip1zWVkYGCBCv2nhrkAr7hI+jpl4KUAAAAASUVORK5CYII=) left top repeat-x #d1d1d1}.page{max-width:1230px;min-width:750px;margin-left:auto;margin-right:auto}header,#header{position:relative;margin:0;padding:0;height:110px}header #headerMenu,#header #headerMenu{height:24px;padding:4px;line-height:22px;text-align:right}header #headerMenu a,#header #headerMenu a{color:#000;text-decoration:none}header #headerMenu a:hover,#header #headerMenu a:hover{text-decoration:underline}header #heading,#header #heading{float:left;height:75px}header #heading img,#header #heading img{height:75px;width:300px}header nav,#header nav{padding:0;margin:0;font-size:1.1em}header nav ul#menu,#header nav ul#menu{height:29px;padding:3px 6px;margin:0;list-style:none;z-index:100000}header nav ul#menu>li,#header nav ul#menu>li{display:inline-block;z-index:100000;margin-bottom:-4px}header nav ul#menu>li a,#header nav ul#menu>li a{padding:4px 10px;text-decoration:none;color:#fff;display:inline-block;height:21px}header nav ul#menu>li a:hover,#header nav ul#menu>li a:hover{color:#ffd5ba;text-decoration:none}header nav ul#menu>li a:active,#header nav ul#menu>li a:active{text-decoration:none}header nav ul#menu>li.sep,#header nav ul#menu>li.sep{margin-top:4px;height:21px;border-left:1px solid #777}header nav ul#menu>li.moveRight,#header nav ul#menu>li.moveRight{margin-left:40px}header nav ul#menu>li>ul,#header nav ul#menu>li>ul{z-index:100000;display:none;list-style:none;position:absolute;margin:2px 0 0 0;-moz-border-radius:0 0 0 0;-webkit-border-radius:0 0 0 0;border-radius:0 0 0 0;border-left:1px solid #ecab72;border-bottom:2px solid #ecab72;border-right:1px solid #ecab72;padding:0;min-width:180px}header nav ul#menu>li>ul li,#header nav ul#menu>li>ul li{position:relative;background-color:rgba(242,242,242,.9);background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAAUCAYAAABMDlehAAAAIUlEQVQI12NgYGBQYGJgYPgLJ/6gciEEMwMDAyMzA1kAAB/mByD2JQzYAAAAAElFTkSuQmCC);background-position:top;background-repeat:repeat-x}header nav ul#menu>li>ul li:hover,#header nav ul#menu>li>ul li:hover{background-color:rgba(249,228,210,.75)}header nav ul#menu>li>ul li.hasSubmenu,#header nav ul#menu>li>ul li.hasSubmenu{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAANCAYAAACgu+4kAAAAa0lEQVQoz2NgGBRg8uTJO4BYhxIDVgPxHyCeDcQS5BpiAcSHgfgzENcBMRe5BgUC8Line truncated
@@ -20,7 +20,7 @@ namespace Disco.Web.Controllers
#region Determine Server Is Core SKU #region Determine Server Is Core SKU
// Added 2012-11-01 G# // Added 2012-11-01 G#
// http://www.discoict.com.au/forum/support/2012/10/install-on-server-core.aspx // http://www.discoict.com.au/forum/support/2012/10/install-on-server-core.aspx
private static Lazy<bool> ServerIsCoreSKU = new Lazy<bool>(() => internal static Lazy<bool> ServerIsCoreSKU = new Lazy<bool>(() =>
{ {
try try
{ {
+36
View File
@@ -0,0 +1,36 @@
using System;
using System.Data.SqlClient;
using System.Threading;
using System.Web.Mvc;
using Disco.Web.Models.InitialConfig;
using Disco.Data.Repository;
using System.Linq;
using System.IO;
using System.Text.RegularExpressions;
using System.IO.Compression;
using System.Management;
using System.Web;
using Disco.Services.Plugins;
namespace Disco.Web.Controllers
{
[OutputCache(Duration = 0, Location = System.Web.UI.OutputCacheLocation.None)]
public partial class UpdateController : Controller
{
protected override void OnActionExecuting(ActionExecutingContext filterContext)
{
if (!Request.IsLocal && !InitialConfigController.ServerIsCoreSKU.Value)
{
filterContext.Result = new HttpStatusCodeResult(System.Net.HttpStatusCode.ServiceUnavailable, "Initial Configuration of Disco is only allowed via a local connection");
}
base.OnActionExecuting(filterContext);
}
public virtual ActionResult Index()
{
var status = UpdatePluginsAfterDiscoUpdateTask.UpdateDiscoPlugins(true);
return RedirectToAction(MVC.Config.Logging.TaskStatus(status.SessionId));
}
}
}
+2 -1
View File
@@ -172,6 +172,7 @@
</Compile> </Compile>
<Compile Include="Controllers\InitialConfigController.cs" /> <Compile Include="Controllers\InitialConfigController.cs" />
<Compile Include="Controllers\PluginWebHandlerController.cs" /> <Compile Include="Controllers\PluginWebHandlerController.cs" />
<Compile Include="Controllers\UpdateController.cs" />
<Compile Include="Extensions\HtmlExtensions.cs" /> <Compile Include="Extensions\HtmlExtensions.cs" />
<Compile Include="App_Start\AppConfig.cs" /> <Compile Include="App_Start\AppConfig.cs" />
<Compile Include="App_Start\BundleConfig.cs" /> <Compile Include="App_Start\BundleConfig.cs" />
@@ -1822,7 +1823,7 @@
<SaveServerSettingsInUserFile>False</SaveServerSettingsInUserFile> <SaveServerSettingsInUserFile>False</SaveServerSettingsInUserFile>
</WebProjectProperties> </WebProjectProperties>
</FlavorProperties> </FlavorProperties>
<UserProperties BuildVersion_StartDate="2001/1/1" BuildVersion_BuildAction="ReBuild" BuildVersion_UseGlobalSettings="True" BuildVersion_DetectChanges="False" /> <UserProperties BuildVersion_DetectChanges="False" BuildVersion_UseGlobalSettings="True" BuildVersion_BuildAction="ReBuild" BuildVersion_StartDate="2001/1/1" />
</VisualStudio> </VisualStudio>
</ProjectExtensions> </ProjectExtensions>
<Import Project="$(SolutionDir)\.nuget\nuget.targets" /> <Import Project="$(SolutionDir)\.nuget\nuget.targets" />
+53 -23
View File
@@ -24,54 +24,84 @@ namespace Disco.Web
base.BeginRequest += new EventHandler(DiscoApplication_BeginRequest); base.BeginRequest += new EventHandler(DiscoApplication_BeginRequest);
base.Error += new EventHandler(DiscoApplication_Error); base.Error += new EventHandler(DiscoApplication_Error);
} }
protected void Application_Start() protected void Application_Start()
{ {
var timer = new Stopwatch(); var timer = new Stopwatch();
long timer_last; long timer_last;
timer.Start(); timer.Start();
Debug.WriteLine("Application Startup Profiling Started"); Debug.WriteLine("Application Startup Profiling Started");
timer_last = timer.ElapsedMilliseconds; timer_last = timer.ElapsedMilliseconds;
if (AppConfig.InitializeDatabase()) if (AppConfig.InitializeDatabase())
{ {
// Database Initialized
Debug.WriteLine("Initialized Database: +{0}ms", timer.ElapsedMilliseconds - timer_last); Debug.WriteLine("Initialized Database: +{0}ms", timer.ElapsedMilliseconds - timer_last);
timer_last = timer.ElapsedMilliseconds; timer_last = timer.ElapsedMilliseconds;
AreaRegistration.RegisterAllAreas(); // Check for Post-Update
Version previousVersion;
Version currentVersion = Disco.BI.Interop.Community.UpdateCheck.CurrentDiscoVersion();
using (DiscoDataContext dbContext = new DiscoDataContext())
{
previousVersion = dbContext.DiscoConfiguration.InstalledDatabaseVersion;
}
if (currentVersion == previousVersion)
{
// Normal Startup
Debug.WriteLine("Registered Areas: +{0}ms", timer.ElapsedMilliseconds - timer_last); AreaRegistration.RegisterAllAreas();
timer_last = timer.ElapsedMilliseconds;
WebApiConfig.Register(GlobalConfiguration.Configuration);
Debug.WriteLine("Registered API: +{0}ms", timer.ElapsedMilliseconds - timer_last); Debug.WriteLine("Registered Areas: +{0}ms", timer.ElapsedMilliseconds - timer_last);
timer_last = timer.ElapsedMilliseconds; timer_last = timer.ElapsedMilliseconds;
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
Debug.WriteLine("Registered Global Filters: +{0}ms", timer.ElapsedMilliseconds - timer_last); WebApiConfig.Register(GlobalConfiguration.Configuration);
timer_last = timer.ElapsedMilliseconds;
RouteConfig.RegisterRoutes(RouteTable.Routes);
Debug.WriteLine("Registered Routes: +{0}ms", timer.ElapsedMilliseconds - timer_last); Debug.WriteLine("Registered API: +{0}ms", timer.ElapsedMilliseconds - timer_last);
timer_last = timer.ElapsedMilliseconds; timer_last = timer.ElapsedMilliseconds;
BundleConfig.RegisterBundles(); FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
Debug.WriteLine("Registered Bundles: +{0}ms", timer.ElapsedMilliseconds - timer_last); Debug.WriteLine("Registered Global Filters: +{0}ms", timer.ElapsedMilliseconds - timer_last);
timer_last = timer.ElapsedMilliseconds; timer_last = timer.ElapsedMilliseconds;
AppConfig.InitalizeEnvironment(); RouteConfig.RegisterRoutes(RouteTable.Routes);
Debug.WriteLine("Initialized Environment: +{0}ms", timer.ElapsedMilliseconds - timer_last); Debug.WriteLine("Registered Routes: +{0}ms", timer.ElapsedMilliseconds - timer_last);
timer_last = timer.ElapsedMilliseconds; timer_last = timer.ElapsedMilliseconds;
BundleConfig.RegisterBundles();
Debug.WriteLine("Registered Bundles: +{0}ms", timer.ElapsedMilliseconds - timer_last);
timer_last = timer.ElapsedMilliseconds;
AppConfig.InitalizeEnvironment();
Debug.WriteLine("Initialized Environment: +{0}ms", timer.ElapsedMilliseconds - timer_last);
timer_last = timer.ElapsedMilliseconds;
}
else
{
// Post-Update Startup
AreaRegistration.RegisterAllAreas();
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterUpdateRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles();
AppConfig.InitializeUpdateEnvironment();
using (DiscoDataContext dbContext = new DiscoDataContext())
{
dbContext.DiscoConfiguration.InstalledDatabaseVersion = currentVersion;
dbContext.SaveChanges();
}
}
} }
else else
{ {
// Database Not Initialized
// Install // Install
InitialConfig = true; InitialConfig = true;
RouteConfig.RegisterInstallRoutes(RouteTable.Routes); RouteConfig.RegisterInstallRoutes(RouteTable.Routes);
+2 -2
View File
@@ -31,5 +31,5 @@ using System.Runtime.InteropServices;
// //
// You can specify all the values or you can default the Revision and Build Numbers // You can specify all the values or you can default the Revision and Build Numbers
// by using the '*' as shown below: // by using the '*' as shown below:
[assembly: AssemblyVersion("1.2.0212.1702")] [assembly: AssemblyVersion("1.2.0214.1848")]
[assembly: AssemblyFileVersion("1.2.0212.1702")] [assembly: AssemblyFileVersion("1.2.0214.1848")]
+158 -23
View File
@@ -37,6 +37,7 @@ public static class MVC
public static Disco.Web.Controllers.JobController Job = new Disco.Web.Controllers.T4MVC_JobController(); public static Disco.Web.Controllers.JobController Job = new Disco.Web.Controllers.T4MVC_JobController();
public static Disco.Web.Controllers.PluginWebHandlerController PluginWebHandler = new Disco.Web.Controllers.T4MVC_PluginWebHandlerController(); public static Disco.Web.Controllers.PluginWebHandlerController PluginWebHandler = new Disco.Web.Controllers.T4MVC_PluginWebHandlerController();
public static Disco.Web.Controllers.SearchController Search = new Disco.Web.Controllers.T4MVC_SearchController(); public static Disco.Web.Controllers.SearchController Search = new Disco.Web.Controllers.T4MVC_SearchController();
public static Disco.Web.Controllers.UpdateController Update = new Disco.Web.Controllers.T4MVC_UpdateController();
public static Disco.Web.Controllers.UserController User = new Disco.Web.Controllers.T4MVC_UserController(); public static Disco.Web.Controllers.UserController User = new Disco.Web.Controllers.T4MVC_UserController();
public static T4MVC.HomeController Home = new T4MVC.HomeController(); public static T4MVC.HomeController Home = new T4MVC.HomeController();
public static T4MVC.SharedController Shared = new T4MVC.SharedController(); public static T4MVC.SharedController Shared = new T4MVC.SharedController();
@@ -1998,6 +1999,84 @@ namespace Disco.Web.Controllers
} }
} }
namespace Disco.Web.Controllers
{
public partial class UpdateController
{
[GeneratedCode("T4MVC", "2.0"), DebuggerNonUserCode]
public UpdateController() { }
[GeneratedCode("T4MVC", "2.0"), DebuggerNonUserCode]
protected UpdateController(Dummy d) { }
[GeneratedCode("T4MVC", "2.0"), DebuggerNonUserCode]
protected RedirectToRouteResult RedirectToAction(ActionResult result)
{
var callInfo = result.GetT4MVCResult();
return RedirectToRoute(callInfo.RouteValueDictionary);
}
[GeneratedCode("T4MVC", "2.0"), DebuggerNonUserCode]
protected RedirectToRouteResult RedirectToActionPermanent(ActionResult result)
{
var callInfo = result.GetT4MVCResult();
return RedirectToRoutePermanent(callInfo.RouteValueDictionary);
}
[GeneratedCode("T4MVC", "2.0"), DebuggerNonUserCode]
public UpdateController Actions { get { return MVC.Update; } }
[GeneratedCode("T4MVC", "2.0")]
public readonly string Area = "";
[GeneratedCode("T4MVC", "2.0")]
public readonly string Name = "Update";
[GeneratedCode("T4MVC", "2.0")]
public const string NameConst = "Update";
static readonly ActionNamesClass s_actions = new ActionNamesClass();
[GeneratedCode("T4MVC", "2.0"), DebuggerNonUserCode]
public ActionNamesClass ActionNames { get { return s_actions; } }
[GeneratedCode("T4MVC", "2.0"), DebuggerNonUserCode]
public class ActionNamesClass
{
public readonly string Index = "Index";
}
[GeneratedCode("T4MVC", "2.0"), DebuggerNonUserCode]
public class ActionNameConstants
{
public const string Index = "Index";
}
static readonly ViewsClass s_views = new ViewsClass();
[GeneratedCode("T4MVC", "2.0"), DebuggerNonUserCode]
public ViewsClass Views { get { return s_views; } }
[GeneratedCode("T4MVC", "2.0"), DebuggerNonUserCode]
public class ViewsClass
{
static readonly _ViewNamesClass s_ViewNames = new _ViewNamesClass();
public _ViewNamesClass ViewNames { get { return s_ViewNames; } }
public class _ViewNamesClass
{
}
}
}
[GeneratedCode("T4MVC", "2.0"), DebuggerNonUserCode]
public class T4MVC_UpdateController : Disco.Web.Controllers.UpdateController
{
public T4MVC_UpdateController() : base(Dummy.Instance) { }
public override System.Web.Mvc.ActionResult Index()
{
var callInfo = new T4MVC_System_Web_Mvc_ActionResult(Area, Name, ActionNames.Index);
return callInfo;
}
}
}
namespace Disco.Web.Controllers namespace Disco.Web.Controllers
{ {
public partial class UserController public partial class UserController
@@ -6759,6 +6838,18 @@ namespace Disco.Web.Areas.API.Controllers
return RedirectToRoutePermanent(callInfo.RouteValueDictionary); return RedirectToRoutePermanent(callInfo.RouteValueDictionary);
} }
[NonAction]
[GeneratedCode("T4MVC", "2.0"), DebuggerNonUserCode]
public System.Web.Mvc.ActionResult Update()
{
return new T4MVC_System_Web_Mvc_ActionResult(Area, Name, ActionNames.Update);
}
[NonAction]
[GeneratedCode("T4MVC", "2.0"), DebuggerNonUserCode]
public System.Web.Mvc.ActionResult UpdateLocal()
{
return new T4MVC_System_Web_Mvc_ActionResult(Area, Name, ActionNames.UpdateLocal);
}
[NonAction] [NonAction]
[GeneratedCode("T4MVC", "2.0"), DebuggerNonUserCode] [GeneratedCode("T4MVC", "2.0"), DebuggerNonUserCode]
public System.Web.Mvc.ActionResult Uninstall() public System.Web.Mvc.ActionResult Uninstall()
@@ -6767,16 +6858,16 @@ namespace Disco.Web.Areas.API.Controllers
} }
[NonAction] [NonAction]
[GeneratedCode("T4MVC", "2.0"), DebuggerNonUserCode] [GeneratedCode("T4MVC", "2.0"), DebuggerNonUserCode]
public System.Web.Mvc.ActionResult InstallLocal()
{
return new T4MVC_System_Web_Mvc_ActionResult(Area, Name, ActionNames.InstallLocal);
}
[NonAction]
[GeneratedCode("T4MVC", "2.0"), DebuggerNonUserCode]
public System.Web.Mvc.ActionResult Install() public System.Web.Mvc.ActionResult Install()
{ {
return new T4MVC_System_Web_Mvc_ActionResult(Area, Name, ActionNames.Install); return new T4MVC_System_Web_Mvc_ActionResult(Area, Name, ActionNames.Install);
} }
[NonAction]
[GeneratedCode("T4MVC", "2.0"), DebuggerNonUserCode]
public System.Web.Mvc.ActionResult InstallLocal()
{
return new T4MVC_System_Web_Mvc_ActionResult(Area, Name, ActionNames.InstallLocal);
}
[GeneratedCode("T4MVC", "2.0"), DebuggerNonUserCode] [GeneratedCode("T4MVC", "2.0"), DebuggerNonUserCode]
public PluginController Actions { get { return MVC.API.Plugin; } } public PluginController Actions { get { return MVC.API.Plugin; } }
@@ -6794,21 +6885,44 @@ namespace Disco.Web.Areas.API.Controllers
public class ActionNamesClass public class ActionNamesClass
{ {
public readonly string UpdateLibraryCatalogue = "UpdateLibraryCatalogue"; public readonly string UpdateLibraryCatalogue = "UpdateLibraryCatalogue";
public readonly string UpdateAll = "UpdateAll";
public readonly string Update = "Update";
public readonly string UpdateLocal = "UpdateLocal";
public readonly string Uninstall = "Uninstall"; public readonly string Uninstall = "Uninstall";
public readonly string InstallLocal = "InstallLocal";
public readonly string Install = "Install"; public readonly string Install = "Install";
public readonly string InstallLocal = "InstallLocal";
} }
[GeneratedCode("T4MVC", "2.0"), DebuggerNonUserCode] [GeneratedCode("T4MVC", "2.0"), DebuggerNonUserCode]
public class ActionNameConstants public class ActionNameConstants
{ {
public const string UpdateLibraryCatalogue = "UpdateLibraryCatalogue"; public const string UpdateLibraryCatalogue = "UpdateLibraryCatalogue";
public const string UpdateAll = "UpdateAll";
public const string Update = "Update";
public const string UpdateLocal = "UpdateLocal";
public const string Uninstall = "Uninstall"; public const string Uninstall = "Uninstall";
public const string InstallLocal = "InstallLocal";
public const string Install = "Install"; public const string Install = "Install";
public const string InstallLocal = "InstallLocal";
} }
static readonly ActionParamsClass_Update s_params_Update = new ActionParamsClass_Update();
[GeneratedCode("T4MVC", "2.0"), DebuggerNonUserCode]
public ActionParamsClass_Update UpdateParams { get { return s_params_Update; } }
[GeneratedCode("T4MVC", "2.0"), DebuggerNonUserCode]
public class ActionParamsClass_Update
{
public readonly string PluginId = "PluginId";
}
static readonly ActionParamsClass_UpdateLocal s_params_UpdateLocal = new ActionParamsClass_UpdateLocal();
[GeneratedCode("T4MVC", "2.0"), DebuggerNonUserCode]
public ActionParamsClass_UpdateLocal UpdateLocalParams { get { return s_params_UpdateLocal; } }
[GeneratedCode("T4MVC", "2.0"), DebuggerNonUserCode]
public class ActionParamsClass_UpdateLocal
{
public readonly string PluginId = "PluginId";
public readonly string Plugin = "Plugin";
}
static readonly ActionParamsClass_Uninstall s_params_Uninstall = new ActionParamsClass_Uninstall(); static readonly ActionParamsClass_Uninstall s_params_Uninstall = new ActionParamsClass_Uninstall();
[GeneratedCode("T4MVC", "2.0"), DebuggerNonUserCode] [GeneratedCode("T4MVC", "2.0"), DebuggerNonUserCode]
public ActionParamsClass_Uninstall UninstallParams { get { return s_params_Uninstall; } } public ActionParamsClass_Uninstall UninstallParams { get { return s_params_Uninstall; } }
@@ -6818,14 +6932,6 @@ namespace Disco.Web.Areas.API.Controllers
public readonly string id = "id"; public readonly string id = "id";
public readonly string UninstallData = "UninstallData"; public readonly string UninstallData = "UninstallData";
} }
static readonly ActionParamsClass_InstallLocal s_params_InstallLocal = new ActionParamsClass_InstallLocal();
[GeneratedCode("T4MVC", "2.0"), DebuggerNonUserCode]
public ActionParamsClass_InstallLocal InstallLocalParams { get { return s_params_InstallLocal; } }
[GeneratedCode("T4MVC", "2.0"), DebuggerNonUserCode]
public class ActionParamsClass_InstallLocal
{
public readonly string Plugin = "Plugin";
}
static readonly ActionParamsClass_Install s_params_Install = new ActionParamsClass_Install(); static readonly ActionParamsClass_Install s_params_Install = new ActionParamsClass_Install();
[GeneratedCode("T4MVC", "2.0"), DebuggerNonUserCode] [GeneratedCode("T4MVC", "2.0"), DebuggerNonUserCode]
public ActionParamsClass_Install InstallParams { get { return s_params_Install; } } public ActionParamsClass_Install InstallParams { get { return s_params_Install; } }
@@ -6834,6 +6940,14 @@ namespace Disco.Web.Areas.API.Controllers
{ {
public readonly string PluginId = "PluginId"; public readonly string PluginId = "PluginId";
} }
static readonly ActionParamsClass_InstallLocal s_params_InstallLocal = new ActionParamsClass_InstallLocal();
[GeneratedCode("T4MVC", "2.0"), DebuggerNonUserCode]
public ActionParamsClass_InstallLocal InstallLocalParams { get { return s_params_InstallLocal; } }
[GeneratedCode("T4MVC", "2.0"), DebuggerNonUserCode]
public class ActionParamsClass_InstallLocal
{
public readonly string Plugin = "Plugin";
}
static readonly ViewsClass s_views = new ViewsClass(); static readonly ViewsClass s_views = new ViewsClass();
[GeneratedCode("T4MVC", "2.0"), DebuggerNonUserCode] [GeneratedCode("T4MVC", "2.0"), DebuggerNonUserCode]
public ViewsClass Views { get { return s_views; } } public ViewsClass Views { get { return s_views; } }
@@ -6859,6 +6973,27 @@ namespace Disco.Web.Areas.API.Controllers
return callInfo; return callInfo;
} }
public override System.Web.Mvc.ActionResult UpdateAll()
{
var callInfo = new T4MVC_System_Web_Mvc_ActionResult(Area, Name, ActionNames.UpdateAll);
return callInfo;
}
public override System.Web.Mvc.ActionResult Update(string PluginId)
{
var callInfo = new T4MVC_System_Web_Mvc_ActionResult(Area, Name, ActionNames.Update);
ModelUnbinderHelpers.AddRouteValues(callInfo.RouteValueDictionary, "PluginId", PluginId);
return callInfo;
}
public override System.Web.Mvc.ActionResult UpdateLocal(string PluginId, System.Web.HttpPostedFileBase Plugin)
{
var callInfo = new T4MVC_System_Web_Mvc_ActionResult(Area, Name, ActionNames.UpdateLocal);
ModelUnbinderHelpers.AddRouteValues(callInfo.RouteValueDictionary, "PluginId", PluginId);
ModelUnbinderHelpers.AddRouteValues(callInfo.RouteValueDictionary, "Plugin", Plugin);
return callInfo;
}
public override System.Web.Mvc.ActionResult Uninstall(string id, bool UninstallData) public override System.Web.Mvc.ActionResult Uninstall(string id, bool UninstallData)
{ {
var callInfo = new T4MVC_System_Web_Mvc_ActionResult(Area, Name, ActionNames.Uninstall); var callInfo = new T4MVC_System_Web_Mvc_ActionResult(Area, Name, ActionNames.Uninstall);
@@ -6867,13 +7002,6 @@ namespace Disco.Web.Areas.API.Controllers
return callInfo; return callInfo;
} }
public override System.Web.Mvc.ActionResult InstallLocal(System.Web.HttpPostedFileBase Plugin)
{
var callInfo = new T4MVC_System_Web_Mvc_ActionResult(Area, Name, ActionNames.InstallLocal);
ModelUnbinderHelpers.AddRouteValues(callInfo.RouteValueDictionary, "Plugin", Plugin);
return callInfo;
}
public override System.Web.Mvc.ActionResult Install(string PluginId) public override System.Web.Mvc.ActionResult Install(string PluginId)
{ {
var callInfo = new T4MVC_System_Web_Mvc_ActionResult(Area, Name, ActionNames.Install); var callInfo = new T4MVC_System_Web_Mvc_ActionResult(Area, Name, ActionNames.Install);
@@ -6881,6 +7009,13 @@ namespace Disco.Web.Areas.API.Controllers
return callInfo; return callInfo;
} }
public override System.Web.Mvc.ActionResult InstallLocal(System.Web.HttpPostedFileBase Plugin)
{
var callInfo = new T4MVC_System_Web_Mvc_ActionResult(Area, Name, ActionNames.InstallLocal);
ModelUnbinderHelpers.AddRouteValues(callInfo.RouteValueDictionary, "Plugin", Plugin);
return callInfo;
}
} }
} }