fix remaining default resx differences, enhance module message with ability to dismiss, fix issue in ConfigManager.RemoveSetting, introduce package registry service

This commit is contained in:
Shaun Walker 2021-06-22 14:14:46 -04:00
parent 247e00ecd4
commit c4e6a4af49
26 changed files with 643 additions and 420 deletions

View File

@ -55,17 +55,15 @@ else
<TabPanel Name="Download" ResourceKey="Download" Security="SecurityAccessLevel.Host">
@if (_packages != null && _packages.Count > 0)
{
<ModuleMessage Type="MessageType.Info" Message="Download one or more language packages from the list below. Once you are ready click Install to complete the installation."></ModuleMessage>
<ModuleMessage Type="MessageType.Info" Message="Download one or more translations from the list below. Once you are ready click Install to complete the installation."></ModuleMessage>
<Pager Items="@_packages">
<Header>
<th>@Localizer["Name"]</th>
<th>@Localizer["Version"]</th>
<th style="width: 1px"></th>
</Header>
<Row>
<td>@context.Name</td>
<td>@context.Version</td>
<td>
<h3 style="display: inline;"><a href="@context.ProductUrl" target="_new">@context.Name</a></h3>&nbsp;&nbsp;by:&nbsp;&nbsp;<strong><a href="@context.OwnerUrl" target="new">@context.Owner</a></strong><br />
<strong>@context.Downloads.ToString("###,###,##0")</strong> downloads&nbsp;&nbsp;|&nbsp;&nbsp; released: <strong>@context.ReleaseDate.ToString("MMM dd, yyyy")</strong>&nbsp;&nbsp;|&nbsp;&nbsp;version: <strong>@context.Version</strong><br />
@(context.Description.Length > 400 ? (context.Description.Substring(0, 400) + "...") : context.Description)
</td>
<td style="vertical-align: middle;">
<button type="button" class="btn btn-primary" @onclick=@(async () => await DownloadLanguage(context.PackageId, context.Version))>@Localizer["Download"]</button>
</td>
</Row>
@ -75,14 +73,14 @@ else
}
else
{
<ModuleMessage Type="MessageType.Info" Message="No Language Packages Are Available To Download"></ModuleMessage>
<ModuleMessage Type="MessageType.Info" Message="No Translations Are Available To Download"></ModuleMessage>
}
</TabPanel>
<TabPanel Name="Upload" ResourceKey="Upload" Security="SecurityAccessLevel.Host">
<table class="table table-borderless">
<tr>
<td>
<Label HelpText="Upload one or more language packages. Once they are uploaded click Install to complete the installation." ResourceKey="Module">Language: </Label>
<Label HelpText="Upload one or more translations. Once they are uploaded click Install to complete the installation." ResourceKey="Module">Language: </Label>
</td>
<td>
<FileManager Filter="nupkg" ShowFiles="false" Folder="Packages" UploadMultiple="true" />
@ -113,7 +111,7 @@ else
_supportedCultures = await LocalizationService.GetCulturesAsync();
_availableCultures = _supportedCultures
.Where(c => !c.Name.Equals(Constants.DefaultCulture) && !languagesCodes.Contains(c.Name));
_packages = await PackageService.GetPackagesAsync("language");
_packages = await PackageService.GetPackagesAsync("translation");
if (_supportedCultures.Count() == 1)
{
@ -164,7 +162,7 @@ else
}
catch (Exception ex)
{
await logger.LogError(ex, "Error Installing Language Package");
await logger.LogError(ex, "Error Installing Translations");
}
}
@ -179,8 +177,8 @@ else
}
catch (Exception ex)
{
await logger.LogError(ex, "Error Downloading Language Package {Name} {Version}", packageid, version);
AddModuleMessage(Localizer["Error.Langauge.Download"], MessageType.Error);
await logger.LogError(ex, "Error Downloading Translation {Name} {Version}", packageid, version);
AddModuleMessage(Localizer["Error.Language.Download"], MessageType.Error);
}
}

View File

@ -22,7 +22,7 @@ else
<th style="width: 1px;">&nbsp;</th>
</Header>
<Row>
<td><ActionDialog Header="Delete Langauge" Message="@string.Format(Localizer["Confirm.Langauge.Delete"], context.Name)" Action="Delete" Security="SecurityAccessLevel.Admin" Class="btn btn-danger" OnClick="@(async () => await DeleteLanguage(context))" Disabled="@((context.IsDefault && _languages.Count > 2) || context.Code == Constants.DefaultCulture)" ResourceKey="DeleteLanguage" /></td>
<td><ActionDialog Header="Delete Language" Message="@string.Format(Localizer["Confirm.Language.Delete"], context.Name)" Action="Delete" Security="SecurityAccessLevel.Admin" Class="btn btn-danger" OnClick="@(async () => await DeleteLanguage(context))" Disabled="@((context.IsDefault && _languages.Count > 2) || context.Code == Constants.DefaultCulture)" ResourceKey="DeleteLanguage" /></td>
<td>@context.Name</td>
<td>@context.Code</td>
<td><TriStateCheckBox Value="@(context.IsDefault)" Disabled="true"></TriStateCheckBox></td>
@ -54,7 +54,7 @@ else
if (UserSecurity.IsAuthorized(PageState.User, RoleNames.Host))
{
_packages = await PackageService.GetPackagesAsync("language");
_packages = await PackageService.GetPackagesAsync("translation");
}
}
@ -97,15 +97,15 @@ else
if (UserSecurity.IsAuthorized(PageState.User, RoleNames.Host))
{
await PackageService.DownloadPackageAsync(Constants.PackageId + ".Client." + code, Constants.Version, "Packages");
await logger.LogInformation("Language Package Downloaded {Code} {Version}", code, Constants.Version);
await logger.LogInformation("Translation Downloaded {Code} {Version}", code, Constants.Version);
await PackageService.InstallPackagesAsync();
AddModuleMessage(string.Format(Localizer["Success.Language.Install"], NavigateUrl("admin/system")), MessageType.Success);
}
}
catch (Exception ex)
{
await logger.LogError(ex, "Error Downloading Language Package {Code} {Version} {Error}", code, Constants.Version, ex.Message);
AddModuleMessage(Localizer["Error.Langauge.Download"], MessageType.Error);
await logger.LogError(ex, "Error Downloading Translation {Code} {Version} {Error}", code, Constants.Version, ex.Message);
AddModuleMessage(Localizer["Error.Language.Download"], MessageType.Error);
}
}
}

View File

@ -14,15 +14,13 @@
<TabPanel Name="Download" ResourceKey="Download">
<ModuleMessage Type="MessageType.Info" Message="Download one or more modules from the list below. Once you are ready click Install to complete the installation."></ModuleMessage>
<Pager Items="@_packages">
<Header>
<th>@Localizer["Name"]</th>
<th>@Localizer["Version"]</th>
<th style="width: 1px"></th>
</Header>
<Row>
<td>@context.Name</td>
<td>@context.Version</td>
<td>
<h3 style="display: inline;"><a href="@context.ProductUrl" target="_new">@context.Name</a></h3>&nbsp;&nbsp;by:&nbsp;&nbsp;<strong><a href="@context.OwnerUrl" target="new">@context.Owner</a></strong><br />
<strong>@context.Downloads.ToString("###,###,##0")</strong> downloads&nbsp;&nbsp;|&nbsp;&nbsp; released: <strong>@context.ReleaseDate.ToString("MMM dd, yyyy")</strong>&nbsp;&nbsp;|&nbsp;&nbsp;version: <strong>@context.Version</strong><br />
@(context.Description.Length > 400 ? (context.Description.Substring(0, 400) + "...") : context.Description)
</td>
<td style="vertical-align: middle;">
<button type="button" class="btn btn-primary" @onclick=@(async () => await DownloadModule(context.PackageId, context.Version))>@Localizer["Download"]</button>
</td>
</Row>

View File

@ -14,15 +14,13 @@
<TabPanel Name="Download" ResourceKey="Download">
<ModuleMessage Type="MessageType.Info" Message="Download one or more themes from the list below. Once you are ready click Install to complete the installation."></ModuleMessage>
<Pager Items="@_packages">
<Header>
<th>@Localizer["Name"]</th>
<th>@Localizer["Version"]</th>
<th style="width: 1px;"></th>
</Header>
<Row>
<td>@context.Name</td>
<td>@context.Version</td>
<td>
<h3 style="display: inline;"><a href="@context.ProductUrl" target="_new">@context.Name</a></h3>&nbsp;&nbsp;by:&nbsp;&nbsp;<strong><a href="@context.OwnerUrl" target="new">@context.Owner</a></strong><br />
<strong>@context.Downloads.ToString("###,###,##0")</strong> downloads&nbsp;&nbsp;|&nbsp;&nbsp; released: <strong>@context.ReleaseDate.ToString("MMM dd, yyyy")</strong>&nbsp;&nbsp;|&nbsp;&nbsp;version: <strong>@context.Version</strong><br />
@(context.Description.Length > 400 ? (context.Description.Substring(0, 400) + "...") : context.Description)
</td>
<td style="vertical-align: middle;">
<button type="button" class="btn btn-primary" @onclick=@(async () => await DownloadTheme(context.PackageId, context.Version))>@Localizer["Download"]</button>
</td>
</Row>

View File

@ -4,12 +4,15 @@
@if (!string.IsNullOrEmpty(_message))
{
<div class="@_classname" role="alert">
<div class="@_classname alert-dismissible fade show" role="alert">
@((MarkupString)_message)
@if (Type == MessageType.Error && PageState != null && UserSecurity.IsAuthorized(PageState.User, RoleNames.Host))
{
@((MarkupString)"&nbsp;&nbsp;")<NavLink href="@NavigateUrl("admin/log")">View Details</NavLink>
}
<button type="button" class="close" data-dismiss="alert" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
</div>
<br />
}

View File

@ -36,5 +36,6 @@
<ItemGroup>
<Folder Include="Resources\" />
<Folder Include="Resources\Themes\Controls\Theme\" />
</ItemGroup>
</Project>

View File

@ -117,7 +117,16 @@
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="Register" xml:space="preserve">
<value>Register</value>
<data name="Server.Text" xml:space="preserve">
<value>Server:</value>
</data>
<data name="Server.HelpText" xml:space="preserve">
<value>Enter the database server</value>
</data>
<data name="Database.Text" xml:space="preserve">
<value>Database:</value>
</data>
<data name="Database.HelpText" xml:space="preserve">
<value>Enter the name of the database</value>
</data>
</root>

View File

@ -0,0 +1,150 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata" id="root">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="Server.Text" xml:space="preserve">
<value>Server:</value>
</data>
<data name="Server.HelpText" xml:space="preserve">
<value>Enter the database server</value>
</data>
<data name="Port.Text" xml:space="preserve">
<value>Port:</value>
</data>
<data name="Port.HelpText" xml:space="preserve">
<value>Enter the port used to connect to the server</value>
</data>
<data name="Database.Text" xml:space="preserve">
<value>Database:</value>
</data>
<data name="Database.HelpText" xml:space="preserve">
<value>Enter the name of the database</value>
</data>
<data name="Uid.Text" xml:space="preserve">
<value>User Id:</value>
</data>
<data name="Uid.HelpText" xml:space="preserve">
<value>Enter the username to use for the database</value>
</data>
<data name="Pwd.Text" xml:space="preserve">
<value>Password:</value>
</data>
<data name="Pwd.HelpText" xml:space="preserve">
<value>Enter the password to use for the database</value>
</data>
</root>

View File

@ -0,0 +1,162 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata" id="root">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="Server.Text" xml:space="preserve">
<value>Server:</value>
</data>
<data name="Server.HelpText" xml:space="preserve">
<value>Enter the database server</value>
</data>
<data name="Port.Text" xml:space="preserve">
<value>Port:</value>
</data>
<data name="Port.HelpText" xml:space="preserve">
<value>Enter the port used to connect to the server</value>
</data>
<data name="Database.Text" xml:space="preserve">
<value>Database:</value>
</data>
<data name="Database.HelpText" xml:space="preserve">
<value>Enter the name of the database</value>
</data>
<data name="IntegratedSecurity.Text" xml:space="preserve">
<value>Integrated Security:</value>
</data>
<data name="IntegratedSecurity.HelpText" xml:space="preserve">
<value>Select if you want integrated security or not</value>
</data>
<data name="Uid.Text" xml:space="preserve">
<value>User Id:</value>
</data>
<data name="Uid.HelpText" xml:space="preserve">
<value>Enter the username to use for the database</value>
</data>
<data name="Pwd.Text" xml:space="preserve">
<value>Password:</value>
</data>
<data name="Pwd.HelpText" xml:space="preserve">
<value>Enter the password to use for the database</value>
</data>
<data name="True" xml:space="preserve">
<value>Wahr</value>
</data>
<data name="False" xml:space="preserve">
<value>Falsch</value>
</data>
</root>

View File

@ -0,0 +1,156 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata" id="root">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="Server.Text" xml:space="preserve">
<value>Server:</value>
</data>
<data name="Server.HelpText" xml:space="preserve">
<value>Enter the database server</value>
</data>
<data name="Database.Text" xml:space="preserve">
<value>Database:</value>
</data>
<data name="Database.HelpText" xml:space="preserve">
<value>Enter the name of the database</value>
</data>
<data name="IntegratedSecurity.Text" xml:space="preserve">
<value>Integrated Security:</value>
</data>
<data name="IntegratedSecurity.HelpText" xml:space="preserve">
<value>Select if you want integrated security or not</value>
</data>
<data name="Uid.Text" xml:space="preserve">
<value>User Id:</value>
</data>
<data name="Uid.HelpText" xml:space="preserve">
<value>Enter the username to use for the database</value>
</data>
<data name="Pwd.Text" xml:space="preserve">
<value>Password:</value>
</data>
<data name="Pwd.HelpText" xml:space="preserve">
<value>Enter the password to use for the database</value>
</data>
<data name="True" xml:space="preserve">
<value>Wahr</value>
</data>
<data name="False" xml:space="preserve">
<value>Falsch</value>
</data>
</root>

View File

@ -117,10 +117,10 @@
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="Login" xml:space="preserve">
<value>Login</value>
<data name="Server.Text" xml:space="preserve">
<value>File Name:</value>
</data>
<data name="Logout" xml:space="preserve">
<value>Logout</value>
<data name="Server.HelpText" xml:space="preserve">
<value>Enter the file name to use for the database</value>
</data>
</root>

View File

@ -117,55 +117,37 @@
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="Version:" xml:space="preserve">
<data name="Version" xml:space="preserve">
<value>Version:</value>
</data>
<data name="Database Configuration" xml:space="preserve">
<data name="DatabaseConfig" xml:space="preserve">
<value>Database Configuration</value>
</data>
<data name="Database Type:" xml:space="preserve">
<data name="DatabaseType" xml:space="preserve">
<value>Database Type:</value>
</data>
<data name="Local Database" xml:space="preserve">
<value>Local Database</value>
</data>
<data name="SQL Server" xml:space="preserve">
<value>SQL Server</value>
</data>
<data name="Server:" xml:space="preserve">
<value>Server:</value>
</data>
<data name="Database:" xml:space="preserve">
<value>Database:</value>
</data>
<data name="Integrated Security:" xml:space="preserve">
<value>Integrated Security:</value>
</data>
<data name="True" xml:space="preserve">
<value>True</value>
</data>
<data name="False" xml:space="preserve">
<value>False</value>
</data>
<data name="Username:" xml:space="preserve">
<value>Username:</value>
</data>
<data name="Password:" xml:space="preserve">
<value>Password:</value>
</data>
<data name="Application Administrator" xml:space="preserve">
<data name="ApplicationAdmin" xml:space="preserve">
<value>Application Administrator</value>
</data>
<data name="Confirm:" xml:space="preserve">
<data name="Username" xml:space="preserve">
<value>Username:</value>
</data>
<data name="Password" xml:space="preserve">
<value>Password:</value>
</data>
<data name="Confirm" xml:space="preserve">
<value>Confirm:</value>
</data>
<data name="Email:" xml:space="preserve">
<data name="Email" xml:space="preserve">
<value>Email:</value>
</data>
<data name="Install Now" xml:space="preserve">
<data name="InstallNow" xml:space="preserve">
<value>Install Now</value>
</data>
<data name="Please Enter All Fields And Ensure Passwords Match And Are Greater Than 5 Characters In Length" xml:space="preserve">
<data name="Error.DbConfig.Load" xml:space="preserve">
<value>Error loading Database Configuration Control</value>
</data>
<data name="Message.Require.DbInfo" xml:space="preserve">
<value>Please Enter All Fields And Ensure Passwords Match And Are Greater Than 5 Characters In Length</value>
</data>
</root>

View File

@ -117,73 +117,4 @@
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="Add" xml:space="preserve">
<value>Add</value>
</data>
<data name="AdminDash" xml:space="preserve">
<value>Admin Dashboard</value>
</data>
<data name="Cancel" xml:space="preserve">
<value>Cancel</value>
</data>
<data name="Container" xml:space="preserve">
<value>Container:</value>
</data>
<data name="ControlPanel" xml:space="preserve">
<value>Control Panel</value>
</data>
<data name="Delete" xml:space="preserve">
<value>Delete</value>
</data>
<data name="Edit" xml:space="preserve">
<value>Edit</value>
</data>
<data name="Error.Authorize.No" xml:space="preserve">
<value>Not Authorized</value>
</data>
<data name="Message.Require.ModuleSelect" xml:space="preserve">
<value>You Must Select A Module</value>
</data>
<data name="Module.AddExisting" xml:space="preserve">
<value>Add Existing Module</value>
</data>
<data name="Module.AddNew" xml:space="preserve">
<value>Add New Module</value>
</data>
<data name="Module.Manage" xml:space="preserve">
<value>Module Management:</value>
</data>
<data name="Module.Select" xml:space="preserve">
<value>Select Module</value>
</data>
<data name="Modules" xml:space="preserve">
<value>Modules</value>
</data>
<data name="Page.Delete" xml:space="preserve">
<value>Delete Page</value>
</data>
<data name="Page.Manage" xml:space="preserve">
<value>Page Management:</value>
</data>
<data name="Page.Module.Add" xml:space="preserve">
<value>Add Module To Page</value>
</data>
<data name="Page.Publish" xml:space="preserve">
<value>Publish Page</value>
</data>
<data name="Page.Select" xml:space="preserve">
<value>Select Page</value>
</data>
<data name="Page.Unpublish" xml:space="preserve">
<value>Unpublish Page</value>
</data>
<data name="Pane" xml:space="preserve">
<value>Pane:</value>
</data>
<data name="Success.Page.ModuleAdd" xml:space="preserve">
<value>Module Added to Page</value>
</data>
<data name="Title" xml:space="preserve">
<value>Title:</value>
</data>
</root>

View File

@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
@ -153,8 +153,8 @@
<data name="AllLanguages" xml:space="preserve">
<value>All The Installed Languages Have Been Added.</value>
</data>
<data name="Error.Langauge.Download" xml:space="preserve">
<value>Error Downloading Language Package</value>
<data name="Error.Language.Download" xml:space="preserve">
<value>Error Downloading Translation</value>
</data>
<data name="Install" xml:space="preserve">
<value>Install</value>
@ -163,12 +163,9 @@
<value>The Only Installed Language Is English</value>
</data>
<data name="Success.Language.Download" xml:space="preserve">
<value>Language Package Downloaded Successfully. Click Install To Complete Installation.</value>
<value>Translation Downloaded Successfully. Click Install To Complete Installation.</value>
</data>
<data name="Success.Language.Install" xml:space="preserve">
<value>Language Packages Installed Successfully. You Must &lt;a href=\"{0}\"&gt;Restart&lt;/a&gt; Your Application To Apply These Changes.</value>
</data>
<data name="Version" xml:space="preserve">
<value>Version</value>
<value>Translations Installed Successfully. You Must &lt;a href=\"{0}\"&gt;Restart&lt;/a&gt; Your Application To Apply These Changes.</value>
</data>
</root>

View File

@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
@ -129,7 +129,7 @@
<data name="Code" xml:space="preserve">
<value>Code</value>
</data>
<data name="Confirm.Langauge.Delete" xml:space="preserve">
<data name="Confirm.Language.Delete" xml:space="preserve">
<value>Are You Sure You Wish To Delete The {0} Language?</value>
</data>
<data name="Error.Language.Delete" xml:space="preserve">
@ -139,13 +139,13 @@
<value>Add Language</value>
</data>
<data name="DeleteLanguage.Header" xml:space="preserve">
<value>Delete Langauge</value>
<value>Delete Language</value>
</data>
<data name="Error.Langauge.Download" xml:space="preserve">
<value>Error Downloading Language Package</value>
<data name="Error.Language.Download" xml:space="preserve">
<value>Error Downloading Translation</value>
</data>
<data name="Success.Language.Install" xml:space="preserve">
<value>Language Package Installed Successfully. You Must &lt;a href=\"{0}\"&gt;Restart&lt;/a&gt; Your Application To Apply These Changes.</value>
<value>Translation Installed Successfully. You Must &lt;a href=\"{0}\"&gt;Restart&lt;/a&gt; Your Application To Apply These Changes.</value>
</data>
<data name="Upgrade" xml:space="preserve">
<value>Upgrade</value>

View File

@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
@ -123,15 +123,9 @@
<data name="Download" xml:space="preserve">
<value>Download</value>
</data>
<data name="Name" xml:space="preserve">
<value>Name</value>
</data>
<data name="Module.Text" xml:space="preserve">
<value>Module: </value>
</data>
<data name="Version" xml:space="preserve">
<value>Version</value>
</data>
<data name="Install" xml:space="preserve">
<value>Install</value>
</data>
@ -142,7 +136,7 @@
<value>Module Installed Successfully. You Must &lt;a href=\"{0}\"&gt;Restart&lt;/a&gt; Your Application To Apply These Changes.</value>
</data>
<data name="Success.Module.Download" xml:space="preserve">
<value>Modules Downloaded Successfully. Click Install To Complete Installation.</value>
<value>Module Downloaded Successfully. Click Install To Complete Installation.</value>
</data>
<data name="Error.Module.Download" xml:space="preserve">
<value>Error Downloading Module</value>

View File

@ -1,201 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="Save" xml:space="preserve">
<value>Save</value>
</data>
<data name="Cancel" xml:space="preserve">
<value>Cancel</value>
</data>
<data name="Yes" xml:space="preserve">
<value>Yes</value>
</data>
<data name="No" xml:space="preserve">
<value>No</value>
</data>
<data name="Name.Text" xml:space="preserve">
<value>Name: </value>
</data>
<data name="Container.Select" xml:space="preserve">
<value>Select Container</value>
</data>
<data name="Error.Theme.LoadPane" xml:space="preserve">
<value>Error Loading Pane Layouts For Theme</value>
</data>
<data name="DefaultContainer.Text" xml:space="preserve">
<value>Default Container: </value>
</data>
<data name="Theme.Select" xml:space="preserve">
<value>Select Theme</value>
</data>
<data name="Default Admin Container" xml:space="preserve">
<value>Default Admin Container</value>
</data>
<data name="Error.Aliases.InUse" xml:space="preserve">
<value>An Alias Specified Has Already Been Used For Another Site</value>
</data>
<data name="Message.required.SiteName" xml:space="preserve">
<value>You Must Provide A Site Name, Alias, And Default Theme/Container</value>
</data>
<data name="Error.SaveSite" xml:space="preserve">
<value>Error Saving Site</value>
</data>
<data name="Aliases.HelpText" xml:space="preserve">
<value>Enter the alias for the server</value>
</data>
<data name="DefaultContainer.HelpText" xml:space="preserve">
<value>Select the default container for the site</value>
</data>
<data name="DefaultAdminContainer.HelpText" xml:space="preserve">
<value>Select the default admin container for the site</value>
</data>
<data name="Tenant.Text" xml:space="preserve">
<value>Tenant: </value>
</data>
<data name="Aliases.Text" xml:space="preserve">
<value>Aliases: </value>
</data>
<data name="IsDeleted.Text" xml:space="preserve">
<value>Is Deleted? </value>
</data>
<data name="DefaultTheme.Text" xml:space="preserve">
<value>Default Theme: </value>
</data>
<data name="DefaultAdminContainer.Text" xml:space="preserve">
<value>Default Admin Container: </value>
</data>
<data name="Name.HelpText" xml:space="preserve">
<value>Enter the name of the site</value>
</data>
<data name="DefaultTheme.HelpText" xml:space="preserve">
<value>Select the default theme for the website</value>
</data>
<data name="IsDeleted.HelpText" xml:space="preserve">
<value>Has this site been deleted?</value>
</data>
<data name="Tenant.HelpText" xml:space="preserve">
<value>The tenant for the site</value>
</data>
<data name="ConnectionString.HelpText" xml:space="preserve">
<value>The database connection string</value>
</data>
<data name="ConnectionString.Text" xml:space="preserve">
<value>Connection String: </value>
</data>
</root>

View File

@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
@ -123,12 +123,6 @@
<data name="Download" xml:space="preserve">
<value>Download</value>
</data>
<data name="Name" xml:space="preserve">
<value>Name</value>
</data>
<data name="Version" xml:space="preserve">
<value>Version</value>
</data>
<data name="Install" xml:space="preserve">
<value>Install</value>
</data>
@ -142,7 +136,7 @@
<value>Theme Installed Successfully. You Must &lt;a href=\"{0}\"&gt;Restart&lt;/a&gt; Your Application To Apply These Changes.</value>
</data>
<data name="Success.Theme.Download" xml:space="preserve">
<value>Themes Downloaded Successfully. Click Install To Complete Installation.</value>
<value>Theme Downloaded Successfully. Click Install To Complete Installation.</value>
</data>
<data name="Error.Theme.Download" xml:space="preserve">
<value>Error Downloading Theme</value>

View File

@ -186,4 +186,7 @@
<data name="Title" xml:space="preserve">
<value>Title:</value>
</data>
<data name="System.Update" xml:space="preserve">
<value>Check For System Updates</value>
</data>
</root>

View File

@ -6,7 +6,8 @@ namespace Oqtane.Services
{
public interface IPackageService
{
Task<List<Package>> GetPackagesAsync(string tag);
Task<List<Package>> GetPackagesAsync(string type);
Task<List<Package>> GetPackagesAsync(string type, string search);
Task DownloadPackageAsync(string packageId, string version, string folder);
Task InstallPackagesAsync();
}

View File

@ -5,6 +5,7 @@ using System.Threading.Tasks;
using System.Linq;
using Oqtane.Documentation;
using Oqtane.Shared;
using System.Net;
namespace Oqtane.Services
{
@ -19,10 +20,15 @@ namespace Oqtane.Services
}
private string Apiurl => CreateApiUrl("Package", _siteState.Alias);
public async Task<List<Package>> GetPackagesAsync(string tag)
public async Task<List<Package>> GetPackagesAsync(string type)
{
List<Package> packages = await GetJsonAsync<List<Package>>($"{Apiurl}?tag={tag}");
return packages.OrderByDescending(item => item.Downloads).ToList();
return await GetPackagesAsync(type, "");
}
public async Task<List<Package>> GetPackagesAsync(string type, string search)
{
List<Package> packages = await GetJsonAsync<List<Package>>($"{Apiurl}?type={type}&search={WebUtility.UrlEncode(search)}");
return packages.OrderByDescending(item => item.Downloads).ToList(); // order by popularity
}
public async Task DownloadPackageAsync(string packageId, string version, string folder)

View File

@ -15,7 +15,6 @@
@if (_moduleDefinitions != null && UserSecurity.IsAuthorized(PageState.User, PermissionNames.Edit, PageState.Page.Permissions))
{
<div class="app-controlpanel" style="@_display">
<div class="@CardClass">
<div class="@HeaderClass">
<span class="font-weight-bold">@Localizer["ControlPanel"]</span>
@ -91,7 +90,6 @@
</div>
}
<hr class="app-rule" />
<div class="row">
<div class="col text-center">
<label for="Module" class="control-label">@Localizer["Module.Manage"] </label>
@ -189,11 +187,14 @@
</select>
</div>
</div>
<br />
<button type="button" class="btn btn-primary btn-block mx-auto" @onclick="@AddModule">@Localizer["Page.Module.Add"]</button>
@((MarkupString) Message)
@if (UserSecurity.IsAuthorized(PageState.User, RoleNames.Host))
{
<hr class="app-rule" />
<NavLink class="btn btn-info btn-block mx-auto" href="@NavigateUrl("admin/update")">@Localizer["System.Update"]</NavLink>
}
</div>
</div>
</div>

View File

@ -21,41 +21,29 @@ namespace Oqtane.Controllers
{
private readonly IInstallationManager _installationManager;
private readonly IWebHostEnvironment _environment;
private readonly IConfigManager _configManager;
private readonly ILogManager _logger;
public PackageController(IInstallationManager installationManager, IWebHostEnvironment environment, ILogManager logger)
public PackageController(IInstallationManager installationManager, IWebHostEnvironment environment, IConfigManager configManager, ILogManager logger)
{
_installationManager = installationManager;
_environment = environment;
_configManager = configManager;
_logger = logger;
}
// GET: api/<controller>?tag=x
// GET: api/<controller>?type=x&search=y
[HttpGet]
[Authorize(Roles = RoleNames.Host)]
public async Task<IEnumerable<Package>> Get(string tag)
public async Task<IEnumerable<Package>> Get(string type, string search)
{
List<Package> packages = new List<Package>();
using (var httpClient = new HttpClient())
// get packages
List<Package> packages;
using (var client = new HttpClient())
{
var searchResult = await GetJson<SearchResult>(httpClient, "https://azuresearch-usnc.nuget.org/query?q=tags:oqtane");
foreach(Data data in searchResult.Data)
{
if (data.Tags.Contains(tag))
{
Package package = new Package();
package.PackageId = data.Id;
package.Name = data.Title;
package.Description = data.Description;
package.Owner = data.Authors[0];
package.Version = data.Version;
package.Downloads = data.TotalDownloads;
packages.Add(package);
}
}
client.DefaultRequestHeaders.Add("Referer", HttpContext.Request.Host.Value);
packages = await GetJson<List<Package>>(client, Constants.PackageRegistryUrl + $"/api/registry/packages/?installationid={GetInstallationId()}&type={type.ToLower()}&version={Constants.Version}&search={search}");
}
return packages;
}
@ -63,19 +51,41 @@ namespace Oqtane.Controllers
[Authorize(Roles = RoleNames.Host)]
public async Task Post(string packageid, string version, string folder)
{
using (var httpClient = new HttpClient())
// get package info
Package package = null;
using (var client = new HttpClient())
{
folder = Path.Combine(_environment.ContentRootPath, folder);
var response = await httpClient.GetAsync("https://www.nuget.org/api/v2/package/" + packageid.ToLower() + "/" + version).ConfigureAwait(false);
response.EnsureSuccessStatusCode();
string filename = packageid + "." + version + ".nupkg";
using (var fileStream = new FileStream(Path.Combine(folder, filename), FileMode.Create, FileAccess.Write, FileShare.None))
client.DefaultRequestHeaders.Add("Referer", HttpContext.Request.Host.Value);
package = await GetJson<Package>(client, Constants.PackageRegistryUrl + $"/api/registry/package/?installationid={GetInstallationId()}&packageid={packageid}&version={version}");
}
if (package != null)
{
using (var httpClient = new HttpClient())
{
await response.Content.CopyToAsync(fileStream).ConfigureAwait(false);
folder = Path.Combine(_environment.ContentRootPath, folder);
var response = await httpClient.GetAsync(package.PackageUrl).ConfigureAwait(false);
response.EnsureSuccessStatusCode();
string filename = packageid + "." + version + ".nupkg";
using (var fileStream = new FileStream(Path.Combine(folder, filename), FileMode.Create, FileAccess.Write, FileShare.None))
{
await response.Content.CopyToAsync(fileStream).ConfigureAwait(false);
}
}
}
}
private string GetInstallationId()
{
var installationid = _configManager.GetSetting("InstallationId", "");
if (installationid == "")
{
installationid = Guid.NewGuid().ToString();
_configManager.AddOrUpdateSetting("InstallationId", installationid, true);
}
return installationid;
}
private async Task<T> GetJson<T>(HttpClient httpClient, string url)
{
Uri uri = new Uri(url);

View File

@ -102,7 +102,10 @@ namespace Oqtane.Infrastructure
jsonObj[currentSection] = value;
break;
case "remove":
jsonObj.Property(currentSection).Remove();
if (jsonObj.Property(currentSection) != null)
{
jsonObj.Property(currentSection).Remove();
}
break;
}
}

View File

@ -1,8 +1,9 @@
using System;
namespace Oqtane.Models
{
/// <summary>
/// A software Package which is like an Oqtane Plugin / Extension.
/// This is used for creating lists from NuGet to offer for installation.
/// A software Package for installation.
/// </summary>
public class Package
{
@ -12,19 +13,29 @@ namespace Oqtane.Models
public string PackageId { get; set; }
/// <summary>
/// Name of the package - may contains part or the entire Namespace.
/// Owner of the package
/// </summary>
public string Owner { get; set; }
/// <summary>
/// Url for the owner of the package
/// </summary>
public string OwnerUrl { get; set; }
/// <summary>
/// Friendly name of the package
/// </summary>
public string Name { get; set; }
/// <summary>
/// Nice description of the Package.
/// Description of the Package.
/// </summary>
public string Description { get; set; }
/// <summary>
/// Owner / Creator of the package - usually retrieved from NuGet.
/// Friendly name of the package
/// </summary>
public string Owner { get; set; }
public string ProductUrl { get; set; }
/// <summary>
/// Version as defined in the NuGet package.
@ -32,8 +43,23 @@ namespace Oqtane.Models
public string Version { get; set; }
/// <summary>
/// Download count on NuGet to show how popular the package is.
/// Download count to show how popular the package is.
/// </summary>
public long Downloads { get; set; }
/// <summary>
/// date the package was released
/// </summary>
public DateTime ReleaseDate { get; set; }
/// <summary>
/// The direct Url for downloading the package
/// </summary>
public string PackageUrl { get; set; }
/// <summary>
/// Indicates if any known security vulnerabilities exist ( only applicable to framework packages )
/// </summary>
public int Vulnerability { get; set; }
}
}

View File

@ -7,6 +7,7 @@ namespace Oqtane.Shared {
public const string ReleaseVersions = "1.0.0,1.0.1,1.0.2,1.0.3,1.0.4,2.0.0,2.0.1,2.0.2,2.1.0";
public const string PackageId = "Oqtane.Framework";
public const string UpdaterPackageId = "Oqtane.Updater";
public const string PackageRegistryUrl = "https://www.oqtane.net";
public const string DefaultDBType = "Oqtane.Database.SqlServer.SqlServerDatabase, Oqtane.Database.SqlServer";