mirror of
https://git.tt-rss.org/git/tt-rss.git
synced 2025-12-13 13:25:54 +00:00
add basic plugin installer (uses tt-rss.org)
This commit is contained in:
@@ -115,7 +115,7 @@ const Filters = {
|
||||
const li = document.createElement('li');
|
||||
li.addClassName("rule");
|
||||
|
||||
li.innerHTML = `${App.FormFields.checkbox_tag("", false, {onclick: 'Lists.onRowChecked(this)'})}
|
||||
li.innerHTML = `${App.FormFields.checkbox_tag("", false, "", {onclick: 'Lists.onRowChecked(this)'})}
|
||||
<span class="name" onclick='App.dialogOf(this).onRuleClicked(this)'>${reply}</span>
|
||||
<span class="payload" >${App.FormFields.hidden_tag("rule[]", rule)}</span>`;
|
||||
|
||||
@@ -147,7 +147,7 @@ const Filters = {
|
||||
const li = document.createElement('li');
|
||||
li.addClassName("action");
|
||||
|
||||
li.innerHTML = `${App.FormFields.checkbox_tag("", false, {onclick: 'Lists.onRowChecked(this)'})}
|
||||
li.innerHTML = `${App.FormFields.checkbox_tag("", false, "", {onclick: 'Lists.onRowChecked(this)'})}
|
||||
<span class="name" onclick='App.dialogOf(this).onActionClicked(this)'>${reply}</span>
|
||||
<span class="payload">${App.FormFields.hidden_tag("action[]", action)}</span>`;
|
||||
|
||||
|
||||
@@ -349,10 +349,128 @@ const Helpers = {
|
||||
}
|
||||
});
|
||||
},
|
||||
install: function() {
|
||||
const dialog = new fox.SingleUseDialog({
|
||||
PI_RES_ALREADY_INSTALLED: "PI_RES_ALREADY_INSTALLED",
|
||||
PI_RES_SUCCESS: "PI_RES_SUCCESS",
|
||||
PI_ERR_NO_CLASS: "PI_ERR_NO_CLASS",
|
||||
PI_ERR_NO_INIT_PHP: "PI_ERR_NO_INIT_PHP",
|
||||
PI_ERR_EXEC_FAILED: "PI_ERR_EXEC_FAILED",
|
||||
PI_ERR_NO_TEMPDIR: "PI_ERR_NO_TEMPDIR",
|
||||
PI_ERR_PLUGIN_NOT_FOUND: "PI_ERR_PLUGIN_NOT_FOUND",
|
||||
PI_ERR_NO_WORKDIR: "PI_ERR_NO_WORKDIR",
|
||||
title: __("List of plugins"),
|
||||
need_refresh: false,
|
||||
onHide: function() {
|
||||
if (this.need_refresh) {
|
||||
Helpers.Prefs.refresh();
|
||||
}
|
||||
},
|
||||
performInstall: function(plugin) {
|
||||
|
||||
const install_dialog = new fox.SingleUseDialog({
|
||||
title: __("Plugin installer"),
|
||||
content: `
|
||||
<ul class="panel panel-scrollable contents">
|
||||
<li class='text-center'>${__("Installing %s, please wait...").replace("%s", plugin)}</li>
|
||||
</ul>
|
||||
|
||||
<footer class='text-center'>
|
||||
${App.FormFields.submit_tag(__("Close this window"))}
|
||||
</footer>`
|
||||
});
|
||||
|
||||
const tmph = dojo.connect(install_dialog, 'onShow', function () {
|
||||
dojo.disconnect(tmph);
|
||||
|
||||
const container = install_dialog.domNode.querySelector(".contents");
|
||||
|
||||
xhr.json("backend.php", {op: "pref-prefs", method: "installPlugin", plugin: plugin}, (reply) => {
|
||||
if (!reply) {
|
||||
container.innerHTML = `<li class='text-center text-error'>${__("Operation failed: check event log.")}</li>`;
|
||||
} else {
|
||||
switch (reply.result) {
|
||||
case dialog.PI_RES_SUCCESS:
|
||||
container.innerHTML = `<li class='text-success text-center'>${__("Plugin has been installed.")}</li>`
|
||||
dialog.need_refresh = true;
|
||||
break;
|
||||
case dialog.PI_RES_ALREADY_INSTALLED:
|
||||
container.innerHTML = `<li class='text-success text-center'>${__("Plugin is already installed.")}</li>`
|
||||
break;
|
||||
default:
|
||||
container.innerHTML = `
|
||||
<li>
|
||||
<h3 style="margin-top: 0">${plugin}</h3>
|
||||
${reply.stderr ? `<pre class="small text-error">${reply.stderr}</pre>` : ''}
|
||||
${reply.stdour ? `<pre class="small text-success">${reply.stdout}</pre>` : ''}
|
||||
<p class="small">
|
||||
${App.FormFields.icon("error_outline") + " " + __("Exited with RC: %d").replace("%d", reply.git_status)}
|
||||
</p>
|
||||
</li>
|
||||
`;
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
install_dialog.show();
|
||||
|
||||
},
|
||||
refresh: function() {
|
||||
const container = dialog.domNode.querySelector(".contents");
|
||||
container.innerHTML = `<li class='text-center'>${__("Looking for plugins...")}</li>`;
|
||||
|
||||
xhr.json("backend.php", {op: "pref-prefs", method: "getAvailablePlugins"}, (reply) => {
|
||||
|
||||
if (!reply) {
|
||||
container.innerHTML = `<li class='text-center text-error'>${__("Operation failed: check event log.")}</li>`;
|
||||
} else {
|
||||
container.innerHTML = "";
|
||||
|
||||
reply.forEach((plugin) => {
|
||||
container.innerHTML += `
|
||||
<li data-row-value="${App.escapeHtml(plugin.name)}">
|
||||
<h3 style="margin-top: 0">${plugin.name}
|
||||
<a target="_blank" href="${App.escapeHtml(plugin.html_url)}">
|
||||
${App.FormFields.icon("open_in_new_window")}
|
||||
</a>
|
||||
</h3>
|
||||
|
||||
<p>${plugin.description}</p>
|
||||
|
||||
${App.FormFields.button_tag(__('Install plugin'), "", {class: 'alt-primary',
|
||||
onclick: `App.dialogOf(this).performInstall("${App.escapeHtml(plugin.name)}")`})}
|
||||
|
||||
<hr/>
|
||||
</li>
|
||||
`
|
||||
});
|
||||
|
||||
dojo.parser.parse(container);
|
||||
}
|
||||
});
|
||||
},
|
||||
content: `
|
||||
<ul class="panel panel-scrollable contents"> </ul>
|
||||
|
||||
<footer>
|
||||
${App.FormFields.button_tag(__("Refresh"), "", {class: 'alt-primary', onclick: 'App.dialogOf(this).refresh()'})}
|
||||
${App.FormFields.cancel_dialog_tag(__("Close"))}
|
||||
</footer>
|
||||
`,
|
||||
});
|
||||
|
||||
const tmph = dojo.connect(dialog, 'onShow', function () {
|
||||
dojo.disconnect(tmph);
|
||||
dialog.refresh();
|
||||
});
|
||||
|
||||
dialog.show();
|
||||
},
|
||||
update: function(name = null) {
|
||||
|
||||
const dialog = new fox.SingleUseDialog({
|
||||
title: __("Plugin Updater"),
|
||||
title: __("Update plugins"),
|
||||
need_refresh: false,
|
||||
plugins_to_update: [],
|
||||
onHide: function() {
|
||||
|
||||
61
js/common.js
61
js/common.js
@@ -262,8 +262,11 @@ const Lists = {
|
||||
if (row)
|
||||
checked ? row.addClassName("Selected") : row.removeClassName("Selected");
|
||||
},
|
||||
select: function(elemId, selected) {
|
||||
$(elemId).querySelectorAll("li").forEach((row) => {
|
||||
select: function(elem, selected) {
|
||||
if (typeof elem == "string")
|
||||
elem = document.getElementById(elem);
|
||||
|
||||
elem.querySelectorAll("li").forEach((row) => {
|
||||
const checkNode = row.querySelector(".dijitCheckBox,input[type=checkbox]");
|
||||
if (checkNode) {
|
||||
const widget = dijit.getEnclosingWidget(checkNode);
|
||||
@@ -278,6 +281,30 @@ const Lists = {
|
||||
}
|
||||
});
|
||||
},
|
||||
getSelected: function(elem) {
|
||||
const rv = [];
|
||||
|
||||
if (typeof elem == "string")
|
||||
elem = document.getElementById(elem);
|
||||
|
||||
elem.querySelectorAll("li").forEach((row) => {
|
||||
if (row.hasClassName("Selected")) {
|
||||
const rowVal = row.getAttribute("data-row-value");
|
||||
|
||||
if (rowVal) {
|
||||
rv.push(rowVal);
|
||||
} else {
|
||||
// either older prefix-XXX notation or separate attribute
|
||||
const rowId = row.getAttribute("data-row-id") || row.id.replace(/^[A-Z]*?-/, "");
|
||||
|
||||
if (!isNaN(rowId))
|
||||
rv.push(parseInt(rowId));
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return rv;
|
||||
}
|
||||
};
|
||||
|
||||
/* exported Tables */
|
||||
@@ -293,8 +320,11 @@ const Tables = {
|
||||
checked ? row.addClassName("Selected") : row.removeClassName("Selected");
|
||||
|
||||
},
|
||||
select: function(elemId, selected) {
|
||||
$(elemId).querySelectorAll("tr").forEach((row) => {
|
||||
select: function(elem, selected) {
|
||||
if (typeof elem == "string")
|
||||
elem = document.getElementById(elem);
|
||||
|
||||
elem.querySelectorAll("tr").forEach((row) => {
|
||||
const checkNode = row.querySelector(".dijitCheckBox,input[type=checkbox]");
|
||||
if (checkNode) {
|
||||
const widget = dijit.getEnclosingWidget(checkNode);
|
||||
@@ -309,16 +339,25 @@ const Tables = {
|
||||
}
|
||||
});
|
||||
},
|
||||
getSelected: function(elemId) {
|
||||
getSelected: function(elem) {
|
||||
const rv = [];
|
||||
|
||||
$(elemId).querySelectorAll("tr").forEach((row) => {
|
||||
if (row.hasClassName("Selected")) {
|
||||
// either older prefix-XXX notation or separate attribute
|
||||
const rowId = row.getAttribute("data-row-id") || row.id.replace(/^[A-Z]*?-/, "");
|
||||
if (typeof elem == "string")
|
||||
elem = document.getElementById(elem);
|
||||
|
||||
if (!isNaN(rowId))
|
||||
rv.push(parseInt(rowId));
|
||||
elem.querySelectorAll("tr").forEach((row) => {
|
||||
if (row.hasClassName("Selected")) {
|
||||
const rowVal = row.getAttribute("data-row-value");
|
||||
|
||||
if (rowVal) {
|
||||
rv.push(rowVal);
|
||||
} else {
|
||||
// either older prefix-XXX notation or separate attribute
|
||||
const rowId = row.getAttribute("data-row-id") || row.id.replace(/^[A-Z]*?-/, "");
|
||||
|
||||
if (!isNaN(rowId))
|
||||
rv.push(parseInt(rowId));
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user