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>
This commit is contained in:
@@ -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>
|
||||
|
||||
@@ -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 +0,0 @@
|
||||
(function () {
|
||||
"use strict";
|
||||
|
||||
function PackagesRepoController($scope, $timeout, ourPackageRepositoryResource, $q, localizationService, notificationsService) {
|
||||
|
||||
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 = {};
|
||||
|
||||
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;
|
||||
|
||||
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 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 +0,0 @@
|
||||
<div ng-controller="Umbraco.Editors.Packages.RepoController as vm" class="clearfix">
|
||||
|
||||
<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>
|
||||
|
||||
</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">
|
||||
<button type="button" class="umb-gallery__thumbnail" ng-repeat="image in vm.package.images" ng-click="vm.openLightbox($index, vm.package.images)">
|
||||
<img ng-src="{{ image.thumbnail }}" />
|
||||
</button>
|
||||
</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>
|
||||
Reference in New Issue
Block a user