init
This commit is contained in:
498
user/plugins/admin/themes/grav/app/utils/packages.js
Normal file
498
user/plugins/admin/themes/grav/app/utils/packages.js
Normal file
@@ -0,0 +1,498 @@
|
||||
import $ from 'jquery';
|
||||
import { config, translations } from 'grav-config';
|
||||
import request from '../utils/request';
|
||||
import { Instance as gpm } from '../utils/gpm';
|
||||
|
||||
class Sorter {
|
||||
getElements(elements, container) {
|
||||
this.elements = elements || document.querySelectorAll('[data-gpm-plugin], [data-gpm-theme]');
|
||||
this.container = container || document.querySelector('.gpm-plugins > table > tbody, .gpm-themes > .themes.card-row');
|
||||
|
||||
return this.elements;
|
||||
}
|
||||
|
||||
static sort(A, B, direction = 'asc') {
|
||||
if (A > B) { return (direction === 'asc') ? 1 : -1; }
|
||||
if (A < B) { return (direction === 'asc') ? -1 : 1; }
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
byCommon(direction = 'asc', data = '') {
|
||||
const elements = this.getElements();
|
||||
this.removeGumroad();
|
||||
|
||||
Array.from(elements).sort((a, b) => {
|
||||
let A = a.dataset[data].toString().toLowerCase();
|
||||
let B = b.dataset[data].toString().toLowerCase();
|
||||
|
||||
return Sorter.sort(A, B, direction);
|
||||
}).forEach((element) => {
|
||||
this.container.appendChild(element);
|
||||
});
|
||||
|
||||
this.addGumroad();
|
||||
return this.container;
|
||||
}
|
||||
|
||||
byName(direction = 'asc', data = 'gpmName') {
|
||||
return this.byCommon(direction, data);
|
||||
}
|
||||
|
||||
byAuthor(direction = 'asc', data = 'gpmAuthor') {
|
||||
return this.byCommon(direction, data);
|
||||
}
|
||||
|
||||
byOfficial(direction = 'asc', data = 'gpmOfficial') {
|
||||
return this.byCommon(direction, data);
|
||||
}
|
||||
|
||||
byPremium(direction = 'asc', data = 'gpmPremium') {
|
||||
return this.byCommon(direction, data);
|
||||
}
|
||||
|
||||
byReleaseDate(direction = 'asc', data = 'gpmReleaseDate') {
|
||||
const elements = this.getElements();
|
||||
|
||||
this.removeGumroad();
|
||||
Array.from(elements).sort((a, b) => {
|
||||
let A = new Date(a.dataset[data]).getTime();
|
||||
let B = new Date(b.dataset[data]).getTime();
|
||||
|
||||
return Sorter.sort(A, B, direction === 'asc' ? 'desc' : 'asc');
|
||||
}).forEach((element) => {
|
||||
this.container.appendChild(element);
|
||||
});
|
||||
|
||||
this.addGumroad();
|
||||
return this.container;
|
||||
}
|
||||
|
||||
byUpdatable(direction = 'asc', data = 'gpmUpdatable') {
|
||||
return this.byCommon(direction, data);
|
||||
}
|
||||
|
||||
byEnabled(direction = 'asc', data = 'gpmEnabled') {
|
||||
return this.byCommon(direction, data);
|
||||
}
|
||||
|
||||
byTesting(direction = 'asc', data = 'gpmTesting') {
|
||||
return this.byCommon(direction, data);
|
||||
}
|
||||
|
||||
addGumroad() {
|
||||
if (window.GumroadOverlay) {
|
||||
window.GumroadOverlay.startNodeAdditionObserver();
|
||||
}
|
||||
}
|
||||
|
||||
removeGumroad() {
|
||||
if (window.GumroadOverlay) {
|
||||
window.GumroadOverlay.nodeAdditionObserver.disconnect();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class Packages {
|
||||
constructor() {
|
||||
this.Sort = new Sorter();
|
||||
}
|
||||
|
||||
static getBackToList(type) {
|
||||
global.location.href = `${config.base_url_relative}/${type}s`;
|
||||
}
|
||||
|
||||
static addDependencyToList(type, dependency, slug = '') {
|
||||
if (['admin', 'form', 'login', 'email', 'grav'].indexOf(dependency) !== -1) { return; }
|
||||
let container = $('.package-dependencies-container');
|
||||
let text = `${dependency} <a href="#" class="button" data-dependency-slug="${dependency}" data-${type}-action="remove-dependency-package">Remove</a>`;
|
||||
|
||||
if (slug) {
|
||||
text += ` (was needed by ${slug})`;
|
||||
}
|
||||
|
||||
container.append(`<li>${text}</li>`);
|
||||
}
|
||||
|
||||
addDependenciesToList(dependencies, slug = '') {
|
||||
dependencies.forEach((dependency) => {
|
||||
Packages.addDependencyToList('plugin', dependency.name || dependency, slug);
|
||||
});
|
||||
}
|
||||
|
||||
static getTaskUrl(type, task) {
|
||||
let url = `${config.base_url_relative}`;
|
||||
url += `/${type}s.json`;
|
||||
url += `/task${config.param_sep}${task}`;
|
||||
return url;
|
||||
}
|
||||
|
||||
static getRemovePackageUrl(type) {
|
||||
return `${Packages.getTaskUrl(type, 'removePackage')}`;
|
||||
}
|
||||
|
||||
static getReinstallPackageUrl(type) {
|
||||
return `${Packages.getTaskUrl(type, 'reinstallPackage')}`;
|
||||
}
|
||||
|
||||
static getGetPackagesDependenciesUrl(type) {
|
||||
return `${Packages.getTaskUrl(type, 'getPackagesDependencies')}`;
|
||||
}
|
||||
|
||||
static getInstallDependenciesOfPackagesUrl(type) {
|
||||
return `${Packages.getTaskUrl(type, 'installDependenciesOfPackages')}`;
|
||||
}
|
||||
|
||||
static getInstallPackageUrl(type) {
|
||||
return `${Packages.getTaskUrl(type, 'installPackage')}`;
|
||||
}
|
||||
|
||||
removePackage(type, slug) {
|
||||
let url = Packages.getRemovePackageUrl(type);
|
||||
|
||||
request(url, {
|
||||
method: 'post',
|
||||
body: {
|
||||
package: slug
|
||||
}
|
||||
}, (response) => {
|
||||
if (response.status === 'success') {
|
||||
$('.remove-package-confirm').addClass('hidden');
|
||||
|
||||
if (response.dependencies && response.dependencies.length > 0) {
|
||||
this.addDependenciesToList(response.dependencies);
|
||||
$('.remove-package-dependencies').removeClass('hidden');
|
||||
} else {
|
||||
$('.remove-package-done').removeClass('hidden');
|
||||
}
|
||||
|
||||
// The package was removed. When the modal closes, move to the packages list
|
||||
$(document).on('closing', '[data-remodal-id="remove-package"]', () => {
|
||||
Packages.getBackToList(type);
|
||||
});
|
||||
} else {
|
||||
$('.remove-package-confirm').addClass('hidden');
|
||||
$('.remove-package-error').removeClass('hidden');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
reinstallPackage(type, slug, package_name, current_version) {
|
||||
$('.button-bar button').addClass('hidden');
|
||||
$('.button-bar .spinning-wheel').removeClass('hidden');
|
||||
|
||||
let url = Packages.getReinstallPackageUrl(type);
|
||||
|
||||
request(url, {
|
||||
method: 'post',
|
||||
body: {
|
||||
slug: slug,
|
||||
type: type,
|
||||
package_name: package_name,
|
||||
current_version: current_version
|
||||
}
|
||||
}, (response) => {
|
||||
if (response.status === 'success') {
|
||||
$('.reinstall-package-confirm').addClass('hidden');
|
||||
$('.reinstall-package-done').removeClass('hidden');
|
||||
} else {
|
||||
$('.reinstall-package-confirm').addClass('hidden');
|
||||
$('.reinstall-package-error').removeClass('hidden');
|
||||
}
|
||||
|
||||
window.location.reload();
|
||||
});
|
||||
}
|
||||
|
||||
removeDependency(type, slug, button) {
|
||||
let url = Packages.getRemovePackageUrl(type);
|
||||
|
||||
request(url, {
|
||||
method: 'post',
|
||||
body: {
|
||||
package: slug
|
||||
}
|
||||
}, (response) => {
|
||||
if (response.status === 'success') {
|
||||
button.removeClass('button');
|
||||
button.replaceWith($('<span>Removed successfully</span>'));
|
||||
|
||||
if (response.dependencies && response.dependencies.length > 0) {
|
||||
this.addDependenciesToList(response.dependencies, slug);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
static addNeededDependencyToList(action, slug) {
|
||||
$('.install-dependencies-package-container .type-' + action).removeClass('hidden');
|
||||
let list = $('.install-dependencies-package-container .type-' + action + ' ul');
|
||||
|
||||
if (action !== 'install') {
|
||||
let current_version = '';
|
||||
let available_version = '';
|
||||
let name = '';
|
||||
|
||||
let resources = gpm.payload.payload.resources;
|
||||
|
||||
if (resources.plugins[slug]) {
|
||||
available_version = resources.plugins[slug].available;
|
||||
current_version = resources.plugins[slug].version;
|
||||
name = resources.plugins[slug].name;
|
||||
} else if (resources.themes[slug]) {
|
||||
available_version = resources.themes[slug].available;
|
||||
current_version = resources.themes[slug].version;
|
||||
name = resources.themes[slug].name;
|
||||
}
|
||||
|
||||
list.append(`<li>${name ? name : slug}, ${translations.PLUGIN_ADMIN.FROM} v<strong>${current_version}</strong> ${translations.PLUGIN_ADMIN.TO} v<strong>${available_version}</strong></li>`);
|
||||
} else {
|
||||
list.append(`<li>${name ? name : slug}</li>`);
|
||||
}
|
||||
}
|
||||
|
||||
getPackagesDependencies(type, slugs, finishedLoadingCallback) {
|
||||
let url = Packages.getGetPackagesDependenciesUrl(type);
|
||||
|
||||
request(url, {
|
||||
method: 'post',
|
||||
body: {
|
||||
packages: slugs
|
||||
}
|
||||
}, (response) => {
|
||||
|
||||
finishedLoadingCallback();
|
||||
|
||||
if (response.status === 'success') {
|
||||
if (response.dependencies) {
|
||||
let hasDependencies = false;
|
||||
for (var dependency in response.dependencies) {
|
||||
if (response.dependencies.hasOwnProperty(dependency)) {
|
||||
if (dependency === 'grav') {
|
||||
continue;
|
||||
}
|
||||
hasDependencies = true;
|
||||
let dependencyName = dependency;
|
||||
let action = response.dependencies[dependency];
|
||||
|
||||
Packages.addNeededDependencyToList(action, dependencyName);
|
||||
}
|
||||
}
|
||||
|
||||
if (hasDependencies) {
|
||||
$('[data-packages-modal] .install-dependencies-package-container').removeClass('hidden');
|
||||
} else {
|
||||
$('[data-packages-modal] .install-package-container').removeClass('hidden');
|
||||
}
|
||||
} else {
|
||||
$('[data-packages-modal] .install-package-container').removeClass('hidden');
|
||||
}
|
||||
} else {
|
||||
$('[data-packages-modal] .install-package-error').removeClass('hidden');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
installDependenciesOfPackages(type, slugs, callbackSuccess, callbackError) {
|
||||
let url = Packages.getInstallDependenciesOfPackagesUrl(type);
|
||||
|
||||
request(url, {
|
||||
method: 'post',
|
||||
body: {
|
||||
packages: slugs
|
||||
}
|
||||
}, callbackSuccess);
|
||||
}
|
||||
|
||||
installPackages(type, slugs, callbackSuccess) {
|
||||
let url = Packages.getInstallPackageUrl(type);
|
||||
|
||||
global.Promise.all(slugs.map((slug) => {
|
||||
return new global.Promise((resolve, reject) => {
|
||||
request(url, {
|
||||
method: 'post',
|
||||
body: {
|
||||
package: slug,
|
||||
type: type
|
||||
}
|
||||
}, (response) => {
|
||||
resolve(response);
|
||||
});
|
||||
});
|
||||
})).then(callbackSuccess);
|
||||
|
||||
}
|
||||
|
||||
static getSlugsFromEvent(event) {
|
||||
let slugs = '';
|
||||
if ($(event.target).is('[data-packages-slugs]')) {
|
||||
slugs = $(event.target).attr('data-packages-slugs');
|
||||
} else {
|
||||
slugs = $(event.target).parent('[data-packages-slugs]').attr('data-packages-slugs');
|
||||
}
|
||||
|
||||
if (typeof slugs === 'undefined') {
|
||||
return null;
|
||||
}
|
||||
|
||||
slugs = slugs.split(',');
|
||||
return typeof slugs === 'string' ? [slugs] : slugs;
|
||||
}
|
||||
|
||||
handleGettingPackageDependencies(type, event, action = 'update') {
|
||||
let slugs = Packages.getSlugsFromEvent(event);
|
||||
|
||||
if (!slugs) {
|
||||
alert('No slug set');
|
||||
return;
|
||||
}
|
||||
|
||||
// Cleanup
|
||||
$('.packages-names-list').html('');
|
||||
$('.install-dependencies-package-container li').remove();
|
||||
|
||||
slugs.forEach((slug) => {
|
||||
if (action === 'update') {
|
||||
let current_version = '';
|
||||
let available_version = '';
|
||||
let name = '';
|
||||
|
||||
let resources = gpm.payload.payload.resources;
|
||||
|
||||
if (resources.plugins[slug]) {
|
||||
available_version = resources.plugins[slug].available;
|
||||
current_version = resources.plugins[slug].version;
|
||||
name = resources.plugins[slug].name;
|
||||
} else if (resources.themes[slug]) {
|
||||
available_version = resources.themes[slug].available;
|
||||
current_version = resources.themes[slug].version;
|
||||
name = resources.themes[slug].name;
|
||||
}
|
||||
|
||||
$('.packages-names-list').append(`<li>${name ? name : slug}, ${translations.PLUGIN_ADMIN.FROM} v<strong>${current_version}</strong> ${translations.PLUGIN_ADMIN.TO} v<strong>${available_version}</strong></li>`);
|
||||
} else {
|
||||
$('.packages-names-list').append(`<li>${name ? name : slug}</li>`);
|
||||
}
|
||||
});
|
||||
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
|
||||
// fix mismatching types when sharing install modal between plugins/themes
|
||||
const query = '[data-packages-modal] [data-theme-action], [data-packages-modal] [data-plugin-action]';
|
||||
const data = $(query).data('themeAction') || $(query).data('pluginAction');
|
||||
$(query).removeAttr('data-theme-action').removeAttr('data-plugin-action').attr(`data-${type}-action`, data);
|
||||
|
||||
// Restore original state
|
||||
$('[data-packages-modal] .loading').removeClass('hidden');
|
||||
$('[data-packages-modal] .install-dependencies-package-container').addClass('hidden');
|
||||
$('[data-packages-modal] .install-package-container').addClass('hidden');
|
||||
$('[data-packages-modal] .installing-dependencies').addClass('hidden');
|
||||
$('[data-packages-modal] .installing-package').addClass('hidden');
|
||||
$('[data-packages-modal] .installation-complete').addClass('hidden');
|
||||
$('[data-packages-modal] .install-package-error').addClass('hidden');
|
||||
|
||||
this.getPackagesDependencies(type, slugs, () => {
|
||||
let slugs_string = slugs.join();
|
||||
$(`[data-packages-modal] [data-${type}-action="install-dependencies-and-package"]`).attr('data-packages-slugs', slugs_string);
|
||||
$(`[data-packages-modal] [data-${type}-action="install-package"]`).attr('data-packages-slugs', slugs_string);
|
||||
$('[data-packages-modal] .loading').addClass('hidden');
|
||||
});
|
||||
}
|
||||
|
||||
handleInstallingDependenciesAndPackage(type, event) {
|
||||
let slugs = Packages.getSlugsFromEvent(event);
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
|
||||
$('[data-packages-modal] .install-dependencies-package-container').addClass('hidden');
|
||||
$('[data-packages-modal] .install-package-container').addClass('hidden');
|
||||
$('[data-packages-modal] .installing-dependencies').removeClass('hidden');
|
||||
|
||||
this.installDependenciesOfPackages(type, slugs, (response) => {
|
||||
$('[data-packages-modal] .installing-dependencies').addClass('hidden');
|
||||
$('[data-packages-modal] .installing-package').removeClass('hidden');
|
||||
this.installPackages(type, slugs, () => {
|
||||
$('[data-packages-modal] .installing-package').addClass('hidden');
|
||||
$('[data-packages-modal] .installation-complete').removeClass('hidden');
|
||||
|
||||
if (response.status === 'error') {
|
||||
let remodal = $.remodal.lookup[$('[data-packages-modal]').data('remodal')];
|
||||
remodal.close();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
setTimeout(() => {
|
||||
if (slugs.length === 1) {
|
||||
global.location.href = `${config.base_url_relative}/${type}s/${slugs[0]}`;
|
||||
} else {
|
||||
global.location.href = `${config.base_url_relative}/${type}s`;
|
||||
}
|
||||
}, 1000);
|
||||
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
handleInstallingPackage(type, event) {
|
||||
let slugs = Packages.getSlugsFromEvent(event);
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
|
||||
$('[data-packages-modal] .install-package-container').addClass('hidden');
|
||||
$('[data-packages-modal] .installing-package').removeClass('hidden');
|
||||
|
||||
this.installPackages(type, slugs, (response) => {
|
||||
$('[data-packages-modal] .installing-package').addClass('hidden');
|
||||
$('[data-packages-modal] .installation-complete').removeClass('hidden');
|
||||
|
||||
const errors = Array.from(response).filter((r) => r.status === 'error');
|
||||
|
||||
if (errors && errors.length) {
|
||||
let remodal = $.remodal.lookup[$('[data-packages-modal].remodal-is-opened').data('remodal')];
|
||||
remodal.close();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (slugs.length === 1) {
|
||||
global.location.href = `${config.base_url_relative}/${type}s/${slugs[0]}`;
|
||||
} else {
|
||||
global.location.href = `${config.base_url_relative}/${type}s`;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
handleRemovingPackage(type, event) {
|
||||
let slug = $(event.target).attr('data-packages-slugs');
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
|
||||
this.removePackage(type, slug);
|
||||
}
|
||||
|
||||
handleReinstallPackage(type, event) {
|
||||
let target = $(event.target);
|
||||
let slug = target.attr('data-package-slug');
|
||||
let package_name = target.attr('data-package-name');
|
||||
let current_version = target.attr('data-package-current-version');
|
||||
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
|
||||
this.reinstallPackage(type, slug, package_name, current_version);
|
||||
}
|
||||
|
||||
handleRemovingDependency(type, event) {
|
||||
let slug = $(event.target).attr('data-dependency-slug');
|
||||
let button = $(event.target);
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
|
||||
this.removeDependency(type, slug, button);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default new Packages();
|
||||
Reference in New Issue
Block a user