diff --git a/service/lib/agama/dbus/software/manager.rb b/service/lib/agama/dbus/software/manager.rb index 67f1e5cbf7..552a46aa47 100644 --- a/service/lib/agama/dbus/software/manager.rb +++ b/service/lib/agama/dbus/software/manager.rb @@ -84,7 +84,7 @@ def initialize(backend, logger) end # value of result hash is category, description, icon, summary and order - dbus_method :ListPatterns, "in Filtered:b, out Result:a{s(ssssi)}" do |filtered| + dbus_method :ListPatterns, "in Filtered:b, out Result:a{s(sssss)}" do |filtered| [ backend.patterns(filtered).each_with_object({}) do |pattern, result| # make sure all attributes are already preloaded, adjust the "patterns" method @@ -94,7 +94,7 @@ def initialize(backend, logger) pattern.description, pattern.icon, pattern.summary, - pattern.order.to_i + pattern.order ] result[pattern.name] = value end diff --git a/service/lib/agama/software/manager.rb b/service/lib/agama/software/manager.rb index e1bcd916b8..1abf0d678f 100644 --- a/service/lib/agama/software/manager.rb +++ b/service/lib/agama/software/manager.rb @@ -123,6 +123,7 @@ def propose select_resolvables result = proposal.calculate logger.info "Proposal result: #{result.inspect}" + selected_patterns_changed result end diff --git a/service/package/rubygem-agama.changes b/service/package/rubygem-agama.changes index cec7cf3320..228e65ded2 100644 --- a/service/package/rubygem-agama.changes +++ b/service/package/rubygem-agama.changes @@ -1,3 +1,9 @@ +------------------------------------------------------------------- +Tue Oct 10 08:51:45 UTC 2023 - Ladislav Slezák + +- Extended Software service to allow configuring selected patterns + (gh#openSUSE/agama#792) + ------------------------------------------------------------------- Wed Oct 4 19:51:32 UTC 2023 - Josef Reidinger diff --git a/web/cspell.json b/web/cspell.json index 12cf6761e3..33f8c76794 100644 --- a/web/cspell.json +++ b/web/cspell.json @@ -19,31 +19,35 @@ "addrs", "ahci", "apsens", - "autologin", "autoconnect", + "autologin", "btrfs", "ccmp", "chzdev", "dasd", "dasds", + "devel", "dbus", "España", "filecontent", "filename", - "fullname", "freedesktop", + "fullname", "gettext", + "hicolor", "ibft", "ifaces", "ipaddr", "iscsi", "jdoe", + "libyui", "lldp", "localdomain", "luks", "mgmt", "mmcblk", "multipath", + "multiuser", "ngettext", "onboot", "partitioner", diff --git a/web/package.json b/web/package.json index 5315672010..9501d20bdb 100644 --- a/web/package.json +++ b/web/package.json @@ -12,7 +12,7 @@ "server": "webpack server --progress", "watch": "webpack --watch --progress", "build": "webpack", - "cspell": "cspell --no-progress --show-suggestions src", + "cspell": "cspell --no-progress --show-suggestions --exclude '*.svg' src", "eslint": "eslint --ext .js --ext .jsx src/", "eslint:fix": "eslint --fix --ext .js --ext .jsx src/", "stylelint": "stylelint 'src/**/*.{css,scss}'", diff --git a/web/package/cockpit-agama.changes b/web/package/cockpit-agama.changes index fab3862456..c25de33aed 100644 --- a/web/package/cockpit-agama.changes +++ b/web/package/cockpit-agama.changes @@ -1,3 +1,9 @@ +------------------------------------------------------------------- +Tue Oct 10 08:50:53 UTC 2023 - Ladislav Slezák + +- Added pattern selector to allow changing the installed software + (gh#openSUSE/agama#792) + ------------------------------------------------------------------- Mon Oct 9 11:30:27 UTC 2023 - Imobach Gonzalez Sosa diff --git a/web/src/assets/styles/app.scss b/web/src/assets/styles/app.scss index 96dc4ae0d5..8df5bcf579 100644 --- a/web/src/assets/styles/app.scss +++ b/web/src/assets/styles/app.scss @@ -109,3 +109,59 @@ button.kebab-toggler { margin-inline-end: 5px; } } + +.pattern-container { + display: grid; + grid-template-columns: 16px auto; + grid-template-rows: auto auto; + gap: 0.2em 1em; + grid-auto-flow: row; + grid-template-areas: + "checkbox label" + "empty summary"; + margin-bottom: 1em; + padding: 0.5em; + border-radius: 5px; +} + +.pattern-container:hover { + background-color: #eee; +} + +.pattern-label { + display: grid; + grid-template-columns: 32px auto; + grid-template-rows: auto; + gap: 0 1em; + grid-auto-flow: row; + grid-template-areas: "label-icon label-text"; + grid-area: label; +} + +.pattern-label-icon { + grid-area: label-icon; + align-self: center; +} + +.pattern-label-text { + grid-area: label-text; + font-size: 110%; + font-weight: bold; + justify-self: start; + align-self: center; +} + +.pattern-summary { + grid-area: summary; + color: #666; +} + +.pattern-checkbox { + grid-area: checkbox; + justify-self: center; + align-self: center; +} + +.pattern-group-name { + font-size: 120%; +} diff --git a/web/src/client/software.js b/web/src/client/software.js index cc6328eb23..5572033707 100644 --- a/web/src/client/software.js +++ b/web/src/client/software.js @@ -74,13 +74,61 @@ class SoftwareBaseClient { /** * Returns how much space installation takes on disk * - * @return {Promise>} + * @return {Promise} */ async getUsedSpace() { const proxy = await this.client.proxy(SOFTWARE_IFACE); return proxy.UsedDiskSpace(); } + /** + * Returns available patterns + * + * @param {boolean} filter - `true` = filter the patterns, `false` = all patterns + * @return {Promise>} + */ + async patterns(filter) { + const proxy = await this.client.proxy(SOFTWARE_IFACE); + return proxy.ListPatterns(filter); + } + + /** + * @typedef {Object.} PatternSelection mapping "name" => + * "who selected the pattern" + */ + + /** + * Returns selected patterns + * + * @return {Promise} + */ + async selectedPatterns() { + const proxy = await this.client.proxy(SOFTWARE_IFACE); + return proxy.SelectedPatterns; + } + + /** + * Select a pattern to install + * + * @param {string} name - name of the pattern + * @return {Promise} + */ + async addPattern(name) { + const proxy = await this.client.proxy(SOFTWARE_IFACE); + return proxy.AddPattern(name); + } + + /** + * Deselect a pattern to install + * + * @param {string} name - name of the pattern + * @return {Promise} + */ + async removePattern(name) { + const proxy = await this.client.proxy(SOFTWARE_IFACE); + return proxy.RemovePattern(name); + } + /** * Returns the selected product * diff --git a/web/src/components/overview/SoftwareSection.jsx b/web/src/components/overview/SoftwareSection.jsx index f8f93bc8fb..2dd432489b 100644 --- a/web/src/components/overview/SoftwareSection.jsx +++ b/web/src/components/overview/SoftwareSection.jsx @@ -21,8 +21,9 @@ import React, { useReducer, useEffect } from "react"; import { Button } from "@patternfly/react-core"; -import { Em, ProgressText, Section } from "~/components/core"; +import { ProgressText, Section } from "~/components/core"; import { Icon } from "~/components/layout"; +import { UsedSize } from "~/components/software"; import { useCancellablePromise } from "~/utils"; import { useInstallerClient } from "~/context/installer"; import { BUSY } from "~/client/status"; @@ -112,17 +113,6 @@ export default function SoftwareSection({ showErrors }) { const errors = showErrors ? state.errors : []; - const UsedSize = () => { - if (state.size === "" || state.size === "0 B") return null; - - // TRANSLATORS: %s will be replaced by the estimated installation size, - // example: "728.8 MiB" - const [msg1, msg2] = _("Installation will take %s").split("%s"); - return ( - <>{msg1}{state.size}{msg2} - ); - }; - const SectionContent = () => { if (state.busy) { const { message, current, total } = state.progress; @@ -133,7 +123,7 @@ export default function SoftwareSection({ showErrors }) { return ( <> - + {errors.length > 0 &&