From dc57114d237d071659afd43140c3f228f65c72e2 Mon Sep 17 00:00:00 2001 From: Yurii Nazarenko Date: Sun, 7 Apr 2024 22:33:08 +0200 Subject: [PATCH] Fix widget --- Makefile | 3 +- src/app/getRrReleaseInfo.cgi | 46 +++++++++++ src/app/rr-manager.js | 30 ++++++- src/app/rr-manager.widget.js | 154 ++++++++++++++++++++++++++++++++--- 4 files changed, 220 insertions(+), 13 deletions(-) create mode 100644 src/app/getRrReleaseInfo.cgi diff --git a/Makefile b/Makefile index bc2a6f1..51d3d76 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ SPK_NAME = rr-manager SPK_VERS = 2.0 -SPK_REV = 22 +SPK_REV = 23 SPK_ICON = src/rr-manager.png DSM_UI_DIR = app @@ -67,6 +67,7 @@ rr-manager_extra_install: install -m 755 -d $(STAGING_DIR)/app/libs/ install -m 755 src/app/getConfig.cgi $(STAGING_DIR)/app/getConfig.cgi install -m 755 src/app/getNetworkInfo.cgi $(STAGING_DIR)/app/getNetworkInfo.cgi + install -m 755 src/app/getRrReleaseInfo.cgi $(STAGING_DIR)/app/getRrReleaseInfo.cgi install -m 755 src/app/config.txt $(STAGING_DIR)/app/config.txt install -m 755 src/app/style.css $(STAGING_DIR)/app/style.css install -m 755 src/app/getAddons.cgi $(STAGING_DIR)/app/getAddons.cgi diff --git a/src/app/getRrReleaseInfo.cgi b/src/app/getRrReleaseInfo.cgi new file mode 100644 index 0000000..6c0c279 --- /dev/null +++ b/src/app/getRrReleaseInfo.cgi @@ -0,0 +1,46 @@ +#!/usr/bin/env bash +# Assuming jq is installed on your system for parsing and generating JSON +# Content-Type header for JSON output +echo "Content-type: application/json" +echo "" + +USER=$(/usr/syno/synoman/webman/modules/authenticate.cgi) + +if [ "${USER}" = "" ]; then + echo -e "Security : user not authenticated\n" +else + # Define the URL for GitHub API + URL="https://api.github.com/repos/RROrg/rr/releases/latest" + + # Fetch the latest release info using the GitHub API + response=$(curl -s "${URL}") + + # Extract the tag name from the response + TAG=$(echo "${response}" | jq -r '.tag_name') + + # Read local version + LOCALTAG=$(cat /usr/rr/VERSION 2>/dev/null | grep LOADERVERSION | cut -d'=' -f2) + + # Check if LOCALTAG is empty + if [ -z "${LOCALTAG}" ]; then + # Generate error message using jq + echo "{}" | jq --arg message "Unknown bootloader version!" '.error = $message' + exit 0 + fi + + # Generate output JSON + if [ "${TAG}" = "${LOCALTAG}" ]; then + # Use jq to generate JSON for up-to-date status + echo "{}" | jq --arg tag "$TAG" --arg message "Actual version is ${TAG}" \ + '.status = "up-to-date" | .tag = $tag | .message = $message' + else + # Use jq to generate JSON for update available, including release notes + # Fetch and escape release notes from GitHub API response + releaseNotes=$(echo "${response}" | jq '.body') + + # Use jq to build the JSON response + echo "{}" | jq --arg tag "$TAG" --argjson notes "$releaseNotes" \ + '.status = "update available" | .tag = $tag | .notes = $notes' + fi + +fi \ No newline at end of file diff --git a/src/app/rr-manager.js b/src/app/rr-manager.js index f57df38..a8eca39 100644 --- a/src/app/rr-manager.js +++ b/src/app/rr-manager.js @@ -449,6 +449,9 @@ Ext.define("SYNOCOMMUNITY.RRManager.Overview.Main", { that.sendWebAPI(args); }); }, + checkRRVersion: function () { + return this.callCustomScript('getRrReleaseInfo.cgi'); + }, onActivate: function () { const self = this; if (this.loaded) return; @@ -457,6 +460,7 @@ Ext.define("SYNOCOMMUNITY.RRManager.Overview.Main", { (async () => { self.systemInfo = await self.getSytemInfo(); self.packages = await self.getPackagesList(); + self.rrCheckVersion = await self.checkRRVersion(); if (self.systemInfo && self.packages) { self.systemInfoTxt = `Model: ${self.systemInfo?.model}, RAM: ${self.systemInfo?.ram} MB, DSM version: ${self.systemInfo?.version_string} `; const rrManagerPackage = self.packages.packages.find(package => package.id == 'rr-manager'); @@ -481,6 +485,30 @@ Ext.define("SYNOCOMMUNITY.RRManager.Overview.Main", { self.panels.healthPanel.fireEvent("data_ready"); self.loaded = true; } + function donwloadUpdate(){ + //TODO: implement download update + debugger; + } + if (self?.rrCheckVersion?.status == "update available") { + self.appWin.getMsgBox().confirmDelete( + "Confirmation",//TODO: implement translation + `The new version ${self.rrCheckVersion.tag} of RR is available. Do you want to update it?`, + //self.formatString(self._V('ui', 'update_rr_confirmation'), currentRrVersion, updateRrVersion), + (userResponse) => { + if ("yes" === userResponse) { + donwloadUpdate(); + } + }, + e, + { + yes: { + text: "Proceed", + btnStyle: "red", + }, + no: { text: "Cancel" }, + } + ); + } })(); self.__checkDownloadFolder(self.__checkRequiredTasks.bind(self)); }, @@ -1821,7 +1849,7 @@ Ext.define("SYNOCOMMUNITY.RRManager.Addons.Main", { i.searchField.searchPanel.hide(); }, onActive: function () { - if(this.loaded) return; + if (this.loaded) return; this.loadData(); }, enableButtonCheck: function () { diff --git a/src/app/rr-manager.widget.js b/src/app/rr-manager.widget.js index 661bc72..2f8d6c3 100644 --- a/src/app/rr-manager.widget.js +++ b/src/app/rr-manager.widget.js @@ -12,16 +12,119 @@ Ext.define("SYNOCOMMUNITY.RRManager.Widget", { extend: "Ext.Panel", minimizable: true, taskButton: undefined, + versionInfo: { + rr_version: '--', + rr_manager_version: '--', + rr_update_version: '--', + }, constructor: function constructor(a) { this.initializeSouthTable(); var b = Ext.apply(this.getConfig(), a); - SYNOCOMMUNITY.SimpleExtJSApp.WidgetCustom.superclass.constructor.call(this, b); + SYNOCOMMUNITY.RRManager.Widget.superclass.constructor.call(this, b); this.westIcon = this.getIconComponent(); this.centerContent = this.getContentComponent(); this.isActive = false; this.timestamp = null; this.uptime = null; - this.appSetting = SYNO.SDS.SystemInfoApp.SystemHealthDefaultApp + this.appSetting = { + appInstance: "SYNOCOMMUNITY.RRManager.AppInstance", + launchParam: "SYNOCOMMUNITY.RRManager.Overview.Main" + }; + }, + getHealthSummary: function () { + const e = this.getIcon(this.TYPE_NORMAL); + s = "hostname"; + message = "this is text message"; + return `
\n\t\t\t\t
${s}
`; + }, + loadInfo: async function () { + if (this.isActive) { + this.mask(_T("common", "loading")); + await this.startPolling(); + } + }, + startPolling: async function () { + const self = this; + const rrRR = await this.checkRRVersion(); + const rrConf = await this.getRRConf(); + self.packages = await self.getPackagesList(); + const rrManagerPackage = self?.packages?.packages?.find(package => package.id == 'rr-manager'); + self.versionInfo = { + rr_version: rrConf?.rr_version, + rr_manager_version: rrManagerPackage?.version, + rr_update_version: rrRR.tag + }; + this.southTable.add(self.renderVersionInfo(self.versionInfo)); + this.southTable.doLayout(); + }, + getPackagesList: function () { + that = this; + return new Promise((resolve, reject) => { + let params = { + additional: ["description", "description_enu", "dependent_packages", "beta", "distributor", "distributor_url"],//, "maintainer", "maintainer_url", "dsm_apps", "dsm_app_page", "dsm_app_launch_name","report_beta_url", "support_center", "startable", "installed_info", "support_url", "is_uninstall_pages", "install_type", "autoupdate", "silent_upgrade"], //, "installing_progress", "ctl_uninstall", "updated_at", "status", "url", "available_operation", "install_type" + ignore_hidden: false, + }; + let args = { + api: 'SYNO.Core.Package', + method: 'list', + version: 2, + params: params, + callback: function (success, message) { + success ? resolve(message) : reject('Unable to get packages!'); + } + }; + that.sendWebAPI(args); + }); + }, + _prefix: '/webman/3rdparty/rr-manager/', + callCustomScript: function (scriptName) { + return new Promise((resolve, reject) => { + Ext.Ajax.request({ + url: `${this._prefix}${scriptName}`, + method: 'GET', + timeout: 60000, + headers: { + 'Content-Type': 'text/html' + }, + success: function (response) { + // if response text is string need to decode it + if (typeof response?.responseText === 'string') { + resolve(Ext.decode(response?.responseText)); + } else { + resolve(response?.responseText); + } + }, + failure: function (result) { + if (typeof result?.responseText === 'string' && result?.responseText && !result?.responseText.startsWith('<')) { + var response = Ext.decode(result?.responseText); + reject(response?.error); + } + else { + reject('Failed with status: ' + result?.status); + } + } + }); + }); + }, + TYPE_DANGER: 0, + TYPE_ATTENTION: 1, + TYPE_NORMAL: 2, + getIcon: function (t) { + switch (t) { + case this.TYPE_DANGER: + return "syno-sysinfo-system-health-west-emergency"; + case this.TYPE_ATTENTION: + return "syno-sysinfo-system-health-west-warning"; + case this.TYPE_NORMAL: + default: + return "syno-sysinfo-system-health-west-normal"; + } + }, + getRRConf: function () { + return this.callCustomScript('getConfig.cgi'); + }, + checkRRVersion: function () { + return this.callCustomScript('getRrReleaseInfo.cgi'); }, getConfig: function getConfig() { return { @@ -39,7 +142,7 @@ Ext.define("SYNOCOMMUNITY.RRManager.Widget", { layout: "vbox", height: "100%", border: false, - padding: "4px 12px 5px 12px", + padding: "0px 11px 5px 11px", cls: "syno-sysinfo-system-health", defaults: { border: false @@ -47,12 +150,13 @@ Ext.define("SYNOCOMMUNITY.RRManager.Widget", { items: [{ xtype: "container", itemId: "northPanel", - height: 20, + height: 80, width: 296, cls: "syno-sysinfo-system-health-status", items: [{ xtype: "box", - itemId: "westIcon" + itemId: "westIcon", + cls: "syno-sysinfo-system-health-west-normal", }, { xtype: "box", itemId: "centerContent", @@ -89,6 +193,9 @@ Ext.define("SYNOCOMMUNITY.RRManager.Widget", { }, onActivate: function onActivate() { this.isActive = true; + (async () => { + await this.loadInfo(); + })(); }, onDeactivate: function onDeactivate() { this.isActive = false; @@ -96,7 +203,9 @@ Ext.define("SYNOCOMMUNITY.RRManager.Widget", { }, mask: Ext.emptyFn, unmask: Ext.emptyFn, + placeHolder: "--", initializeSouthTable: function initializeSouthTable() { + self = this; var b = Ext.util.Format.htmlEncode(_V("widget", "message")); var c = Ext.util.Format.htmlEncode(_S("hostname")); this.southTable = new Ext.Panel({ @@ -109,16 +218,39 @@ Ext.define("SYNOCOMMUNITY.RRManager.Widget", { columns: 2, cellCls: "sys-info-row" }, - items: [{ + items: [] + }); + }, + renderVersionInfo: function (versionInfo) { + return [ + { xtype: "box", - html: String.format('

{0}

', b, Ext.util.Format.htmlEncode(b)) + html: String.format('

{0}

', "💊RR:", Ext.util.Format.htmlEncode("💊RR:")) }, { + name: "rrVerison", + id: "rrVerison", xtype: "box", - html: String.format('

{0}

', c, Ext.util.Format.htmlEncode(c)) - }] - }) + html: String.format('

{0}

', versionInfo.rr_version, Ext.util.Format.htmlEncode(versionInfo.rr_version)) + }, + { + xtype: "box", + html: String.format('

{0}

', "🛡️RR Manager:", Ext.util.Format.htmlEncode("🛡️RR Manager:")) + }, { + name: "rrMVersion", + id: "rrMVersion", + xtype: "box", + html: String.format('

{0}

', versionInfo.rr_manager_version, Ext.util.Format.htmlEncode(versionInfo.rr_manager_version)) + }, + { + xtype: "box", + html: String.format('

{0}

', "RR update available!", Ext.util.Format.htmlEncode("RR update available!")) + }, { + xtype: "box", + id: "rrUpdateVersionAvailable", + html: String.format('{0}', versionInfo.rr_update_version, Ext.util.Format.htmlEncode("http://")) + } + ]; }, - destroy: function destroy() { var a = this; a.onDeactivate();