V10: Umbraco Marketplace (#13511)
* v11: Umbraco Marketplace replaces packages repo (#13371) * add lang keys for marketplace * remove old 'repo' page and deprecate related services * add new view for Umbraco Marketplace * optimise margin/padding for other tabs * mark Our Repository constants as obsolete * improve css path to iframe slightly with more aliases and classnames * remove style qs * update URL of Marketplace * add ng-controller with utitlities for future PostMessage API * rename marketplace loaded function * remove iframe postmessage logic for time being * add handling of dynamic querystring params * assume url does not change * Added support for additional parameters for marketplace * Update src/JsonSchema/AppSettings.cs Fix styling issue Co-authored-by: Ronald Barendse <ronald@barend.se> * Update src/Umbraco.Core/Configuration/Models/MarketplaceSettings.cs Fix styling issue Co-authored-by: Ronald Barendse <ronald@barend.se> * Update src/Umbraco.Core/Configuration/Models/MarketplaceSettings.cs Make comment more descriptive Co-authored-by: Ronald Barendse <ronald@barend.se> * Update src/Umbraco.Core/Constants-Marketplace.cs Fix styling issue Co-authored-by: Ronald Barendse <ronald@barend.se> Co-authored-by: Bjarke Berg <mail@bergmania.dk> Co-authored-by: Ronald Barendse <ronald@barend.se> * Info panes not loading prerequisites (#13486) * load relations immediately on init and remove call to non-existing function `appTabChange` on destroy * load relations immediately on init and remove now not-used eventsService * update marketplace url to its final, live url * re-add files to prevent breaking change Co-authored-by: Bjarke Berg <mail@bergmania.dk> Co-authored-by: Ronald Barendse <ronald@barend.se>
This commit is contained in:
@@ -91,6 +91,8 @@ namespace JsonSchema
|
||||
public InstallDefaultDataSettings? DefaultDataCreation { get; set; }
|
||||
|
||||
public DataTypesSettings? DataTypes { get; set; }
|
||||
|
||||
public MarketplaceSettings? Marketplace { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -7,7 +7,8 @@ namespace Umbraco.Cms.Core.Configuration.Models;
|
||||
/// Typed configuration options for active directory settings.
|
||||
/// </summary>
|
||||
[UmbracoOptions(Constants.Configuration.ConfigActiveDirectory)]
|
||||
[Obsolete("This is not used anymore. Will be removed in Umbraco 12")]public class ActiveDirectorySettings
|
||||
[Obsolete("This is not used anymore. Will be removed in Umbraco 12")]
|
||||
public class ActiveDirectorySettings
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets a value for the Active Directory domain.
|
||||
|
||||
16
src/Umbraco.Core/Configuration/Models/MarketplaceSettings.cs
Normal file
16
src/Umbraco.Core/Configuration/Models/MarketplaceSettings.cs
Normal file
@@ -0,0 +1,16 @@
|
||||
// Copyright (c) Umbraco.
|
||||
// See LICENSE for more details.
|
||||
|
||||
namespace Umbraco.Cms.Core.Configuration.Models;
|
||||
|
||||
/// <summary>
|
||||
/// Configuration options for the Marketplace.
|
||||
/// </summary>
|
||||
[UmbracoOptions(Constants.Configuration.ConfigMarketplace)]
|
||||
public class MarketplaceSettings
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the additional parameters that are sent to the Marketplace.
|
||||
/// </summary>
|
||||
public Dictionary<string, string> AdditionalParameters { get; set; } = new ();
|
||||
}
|
||||
@@ -27,6 +27,7 @@ public static partial class Constants
|
||||
public const string ConfigHostingDebug = ConfigHostingPrefix + "Debug";
|
||||
public const string ConfigCustomErrorsMode = ConfigCustomErrorsPrefix + "Mode";
|
||||
public const string ConfigActiveDirectory = ConfigPrefix + "ActiveDirectory";
|
||||
public const string ConfigMarketplace = ConfigPrefix + "Marketplace";
|
||||
public const string ConfigLegacyPasswordMigration = ConfigPrefix + "LegacyPasswordMigration";
|
||||
public const string ConfigContent = ConfigPrefix + "Content";
|
||||
public const string ConfigCoreDebug = ConfigCorePrefix + "Debug";
|
||||
|
||||
12
src/Umbraco.Core/Constants-Marketplace.cs
Normal file
12
src/Umbraco.Core/Constants-Marketplace.cs
Normal file
@@ -0,0 +1,12 @@
|
||||
namespace Umbraco.Cms.Core;
|
||||
|
||||
public static partial class Constants
|
||||
{
|
||||
/// <summary>
|
||||
/// Defines the constants used for the Umbraco Marketplace.
|
||||
/// </summary>
|
||||
public static class Marketplace
|
||||
{
|
||||
public const string Url = "https://marketplace.umbraco.com";
|
||||
}
|
||||
}
|
||||
@@ -5,6 +5,7 @@ public static partial class Constants
|
||||
/// <summary>
|
||||
/// Defines the constants used for the Umbraco package repository
|
||||
/// </summary>
|
||||
[Obsolete("This is no longer used and will be removed in Umbraco 13")]
|
||||
public static class PackageRepository
|
||||
{
|
||||
public const string RestApiBaseUrl = "https://our.umbraco.com/webapi/packages/v1";
|
||||
|
||||
@@ -50,6 +50,7 @@ public static partial class UmbracoBuilderExtensions
|
||||
builder
|
||||
.AddUmbracoOptions<ModelsBuilderSettings>()
|
||||
.AddUmbracoOptions<ActiveDirectorySettings>()
|
||||
.AddUmbracoOptions<MarketplaceSettings>()
|
||||
.AddUmbracoOptions<ContentSettings>()
|
||||
.AddUmbracoOptions<CoreDebugSettings>()
|
||||
.AddUmbracoOptions<ExceptionFilterSettings>()
|
||||
|
||||
@@ -1262,6 +1262,7 @@ Mange hilsner fra Umbraco robotten
|
||||
<key alias="media">Mediearkiv</key>
|
||||
<key alias="member">Medlemmer</key>
|
||||
<key alias="packages">Pakker</key>
|
||||
<key alias="marketplace">Marketplace</key>
|
||||
<key alias="newsletters">Nyhedsbreve</key>
|
||||
<key alias="settings">Indstillinger</key>
|
||||
<key alias="statistics">Statistik</key>
|
||||
|
||||
@@ -1476,6 +1476,7 @@ To manage your website, simply open the Umbraco backoffice and start adding cont
|
||||
<key alias="member">Members</key>
|
||||
<key alias="newsletters">Newsletters</key>
|
||||
<key alias="packages">Packages</key>
|
||||
<key alias="marketplace">Marketplace</key>
|
||||
<key alias="settings">Settings</key>
|
||||
<key alias="statistics">Statistics</key>
|
||||
<key alias="translation">Translation</key>
|
||||
|
||||
@@ -1513,6 +1513,7 @@ To manage your website, simply open the Umbraco backoffice and start adding cont
|
||||
<key alias="media">Media</key>
|
||||
<key alias="member">Members</key>
|
||||
<key alias="packages">Packages</key>
|
||||
<key alias="marketplace">Marketplace</key>
|
||||
<key alias="settings">Settings</key>
|
||||
<key alias="translation">Translation</key>
|
||||
<key alias="users">Users</key>
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System.Runtime.Serialization;
|
||||
using System.Web;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Mvc.ViewFeatures;
|
||||
using Microsoft.AspNetCore.Routing;
|
||||
@@ -54,6 +55,7 @@ namespace Umbraco.Cms.Web.BackOffice.Controllers
|
||||
private MemberPasswordConfigurationSettings _memberPasswordConfigurationSettings;
|
||||
private DataTypesSettings _dataTypesSettings;
|
||||
private readonly ITempDataDictionaryFactory _tempDataDictionaryFactory;
|
||||
private MarketplaceSettings _marketplaceSettings;
|
||||
|
||||
[Obsolete("Use constructor that takes IOptionsMontior<DataTypeSettings>, scheduled for removal in V12")]
|
||||
public BackOfficeServerVariables(
|
||||
@@ -139,6 +141,7 @@ namespace Umbraco.Cms.Web.BackOffice.Controllers
|
||||
{
|
||||
}
|
||||
|
||||
[Obsolete("Use constructor that takes IOptionsMonitor<MarketplaceSettings>, scheduled for removal in V13")]
|
||||
public BackOfficeServerVariables(
|
||||
LinkGenerator linkGenerator,
|
||||
IRuntimeState runtimeState,
|
||||
@@ -159,6 +162,52 @@ namespace Umbraco.Cms.Web.BackOffice.Controllers
|
||||
IOptionsMonitor<MemberPasswordConfigurationSettings> memberPasswordConfigurationSettings,
|
||||
IOptionsMonitor<DataTypesSettings> dataTypesSettings,
|
||||
ITempDataDictionaryFactory tempDataDictionaryFactory)
|
||||
: this(
|
||||
linkGenerator,
|
||||
runtimeState,
|
||||
features,
|
||||
globalSettings,
|
||||
umbracoVersion,
|
||||
contentSettings,
|
||||
httpContextAccessor,
|
||||
treeCollection,
|
||||
hostingEnvironment,
|
||||
runtimeSettings,
|
||||
securitySettings,
|
||||
runtimeMinifier,
|
||||
externalLogins,
|
||||
imageUrlGenerator,
|
||||
previewRoutes,
|
||||
emailSender,
|
||||
memberPasswordConfigurationSettings,
|
||||
dataTypesSettings,
|
||||
tempDataDictionaryFactory,
|
||||
StaticServiceProvider.Instance.GetRequiredService<IOptionsMonitor<MarketplaceSettings>>()
|
||||
)
|
||||
{
|
||||
}
|
||||
|
||||
public BackOfficeServerVariables(
|
||||
LinkGenerator linkGenerator,
|
||||
IRuntimeState runtimeState,
|
||||
UmbracoFeatures features,
|
||||
IOptionsMonitor<GlobalSettings> globalSettings,
|
||||
IUmbracoVersion umbracoVersion,
|
||||
IOptionsMonitor<ContentSettings> contentSettings,
|
||||
IHttpContextAccessor httpContextAccessor,
|
||||
TreeCollection treeCollection,
|
||||
IHostingEnvironment hostingEnvironment,
|
||||
IOptionsMonitor<RuntimeSettings> runtimeSettings,
|
||||
IOptionsMonitor<SecuritySettings> securitySettings,
|
||||
IRuntimeMinifier runtimeMinifier,
|
||||
IBackOfficeExternalLoginProviders externalLogins,
|
||||
IImageUrlGenerator imageUrlGenerator,
|
||||
PreviewRoutes previewRoutes,
|
||||
IEmailSender emailSender,
|
||||
IOptionsMonitor<MemberPasswordConfigurationSettings> memberPasswordConfigurationSettings,
|
||||
IOptionsMonitor<DataTypesSettings> dataTypesSettings,
|
||||
ITempDataDictionaryFactory tempDataDictionaryFactory,
|
||||
IOptionsMonitor<MarketplaceSettings> marketplaceSettings)
|
||||
{
|
||||
_linkGenerator = linkGenerator;
|
||||
_runtimeState = runtimeState;
|
||||
@@ -179,6 +228,7 @@ namespace Umbraco.Cms.Web.BackOffice.Controllers
|
||||
_tempDataDictionaryFactory = tempDataDictionaryFactory;
|
||||
_memberPasswordConfigurationSettings = memberPasswordConfigurationSettings.CurrentValue;
|
||||
_dataTypesSettings = dataTypesSettings.CurrentValue;
|
||||
_marketplaceSettings = marketplaceSettings.CurrentValue;
|
||||
|
||||
globalSettings.OnChange(x => _globalSettings = x);
|
||||
contentSettings.OnChange(x => _contentSettings = x);
|
||||
@@ -186,6 +236,7 @@ namespace Umbraco.Cms.Web.BackOffice.Controllers
|
||||
securitySettings.OnChange(x => _securitySettings = x);
|
||||
dataTypesSettings.OnChange(x => _dataTypesSettings = x);
|
||||
memberPasswordConfigurationSettings.OnChange(x => _memberPasswordConfigurationSettings = x);
|
||||
marketplaceSettings.OnChange(x => _marketplaceSettings = x);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -298,6 +349,7 @@ namespace Umbraco.Cms.Web.BackOffice.Controllers
|
||||
{"gridConfig", _linkGenerator.GetPathByAction(nameof(BackOfficeController.GetGridConfig), backOfficeControllerName, new { area = Constants.Web.Mvc.BackOfficeArea })},
|
||||
// TODO: This is ultra confusing! this same key is used for different things, when returning the full app when authenticated it is this URL but when not auth'd it's actually the ServerVariables address
|
||||
{"serverVarsJs", _linkGenerator.GetPathByAction(nameof(BackOfficeController.Application), backOfficeControllerName, new { area = Constants.Web.Mvc.BackOfficeArea })},
|
||||
{"marketplaceUrl", GetMarketplaceUrl()},
|
||||
//API URLs
|
||||
{
|
||||
"packagesRestApiBaseUrl", Constants.PackageRepository.RestApiBaseUrl
|
||||
@@ -625,6 +677,25 @@ namespace Umbraco.Cms.Web.BackOffice.Controllers
|
||||
return defaultVals;
|
||||
}
|
||||
|
||||
private string GetMarketplaceUrl()
|
||||
{
|
||||
var uriBuilder = new UriBuilder(Constants.Marketplace.Url);
|
||||
|
||||
var query = HttpUtility.ParseQueryString(uriBuilder.Query);
|
||||
|
||||
query["umbversion"] = _runtimeState.SemanticVersion.ToSemanticStringWithoutBuild();
|
||||
query["style"] = "backoffice";
|
||||
|
||||
foreach (var kvp in _marketplaceSettings.AdditionalParameters)
|
||||
{
|
||||
query[kvp.Key] = kvp.Value;
|
||||
}
|
||||
|
||||
uriBuilder.Query = query.ToString();
|
||||
|
||||
return uriBuilder.ToString();
|
||||
}
|
||||
|
||||
[DataContract]
|
||||
private class PluginTree
|
||||
{
|
||||
|
||||
@@ -2,8 +2,9 @@
|
||||
* @ngdoc service
|
||||
* @name umbraco.resources.ourPackageRepositoryResource
|
||||
* @description handles data for package installations
|
||||
* @deprecated This resource is deprecated and will be removed in future versions. Umbraco no longer supports the Our Umbraco repository.
|
||||
**/
|
||||
function ourPackageRepositoryResource($q, $http, umbDataFormatter, umbRequestHelper) {
|
||||
function ourPackageRepositoryResource($http, umbRequestHelper) {
|
||||
|
||||
var baseurl = Umbraco.Sys.ServerVariables.umbracoUrls.packagesRestApiBaseUrl;
|
||||
|
||||
|
||||
@@ -1,3 +1,41 @@
|
||||
[data-element="editor-packages"] {
|
||||
.umb-pane {
|
||||
height: 100%;
|
||||
margin: 0;
|
||||
|
||||
.umb-pane-content,
|
||||
.umb-editor-sub-views {
|
||||
height: 100%;
|
||||
|
||||
.umb-editor-sub-view {
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
.sub-view-Marketplace {
|
||||
height: 100%;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
|
||||
.umb-editor-sub-view__content {
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.umb-marketplace-view-wrapper {
|
||||
height: 100%;
|
||||
display: flex;
|
||||
align-items: stretch;
|
||||
}
|
||||
|
||||
.umb-marketplace-view {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.umb-packages-view-title {
|
||||
font-size: 20px;
|
||||
font-weight: bold;
|
||||
|
||||
@@ -6,6 +6,6 @@
|
||||
</div>
|
||||
|
||||
<div class="umb-pane">
|
||||
<div ng-transclude></div>
|
||||
<div class="umb-pane-content" ng-transclude></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,17 +1,12 @@
|
||||
<div class="umb-editor-sub-views">
|
||||
|
||||
<div
|
||||
id="sub-view-{{$index}}"
|
||||
class="umb-editor-sub-view"
|
||||
ng-repeat="subView in subViews track by subView.alias"
|
||||
ng-class="'sub-view-' + subView.name"
|
||||
val-sub-view="subView">
|
||||
|
||||
<div class="umb-editor-sub-view__content"
|
||||
ng-show="subView.active === true"
|
||||
ng-include="subView.view">
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div
|
||||
id="sub-view-{{$index}}"
|
||||
class="umb-editor-sub-view"
|
||||
ng-repeat="subView in subViews track by subView.alias"
|
||||
ng-class="'sub-view-' + subView.name"
|
||||
val-sub-view="subView"
|
||||
ng-if="subView.active"
|
||||
>
|
||||
<div class="umb-editor-sub-view__content" ng-include="subView.view"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -6,10 +6,9 @@
|
||||
* @description
|
||||
* The controller for the info view of the datatype editor
|
||||
*/
|
||||
function DataTypeInfoController($scope, $routeParams, dataTypeResource, eventsService, $timeout, editorService) {
|
||||
function DataTypeInfoController($scope, $routeParams, dataTypeResource, $timeout, editorService) {
|
||||
|
||||
var vm = this;
|
||||
var evts = [];
|
||||
var referencesLoaded = false;
|
||||
|
||||
vm.references = {};
|
||||
@@ -48,7 +47,7 @@ function DataTypeInfoController($scope, $routeParams, dataTypeResource, eventsSe
|
||||
|
||||
function open(id, event, type) {
|
||||
// targeting a new tab/window?
|
||||
if (event.ctrlKey ||
|
||||
if (event.ctrlKey ||
|
||||
event.shiftKey ||
|
||||
event.metaKey || // apple
|
||||
(event.button && event.button === 1) // middle click, >IE9 + everyone else
|
||||
@@ -85,25 +84,7 @@ function DataTypeInfoController($scope, $routeParams, dataTypeResource, eventsSe
|
||||
}
|
||||
}
|
||||
|
||||
// load data type references when the references tab is activated
|
||||
evts.push(eventsService.on("app.tabChange", function (event, args) {
|
||||
$timeout(function () {
|
||||
if (args.alias === "info") {
|
||||
loadRelations();
|
||||
}
|
||||
});
|
||||
}));
|
||||
|
||||
//ensure to unregister from all events!
|
||||
$scope.$on('$destroy', function () {
|
||||
for (var e in evts) {
|
||||
eventsService.unsubscribe(evts[e]);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
||||
loadRelations();
|
||||
}
|
||||
|
||||
angular.module("umbraco").controller("Umbraco.Editors.DataType.InfoController", DataTypeInfoController);
|
||||
|
||||
@@ -1,99 +1,99 @@
|
||||
(function () {
|
||||
"use strict";
|
||||
"use strict";
|
||||
|
||||
function PackagesOverviewController($scope, $location, $routeParams, localizationService, localStorageService) {
|
||||
function PackagesOverviewController($location, $routeParams, localizationService, localStorageService) {
|
||||
|
||||
//Hack!
|
||||
// if there is a local storage value for packageInstallData then we need to redirect there,
|
||||
// the issue is that we still have webforms and we cannot go to a hash location and then window.reload
|
||||
// because it will double load it.
|
||||
// we will refresh and then navigate there.
|
||||
//Hack!
|
||||
// if there is a local storage value for packageInstallData then we need to redirect there,
|
||||
// the issue is that we still have webforms and we cannot go to a hash location and then window.reload
|
||||
// because it will double load it.
|
||||
// we will refresh and then navigate there.
|
||||
|
||||
let packageInstallData = localStorageService.get("packageInstallData");
|
||||
let packageUri = $routeParams.method;
|
||||
let packageInstallData = localStorageService.get("packageInstallData");
|
||||
let packageUri = $routeParams.method;
|
||||
|
||||
if (packageInstallData) {
|
||||
localStorageService.remove("packageInstallData");
|
||||
if (packageInstallData) {
|
||||
localStorageService.remove("packageInstallData");
|
||||
|
||||
if (packageInstallData.postInstallationPath) {
|
||||
//navigate to the custom installer screen if set
|
||||
$location.path(packageInstallData.postInstallationPath).search("packageId", packageInstallData.id);
|
||||
return;
|
||||
}
|
||||
if (packageInstallData.postInstallationPath) {
|
||||
//navigate to the custom installer screen if set
|
||||
$location.path(packageInstallData.postInstallationPath).search("packageId", packageInstallData.id);
|
||||
return;
|
||||
}
|
||||
|
||||
//if it is "installed" then set the uri/path to that
|
||||
if (packageInstallData === "installed") {
|
||||
packageUri = "installed";
|
||||
}
|
||||
}
|
||||
|
||||
var vm = this;
|
||||
vm.page = {};
|
||||
vm.page.labels = {};
|
||||
vm.page.name = "";
|
||||
vm.page.navigation = [];
|
||||
|
||||
onInit();
|
||||
|
||||
function onInit() {
|
||||
|
||||
loadNavigation();
|
||||
|
||||
setPageName();
|
||||
}
|
||||
|
||||
function loadNavigation() {
|
||||
|
||||
var labels = ["sections_packages", "packager_installed", "packager_installLocal", "packager_created"];
|
||||
|
||||
localizationService.localizeMany(labels).then(function (data) {
|
||||
vm.page.labels.packages = data[0];
|
||||
vm.page.labels.installed = data[1];
|
||||
vm.page.labels.install = data[2];
|
||||
vm.page.labels.created = data[3];
|
||||
|
||||
vm.page.navigation = [
|
||||
{
|
||||
"name": vm.page.labels.packages,
|
||||
"icon": "icon-cloud",
|
||||
"view": "views/packages/views/repo.html",
|
||||
"active": !packageUri || packageUri === "repo",
|
||||
"alias": "umbPackages",
|
||||
"action": function () {
|
||||
$location.path("/packages/packages/repo");
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": vm.page.labels.installed,
|
||||
"icon": "icon-box",
|
||||
"view": "views/packages/views/installed.html",
|
||||
"active": packageUri === "installed",
|
||||
"alias": "umbInstalled",
|
||||
"action": function () {
|
||||
$location.path("/packages/packages/installed");
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": vm.page.labels.created,
|
||||
"icon": "icon-files",
|
||||
"view": "views/packages/views/created.html",
|
||||
"active": packageUri === "created",
|
||||
"alias": "umbCreatedPackages",
|
||||
"action": function () {
|
||||
$location.path("/packages/packages/created");
|
||||
}
|
||||
}
|
||||
];
|
||||
});
|
||||
}
|
||||
|
||||
function setPageName() {
|
||||
localizationService.localize("sections_packages").then(function (data) {
|
||||
vm.page.name = data;
|
||||
})
|
||||
}
|
||||
//if it is "installed" then set the uri/path to that
|
||||
if (packageInstallData === "installed") {
|
||||
packageUri = "installed";
|
||||
}
|
||||
}
|
||||
|
||||
angular.module("umbraco").controller("Umbraco.Editors.Packages.OverviewController", PackagesOverviewController);
|
||||
var vm = this;
|
||||
vm.page = {};
|
||||
vm.page.labels = {};
|
||||
vm.page.name = "";
|
||||
vm.page.navigation = [];
|
||||
|
||||
onInit();
|
||||
|
||||
function onInit() {
|
||||
|
||||
loadNavigation();
|
||||
|
||||
setPageName();
|
||||
}
|
||||
|
||||
function loadNavigation() {
|
||||
|
||||
var labels = ["sections_marketplace", "packager_installed", "packager_installLocal", "packager_created"];
|
||||
|
||||
localizationService.localizeMany(labels).then(function (data) {
|
||||
vm.page.labels.marketplace = data[0];
|
||||
vm.page.labels.installed = data[1];
|
||||
vm.page.labels.install = data[2];
|
||||
vm.page.labels.created = data[3];
|
||||
|
||||
vm.page.navigation = [
|
||||
{
|
||||
"name": vm.page.labels.marketplace,
|
||||
"icon": "icon-cloud",
|
||||
"view": "views/packages/views/marketplace.html",
|
||||
"active": !packageUri || packageUri === "repo",
|
||||
"alias": "umbMarketplace",
|
||||
"action": function () {
|
||||
$location.path("/packages/packages/repo");
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": vm.page.labels.installed,
|
||||
"icon": "icon-box",
|
||||
"view": "views/packages/views/installed.html",
|
||||
"active": packageUri === "installed",
|
||||
"alias": "umbInstalled",
|
||||
"action": function () {
|
||||
$location.path("/packages/packages/installed");
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": vm.page.labels.created,
|
||||
"icon": "icon-files",
|
||||
"view": "views/packages/views/created.html",
|
||||
"active": packageUri === "created",
|
||||
"alias": "umbCreatedPackages",
|
||||
"action": function () {
|
||||
$location.path("/packages/packages/created");
|
||||
}
|
||||
}
|
||||
];
|
||||
});
|
||||
}
|
||||
|
||||
function setPageName() {
|
||||
localizationService.localize("sections_marketplace").then(function (data) {
|
||||
vm.page.name = data;
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
angular.module("umbraco").controller("Umbraco.Editors.Packages.OverviewController", PackagesOverviewController);
|
||||
|
||||
})();
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
(function () {
|
||||
"use strict";
|
||||
|
||||
function MarketplaceController($sce) {
|
||||
|
||||
var vm = this;
|
||||
var marketplaceUrl = new URL(Umbraco.Sys.ServerVariables.umbracoUrls.marketplaceUrl);
|
||||
|
||||
function init() {
|
||||
vm.marketplaceUrl = $sce.trustAsResourceUrl(marketplaceUrl.toString());
|
||||
}
|
||||
|
||||
init();
|
||||
}
|
||||
|
||||
angular.module("umbraco").controller("Umbraco.Editors.Packages.MarketplaceController", MarketplaceController);
|
||||
|
||||
})();
|
||||
@@ -0,0 +1,13 @@
|
||||
<div
|
||||
class="umb-marketplace-view-wrapper clearfix"
|
||||
ng-controller="Umbraco.Editors.Packages.MarketplaceController as vm"
|
||||
>
|
||||
<iframe
|
||||
ng-if="::vm.marketplaceUrl"
|
||||
ng-src="{{ ::vm.marketplaceUrl }}"
|
||||
class="umb-marketplace-view"
|
||||
title="Umbraco Marketplace"
|
||||
allowfullscreen
|
||||
allow="geolocation; autoplay; clipboard-write; encrypted-media"
|
||||
></iframe>
|
||||
</div>
|
||||
@@ -1,265 +1,265 @@
|
||||
(function () {
|
||||
"use strict";
|
||||
"use strict";
|
||||
|
||||
function PackagesRepoController($scope, $timeout, ourPackageRepositoryResource, $q, localizationService, notificationsService) {
|
||||
function PackagesRepoController($scope, $timeout, ourPackageRepositoryResource, $q, localizationService, notificationsService) {
|
||||
|
||||
var vm = this;
|
||||
var vm = this;
|
||||
|
||||
vm.packageViewState = "packageList";
|
||||
vm.categories = [];
|
||||
vm.loading = true;
|
||||
vm.pagination = {
|
||||
pageNumber: 1,
|
||||
totalPages: 10,
|
||||
pageSize: 24
|
||||
};
|
||||
vm.searchQuery = "";
|
||||
vm.selectCategory = selectCategory;
|
||||
vm.showPackageDetails = showPackageDetails;
|
||||
vm.setPackageViewState = setPackageViewState;
|
||||
vm.nextPage = nextPage;
|
||||
vm.prevPage = prevPage;
|
||||
vm.goToPage = goToPage;
|
||||
vm.openLightbox = openLightbox;
|
||||
vm.closeLightbox = closeLightbox;
|
||||
vm.search = search;
|
||||
vm.installCompleted = false;
|
||||
vm.highlightedPackageCollections = [];
|
||||
vm.labels = {};
|
||||
vm.packageViewState = "packageList";
|
||||
vm.categories = [];
|
||||
vm.loading = true;
|
||||
vm.pagination = {
|
||||
pageNumber: 1,
|
||||
totalPages: 10,
|
||||
pageSize: 24
|
||||
};
|
||||
vm.searchQuery = "";
|
||||
vm.selectCategory = selectCategory;
|
||||
vm.showPackageDetails = showPackageDetails;
|
||||
vm.setPackageViewState = setPackageViewState;
|
||||
vm.nextPage = nextPage;
|
||||
vm.prevPage = prevPage;
|
||||
vm.goToPage = goToPage;
|
||||
vm.openLightbox = openLightbox;
|
||||
vm.closeLightbox = closeLightbox;
|
||||
vm.search = search;
|
||||
vm.installCompleted = false;
|
||||
vm.highlightedPackageCollections = [];
|
||||
vm.labels = {};
|
||||
|
||||
var defaultSort = "Latest";
|
||||
var currSort = defaultSort;
|
||||
var defaultSort = "Latest";
|
||||
var currSort = defaultSort;
|
||||
|
||||
//used to cancel any request in progress if another one needs to take it's place
|
||||
var canceler = null;
|
||||
//used to cancel any request in progress if another one needs to take it's place
|
||||
var canceler = null;
|
||||
|
||||
function getActiveCategory() {
|
||||
if (vm.searchQuery !== "") {
|
||||
return "";
|
||||
}
|
||||
for (var i = 0; i < vm.categories.length; i++) {
|
||||
if (vm.categories[i].active === true) {
|
||||
return vm.categories[i].name;
|
||||
}
|
||||
}
|
||||
return "";
|
||||
function getActiveCategory() {
|
||||
if (vm.searchQuery !== "") {
|
||||
return "";
|
||||
}
|
||||
for (var i = 0; i < vm.categories.length; i++) {
|
||||
if (vm.categories[i].active === true) {
|
||||
return vm.categories[i].name;
|
||||
}
|
||||
|
||||
function init() {
|
||||
|
||||
vm.loading = true;
|
||||
localizationService.localizeMany(["packager_packagesPopular", "packager_packagesPromoted"])
|
||||
.then(function (labels) {
|
||||
vm.labels.popularPackages = labels[0];
|
||||
vm.labels.promotedPackages = labels[1];
|
||||
|
||||
var popularPackages, promotedPackages;
|
||||
$q.all([
|
||||
ourPackageRepositoryResource.getCategories()
|
||||
.then(function (cats) {
|
||||
vm.categories = cats.filter(function (cat) {
|
||||
return cat.name !== "Umbraco Pro";
|
||||
});
|
||||
}),
|
||||
ourPackageRepositoryResource.getPopular(10)
|
||||
.then(function (pack) {
|
||||
popularPackages = { title: vm.labels.popularPackages, packages: pack.packages };
|
||||
}),
|
||||
ourPackageRepositoryResource.getPromoted(20)
|
||||
.then(function (pack) {
|
||||
promotedPackages = { title: vm.labels.promotedPackages, packages: pack.packages };
|
||||
}),
|
||||
ourPackageRepositoryResource.search(vm.pagination.pageNumber - 1, vm.pagination.pageSize, currSort)
|
||||
.then(function (pack) {
|
||||
vm.packages = pack.packages;
|
||||
vm.pagination.totalPages = Math.ceil(pack.total / vm.pagination.pageSize);
|
||||
})
|
||||
])
|
||||
.then(function () {
|
||||
vm.highlightedPackageCollections = [popularPackages, promotedPackages];
|
||||
vm.loading = false;
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function selectCategory(selectedCategory, categories) {
|
||||
|
||||
for (var i = 0; i < categories.length; i++) {
|
||||
var category = categories[i];
|
||||
if (category.name === selectedCategory.name) {
|
||||
//it's already selected, let's unselect to show all again
|
||||
if (category.active === true) {
|
||||
category.active = false;
|
||||
}
|
||||
else {
|
||||
category.active = true;
|
||||
}
|
||||
}
|
||||
else {
|
||||
category.active = false;
|
||||
}
|
||||
}
|
||||
|
||||
vm.loading = true;
|
||||
vm.searchQuery = "";
|
||||
|
||||
var reset = selectedCategory.active === false;
|
||||
var searchCategory = reset ? "" : selectedCategory.name;
|
||||
|
||||
currSort = defaultSort;
|
||||
|
||||
var popularPackages, promotedPackages;
|
||||
$q.all([
|
||||
ourPackageRepositoryResource.getPopular(10, searchCategory)
|
||||
.then(function (pack) {
|
||||
popularPackages = { title: vm.labels.popularPackages, packages: pack.packages };
|
||||
}),
|
||||
ourPackageRepositoryResource.getPromoted(20, searchCategory)
|
||||
.then(function (pack) {
|
||||
promotedPackages = { title: vm.labels.promotedPackages, packages: pack.packages };
|
||||
}),
|
||||
ourPackageRepositoryResource.search(vm.pagination.pageNumber - 1, vm.pagination.pageSize, currSort, searchCategory, vm.searchQuery)
|
||||
.then(function (pack) {
|
||||
vm.packages = pack.packages;
|
||||
vm.pagination.totalPages = Math.ceil(pack.total / vm.pagination.pageSize);
|
||||
vm.pagination.pageNumber = 1;
|
||||
})
|
||||
])
|
||||
.then(function () {
|
||||
vm.highlightedPackageCollections = [popularPackages, promotedPackages];
|
||||
vm.loading = false;
|
||||
});
|
||||
}
|
||||
|
||||
function showPackageDetails(selectedPackage) {
|
||||
ourPackageRepositoryResource.getDetails(selectedPackage.id)
|
||||
.then(function (pack) {
|
||||
vm.package = pack;
|
||||
vm.packageViewState = "packageDetails";
|
||||
});
|
||||
}
|
||||
|
||||
function setPackageViewState(state) {
|
||||
if (state) {
|
||||
vm.packageViewState = state;
|
||||
}
|
||||
}
|
||||
|
||||
function nextPage(pageNumber) {
|
||||
ourPackageRepositoryResource.search(pageNumber - 1, vm.pagination.pageSize, currSort, getActiveCategory(), vm.searchQuery)
|
||||
.then(function (pack) {
|
||||
vm.packages = pack.packages;
|
||||
vm.pagination.totalPages = Math.ceil(pack.total / vm.pagination.pageSize);
|
||||
});
|
||||
}
|
||||
|
||||
function prevPage(pageNumber) {
|
||||
ourPackageRepositoryResource.search(pageNumber - 1, vm.pagination.pageSize, currSort, getActiveCategory(), vm.searchQuery)
|
||||
.then(function (pack) {
|
||||
vm.packages = pack.packages;
|
||||
vm.pagination.totalPages = Math.ceil(pack.total / vm.pagination.pageSize);
|
||||
});
|
||||
}
|
||||
|
||||
function goToPage(pageNumber) {
|
||||
ourPackageRepositoryResource.search(pageNumber - 1, vm.pagination.pageSize, currSort, getActiveCategory(), vm.searchQuery)
|
||||
.then(function (pack) {
|
||||
vm.packages = pack.packages;
|
||||
vm.pagination.totalPages = Math.ceil(pack.total / vm.pagination.pageSize);
|
||||
});
|
||||
}
|
||||
var previousElement = null;
|
||||
|
||||
function openLightbox(itemIndex, items) {
|
||||
|
||||
previousElement = ( document.activeElement || document.body );
|
||||
|
||||
vm.lightbox = {
|
||||
show: true,
|
||||
items: items,
|
||||
activeIndex: itemIndex,
|
||||
focus: true
|
||||
};
|
||||
}
|
||||
|
||||
function closeLightbox() {
|
||||
vm.lightbox.show = false;
|
||||
vm.lightbox = null;
|
||||
|
||||
if(previousElement){
|
||||
setTimeout(function(){
|
||||
previousElement.focus();
|
||||
previousElement = null;
|
||||
}, 100)
|
||||
}
|
||||
document.activeElement.blur();
|
||||
}
|
||||
|
||||
|
||||
var searchDebounced = _.debounce(function (e) {
|
||||
//a canceler exists, so perform the cancelation operation and reset
|
||||
if (canceler) {
|
||||
canceler.resolve();
|
||||
}
|
||||
|
||||
canceler = $q.defer();
|
||||
|
||||
$scope.$apply(function () {
|
||||
currSort = vm.searchQuery ? "Default" : "Latest";
|
||||
|
||||
ourPackageRepositoryResource.search(vm.pagination.pageNumber - 1,
|
||||
vm.pagination.pageSize,
|
||||
currSort,
|
||||
"",
|
||||
vm.searchQuery,
|
||||
canceler.promise)
|
||||
.then(function (pack) {
|
||||
vm.packages = pack.packages;
|
||||
vm.pagination.totalPages = Math.ceil(pack.total / vm.pagination.pageSize);
|
||||
vm.pagination.pageNumber = 1;
|
||||
vm.loading = false;
|
||||
//set back to null so it can be re-created
|
||||
canceler = null;
|
||||
})
|
||||
.catch(function (err) {
|
||||
canceler = null;
|
||||
|
||||
if (err) {
|
||||
// If an abort happened, ignore it since it happened because of a new search
|
||||
if (err.xhrStatus === 'abort') {
|
||||
return;
|
||||
}
|
||||
|
||||
// Otherwise, show the error
|
||||
if (err.errorMsg) {
|
||||
notificationsService.error(err.errorMsg);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
console.error(err);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
}, 200);
|
||||
|
||||
function search(searchQuery) {
|
||||
vm.loading = true;
|
||||
searchDebounced();
|
||||
}
|
||||
|
||||
vm.reloadPage = function () {
|
||||
//reload on next digest (after cookie)
|
||||
$timeout(function () {
|
||||
window.location.reload(true);
|
||||
});
|
||||
}
|
||||
|
||||
init();
|
||||
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
angular.module("umbraco").controller("Umbraco.Editors.Packages.RepoController", PackagesRepoController);
|
||||
function init() {
|
||||
|
||||
vm.loading = true;
|
||||
localizationService.localizeMany(["packager_packagesPopular", "packager_packagesPromoted"])
|
||||
.then(function (labels) {
|
||||
vm.labels.popularPackages = labels[0];
|
||||
vm.labels.promotedPackages = labels[1];
|
||||
|
||||
var popularPackages, promotedPackages;
|
||||
$q.all([
|
||||
ourPackageRepositoryResource.getCategories()
|
||||
.then(function (cats) {
|
||||
vm.categories = cats.filter(function (cat) {
|
||||
return cat.name !== "Umbraco Pro";
|
||||
});
|
||||
}),
|
||||
ourPackageRepositoryResource.getPopular(10)
|
||||
.then(function (pack) {
|
||||
popularPackages = { title: vm.labels.popularPackages, packages: pack.packages };
|
||||
}),
|
||||
ourPackageRepositoryResource.getPromoted(20)
|
||||
.then(function (pack) {
|
||||
promotedPackages = { title: vm.labels.promotedPackages, packages: pack.packages };
|
||||
}),
|
||||
ourPackageRepositoryResource.search(vm.pagination.pageNumber - 1, vm.pagination.pageSize, currSort)
|
||||
.then(function (pack) {
|
||||
vm.packages = pack.packages;
|
||||
vm.pagination.totalPages = Math.ceil(pack.total / vm.pagination.pageSize);
|
||||
})
|
||||
])
|
||||
.then(function () {
|
||||
vm.highlightedPackageCollections = [popularPackages, promotedPackages];
|
||||
vm.loading = false;
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function selectCategory(selectedCategory, categories) {
|
||||
|
||||
for (var i = 0; i < categories.length; i++) {
|
||||
var category = categories[i];
|
||||
if (category.name === selectedCategory.name) {
|
||||
//it's already selected, let's unselect to show all again
|
||||
if (category.active === true) {
|
||||
category.active = false;
|
||||
}
|
||||
else {
|
||||
category.active = true;
|
||||
}
|
||||
}
|
||||
else {
|
||||
category.active = false;
|
||||
}
|
||||
}
|
||||
|
||||
vm.loading = true;
|
||||
vm.searchQuery = "";
|
||||
|
||||
var reset = selectedCategory.active === false;
|
||||
var searchCategory = reset ? "" : selectedCategory.name;
|
||||
|
||||
currSort = defaultSort;
|
||||
|
||||
var popularPackages, promotedPackages;
|
||||
$q.all([
|
||||
ourPackageRepositoryResource.getPopular(10, searchCategory)
|
||||
.then(function (pack) {
|
||||
popularPackages = { title: vm.labels.popularPackages, packages: pack.packages };
|
||||
}),
|
||||
ourPackageRepositoryResource.getPromoted(20, searchCategory)
|
||||
.then(function (pack) {
|
||||
promotedPackages = { title: vm.labels.promotedPackages, packages: pack.packages };
|
||||
}),
|
||||
ourPackageRepositoryResource.search(vm.pagination.pageNumber - 1, vm.pagination.pageSize, currSort, searchCategory, vm.searchQuery)
|
||||
.then(function (pack) {
|
||||
vm.packages = pack.packages;
|
||||
vm.pagination.totalPages = Math.ceil(pack.total / vm.pagination.pageSize);
|
||||
vm.pagination.pageNumber = 1;
|
||||
})
|
||||
])
|
||||
.then(function () {
|
||||
vm.highlightedPackageCollections = [popularPackages, promotedPackages];
|
||||
vm.loading = false;
|
||||
});
|
||||
}
|
||||
|
||||
function showPackageDetails(selectedPackage) {
|
||||
ourPackageRepositoryResource.getDetails(selectedPackage.id)
|
||||
.then(function (pack) {
|
||||
vm.package = pack;
|
||||
vm.packageViewState = "packageDetails";
|
||||
});
|
||||
}
|
||||
|
||||
function setPackageViewState(state) {
|
||||
if (state) {
|
||||
vm.packageViewState = state;
|
||||
}
|
||||
}
|
||||
|
||||
function nextPage(pageNumber) {
|
||||
ourPackageRepositoryResource.search(pageNumber - 1, vm.pagination.pageSize, currSort, getActiveCategory(), vm.searchQuery)
|
||||
.then(function (pack) {
|
||||
vm.packages = pack.packages;
|
||||
vm.pagination.totalPages = Math.ceil(pack.total / vm.pagination.pageSize);
|
||||
});
|
||||
}
|
||||
|
||||
function prevPage(pageNumber) {
|
||||
ourPackageRepositoryResource.search(pageNumber - 1, vm.pagination.pageSize, currSort, getActiveCategory(), vm.searchQuery)
|
||||
.then(function (pack) {
|
||||
vm.packages = pack.packages;
|
||||
vm.pagination.totalPages = Math.ceil(pack.total / vm.pagination.pageSize);
|
||||
});
|
||||
}
|
||||
|
||||
function goToPage(pageNumber) {
|
||||
ourPackageRepositoryResource.search(pageNumber - 1, vm.pagination.pageSize, currSort, getActiveCategory(), vm.searchQuery)
|
||||
.then(function (pack) {
|
||||
vm.packages = pack.packages;
|
||||
vm.pagination.totalPages = Math.ceil(pack.total / vm.pagination.pageSize);
|
||||
});
|
||||
}
|
||||
var previousElement = null;
|
||||
|
||||
function openLightbox(itemIndex, items) {
|
||||
|
||||
previousElement = ( document.activeElement || document.body );
|
||||
|
||||
vm.lightbox = {
|
||||
show: true,
|
||||
items: items,
|
||||
activeIndex: itemIndex,
|
||||
focus: true
|
||||
};
|
||||
}
|
||||
|
||||
function closeLightbox() {
|
||||
vm.lightbox.show = false;
|
||||
vm.lightbox = null;
|
||||
|
||||
if(previousElement){
|
||||
setTimeout(function(){
|
||||
previousElement.focus();
|
||||
previousElement = null;
|
||||
}, 100)
|
||||
}
|
||||
document.activeElement.blur();
|
||||
}
|
||||
|
||||
|
||||
var searchDebounced = _.debounce(function (e) {
|
||||
//a canceler exists, so perform the cancelation operation and reset
|
||||
if (canceler) {
|
||||
canceler.resolve();
|
||||
}
|
||||
|
||||
canceler = $q.defer();
|
||||
|
||||
$scope.$apply(function () {
|
||||
currSort = vm.searchQuery ? "Default" : "Latest";
|
||||
|
||||
ourPackageRepositoryResource.search(vm.pagination.pageNumber - 1,
|
||||
vm.pagination.pageSize,
|
||||
currSort,
|
||||
"",
|
||||
vm.searchQuery,
|
||||
canceler.promise)
|
||||
.then(function (pack) {
|
||||
vm.packages = pack.packages;
|
||||
vm.pagination.totalPages = Math.ceil(pack.total / vm.pagination.pageSize);
|
||||
vm.pagination.pageNumber = 1;
|
||||
vm.loading = false;
|
||||
//set back to null so it can be re-created
|
||||
canceler = null;
|
||||
})
|
||||
.catch(function (err) {
|
||||
canceler = null;
|
||||
|
||||
if (err) {
|
||||
// If an abort happened, ignore it since it happened because of a new search
|
||||
if (err.xhrStatus === 'abort') {
|
||||
return;
|
||||
}
|
||||
|
||||
// Otherwise, show the error
|
||||
if (err.errorMsg) {
|
||||
notificationsService.error(err.errorMsg);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
console.error(err);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
}, 200);
|
||||
|
||||
function search(searchQuery) {
|
||||
vm.loading = true;
|
||||
searchDebounced();
|
||||
}
|
||||
|
||||
vm.reloadPage = function () {
|
||||
//reload on next digest (after cookie)
|
||||
$timeout(function () {
|
||||
window.location.reload(true);
|
||||
});
|
||||
}
|
||||
|
||||
init();
|
||||
|
||||
}
|
||||
|
||||
angular.module("umbraco").controller("Umbraco.Editors.Packages.RepoController", PackagesRepoController);
|
||||
|
||||
})();
|
||||
|
||||
@@ -1,318 +1,318 @@
|
||||
<div ng-controller="Umbraco.Editors.Packages.RepoController as vm" class="clearfix">
|
||||
|
||||
<umb-load-indicator ng-show="vm.loading"></umb-load-indicator>
|
||||
<umb-load-indicator ng-show="vm.loading"></umb-load-indicator>
|
||||
|
||||
<!-- LIST -->
|
||||
<div class="umb-packages-view-wrapper" ng-if="vm.packageViewState === 'packageList'">
|
||||
|
||||
<div class="umb-packages-section">
|
||||
<div class="umb-packages-search">
|
||||
<label for="package-query" class="sr-only">
|
||||
<localize key="packager_packageSearch">Search for packages</localize>
|
||||
</label>
|
||||
<input type="text"
|
||||
class="-full-width-input"
|
||||
name="query"
|
||||
id="package-query"
|
||||
localize="placeholder"
|
||||
placeholder="@packager_packageSearch"
|
||||
ng-model="vm.searchQuery"
|
||||
ng-on-input="vm.search()"
|
||||
no-dirty-check />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="umb-packages-section" ng-if="vm.searchQuery == ''">
|
||||
<div class="umb-packages-categories">
|
||||
<button type="button"
|
||||
class="umb-packages-category"
|
||||
ng-click="vm.selectCategory(category, vm.categories)"
|
||||
ng-repeat="category in vm.categories"
|
||||
ng-class="{'-active': category.active, '-first': $first, '-last': $last}">
|
||||
{{category.name}}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div ng-show="vm.loading === false">
|
||||
|
||||
<div ng-repeat="highlightedPackageCollection in vm.highlightedPackageCollections">
|
||||
<div class="umb-packages-section" ng-if="vm.searchQuery == '' && highlightedPackageCollection.packages.length > 0">
|
||||
<h4><strong>{{highlightedPackageCollection.title}}</strong></h4>
|
||||
<div class="umb-packages">
|
||||
|
||||
<div class="umb-package" ng-repeat="package in highlightedPackageCollection.packages">
|
||||
<button type="button" class="umb-package-link" ng-click="vm.showPackageDetails(package)">
|
||||
|
||||
<div class="flex flex-column">
|
||||
<div class="umb-package-icon">
|
||||
<img ng-src="{{package.icon}}" alt="" />
|
||||
</div>
|
||||
|
||||
<div class="umb-package-info">
|
||||
<div class="umb-package-name">{{package.name}}</div>
|
||||
<div class="umb-package-description">{{package.excerpt | limitTo: 40}}<span ng-if="package.excerpt > (package.excerpt | limitTo: 40)">...</span></div>
|
||||
|
||||
<div class="umb-package-numbers">
|
||||
<small class="umb-package-downloads">
|
||||
<umb-icon icon="icon-download-alt"></umb-icon>
|
||||
<strong>{{package.downloads}}</strong>
|
||||
</small>
|
||||
<small class="umb-package-likes">
|
||||
<umb-icon icon="icon-hearts" class="icon-hearts"></umb-icon>
|
||||
<strong>{{package.likes}}</strong>
|
||||
</small>
|
||||
</div>
|
||||
<div class="umb-package-cloud">
|
||||
<div ng-if="package.certifiedToWorkOnUmbracoCloud">
|
||||
<umb-icon icon="icon-cloud" class="icon-cloud"></umb-icon>
|
||||
<span><localize key="packager_verifiedToWorkOnUmbracoCloud">Verified to work on Umbraco Cloud</localize></span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</button>
|
||||
</div> <!-- end package -->
|
||||
|
||||
</div> <!-- end packages -->
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="umb-packages-section" ng-if="vm.packages.length > 0">
|
||||
|
||||
<h4 ng-if="vm.searchQuery === ''"><strong><localize key="packager_packagesNew">New Releases</localize></strong></h4>
|
||||
<h4 ng-if="vm.searchQuery !== ''"><strong><localize key="packager_packageSearchResults">Results for</localize> '{{ vm.searchQuery }}'</strong></h4>
|
||||
|
||||
<div class="umb-packages">
|
||||
|
||||
<div class="umb-package" ng-repeat="package in vm.packages">
|
||||
<button type="button" class="umb-package-link" ng-click="vm.showPackageDetails(package)">
|
||||
|
||||
<div class="flex flex-column">
|
||||
<div class="umb-package-icon">
|
||||
<img ng-src="{{package.icon}}" alt="" />
|
||||
</div>
|
||||
|
||||
<div class="umb-package-info">
|
||||
<div class="umb-package-name">{{ package.name }}</div>
|
||||
<div class="umb-package-description">{{ package.excerpt | limitTo: 40 }}<span ng-if="package.excerpt > (package.excerpt | limitTo: 40)">...</span></div>
|
||||
|
||||
<div class="umb-package-numbers">
|
||||
<small class="umb-package-downloads">
|
||||
<umb-icon icon="icon-download-alt"></umb-icon>
|
||||
<strong>{{package.downloads}}</strong>
|
||||
</small>
|
||||
<small class="umb-package-likes">
|
||||
<umb-icon icon="icon-hearts" class="icon-hearts"></umb-icon>
|
||||
<strong>{{package.likes}}</strong>
|
||||
</small>
|
||||
</div>
|
||||
<div class="umb-package-cloud">
|
||||
<div ng-if="package.certifiedToWorkOnUmbracoCloud">
|
||||
<umb-icon icon="icon-cloud" class="icon-cloud"></umb-icon>
|
||||
<span><localize key="packager_verifiedToWorkOnUmbracoCloud">Verified to work on Umbraco Cloud</localize></span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</button>
|
||||
</div> <!-- end package -->
|
||||
|
||||
</div> <!-- end packages -->
|
||||
</div>
|
||||
|
||||
<div class="umb-packages__pagination" ng-if="vm.pagination.totalPages > 1 && vm.loading === false">
|
||||
|
||||
<umb-pagination page-number="vm.pagination.pageNumber"
|
||||
total-pages="vm.pagination.totalPages"
|
||||
on-next="vm.nextPage"
|
||||
on-prev="vm.prevPage"
|
||||
on-go-to-page="vm.goToPage">
|
||||
</umb-pagination>
|
||||
|
||||
</div>
|
||||
|
||||
<!-- Empty state -->
|
||||
<umb-empty-state ng-if="vm.packages.length === 0 && vm.loading === false && vm.searchQuery !== ''"
|
||||
position="center">
|
||||
<h4><strong><localize key="packager_packageNoResults">We couldn't find anything for</localize> '{{ vm.searchQuery }}'</strong></h4>
|
||||
<p class="faded"><localize key="packager_packageNoResultsDescription">Please try searching for another package or browse through the categories</localize>.</p>
|
||||
</umb-empty-state>
|
||||
|
||||
<umb-empty-state ng-if="vm.popular.length === 0 && vm.loading === false && vm.searchQuery === ''"
|
||||
position="center">
|
||||
<h4><strong><localize key="general_searchNoResult">Sorry, we can not find what you are looking for.</localize></strong></h4>
|
||||
<p class="faded"><localize key="packager_packageNoResultsDescription">Please try searching for another package or browse through the categories</localize>.</p>
|
||||
</umb-empty-state>
|
||||
|
||||
</div>
|
||||
<!-- LIST -->
|
||||
<div class="umb-packages-view-wrapper" ng-if="vm.packageViewState === 'packageList'">
|
||||
|
||||
<div class="umb-packages-section">
|
||||
<div class="umb-packages-search">
|
||||
<label for="package-query" class="sr-only">
|
||||
<localize key="packager_packageSearch">Search for packages</localize>
|
||||
</label>
|
||||
<input type="text"
|
||||
class="-full-width-input"
|
||||
name="query"
|
||||
id="package-query"
|
||||
localize="placeholder"
|
||||
placeholder="@packager_packageSearch"
|
||||
ng-model="vm.searchQuery"
|
||||
ng-on-input="vm.search()"
|
||||
no-dirty-check />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="umb-packages-section" ng-if="vm.searchQuery == ''">
|
||||
<div class="umb-packages-categories">
|
||||
<button type="button"
|
||||
class="umb-packages-category"
|
||||
ng-click="vm.selectCategory(category, vm.categories)"
|
||||
ng-repeat="category in vm.categories"
|
||||
ng-class="{'-active': category.active, '-first': $first, '-last': $last}">
|
||||
{{category.name}}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- DETAILS -->
|
||||
<div ng-if="vm.packageViewState === 'packageDetails' && vm.loading === false">
|
||||
<div ng-show="vm.loading === false">
|
||||
|
||||
<umb-editor-sub-header>
|
||||
<umb-editor-sub-header-content-left>
|
||||
<button type="button" class="umb-package-details__back-action" ng-click="vm.setPackageViewState('packageList');" prevent-default><span aria-hidden="true">←</span> <localize key="general_back">Back</localize></button>
|
||||
</umb-editor-sub-header-content-left>
|
||||
</umb-editor-sub-header>
|
||||
<div ng-repeat="highlightedPackageCollection in vm.highlightedPackageCollections">
|
||||
<div class="umb-packages-section" ng-if="vm.searchQuery == '' && highlightedPackageCollection.packages.length > 0">
|
||||
<h4><strong>{{highlightedPackageCollection.title}}</strong></h4>
|
||||
<div class="umb-packages">
|
||||
|
||||
<div class="umb-packages-view-wrapper">
|
||||
<div class="umb-package" ng-repeat="package in highlightedPackageCollection.packages">
|
||||
<button type="button" class="umb-package-link" ng-click="vm.showPackageDetails(package)">
|
||||
|
||||
<div class="umb-package-details">
|
||||
<div class="flex flex-column">
|
||||
<div class="umb-package-icon">
|
||||
<img ng-src="{{package.icon}}" alt="" />
|
||||
</div>
|
||||
|
||||
<div class="umb-package-details__main-content">
|
||||
<div class="umb-package-info">
|
||||
<div class="umb-package-name">{{package.name}}</div>
|
||||
<div class="umb-package-description">{{package.excerpt | limitTo: 40}}<span ng-if="package.excerpt > (package.excerpt | limitTo: 40)">...</span></div>
|
||||
|
||||
<umb-box>
|
||||
<umb-box-content>
|
||||
<div class="umb-packages-view-title">{{ vm.package.name }}</div>
|
||||
<div class="umb-package-details__description" ng-bind-html="vm.package.description"></div>
|
||||
<div class="umb-gallery">
|
||||
<div class="umb-gallery__thumbnails">
|
||||
<a ng-href="{{ image.source }}" type="button" class="umb-gallery__thumbnail" ng-repeat="image in vm.package.images" ng-click="vm.openLightbox($index, vm.package.images)" prevent-default>
|
||||
<img ng-src="{{ image.thumbnail }}" alt="" />
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</umb-box-content>
|
||||
</umb-box>
|
||||
|
||||
<umb-lightbox
|
||||
ng-if="vm.lightbox.show"
|
||||
items="vm.lightbox.items"
|
||||
active-item-index="vm.lightbox.activeIndex"
|
||||
on-close="vm.closeLightbox">
|
||||
</umb-lightbox>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="umb-package-details__sidebar">
|
||||
|
||||
<umb-box>
|
||||
<umb-box-content>
|
||||
<div class="umb-package-details__section-title"><localize key="packager_installInstructions">Install Instructions</localize></div>
|
||||
<div class="umb-package-details__install-instructions">
|
||||
dotnet add package <span>{{vm.package.nuGetPackageId}}</span>
|
||||
<div class="umb-package-numbers">
|
||||
<small class="umb-package-downloads">
|
||||
<umb-icon icon="icon-download-alt"></umb-icon>
|
||||
<strong>{{package.downloads}}</strong>
|
||||
</small>
|
||||
<small class="umb-package-likes">
|
||||
<umb-icon icon="icon-hearts" class="icon-hearts"></umb-icon>
|
||||
<strong>{{package.likes}}</strong>
|
||||
</small>
|
||||
</div>
|
||||
<div class="umb-package-cloud">
|
||||
<div ng-if="package.certifiedToWorkOnUmbracoCloud">
|
||||
<umb-icon icon="icon-cloud" class="icon-cloud"></umb-icon>
|
||||
<span><localize key="packager_verifiedToWorkOnUmbracoCloud">Verified to work on Umbraco Cloud</localize></span>
|
||||
</div>
|
||||
</umb-box-content>
|
||||
</umb-box>
|
||||
|
||||
<umb-box>
|
||||
<umb-box-content>
|
||||
<div class="umb-package-details__owner-profile">
|
||||
|
||||
<div class="umb-package-details__owner-profile-avatar">
|
||||
<umb-avatar
|
||||
size="m"
|
||||
img-src="{{ 'https://our.umbraco.com' + vm.package.ownerInfo.ownerAvatar }}">
|
||||
</umb-avatar>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<div class="umb-package-details__owner-profile-name">{{ vm.package.ownerInfo.owner }}</div>
|
||||
<div class="umb-package-details__owner-profile-karma">
|
||||
{{ vm.package.ownerInfo.owner }} <localize key="packager_packageHas">has</localize> <strong>{{ vm.package.ownerInfo.karma }}</strong> <localize key="packager_packageKarmaPoints">karma points</localize>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</umb-box-content>
|
||||
</umb-box>
|
||||
|
||||
<umb-box>
|
||||
<umb-box-content>
|
||||
<div class="umb-package-details__section-title"><localize key="packager_packageInfo">Information</localize></div>
|
||||
<div>
|
||||
|
||||
<div class="umb-package-details__information-item" ng-if="vm.package.ownerInfo.owner">
|
||||
<div class="umb-package-details__information-item-label"><localize key="packager_packageOwner">Owner</localize>:</div>
|
||||
<div class="umb-package-details__information-item-content">{{vm.package.ownerInfo.owner}}</div>
|
||||
</div>
|
||||
|
||||
<div class="umb-package-details__information-item" ng-if="vm.package.ownerInfo.contributors">
|
||||
<div class="umb-package-details__information-item-label"><localize key="packager_packageContrib">Contributors</localize>:</div>
|
||||
<div class="umb-package-details__information-item-content">
|
||||
<span ng-repeat="contributor in vm.package.ownerInfo.contributors">{{ contributor }}<span ng-if="!$last">, </span></span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="umb-package-details__information-item" ng-if="vm.package.created">
|
||||
<div class="umb-package-details__information-item-label"><localize key="packager_packageCreated">Created</localize>:</div>
|
||||
<div class="umb-package-details__information-item-content">{{vm.package.created | date:'yyyy-MM-dd HH:mm:ss'}}</div>
|
||||
</div>
|
||||
|
||||
<div class="umb-package-details__information-item" ng-if="vm.package.latestVersion">
|
||||
<div class="umb-package-details__information-item-label"><localize key="packager_packageCurrentVersion">Current version</localize>:</div>
|
||||
<div class="umb-package-details__information-item-content">{{vm.package.latestVersion}}</div>
|
||||
</div>
|
||||
|
||||
<div class="umb-package-details__information-item" ng-if="vm.package.information.netVersion">
|
||||
<div class="umb-package-details__information-item-label"><localize key="packager_packageNetVersion">.NET Version</localize>:</div>
|
||||
<div class="umb-package-details__information-item-content">{{vm.package.information.netVersion}}</div>
|
||||
</div>
|
||||
|
||||
<div class="umb-package-details__information-item" ng-if="vm.package.licenseName">
|
||||
<div class="umb-package-details__information-item-label"><localize key="packager_packageLicense">License</localize>:</div>
|
||||
<div class="umb-package-details__information-item-content">{{vm.package.licenseName}}</div>
|
||||
</div>
|
||||
|
||||
<div class="umb-package-details__information-item" ng-if="vm.package.downloads">
|
||||
<div class="umb-package-details__information-item-label"><localize key="packager_packageDownloads">Downloads</localize>:</div>
|
||||
<div class="umb-package-details__information-item-content">{{vm.package.downloads}}</div>
|
||||
</div>
|
||||
|
||||
<div class="umb-package-details__information-item" ng-if="vm.package.ownerInfo.karma">
|
||||
<div class="umb-package-details__information-item-label"><localize key="packager_packageLikes">Likes</localize>:</div>
|
||||
<div class="umb-package-details__information-item-content">{{vm.package.likes}}</div>
|
||||
</div>
|
||||
|
||||
<div class="umb-package-details__information-item" ng-if="vm.package.certifiedToWorkOnUmbracoCloud">
|
||||
<div class="umb-package-details__information-item-label"><localize key="packager_verifiedToWorkOnUmbracoCloud">Verified to work on Umbraco CLoud</localize></div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</umb-box-content>
|
||||
</umb-box>
|
||||
|
||||
<umb-box>
|
||||
<umb-box-content>
|
||||
<div class="umb-package-details__section-title"><localize key="packager_packageCompatibility">Compatibility</localize></div>
|
||||
<div class="umb-package-details__section-description"><localize key="packager_packageCompatibilityDescription">This package is compatible with the following versions of Umbraco, as reported by community members. Full compatability cannot be guaranteed for versions reported below 100%</localize></div>
|
||||
<div class="umb-package-details__compatability" ng-repeat="compatibility in vm.package.compatibility | filter:percentage > 0">
|
||||
<div class="umb-package-details__compatability-label">
|
||||
<span class="umb-package-details__information-item-label">{{compatibility.version}}</span>
|
||||
<span class="umb-package-details__information-item-label-2">({{compatibility.percentage}}%)</span>
|
||||
</div>
|
||||
<umb-progress-bar
|
||||
percentage="{{compatibility.percentage}}">
|
||||
</umb-progress-bar>
|
||||
</div>
|
||||
</umb-box-content>
|
||||
</umb-box>
|
||||
|
||||
<umb-box ng-if="vm.package.externalSources">
|
||||
<umb-box-content>
|
||||
<div class="umb-package-details__section-title"><localize key="packager_packageExternalSources">External sources</localize></div>
|
||||
<div>
|
||||
<div class="umb-package-details__information-item" ng-repeat="externalSource in vm.package.externalSources">
|
||||
<a class="umb-package-details__link" href="{{externalSource.url}}" target="_blank" rel="noopener noreferrer">
|
||||
<umb-icon icon="icon-out"></umb-icon>
|
||||
{{externalSource.name}}
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</umb-box-content>
|
||||
</umb-box>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</button>
|
||||
</div> <!-- end package -->
|
||||
|
||||
</div> <!-- end packages -->
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="umb-packages-section" ng-if="vm.packages.length > 0">
|
||||
|
||||
<h4 ng-if="vm.searchQuery === ''"><strong><localize key="packager_packagesNew">New Releases</localize></strong></h4>
|
||||
<h4 ng-if="vm.searchQuery !== ''"><strong><localize key="packager_packageSearchResults">Results for</localize> '{{ vm.searchQuery }}'</strong></h4>
|
||||
|
||||
<div class="umb-packages">
|
||||
|
||||
<div class="umb-package" ng-repeat="package in vm.packages">
|
||||
<button type="button" class="umb-package-link" ng-click="vm.showPackageDetails(package)">
|
||||
|
||||
<div class="flex flex-column">
|
||||
<div class="umb-package-icon">
|
||||
<img ng-src="{{package.icon}}" alt="" />
|
||||
</div>
|
||||
|
||||
<div class="umb-package-info">
|
||||
<div class="umb-package-name">{{ package.name }}</div>
|
||||
<div class="umb-package-description">{{ package.excerpt | limitTo: 40 }}<span ng-if="package.excerpt > (package.excerpt | limitTo: 40)">...</span></div>
|
||||
|
||||
<div class="umb-package-numbers">
|
||||
<small class="umb-package-downloads">
|
||||
<umb-icon icon="icon-download-alt"></umb-icon>
|
||||
<strong>{{package.downloads}}</strong>
|
||||
</small>
|
||||
<small class="umb-package-likes">
|
||||
<umb-icon icon="icon-hearts" class="icon-hearts"></umb-icon>
|
||||
<strong>{{package.likes}}</strong>
|
||||
</small>
|
||||
</div>
|
||||
<div class="umb-package-cloud">
|
||||
<div ng-if="package.certifiedToWorkOnUmbracoCloud">
|
||||
<umb-icon icon="icon-cloud" class="icon-cloud"></umb-icon>
|
||||
<span><localize key="packager_verifiedToWorkOnUmbracoCloud">Verified to work on Umbraco Cloud</localize></span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</button>
|
||||
</div> <!-- end package -->
|
||||
|
||||
</div> <!-- end packages -->
|
||||
</div>
|
||||
|
||||
<div class="umb-packages__pagination" ng-if="vm.pagination.totalPages > 1 && vm.loading === false">
|
||||
|
||||
<umb-pagination page-number="vm.pagination.pageNumber"
|
||||
total-pages="vm.pagination.totalPages"
|
||||
on-next="vm.nextPage"
|
||||
on-prev="vm.prevPage"
|
||||
on-go-to-page="vm.goToPage">
|
||||
</umb-pagination>
|
||||
|
||||
</div>
|
||||
|
||||
<!-- Empty state -->
|
||||
<umb-empty-state ng-if="vm.packages.length === 0 && vm.loading === false && vm.searchQuery !== ''"
|
||||
position="center">
|
||||
<h4><strong><localize key="packager_packageNoResults">We couldn't find anything for</localize> '{{ vm.searchQuery }}'</strong></h4>
|
||||
<p class="faded"><localize key="packager_packageNoResultsDescription">Please try searching for another package or browse through the categories</localize>.</p>
|
||||
</umb-empty-state>
|
||||
|
||||
<umb-empty-state ng-if="vm.popular.length === 0 && vm.loading === false && vm.searchQuery === ''"
|
||||
position="center">
|
||||
<h4><strong><localize key="general_searchNoResult">Sorry, we can not find what you are looking for.</localize></strong></h4>
|
||||
<p class="faded"><localize key="packager_packageNoResultsDescription">Please try searching for another package or browse through the categories</localize>.</p>
|
||||
</umb-empty-state>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
<!-- DETAILS -->
|
||||
<div ng-if="vm.packageViewState === 'packageDetails' && vm.loading === false">
|
||||
|
||||
<umb-editor-sub-header>
|
||||
<umb-editor-sub-header-content-left>
|
||||
<button type="button" class="umb-package-details__back-action" ng-click="vm.setPackageViewState('packageList');" prevent-default><span aria-hidden="true">←</span> <localize key="general_back">Back</localize></button>
|
||||
</umb-editor-sub-header-content-left>
|
||||
</umb-editor-sub-header>
|
||||
|
||||
<div class="umb-packages-view-wrapper">
|
||||
|
||||
<div class="umb-package-details">
|
||||
|
||||
<div class="umb-package-details__main-content">
|
||||
|
||||
<umb-box>
|
||||
<umb-box-content>
|
||||
<div class="umb-packages-view-title">{{ vm.package.name }}</div>
|
||||
<div class="umb-package-details__description" ng-bind-html="vm.package.description"></div>
|
||||
<div class="umb-gallery">
|
||||
<div class="umb-gallery__thumbnails">
|
||||
<a ng-href="{{ image.source }}" type="button" class="umb-gallery__thumbnail" ng-repeat="image in vm.package.images" ng-click="vm.openLightbox($index, vm.package.images)" prevent-default>
|
||||
<img ng-src="{{ image.thumbnail }}" alt="" />
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</umb-box-content>
|
||||
</umb-box>
|
||||
|
||||
<umb-lightbox
|
||||
ng-if="vm.lightbox.show"
|
||||
items="vm.lightbox.items"
|
||||
active-item-index="vm.lightbox.activeIndex"
|
||||
on-close="vm.closeLightbox">
|
||||
</umb-lightbox>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="umb-package-details__sidebar">
|
||||
|
||||
<umb-box>
|
||||
<umb-box-content>
|
||||
<div class="umb-package-details__section-title"><localize key="packager_installInstructions">Install Instructions</localize></div>
|
||||
<div class="umb-package-details__install-instructions">
|
||||
dotnet add package <span>{{vm.package.nuGetPackageId}}</span>
|
||||
</div>
|
||||
</umb-box-content>
|
||||
</umb-box>
|
||||
|
||||
<umb-box>
|
||||
<umb-box-content>
|
||||
<div class="umb-package-details__owner-profile">
|
||||
|
||||
<div class="umb-package-details__owner-profile-avatar">
|
||||
<umb-avatar
|
||||
size="m"
|
||||
img-src="{{ 'https://our.umbraco.com' + vm.package.ownerInfo.ownerAvatar }}">
|
||||
</umb-avatar>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<div class="umb-package-details__owner-profile-name">{{ vm.package.ownerInfo.owner }}</div>
|
||||
<div class="umb-package-details__owner-profile-karma">
|
||||
{{ vm.package.ownerInfo.owner }} <localize key="packager_packageHas">has</localize> <strong>{{ vm.package.ownerInfo.karma }}</strong> <localize key="packager_packageKarmaPoints">karma points</localize>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</umb-box-content>
|
||||
</umb-box>
|
||||
|
||||
<umb-box>
|
||||
<umb-box-content>
|
||||
<div class="umb-package-details__section-title"><localize key="packager_packageInfo">Information</localize></div>
|
||||
<div>
|
||||
|
||||
<div class="umb-package-details__information-item" ng-if="vm.package.ownerInfo.owner">
|
||||
<div class="umb-package-details__information-item-label"><localize key="packager_packageOwner">Owner</localize>:</div>
|
||||
<div class="umb-package-details__information-item-content">{{vm.package.ownerInfo.owner}}</div>
|
||||
</div>
|
||||
|
||||
<div class="umb-package-details__information-item" ng-if="vm.package.ownerInfo.contributors">
|
||||
<div class="umb-package-details__information-item-label"><localize key="packager_packageContrib">Contributors</localize>:</div>
|
||||
<div class="umb-package-details__information-item-content">
|
||||
<span ng-repeat="contributor in vm.package.ownerInfo.contributors">{{ contributor }}<span ng-if="!$last">, </span></span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="umb-package-details__information-item" ng-if="vm.package.created">
|
||||
<div class="umb-package-details__information-item-label"><localize key="packager_packageCreated">Created</localize>:</div>
|
||||
<div class="umb-package-details__information-item-content">{{vm.package.created | date:'yyyy-MM-dd HH:mm:ss'}}</div>
|
||||
</div>
|
||||
|
||||
<div class="umb-package-details__information-item" ng-if="vm.package.latestVersion">
|
||||
<div class="umb-package-details__information-item-label"><localize key="packager_packageCurrentVersion">Current version</localize>:</div>
|
||||
<div class="umb-package-details__information-item-content">{{vm.package.latestVersion}}</div>
|
||||
</div>
|
||||
|
||||
<div class="umb-package-details__information-item" ng-if="vm.package.information.netVersion">
|
||||
<div class="umb-package-details__information-item-label"><localize key="packager_packageNetVersion">.NET Version</localize>:</div>
|
||||
<div class="umb-package-details__information-item-content">{{vm.package.information.netVersion}}</div>
|
||||
</div>
|
||||
|
||||
<div class="umb-package-details__information-item" ng-if="vm.package.licenseName">
|
||||
<div class="umb-package-details__information-item-label"><localize key="packager_packageLicense">License</localize>:</div>
|
||||
<div class="umb-package-details__information-item-content">{{vm.package.licenseName}}</div>
|
||||
</div>
|
||||
|
||||
<div class="umb-package-details__information-item" ng-if="vm.package.downloads">
|
||||
<div class="umb-package-details__information-item-label"><localize key="packager_packageDownloads">Downloads</localize>:</div>
|
||||
<div class="umb-package-details__information-item-content">{{vm.package.downloads}}</div>
|
||||
</div>
|
||||
|
||||
<div class="umb-package-details__information-item" ng-if="vm.package.ownerInfo.karma">
|
||||
<div class="umb-package-details__information-item-label"><localize key="packager_packageLikes">Likes</localize>:</div>
|
||||
<div class="umb-package-details__information-item-content">{{vm.package.likes}}</div>
|
||||
</div>
|
||||
|
||||
<div class="umb-package-details__information-item" ng-if="vm.package.certifiedToWorkOnUmbracoCloud">
|
||||
<div class="umb-package-details__information-item-label"><localize key="packager_verifiedToWorkOnUmbracoCloud">Verified to work on Umbraco CLoud</localize></div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</umb-box-content>
|
||||
</umb-box>
|
||||
|
||||
<umb-box>
|
||||
<umb-box-content>
|
||||
<div class="umb-package-details__section-title"><localize key="packager_packageCompatibility">Compatibility</localize></div>
|
||||
<div class="umb-package-details__section-description"><localize key="packager_packageCompatibilityDescription">This package is compatible with the following versions of Umbraco, as reported by community members. Full compatability cannot be guaranteed for versions reported below 100%</localize></div>
|
||||
<div class="umb-package-details__compatability" ng-repeat="compatibility in vm.package.compatibility | filter:percentage > 0">
|
||||
<div class="umb-package-details__compatability-label">
|
||||
<span class="umb-package-details__information-item-label">{{compatibility.version}}</span>
|
||||
<span class="umb-package-details__information-item-label-2">({{compatibility.percentage}}%)</span>
|
||||
</div>
|
||||
<umb-progress-bar
|
||||
percentage="{{compatibility.percentage}}">
|
||||
</umb-progress-bar>
|
||||
</div>
|
||||
</umb-box-content>
|
||||
</umb-box>
|
||||
|
||||
<umb-box ng-if="vm.package.externalSources">
|
||||
<umb-box-content>
|
||||
<div class="umb-package-details__section-title"><localize key="packager_packageExternalSources">External sources</localize></div>
|
||||
<div>
|
||||
<div class="umb-package-details__information-item" ng-repeat="externalSource in vm.package.externalSources">
|
||||
<a class="umb-package-details__link" href="{{externalSource.url}}" target="_blank" rel="noopener noreferrer">
|
||||
<umb-icon icon="icon-out"></umb-icon>
|
||||
{{externalSource.name}}
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</umb-box-content>
|
||||
</umb-box>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
@@ -54,14 +54,7 @@ function RelationTypeEditController($scope, $routeParams, relationTypeResource,
|
||||
});
|
||||
|
||||
// load references when the 'relations' tab is first activated/switched to
|
||||
var appTabChange = eventsService.on("app.tabChange", function (event, args) {
|
||||
if (args.alias === "relations") {
|
||||
loadRelations();
|
||||
}
|
||||
});
|
||||
$scope.$on('$destroy', function () {
|
||||
appTabChange();
|
||||
});
|
||||
loadRelations();
|
||||
|
||||
// Inital page/overview API call of relation type
|
||||
relationTypeResource.getById($routeParams.id)
|
||||
|
||||
Reference in New Issue
Block a user