summaryrefslogtreecommitdiff
path: root/js
diff options
context:
space:
mode:
authorAndrew Dolgov <[email protected]>2021-03-03 19:07:39 +0300
committerAndrew Dolgov <[email protected]>2021-03-03 19:07:39 +0300
commitcb7f322f09fb8ed9be95978db82f99a2e8a4661b (patch)
tree7c84b6ba264fd07a3a5105ce946390a5c5554dad /js
parent06cb181f7315b709d9d8ab926f7607f3227ad168 (diff)
add basic plugin installer (uses tt-rss.org)
Diffstat (limited to 'js')
-rw-r--r--js/CommonFilters.js4
-rw-r--r--js/PrefHelpers.js120
-rwxr-xr-xjs/common.js59
3 files changed, 170 insertions, 13 deletions
diff --git a/js/CommonFilters.js b/js/CommonFilters.js
index 0b907e2ba..606cf2076 100644
--- a/js/CommonFilters.js
+++ b/js/CommonFilters.js
@@ -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>`;
diff --git a/js/PrefHelpers.js b/js/PrefHelpers.js
index fc59ebb70..5658ce9b0 100644
--- a/js/PrefHelpers.js
+++ b/js/PrefHelpers.js
@@ -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() {
diff --git a/js/common.js b/js/common.js
index 194fdcd9d..9c748f9c5 100755
--- a/js/common.js
+++ b/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 (typeof elem == "string")
+ elem = document.getElementById(elem);
+
+ elem.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]*?-/, "");
+ 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));
+ if (!isNaN(rowId))
+ rv.push(parseInt(rowId));
+ }
}
});