init
This commit is contained in:
@@ -0,0 +1,24 @@
|
||||
import $ from 'jquery';
|
||||
import request from '../utils/request';
|
||||
|
||||
const switcher = $('input[type="radio"][name="channel-switch"]');
|
||||
|
||||
if (switcher) {
|
||||
switcher.on('change', (event) => {
|
||||
let radio = $(event.target);
|
||||
let url = `${radio.parent('[data-url]').data('url')}`;
|
||||
|
||||
request(url, {
|
||||
method: 'post',
|
||||
body: {
|
||||
task: 'gpmRelease',
|
||||
release: radio.val()
|
||||
}
|
||||
},
|
||||
(response) => {
|
||||
if (response.reload) {
|
||||
global.location.reload();
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
26
user/plugins/admin/themes/grav/app/updates/check.js
Normal file
26
user/plugins/admin/themes/grav/app/updates/check.js
Normal file
@@ -0,0 +1,26 @@
|
||||
import $ from 'jquery';
|
||||
import { Instance as gpm } from '../utils/gpm';
|
||||
import { translations } from 'grav-config';
|
||||
import toastr from '../utils/toastr';
|
||||
|
||||
// Check for updates trigger
|
||||
$('[data-gpm-checkupdates]').on('click', function() {
|
||||
let element = $(this);
|
||||
element.find('i').addClass('fa-spin');
|
||||
|
||||
gpm.fetch((response) => {
|
||||
element.find('i').removeClass('fa-spin');
|
||||
let payload = response.payload;
|
||||
|
||||
if (!payload) { return; }
|
||||
if (!payload.grav.isUpdatable && !payload.resources.total) {
|
||||
toastr.success(translations.PLUGIN_ADMIN.EVERYTHING_UP_TO_DATE);
|
||||
} else {
|
||||
var grav = payload.grav.isUpdatable ? 'Grav v' + payload.grav.available : '';
|
||||
var resources = payload.resources.total ? payload.resources.total + ' ' + translations.PLUGIN_ADMIN.UPDATES_ARE_AVAILABLE : '';
|
||||
|
||||
if (!resources) { grav += ' ' + translations.PLUGIN_ADMIN.IS_AVAILABLE_FOR_UPDATE; }
|
||||
toastr.info(grav + (grav && resources ? ' ' + translations.PLUGIN_ADMIN.AND + ' ' : '') + resources);
|
||||
}
|
||||
}, true);
|
||||
});
|
||||
68
user/plugins/admin/themes/grav/app/updates/feed.js
Normal file
68
user/plugins/admin/themes/grav/app/updates/feed.js
Normal file
@@ -0,0 +1,68 @@
|
||||
import $ from 'jquery';
|
||||
import { config } from 'grav-config';
|
||||
import request from '../utils/request';
|
||||
|
||||
const URI = `${config.base_url_relative}/ajax.json/task${config.param_sep}getNewsFeed`;
|
||||
|
||||
class Feed {
|
||||
constructor() {
|
||||
this.data = null;
|
||||
}
|
||||
|
||||
fetch(refresh = false, callback = function() {}) {
|
||||
request(URI, {
|
||||
method: 'post',
|
||||
body: { refresh }
|
||||
}, (response) => {
|
||||
this.data = response;
|
||||
callback(response);
|
||||
});
|
||||
}
|
||||
|
||||
refresh(refresh = false) {
|
||||
const feed = $('#news-feed .widget-content');
|
||||
if (!feed.length) { return; }
|
||||
|
||||
let loader = feed.find('.widget-loader');
|
||||
loader.find('div').remove();
|
||||
loader.find('.fa-warning').removeClass('fa-warning').addClass('fa-refresh fa-spin');
|
||||
loader.show();
|
||||
|
||||
feed.find('> ul').hide();
|
||||
|
||||
if (!this.data || this.data.error || refresh) {
|
||||
this.fetch(refresh, this.updateContent.bind(this));
|
||||
} else {
|
||||
this.updateContent();
|
||||
}
|
||||
}
|
||||
|
||||
updateContent() {
|
||||
const feed = $('#news-feed .widget-content');
|
||||
if (!feed.length) { return; }
|
||||
|
||||
let loader = feed.find('.widget-loader').hide();
|
||||
let content = feed.find('> ul').empty().show();
|
||||
|
||||
if (this.data.error || this.data.status === 'error') {
|
||||
loader.show().find('div').remove();
|
||||
loader.find('.fa-refresh').removeClass('fa-refresh fa-spin').addClass('fa-warning');
|
||||
loader.append(`<div>${this.data.error ? this.data.error.message : this.data.message || 'Unable to download news feed'}</div>`);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.data && this.data.feed_data) {
|
||||
content.append(this.data.feed_data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let feed = new Feed();
|
||||
$(document).ready(() => feed.refresh());
|
||||
$(document).on('click', '[data-refresh="feed"]', (event) => {
|
||||
event.preventDefault();
|
||||
feed.refresh(true);
|
||||
});
|
||||
|
||||
export default feed;
|
||||
196
user/plugins/admin/themes/grav/app/updates/index.js
Normal file
196
user/plugins/admin/themes/grav/app/updates/index.js
Normal file
@@ -0,0 +1,196 @@
|
||||
import $ from 'jquery';
|
||||
import unique from 'mout/array/unique';
|
||||
import { config, translations } from 'grav-config';
|
||||
import { Instance as gpm } from '../utils/gpm';
|
||||
import Notifications from './notifications';
|
||||
|
||||
import Feed from './feed';
|
||||
import './check';
|
||||
import './update';
|
||||
import './channel-switcher';
|
||||
|
||||
export default class Updates {
|
||||
constructor(payload = {}) {
|
||||
this.setPayload(payload);
|
||||
this.task = `task${config.param_sep}`;
|
||||
this.updateURL = '';
|
||||
}
|
||||
|
||||
setPayload(payload = {}) {
|
||||
this.payload = payload;
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
fetch(force = false) {
|
||||
gpm.fetch((response) => this.setPayload(response), force);
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
maintenance(mode = 'hide') {
|
||||
let element = $('#updates [data-update-packages]');
|
||||
|
||||
element[mode === 'show' ? 'fadeIn' : 'fadeOut']();
|
||||
|
||||
if (mode === 'hide') {
|
||||
$('.badges.with-updates').removeClass('with-updates').find('.badge.updates').remove();
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
grav() {
|
||||
let payload = this.payload.grav;
|
||||
|
||||
if (payload && payload.isUpdatable) {
|
||||
let task = this.task;
|
||||
let bar = '';
|
||||
|
||||
if (!payload.isSymlink) {
|
||||
this.updateURL = `${config.base_url_relative}/update.json/${task}updategrav/admin-nonce${config.param_sep}${config.admin_nonce}`;
|
||||
bar += `<button data-remodal-target="update-grav" class="button button-small secondary pointer-events-none" id="grav-update-button">${translations.PLUGIN_ADMIN.UPDATE_GRAV_NOW} <span class="cnt-down">(5s)</span></button>`;
|
||||
} else {
|
||||
bar += `<span class="hint--left" style="float: right;" data-hint="${translations.PLUGIN_ADMIN.GRAV_SYMBOLICALLY_LINKED}"><i class="fa fa-fw fa-link"></i></span>`;
|
||||
}
|
||||
|
||||
bar += `
|
||||
Grav <b>v${payload.available}</b> ${translations.PLUGIN_ADMIN.IS_NOW_AVAILABLE}! <span class="less">(${translations.PLUGIN_ADMIN.CURRENT} v${payload.version})</span>
|
||||
`;
|
||||
|
||||
let element = $('[data-gpm-grav]').removeClass('hidden');
|
||||
|
||||
if (element.is(':empty')) {
|
||||
element.hide();
|
||||
}
|
||||
|
||||
element
|
||||
.addClass('grav')
|
||||
.html(`${bar}`)
|
||||
.slideDown(150, function() {
|
||||
var c = 5;
|
||||
var x = setInterval(function() {
|
||||
c -= 1;
|
||||
element.find('.pointer-events-none .cnt-down').text('(' + c + 's)');
|
||||
}, 1000);
|
||||
|
||||
setTimeout(function() {
|
||||
clearInterval(x);
|
||||
element.find('.pointer-events-none .cnt-down').remove();
|
||||
element.find('.pointer-events-none').removeClass('pointer-events-none');
|
||||
}, 5000);
|
||||
})
|
||||
.parent('#messages').addClass('default-box-shadow');
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
resources() {
|
||||
if (!this.payload || !this.payload.resources || !this.payload.resources.total) {
|
||||
return this.maintenance('hide');
|
||||
}
|
||||
|
||||
let is_current_package_latest = true;
|
||||
let map = ['plugins', 'themes'];
|
||||
let singles = ['plugin', 'theme'];
|
||||
let { plugins, themes } = this.payload.resources;
|
||||
|
||||
if (!this.payload.resources.total) { return this; }
|
||||
|
||||
[plugins, themes].forEach(function(resources, index) {
|
||||
if (!resources || Array.isArray(resources)) { return; }
|
||||
let length = Object.keys(resources).length;
|
||||
let type = map[index];
|
||||
|
||||
// sidebar
|
||||
$(`#admin-menu a[href$="/${map[index]}"]`)
|
||||
.find('.badges')
|
||||
.addClass('with-updates')
|
||||
.find('.badge.updates').text(length);
|
||||
|
||||
var type_translation = '';
|
||||
// update all
|
||||
|
||||
if (type === 'plugins') {
|
||||
type_translation = translations.PLUGIN_ADMIN.PLUGINS;
|
||||
} else {
|
||||
type_translation = translations.PLUGIN_ADMIN.THEMES;
|
||||
}
|
||||
|
||||
let updateAll = $(`.grav-update.${type}`);
|
||||
updateAll.css('display', 'block').html(`
|
||||
<p>
|
||||
<a href="#" class="button button-small secondary" data-remodal-target="update-packages" data-packages-slugs="${Object.keys(resources).join()}" data-${singles[index]}-action="start-packages-update">${translations.PLUGIN_ADMIN.UPDATE} ${translations.PLUGIN_ADMIN.ALL} ${type_translation}</a>
|
||||
<i class="fa fa-bullhorn"></i>
|
||||
${length} ${translations.PLUGIN_ADMIN.OF_YOUR} ${type_translation.toLowerCase()} ${translations.PLUGIN_ADMIN.HAVE_AN_UPDATE_AVAILABLE}
|
||||
</p>
|
||||
`);
|
||||
|
||||
let existing_slugs = $('[data-update-packages]').attr('data-packages-slugs') || '';
|
||||
|
||||
if (existing_slugs) {
|
||||
existing_slugs = existing_slugs.split(',');
|
||||
} else {
|
||||
existing_slugs = [];
|
||||
}
|
||||
|
||||
let slugs = unique(existing_slugs.concat(Object.keys(resources))).join();
|
||||
$('[data-update-packages]').attr('data-packages-slugs', `${slugs}`);
|
||||
|
||||
Object.keys(resources).forEach(function(item) {
|
||||
// listing page
|
||||
let container = $(`[data-gpm-${singles[index]}="${item}"]`);
|
||||
let element = container.find('.gpm-name');
|
||||
let url = element.find('a');
|
||||
let content_wrapper = container.parents('.content-wrapper');
|
||||
|
||||
if (type === 'plugins' && !element.find('.badge.update').length) {
|
||||
element.append(`<a class="plugin-update-button" href="${url.attr('href')}"><span class="badge update">${translations.PLUGIN_ADMIN.UPDATE_AVAILABLE}!</span></a>`);
|
||||
content_wrapper.addClass('has-updates');
|
||||
} else if (type === 'themes') {
|
||||
element.append(`<div class="gpm-ribbon"><a href="${url.attr('href')}">${translations.PLUGIN_ADMIN.UPDATE.toUpperCase()}</a></div>`);
|
||||
content_wrapper.addClass('has-updates');
|
||||
}
|
||||
|
||||
// details page
|
||||
if (container.length) {
|
||||
let details = $(`.grav-update.${singles[index]}`);
|
||||
if (details.length) {
|
||||
let releaseType = resources[item].type === 'testing' ? '<span class="gpm-testing">test release</span>' : '';
|
||||
details.html(`
|
||||
<p>
|
||||
<a href="#" class="button button-small secondary" data-remodal-target="update-packages" data-packages-slugs="${item}" data-${singles[index]}-action="start-package-installation">${translations.PLUGIN_ADMIN.UPDATE} ${singles[index].charAt(0).toUpperCase() + singles[index].substr(1).toLowerCase()}</a>
|
||||
<i class="fa fa-bullhorn"></i>
|
||||
<strong>v${resources[item].available}</strong> ${releaseType} ${translations.PLUGIN_ADMIN.OF_THIS} ${singles[index]} ${translations.PLUGIN_ADMIN.IS_NOW_AVAILABLE}!
|
||||
</p>
|
||||
`).css('display', 'block');
|
||||
|
||||
is_current_package_latest = false;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
$('[data-update-packages]').removeClass('hidden');
|
||||
});
|
||||
|
||||
$('.content-wrapper').addClass('updates-checked');
|
||||
|
||||
if (!is_current_package_latest) {
|
||||
$('.warning-reinstall-not-latest-release').removeClass('hidden');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let Instance = new Updates();
|
||||
export { Instance, Notifications, Feed };
|
||||
|
||||
// automatically refresh UI for updates (graph, sidebar, plugin/themes pages) after every fetch
|
||||
gpm.on('fetched', (response, raw) => {
|
||||
Instance.setPayload(response.payload || {});
|
||||
Instance.grav().resources();
|
||||
});
|
||||
|
||||
if (config.enable_auto_updates_check === '1') {
|
||||
gpm.fetch();
|
||||
}
|
||||
169
user/plugins/admin/themes/grav/app/updates/notifications.js
Normal file
169
user/plugins/admin/themes/grav/app/updates/notifications.js
Normal file
@@ -0,0 +1,169 @@
|
||||
import $ from 'jquery';
|
||||
import { config } from 'grav-config';
|
||||
import request from '../utils/request';
|
||||
|
||||
const canFetchNotifications = () => config.notifications.enabled;
|
||||
const notificationsFilters = () => config.notifications.filters;
|
||||
|
||||
class Notifications {
|
||||
|
||||
static addShowAllInFeed() {
|
||||
$('#notifications ul').append('<li class="show-all" data-notification-action="show-all-notifications">Show all</li>');
|
||||
}
|
||||
|
||||
static showNotificationInFeed(notification) {
|
||||
let notifications = $('#notifications').removeClass('hidden');
|
||||
|
||||
let loader = notifications.find('.widget-loader').hide();
|
||||
let content = notifications.find('.widget-content > ul').show();
|
||||
loader.find('div').remove();
|
||||
loader.find('.fa-warning').removeClass('fa-warning').addClass('fa-refresh fa-spin');
|
||||
|
||||
content
|
||||
.append(notification)
|
||||
.find('li:nth-child(n+11)').addClass('hidden'); // hide all items > 10
|
||||
|
||||
if (content.find('li.hidden').length) {
|
||||
Notifications.addShowAllInFeed();
|
||||
}
|
||||
}
|
||||
|
||||
static showNotificationInTop(notification) {
|
||||
const container = $('.top-notifications-container');
|
||||
const dummy = $('<div />').html(notification);
|
||||
|
||||
container.removeClass('hidden').append(dummy.children());
|
||||
dummy.children().slideDown(150);
|
||||
}
|
||||
|
||||
static showNotificationInDashboard(notification) {
|
||||
const container = $('.dashboard-notifications-container');
|
||||
const dummy = $('<div />').html(notification);
|
||||
|
||||
container.removeClass('hidden').append(dummy.children());
|
||||
dummy.children().slideDown(150);
|
||||
}
|
||||
|
||||
static showNotificationInPlugins(notification) {
|
||||
const container = $('.plugins-notifications-container');
|
||||
const dummy = $('<div />').html(notification);
|
||||
|
||||
container.removeClass('hidden').append(dummy.children());
|
||||
dummy.children().slideDown(150);
|
||||
}
|
||||
|
||||
static showNotificationInThemes(notification) {
|
||||
const container = $('.themes-notifications-container');
|
||||
const dummy = $('<div />').html(notification);
|
||||
|
||||
container.removeClass('hidden').append(dummy.children());
|
||||
dummy.children().slideDown(150);
|
||||
}
|
||||
|
||||
static processLocation(location, notification) {
|
||||
switch (location) {
|
||||
case 'feed':
|
||||
Notifications.showNotificationInFeed(notification);
|
||||
break;
|
||||
case 'top':
|
||||
if (!notification.read) {
|
||||
Notifications.showNotificationInTop(notification);
|
||||
}
|
||||
break;
|
||||
case 'dashboard':
|
||||
if (!notification.read) {
|
||||
Notifications.showNotificationInDashboard(notification);
|
||||
}
|
||||
break;
|
||||
case 'plugins':
|
||||
if (!notification.read) {
|
||||
Notifications.showNotificationInPlugins(notification);
|
||||
}
|
||||
break;
|
||||
case 'themes':
|
||||
if (!notification.read) {
|
||||
Notifications.showNotificationInThemes(notification);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Grav.default.Notifications.fetch()
|
||||
fetch({ filter = notificationsFilters(), refresh = false } = {}) {
|
||||
if (!canFetchNotifications()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
let feed = $('#notifications');
|
||||
let loader = feed.find('.widget-loader');
|
||||
let content = feed.find('.widget-content > ul');
|
||||
loader.find('div').remove();
|
||||
loader.find('.fa-warning').removeClass('fa-warning').addClass('fa-refresh fa-spin');
|
||||
loader.show();
|
||||
content.hide();
|
||||
|
||||
let processNotifications = (response) => {
|
||||
let notifications = response.notifications;
|
||||
|
||||
$('#notifications').find('.widget-content > ul').empty();
|
||||
|
||||
if (notifications) {
|
||||
Object.keys(notifications).forEach((location) => Notifications.processLocation(location, notifications[location]));
|
||||
}
|
||||
};
|
||||
|
||||
request(`${config.base_url_relative}/task${config.param_sep}getNotifications`, {
|
||||
method: 'post',
|
||||
body: { refresh, filter }
|
||||
}, (response) => {
|
||||
processNotifications(response);
|
||||
}).catch(() => {
|
||||
let widget = $('#notifications .widget-content');
|
||||
widget
|
||||
.find('.widget-loader')
|
||||
.find('div').remove();
|
||||
|
||||
widget
|
||||
.find('.widget-loader')
|
||||
.append('<div>Failed to retrieve notifications</div>')
|
||||
.find('.fa-spin')
|
||||
.removeClass('fa-spin fa-refresh').addClass('fa-warning');
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
let notifications = new Notifications();
|
||||
export default notifications;
|
||||
|
||||
if (canFetchNotifications()) {
|
||||
notifications.fetch();
|
||||
|
||||
/* Hide a notification and store it hidden */
|
||||
// <a href="#" data-notification-action="hide-notification" data-notification-id="${notification.id}" class="close hide-notification"><i class="fa fa-close"></i></a>
|
||||
$(document).on('click', '[data-notification-action="hide-notification"]', (event) => {
|
||||
let notification_id = $(event.target).parents('.hide-notification').data('notification-id');
|
||||
|
||||
let url = `${config.base_url_relative}/notifications.json/task${config.param_sep}hideNotification/notification_id${config.param_sep}${notification_id}`;
|
||||
|
||||
request(url, { method: 'post' }, () => {});
|
||||
|
||||
$(event.target).parents('.single-notification').hide();
|
||||
});
|
||||
|
||||
$(document).on('click', '[data-notification-action="hide-notification"]', (event) => {
|
||||
const target = $(event.currentTarget);
|
||||
const notification = target.parent();
|
||||
|
||||
notification.slideUp(() => notification.remove());
|
||||
});
|
||||
|
||||
$(document).on('click', '[data-notification-action="show-all-notifications"]', (event) => {
|
||||
$('#notifications .show-all').hide();
|
||||
$('#notifications .hidden').removeClass('hidden');
|
||||
});
|
||||
|
||||
$(document).on('click', '[data-refresh="notifications"]', (event) => {
|
||||
event.preventDefault();
|
||||
notifications.fetch({ filter: ['feed'], refresh: true });
|
||||
});
|
||||
}
|
||||
22
user/plugins/admin/themes/grav/app/updates/update.js
Normal file
22
user/plugins/admin/themes/grav/app/updates/update.js
Normal file
@@ -0,0 +1,22 @@
|
||||
import $ from 'jquery';
|
||||
import { translations } from 'grav-config';
|
||||
import formatBytes from '../utils/formatbytes';
|
||||
import request from '../utils/request';
|
||||
import { Instance as Update } from './index';
|
||||
|
||||
// Dashboard update and Grav update
|
||||
$(document).on('click.remodal', '[data-remodal-id="update-grav"] [data-remodal-action="confirm"]', () => {
|
||||
const element = $('#grav-update-button');
|
||||
element.html(`${translations.PLUGIN_ADMIN.UPDATING_PLEASE_WAIT} ${formatBytes(Update.payload.grav.assets['grav-update'].size)}..`);
|
||||
|
||||
element.attr('disabled', 'disabled').find('> .fa').removeClass('fa-cloud-download').addClass('fa-refresh fa-spin');
|
||||
|
||||
request(Update.updateURL, (response) => {
|
||||
if (response.type === 'updategrav') {
|
||||
$('[data-gpm-grav]').remove();
|
||||
$('#footer .grav-version').html(response.version);
|
||||
}
|
||||
|
||||
element.removeAttr('disabled').find('> .fa').removeClass('fa-refresh fa-spin').addClass('fa-cloud-download');
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user