From 57ad28ed584552af6be26ab2fb02795202b203e7 Mon Sep 17 00:00:00 2001 From: Cristopfer Luis Viana da Silva Date: Mon, 5 Feb 2024 11:26:28 -0300 Subject: [PATCH] fix: cockpit-sensors with correty base project --- .cirrus.yml | 2 +- README.md | 40 ++- org.cockpit-project.sensors.metainfo.xml | 17 ++ org.cockpit-project.starter-kit.metainfo.xml | 17 -- package.json | 8 +- packaging/cockpit-sensors.control | 10 + ...er-kit.spec.in => cockpit-sensors.spec.in} | 6 +- packit.yaml | 18 +- po/de.po | 52 ++-- po/pt_BR.po | 53 ++++ src/app.jsx | 285 +++++++++++++++++- test/browser/main.fmf | 2 +- test/check-application | 8 +- 13 files changed, 440 insertions(+), 78 deletions(-) create mode 100644 org.cockpit-project.sensors.metainfo.xml delete mode 100644 org.cockpit-project.starter-kit.metainfo.xml create mode 100644 packaging/cockpit-sensors.control rename packaging/{cockpit-starter-kit.spec.in => cockpit-sensors.spec.in} (92%) create mode 100644 po/pt_BR.po diff --git a/.cirrus.yml b/.cirrus.yml index e49a77b..7ba6563 100644 --- a/.cirrus.yml +++ b/.cirrus.yml @@ -16,7 +16,7 @@ test_task: fix_kvm_script: sudo chmod 666 /dev/kvm # test PO template generation - pot_build_script: make po/starter-kit.pot + pot_build_script: make po/sensors.pot # chromium has too little /dev/shm, and we can't make that bigger check_script: TEST_BROWSER=firefox TEST_JOBS=$(nproc) TEST_OS=$TEST_OS make check diff --git a/README.md b/README.md index 24730e9..4184c4a 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,32 @@ +# Cockpit Sensors + +module that displays all data reported by lm-sensors + +# Usage + +- Download the lastest [Sensors release](https://github.com/ocristopfer/cockpit-sensors/releases) +- Extract the content of dist folder to /usr/share/cockpit/sensors +- Check if Sensors tools is show on menu + +- Installation script provided by [@subz390](https://github.com/subz390): + +```shell +wget https://github.com/ocristopfer/cockpit-sensors/releases/latest/download/cockpit-sensors.tar.xz && \ + tar -xf cockpit-sensors.tar.xz cockpit-sensors/dist && \ + mv cockpit-sensors/dist /usr/share/cockpit/sensors && \ + rm -r cockpit-sensors && \ + rm cockpit-sensors.tar.xz +``` + +- .deb package: + https://github.com/ocristopfer/cockpit-sensors/releases/latest/download/cockpit-sensors.deb + +# Prints + +![alt text](https://i.ibb.co/tQ22dF4/cockpit.png) + +# Module created using Starter Kit + # Cockpit Starter Kit Scaffolding for a [Cockpit](https://cockpit-project.org/) module. @@ -12,7 +41,6 @@ On Fedora: $ sudo dnf install gettext nodejs npm make - # Getting and building the source These commands check out the source and build it into the `dist/` directory: @@ -156,7 +184,7 @@ To run the tests in the exact same way for upstream pull requests and for [Fedora package update gating](https://docs.fedoraproject.org/en-US/ci/), the tests are wrapped in the [FMF metadata format](https://github.com/teemtee/fmf) for using with the [tmt test management tool](https://docs.fedoraproject.org/en-US/ci/tmt/). -Note that Packit tests can *not* run their own virtual machine images, thus +Note that Packit tests can _not_ run their own virtual machine images, thus they only run [@nondestructive tests](https://github.com/cockpit-project/cockpit/blob/main/test/common/testlib.py). # Customizing @@ -201,7 +229,7 @@ which is run weekly or upon [manual request](https://github.com/cockpit-project/ # Further reading - * The [Starter Kit announcement](https://cockpit-project.org/blog/cockpit-starter-kit.html) - blog post explains the rationale for this project. - * [Cockpit Deployment and Developer documentation](https://cockpit-project.org/guide/latest/) - * [Make your project easily discoverable](https://cockpit-project.org/blog/making-a-cockpit-application.html) +- The [Starter Kit announcement](https://cockpit-project.org/blog/cockpit-starter-kit.html) + blog post explains the rationale for this project. +- [Cockpit Deployment and Developer documentation](https://cockpit-project.org/guide/latest/) +- [Make your project easily discoverable](https://cockpit-project.org/blog/making-a-cockpit-application.html) diff --git a/org.cockpit-project.sensors.metainfo.xml b/org.cockpit-project.sensors.metainfo.xml new file mode 100644 index 0000000..2ee46d8 --- /dev/null +++ b/org.cockpit-project.sensors.metainfo.xml @@ -0,0 +1,17 @@ + + + org.cockpit_project.sensors + CC0-1.0 + Sensors + Sensors cockpit module + +

+ Sensors cockpit module +

+
+ org.cockpit_project.cockpit + sensors + https://github.com/ocristopfer/cockpit-sensors + https://github.com/ocristopfer/cockpit-sensors/issues + cockpit-devel_AT_lists.fedorahosted.org +
diff --git a/org.cockpit-project.starter-kit.metainfo.xml b/org.cockpit-project.starter-kit.metainfo.xml deleted file mode 100644 index 8e19746..0000000 --- a/org.cockpit-project.starter-kit.metainfo.xml +++ /dev/null @@ -1,17 +0,0 @@ - - - org.cockpit_project.starter_kit - CC0-1.0 - Starter Kit - Scaffolding for a cockpit module - -

- Scaffolding for a cockpit module. -

-
- org.cockpit_project.cockpit - starter-kit - https://github.com/cockpit-project/starter-kit - https://github.com/cockpit-project/starter-kit/issues - cockpit-devel_AT_lists.fedorahosted.org -
diff --git a/package.json b/package.json index aff54f5..3d55232 100644 --- a/package.json +++ b/package.json @@ -1,10 +1,10 @@ { - "name": "starter-kit", - "description": "Scaffolding for a cockpit module", + "name": "sensors", + "description": "Module that displays all data reported by lm-sensors", "type": "module", "main": "index.js", - "repository": "git@github.com:cockpit/starter-kit.git", - "author": "", + "repository": "git@github.com:ocristopfer/cockpit-sensors.git", + "author": "https://github.com/ocristopfer", "license": "LGPL-2.1", "engines": { "node": ">= 16" diff --git a/packaging/cockpit-sensors.control b/packaging/cockpit-sensors.control new file mode 100644 index 0000000..5fcda75 --- /dev/null +++ b/packaging/cockpit-sensors.control @@ -0,0 +1,10 @@ +Package: cockpit-sensors +Name: Cockpit Sensors +Description: Cockpit Sensors Module that displays all data reported by lm-sensors. +Author: ocristopfer +Maintainer: ocristopfer +Version: 1.4.2 +Depends: lm-sensors +Architecture: all +Homepage: https://github.com/ocristopfer/cockpit-sensors +Website: https://github.com/ocristopfer/cockpit-sensors \ No newline at end of file diff --git a/packaging/cockpit-starter-kit.spec.in b/packaging/cockpit-sensors.spec.in similarity index 92% rename from packaging/cockpit-starter-kit.spec.in rename to packaging/cockpit-sensors.spec.in index c6b43a3..64d959a 100644 --- a/packaging/cockpit-starter-kit.spec.in +++ b/packaging/cockpit-sensors.spec.in @@ -1,7 +1,7 @@ -Name: cockpit-starter-kit +Name: cockpit-sensors Version: %{VERSION} Release: 1%{?dist} -Summary: Cockpit Starter Kit Example Module +Summary: Cockpit Sensors Module License: LGPL-2.1-or-later Source0: https://github.com/cockpit-project/starter-kit/releases/download/%{version}/%{name}-%{version}.tar.xz @@ -21,7 +21,7 @@ Requires: cockpit-bridge %{NPM_PROVIDES} %description -Cockpit Starter Kit Example Module +Cockpit Sensors Module %prep %autosetup -n %{name} -a 1 diff --git a/packit.yaml b/packit.yaml index 6258a2e..d57c8d5 100644 --- a/packit.yaml +++ b/packit.yaml @@ -2,7 +2,7 @@ # To use this, enable Packit-as-a-service in GitHub: https://packit.dev/docs/packit-as-a-service/ # See https://packit.dev/docs/configuration/ for the format of this file -specfile_path: cockpit-starter-kit.spec +specfile_path: cockpit-sensors.spec # use the nicely formatted release description from our upstream release, instead of git shortlog copy_upstream_release_description: true @@ -12,24 +12,24 @@ srpm_build_deps: actions: post-upstream-clone: - - make cockpit-starter-kit.spec + - make cockpit-sensors.spec # replace Source1 manually, as create-archive: can't handle multiple tarballs - make node-cache - sh -c 'sed -i "/^Source1:/ s/https:.*/$(ls *-node*.tar.xz)/" cockpit-*.spec' create-archive: make dist - # starter-kit.git has no release tags; your project can drop this once you have a release + # sensors.git has no release tags; your project can drop this once you have a release get-current-version: make print-version jobs: - job: copr_build trigger: pull_request targets: - - fedora-all - - fedora-latest-aarch64 - - centos-stream-8 - - centos-stream-9 - - centos-stream-9-aarch64 - + - fedora-all + - fedora-latest-aarch64 + - centos-stream-8 + - centos-stream-9 + - centos-stream-9-aarch64 + - job: tests trigger: pull_request targets: diff --git a/po/de.po b/po/de.po index 0394e91..17b3f1a 100644 --- a/po/de.po +++ b/po/de.po @@ -1,8 +1,8 @@ -# starter-kit German translations +# sensors German translations #, fuzzy msgid "" msgstr "" -"Project-Id-Version: starter-kit 1.0\n" +"Project-Id-Version: sensors 1.0\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2022-03-09 16:09+0100\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" @@ -15,25 +15,39 @@ msgstr "" "Plural-Forms: nplurals=2; plural=n != 1\n" #: src/index.html:20 -msgid "Cockpit Starter Kit" -msgstr "Cockpit Bausatz" +msgid "Cockpit Sensors" +msgstr "Cockpit Sensoren" -#: src/app.jsx:43 -msgid "Running on $0" -msgstr "Läuft auf $0" +#: src/manifest.json:8 +#: org.cockpit-project.sensors.metainfo.xml:5 +#: src/app.jsx:162 +msgid "Sensors" +msgstr "Sensoren" -#: org.cockpit-project.starter-kit.metainfo.xml:6 -msgid "Scaffolding for a cockpit module" -msgstr "Gerüst für ein Cockpit-Modul" +#: org.cockpit-project.sensors.metainfo.xml:8 +msgid "Sensors cockpit module" +msgstr "Sensoren Cockpit Modul" -#: org.cockpit-project.starter-kit.metainfo.xml:8 -msgid "Scaffolding for a cockpit module." -msgstr "Gerüst für ein Cockpit-Modul." +#: src/app.jsx:86 +msgid "lm-sensors not found, you want install it ?" +msgstr "lm-sensors nicht gefunden, möchten Sie es installieren?" -#: src/manifest.json:0 org.cockpit-project.starter-kit.metainfo.xml:5 -msgid "Starter Kit" -msgstr "Bausatz" +#: src/app.jsx:95 +msgid "this version of lm-sensors don't suport output sensors data!" +msgstr "diese Version von lm-sensors unterstützt keine Ausgabe von Sensordaten!" -#: src/app.jsx:29 -msgid "Unknown" -msgstr "Unbekannt" +#: src/app.jsx:130 +msgid "lm-sensors has a bug that converts all data to fahrenheit, including voltage, fans and etc." +msgstr "lm-sensors hat einen Fehler, der alle Daten in Fahrenheit umwandelt, einschließlich Spannung, Lüfter usw." + +#: src/app.jsx:200 +msgid "Show temperature in Fahrenheit" +msgstr "Temperatur in Fahrenheit anzeigen" + +#: src/app.jsx:206 +msgid "Expand all cards" +msgstr "Erweitern Sie alle Karten" + +#: src/app.jsx:174 +msgid "Install" +msgstr "Installieren" \ No newline at end of file diff --git a/po/pt_BR.po b/po/pt_BR.po new file mode 100644 index 0000000..a4ff64e --- /dev/null +++ b/po/pt_BR.po @@ -0,0 +1,53 @@ +# sensors Portugues translations +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: sensors 1.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2022-03-09 16:09+0100\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: Cristopfer Luis \n" +"Language-Team: LANGUAGE \n" +"Language: pt_BR\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=n != 1\n" + +#: src/index.html:20 +msgid "Cockpit Sensors" +msgstr "Sensores para Cockpit" + +#: src/manifest.json:8 +#: org.cockpit-project.sensors.metainfo.xml:5 +#: src/app.jsx:162 +msgid "Sensors" +msgstr "Sensores" + +#: org.cockpit-project.sensors.metainfo.xml:8 +msgid "Sensors cockpit module" +msgstr "Sensores do lm-sensors para o cockpit" + +#: src/app.jsx:86 +msgid "lm-sensors not found, you want install it ?" +msgstr "Não foi encontrado o lm-sensors, deseja instala-lo?" + +#: src/app.jsx:95 +msgid "this version of lm-sensors don't suport output sensors data!" +msgstr "Essa versão do lm-sensors não tem suporte para saida de dados!" + +#: src/app.jsx:130 +msgid "lm-sensors has a bug that converts all data to fahrenheit, including voltage, fans and etc." +msgstr "lm-sensors tem um problema aonde ele converte todos os dados para fahrenheit, incluindo voltage, vetoinhas e etc." + +#: src/app.jsx:200 +msgid "Show temperature in Fahrenheit" +msgstr "Exibir temperatus em Fahrenheit" + +#: src/app.jsx:206 +msgid "Expand all cards" +msgstr "Expandir todos os cards" + +#: src/app.jsx:174 +msgid "Install" +msgstr "Instalar" \ No newline at end of file diff --git a/src/app.jsx b/src/app.jsx index 6d2e4e2..fa79b26 100644 --- a/src/app.jsx +++ b/src/app.jsx @@ -19,32 +19,289 @@ import cockpit from 'cockpit'; import React from 'react'; -import { Alert } from "@patternfly/react-core/dist/esm/components/Alert/index.js"; -import { Card, CardBody, CardTitle } from "@patternfly/react-core/dist/esm/components/Card/index.js"; +import { Alert, Card, CardTitle, CardHeader, CardBody, CardExpandableContent, Checkbox, Button, Spinner, Flex, FlexItem } from '@patternfly/react-core'; +import { FanIcon, ThermometerHalfIcon, ChargingStationIcon, CpuIcon } from '@patternfly/react-icons/dist/esm/icons/'; const _ = cockpit.gettext; export class Application extends React.Component { constructor() { super(); - this.state = { hostname: _("Unknown") }; + this.state = { sensors: {}, intervalId: {}, alert: null, fahrenheitTemp: [], fahrenheitChecked: false, isShowBtnInstall: false, sensorArgumet: "-j", isShowLoading: false, isExpanded: {}, expandAllCards: false, isError: false, hidedCards: [] }; + } - cockpit.file('/etc/hostname').watch(content => { - this.setState({ hostname: content.trim() }); + componentDidMount() { + const intervalId = setInterval(() => { + if (!this.state.isShowBtnInstall && !this.state.isError) + this.loadSensors(); + }, 1000); + this.setState({ intervalId }); + } + + componentWillUnmount() { + clearInterval(this.state.intervalId); + } + + loadSensors = () => { + cockpit + .spawn(["sensors", this.state.sensorArgumet], { err: "message", superuser: "try" }) + .done((sucess) => { + if (this.state.sensorArgumet === "-j") { + this.setState({ sensors: JSON.parse(sucess), isShowBtnInstall: false }); + } else { + const sensorsJson = {}; + sucess.split(/\n\s*\n/).forEach(raw => { + let sensorsGroupName = ""; + let index = 0; + let sensorTitle = ""; + raw.split(/\n\s*/).forEach(element => { + if (index === 0) { + sensorsGroupName = element; + sensorsJson[sensorsGroupName] = {}; + } + if (index === 1) { + const adapter = element.split(":"); + sensorsJson[sensorsGroupName][adapter[0]] = adapter[1].trim(); + } + if (index >= 2) { + const sensor = element.trim().split(":"); + if (sensor[1] === "") { + sensorTitle = element.split(":")[0]; + sensorsJson[sensorsGroupName][sensorTitle] = {}; + } else { + sensorsJson[sensorsGroupName][sensorTitle][sensor[0]] = parseFloat(sensor[1].trim()); + } + } + + index += 1; + }); + }); + this.setState({ sensors: sensorsJson, isShowBtnInstall: false }); + } + }) + .fail((err) => { + if (err.message === "not-found") { + this.setState({ isShowBtnInstall: true }); + this.setAlert(_('lm-sensors not found, you want install it ?'), 'danger'); + this.getLmSensorsInstallCmd(0); + return; + } + if (err.message === "sensors: invalid option -- 'j'") { + this.setState({ sensorArgumet: "-u" }); + return; + } + + if (err.message === "sensors: invalid option -- 'u'") { + this.setAlert(_("this version of lm-sensors don't suport output sensors data!"), 'danger'); + this.setState({ isError: true }); + return; + } + this.setAlert(err.message, 'warning'); + clearInterval(this.state.intervalId); + }); + }; + + setIcon = (name) => { + if (typeof name !== 'undefined') { + if (name.includes('fan')) { + return ; + } + if (name.includes('temp')) { + return ; + } + if (name.includes('in')) { + return ; + } + if (name.includes('cpu')) { + return ; + } + } + return <>; + }; + + adjustLabel = (label) => { + return label.replace(label.substring(0, label.indexOf('_')) + '_', ''); + }; + + setAlert = (msg, variant) => { + this.setState({ alert: { msg, variant } }); + }; + + handleChange = (checked, event) => { + this.setState({ fahrenheitChecked: checked }); + if (checked) { + // this.setAlert(_('lm-sensors has a bug that converts all data to fahrenheit, including voltage, fans and etc.'), 'info'); + this.setState({ fahrenheitTemp: ['-f'] }); + } else { + this.setState({ fahrenheitTemp: [], alert: null }); + } + }; + + handleChangeCards = (checked, event) => { + const isExpanded = this.state.isExpanded; + Object.keys(isExpanded).forEach((element) => { + isExpanded[element] = checked; }); + console.log(this.state.isExpanded, isExpanded); + this.setState({ isExpanded, expandAllCards: checked }); + }; + + lstPacktsManager = ["apk", "apt-get", "dnf", "zypper"]; + installCmd = null; + getLmSensorsInstallCmd = async (index) => { + const cmd = this.lstPacktsManager[index]; + await cockpit.spawn([cmd, "-v"]) + .then((sucesso) => { + switch (cmd) { + case "apk": + this.installCmd = [cmd, "add", "--no-cache", "lm-sensors", "-y"]; + break; + case "dnf": + this.installCmd = [cmd, "install", "lm_sensors", "-y"]; + break; + case "zypper": + this.installCmd = [cmd, "install", "-y", "sensors"]; + break; + case "apt-get": + default: + this.installCmd = [cmd, "install", "lm-sensors", "-y"]; + } + }) + .fail((e) => { + this.getLmSensorsInstallCmd(index + 1); + }); + }; + + handleInstallSensors = async () => { + this.setState({ isShowLoading: true }); + cockpit.spawn(this.installCmd, { err: "message", superuser: "require" }) + .done((sucess) => { + console.log('instalou ?'); + this.setState({ isShowLoading: false, isShowBtnInstall: false, alert: null }); + cockpit.spawn(["sensors-detect", "--auto"], { err: "message", superuser: "require" }) + .done((sucess) => { + cockpit.spawn(["modprobe", "coretemp"], { err: "message", superuser: "require" }); + cockpit.spawn(["modprobe", "i2c-i801"], { err: "message", superuser: "require" }); + cockpit.spawn(["modprobe", "drivetemp"], { err: "message", superuser: "require" }); + }) + .fail((err) => { + this.setAlert(err.message, 'warning'); + }); + }) + .fail((err) => { + console.log('erro ?'); + this.setState({ isShowLoading: false, isShowBtnInstall: false }); + this.setAlert(err.message, 'warning'); + }); + }; + + adjustValue = (name, value) => { + if (typeof name !== 'undefined') { + if (name.includes('temp')) { + return this.state.fahrenheitChecked + ? parseFloat((value * 9 / 5) + 32).toFixed(1) + .toString() + .concat(' °F') + : parseFloat(value).toFixed(1) + .toString() + .concat(' °C'); + } + + if (name.includes('fan')) { + return value.toString().concat(' RPM'); + } + } + return value; + }; + + handleOnExpand = (event, id) => { + // eslint-disable-next-line no-console + + const isExpanded = this.state.isExpanded; + isExpanded[id] = !isExpanded[id]; + console.log(id, this.state.isExpanded, isExpanded); + this.setState({ isExpanded }); + }; + + hideCard(cardId) { + const hidedCards = this.state.hidedCards.push(cardId); + console.log(cardId, hidedCards); + this.setState({ hidedCards }); } render() { + const { sensors, alert, fahrenheitChecked, isShowBtnInstall, isShowLoading, isExpanded, expandAllCards } = this.state; return ( - - Starter Kit - - - - + <> + + {_('Sensors')} + + + + <> + {isShowLoading ? : <>} + {alert != null ? {alert.msg} : <>} + {isShowBtnInstall ? : <>} + + {sensors !== null + ? Object.entries(sensors).map((key, keyIndex) => + + {key[0]} + + {key[1].Adapter} + + {Object.entries(key[1]).map((item, itemIndex) => { + if (itemIndex === 0) return ""; + const chave = keyIndex.toString() + itemIndex.toString(); + if (isExpanded[chave] === undefined) { + isExpanded[chave] = false; + } + return ( + + + this.handleOnExpand(e, chave)} + toggleButtonProps={{ + id: 'toggle-button2', + 'aria-label': 'Patternfly Details', + 'aria-expanded': isExpanded[chave] + }} + >{item[0]} + + {this.setIcon(Object.keys(item[1])[0])} {this.adjustValue(Object.keys(item[1])[0], Object.values(item[1])[0])} + + + + {Object.entries(item[1]).map((sensors, index) => ( + {this.adjustLabel(sensors[0])}: {sensors[1]}
+ ))} +
+
+
+
+ ); + })} +
+
+
+ ) + : ''} +
+
+ ); } } diff --git a/test/browser/main.fmf b/test/browser/main.fmf index d2dddd6..8758f93 100644 --- a/test/browser/main.fmf +++ b/test/browser/main.fmf @@ -1,7 +1,7 @@ summary: Run browser integration tests on the host require: - - cockpit-starter-kit + - cockpit-sensors - cockpit-ws - cockpit-system - bzip2 diff --git a/test/check-application b/test/check-application index 4725aad..e3998c4 100755 --- a/test/check-application +++ b/test/check-application @@ -16,7 +16,7 @@ class TestApplication(testlib.MachineCase): b = self.browser m = self.machine - self.login_and_go("/starter-kit") + self.login_and_go("/sensors") # verify expected heading b.wait_text(".pf-v5-c-card__title", "Starter Kit") @@ -39,12 +39,12 @@ class TestApplication(testlib.MachineCase): b.click("#display-language-modal button.pf-m-primary") b.wait_visible("#content") # menu label (from manifest) should be translated - b.wait_text("#host-apps a[href='/starter-kit']", "Bausatz") + b.wait_text("#host-apps a[href='/sensors']", "Bausatz") # window title should be translated; this is not considered as "visible" self.assertIn("Bausatz", b.call_js_func("ph_text", "head title")) - b.go("/starter-kit") - b.enter_page("/starter-kit") + b.go("/sensors") + b.enter_page("/sensors") # page label (from js) should be translated b.wait_in_text(".pf-v5-c-alert__title", "Läuft auf")