Skip to content

Commit 965b503

Browse files
Adapt UI to the new API (step 1) (#2848)
First steps adapting the UI to use the new HTTP API. The goal is to define where to place everything, to adapt the code according the new API types, and to adapt the hooks according to the new API. There are many things still using the old API (e.g., users, software, hostname, etc). They will be adapted later once the new API is ready for them. Meaningful changes: * *api.ts*: contains all the calls to the http API. * */api*: contains the types provides by the API. * */hooks/api.ts*: contains all the hooks/queries to directly interact with the API. * */hooks/[scope]*: contains hooks for a concrete scope (e.g., storage). These hooks do not introduce new queries but use *select* over an API query. * */helpers*: contains helpers for the types of the API. Special remarks: * The UI code should directly use the types provided by the API. Defining own types should be done as last resort. * Tests are not fixed yet. It will be done little by little while fixing each page. * All pages must be revisited, checked and fixed.
2 parents 4768c4c + 34d2456 commit 965b503

File tree

172 files changed

+1844
-2750
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

172 files changed

+1844
-2750
lines changed

rust/Cargo.lock

Lines changed: 17 additions & 12 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

rust/agama-manager/src/message.rs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,3 +141,18 @@ impl SetStorageModel {
141141
impl Message for SetStorageModel {
142142
type Reply = ();
143143
}
144+
145+
#[derive(Clone)]
146+
pub struct SolveStorageModel {
147+
pub model: Value,
148+
}
149+
150+
impl SolveStorageModel {
151+
pub fn new(model: Value) -> Self {
152+
Self { model }
153+
}
154+
}
155+
156+
impl Message for SolveStorageModel {
157+
type Reply = Option<Value>;
158+
}

rust/agama-manager/src/service.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -449,6 +449,20 @@ impl MessageHandler<message::SetStorageModel> for Service {
449449
}
450450
}
451451

452+
#[async_trait]
453+
impl MessageHandler<message::SolveStorageModel> for Service {
454+
/// It solves the storage model.
455+
async fn handle(
456+
&mut self,
457+
message: message::SolveStorageModel,
458+
) -> Result<Option<Value>, Error> {
459+
Ok(self
460+
.storage
461+
.call(storage::message::SolveConfigModel::new(message.model))
462+
.await?)
463+
}
464+
}
465+
452466
// FIXME: write a macro to forward a message.
453467
#[async_trait]
454468
impl MessageHandler<software::message::SetResolvables> for Service {

rust/agama-server/src/server/web.rs

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,14 +27,14 @@ use agama_software::Resolvable;
2727
use agama_utils::{
2828
actor::Handler,
2929
api::{
30-
event,
30+
event, query,
3131
question::{Question, QuestionSpec, UpdateQuestion},
3232
Action, Config, IssueMap, Patch, Status, SystemInfo,
3333
},
3434
question,
3535
};
3636
use axum::{
37-
extract::{Path, State},
37+
extract::{Path, Query, State},
3838
response::{IntoResponse, Response},
3939
routing::{get, post, put},
4040
Json, Router,
@@ -110,11 +110,11 @@ pub async fn server_service(
110110
"/private/storage_model",
111111
get(get_storage_model).put(set_storage_model),
112112
)
113+
.route("/private/solve_storage_model", get(solve_storage_model))
113114
.route("/private/resolvables/:id", put(set_resolvables))
114115
.with_state(state))
115116
}
116117

117-
/// Returns the status of the installation.
118118
#[utoipa::path(
119119
get,
120120
path = "/status",
@@ -380,6 +380,28 @@ async fn set_storage_model(
380380
Ok(())
381381
}
382382

383+
/// Solves a storage config model.
384+
#[utoipa::path(
385+
get,
386+
path = "/private/solve_storage_model",
387+
context_path = "/api/v2",
388+
params(query::SolveStorageModel),
389+
responses(
390+
(status = 200, description = "Solve the storage model", body = String),
391+
(status = 400, description = "Not possible to solve the storage model")
392+
)
393+
)]
394+
async fn solve_storage_model(
395+
State(state): State<ServerState>,
396+
Query(params): Query<query::SolveStorageModel>,
397+
) -> Result<Json<Option<Value>>, Error> {
398+
let solved_model = state
399+
.manager
400+
.call(message::SolveStorageModel::new(params.model))
401+
.await?;
402+
Ok(Json(solved_model))
403+
}
404+
383405
#[utoipa::path(
384406
put,
385407
path = "/resolvables/:id",

rust/agama-server/src/web/docs/config.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,7 @@ impl ApiDocBuilder for ConfigApiDocBuilder {
175175
.schema_from::<agama_utils::api::question::UpdateQuestion>()
176176
.schema_from::<agama_utils::api::software::RepositoryConfig>()
177177
.schema_from::<agama_utils::api::status::State>()
178+
.schema_from::<agama_utils::api::query::SolveStorageModel>()
178179
.build()
179180
}
180181
}

rust/agama-utils/src/api.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ pub use action::Action;
5454
pub mod l10n;
5555
pub mod manager;
5656
pub mod network;
57+
pub mod query;
5758
pub mod question;
5859
pub mod software;
5960
pub mod storage;

rust/agama-utils/src/api/query.rs

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
// Copyright (c) [2025] SUSE LLC
2+
//
3+
// All Rights Reserved.
4+
//
5+
// This program is free software; you can redistribute it and/or modify it
6+
// under the terms of the GNU General Public License as published by the Free
7+
// Software Foundation; either version 2 of the License, or (at your option)
8+
// any later version.
9+
//
10+
// This program is distributed in the hope that it will be useful, but WITHOUT
11+
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12+
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
13+
// more details.
14+
//
15+
// You should have received a copy of the GNU General Public License along
16+
// with this program; if not, contact SUSE LLC.
17+
//
18+
// To contact SUSE LLC about this file by physical or electronic mail, you may
19+
// find current contact information at www.suse.com.
20+
21+
use serde::Deserialize;
22+
use serde_json::Value;
23+
24+
#[derive(Deserialize, utoipa::IntoParams, utoipa::ToSchema)]
25+
pub struct SolveStorageModel {
26+
/// Serialized storage model.
27+
pub model: Value,
28+
}

rust/share/device.storage.schema.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"$schema": "https://json-schema.org/draft/2019-09/schema",
33
"$id": "https://github.com/openSUSE/agama/blob/master/rust/share/device.storage.schema.json",
4-
"title": "Storage device",
4+
"title": "Device",
55
"description": "Schema to describe a device both in 'system' and 'proposal'.",
66
"type": "object",
77
"additionalProperties": false,

rust/share/system.storage.schema.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@
5555
"encryptionMethod": {
5656
"title": "Encryption method",
5757
"enum": [
58-
"luks1", "luks2", "pervasiveLuks2", "tmpFde", "protectedSwap", "secureSwap", "randomSwap"
58+
"luks1", "luks2", "pervasiveLuks2", "tpmFde", "protectedSwap", "secureSwap", "randomSwap"
5959
]
6060
},
6161
"volume": {

web/src/App.tsx

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -24,11 +24,8 @@ import React, { useEffect } from "react";
2424
import { Navigate, Outlet, useLocation } from "react-router";
2525
import { Loading } from "~/components/layout";
2626
import { useProduct, useProductChanges } from "~/queries/software";
27-
import { useProposalChanges } from "~/queries/proposal";
28-
import { useSystemChanges } from "~/queries/system";
29-
import { useIssuesChanges } from "~/queries/issues";
27+
import { useSystemChanges, useProposalChanges, useIssuesChanges } from "~/hooks/api";
3028
import { useInstallerStatus, useInstallerStatusChanges } from "~/queries/status";
31-
import { useDeprecatedChanges } from "~/queries/storage";
3229
import { ROOT, PRODUCT } from "~/routes/paths";
3330
import { InstallationPhase } from "~/types/status";
3431
import { useQueryClient } from "@tanstack/react-query";
@@ -43,7 +40,6 @@ function App() {
4340
useProductChanges();
4441
useIssuesChanges();
4542
useInstallerStatusChanges();
46-
useDeprecatedChanges();
4743

4844
const location = useLocation();
4945
const { isBusy, phase } = useInstallerStatus({ suspense: true });

0 commit comments

Comments
 (0)