fix ui
All checks were successful
checks-impure / test (pull_request) Successful in 1m30s
checks / test (pull_request) Successful in 2m24s

This commit is contained in:
Johannes Kirschbauer 2023-11-17 11:42:20 +01:00
parent 43dbdf20d4
commit f419ff842a
Signed by: hsjobeki
SSH Key Fingerprint: SHA256:vX3utDqig7Ph5L0JPv87ZTPb/w7cMzREKVZzzLFg9qU
11 changed files with 116 additions and 91 deletions

View File

@ -8,7 +8,7 @@
{
packages = {
# disabled because frontend is broken after cli refactoring
# ui = base.pkg.global;
ui = base.pkg.global;
ui-assets = pkgs.callPackage ./nix/ui-assets.nix { };
# EXAMPLE: GITEA_TOKEN=$(rbw get -f GITEA_TOKEN git.clan.lol) nix run .#update-ui-assets
update-ui-assets = pkgs.callPackage ./nix/update-ui-assets.nix { };

View File

@ -77,18 +77,18 @@ export default function RootLayout({
show={showSidebarDerived}
onClose={() => setShowSidebar(false)}
clanSelect={
appState.data.clanName && (
appState.data.clanDir && (
<Select
color="secondary"
label="clan"
fullWidth
variant="standard"
disableUnderline
value={appState.data.clanName}
value={appState.data.clanDir}
onChange={(ev) => {
appState.setAppState((c) => ({
...c,
clanName: ev.target.value,
clanDir: ev.target.value,
}));
}}
>

View File

@ -4,12 +4,13 @@ import { MachineContextProvider } from "@/components/hooks/useMachines";
export default function Layout({ children }: { children: React.ReactNode }) {
const {
data: { clanName },
data: { clanDir },
} = useAppState();
return (
<>
{clanName && (
<MachineContextProvider flakeName={clanName}>
{!clanDir && <div>No clan selected</div>}
{clanDir && (
<MachineContextProvider flakeName={clanDir}>
{children}
</MachineContextProvider>
)}

View File

@ -1,5 +1,7 @@
import { getMachineSchema } from "@/api/machine/machine";
import { HTTPValidationError } from "@/api/model";
import { useListClanModules } from "@/api/modules/modules";
import { clanErrorToast } from "@/error/errorToast";
import {
Alert,
AlertTitle,
@ -15,6 +17,7 @@ import InputLabel from "@mui/material/InputLabel";
import MenuItem from "@mui/material/MenuItem";
import OutlinedInput from "@mui/material/OutlinedInput";
import Select, { SelectChangeEvent } from "@mui/material/Select";
import { AxiosError } from "axios";
import { useEffect, useState } from "react";
import { Controller } from "react-hook-form";
import { toast } from "react-hot-toast";
@ -31,40 +34,6 @@ const MenuProps = {
},
};
// interface IupdateSchema {
// clanName: string;
// modules: string[];
// formHooks: FormHooks;
// setSchemaError: Dispatch<SetStateAction<null | string>>;
// }
// const updateSchema = ({
// clanName,
// modules,
// formHooks,
// setSchemaError,
// }: IupdateSchema) => {
// formHooks.setValue("isSchemaLoading", true);
// getMachineSchema(clanName, {
// clanImports: modules,
// })
// .then((response) => {
// if (response.statusText == "OK") {
// formHooks.setValue("schema", response.data.schema);
// setSchemaError(null);
// }
// })
// .catch((error) => {
// formHooks.setValue("schema", {});
// console.error({ error });
// setSchemaError(error.message);
// toast.error(`${error.message}`);
// })
// .finally(() => {
// formHooks.setValue("isSchemaLoading", false);
// });
// };
type ClanModulesProps = FormStepContentProps;
const SchemaSuccessMsg = () => (
@ -93,22 +62,34 @@ const SchemaErrorMsg = (props: SchemaErrorMsgProps) => (
);
export default function ClanModules(props: ClanModulesProps) {
const { clanName, formHooks } = props;
const { data, isLoading } = useListClanModules(clanName);
const { clanDir, formHooks } = props;
const { data, isLoading } = useListClanModules({ flake_dir: clanDir });
const [schemaError] = useState<string | null>(null);
const selectedModules = formHooks.watch("modules");
useEffect(() => {
getMachineSchema(clanName, {
clanImports: [],
}).then((response) => {
if (response.statusText == "OK") {
formHooks.setValue("schema", response.data.schema);
}
});
const load = async () => {
try {
const response = await getMachineSchema(
{
clanImports: [],
},
{
flake_dir: clanDir,
},
);
// Only re-run if global clanName has changed
if (response.statusText == "OK") {
formHooks.setValue("schema", response.data.schema);
}
} catch (e) {
clanErrorToast(e as AxiosError<HTTPValidationError>);
}
};
load();
// Only re-run if global clanDir has changed
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [clanName]);
}, [clanDir]);
const isSchemaLoading = formHooks.watch("isSchemaLoading");
const handleChange = (
@ -119,9 +100,14 @@ export default function ClanModules(props: ClanModulesProps) {
} = event;
const newValue = typeof value === "string" ? value.split(",") : value;
formHooks.setValue("modules", newValue);
getMachineSchema(clanName, {
clanImports: newValue,
})
getMachineSchema(
{
clanImports: newValue,
},
{
flake_dir: clanDir,
},
)
.then((response) => {
if (response.statusText == "OK") {
formHooks.setValue("schema", response.data.schema);

View File

@ -29,7 +29,7 @@ interface PureCustomConfigProps extends FormStepContentProps {
initialValues: any;
}
export function CustomConfig(props: FormStepContentProps) {
const { formHooks, clanName } = props;
const { formHooks, clanDir } = props;
const schema = formHooks.watch("schema");
const initialValues = useMemo(
@ -49,7 +49,7 @@ export function CustomConfig(props: FormStepContentProps) {
return (
<PureCustomConfig
clanName={clanName}
clanDir={clanDir}
formHooks={formHooks}
initialValues={initialValues}
/>

View File

@ -1,4 +1,4 @@
import { putMachine } from "@/api/machine/machine";
import { setMachineConfig } from "@/api/machine/machine";
import {
Box,
Button,
@ -21,7 +21,7 @@ import { CreateMachineForm, FormStep } from "./interfaces";
export function CreateMachineForm() {
const {
data: { clanName },
data: { clanDir },
} = useAppState();
const formHooks = useForm<CreateMachineForm>({
defaultValues: {
@ -41,8 +41,8 @@ export function CreateMachineForm() {
{
id: "modules",
label: "Modules",
content: clanName ? (
<ClanModules clanName={clanName} formHooks={formHooks} />
content: clanDir ? (
<ClanModules clanDir={clanDir} formHooks={formHooks} />
) : (
<LinearProgress />
),
@ -50,8 +50,8 @@ export function CreateMachineForm() {
{
id: "config",
label: "Customize",
content: clanName ? (
<CustomConfig formHooks={formHooks} clanName={clanName} />
content: clanDir ? (
<CustomConfig formHooks={formHooks} clanDir={clanDir} />
) : (
<LinearProgress />
),
@ -74,15 +74,21 @@ export function CreateMachineForm() {
async function onSubmit(data: CreateMachineForm) {
console.log({ data }, "Aggregated Data; creating machine from");
if (clanName) {
if (clanDir) {
if (!data.name) {
toast.error("Machine name should not be empty");
return;
}
await putMachine(clanName, data.name, {
clan: data.config.formData,
clanImports: data.modules,
});
await setMachineConfig(
data.name,
{
clan: data.config.formData,
clanImports: data.modules,
},
{
flake_dir: clanDir,
},
);
}
}

View File

@ -22,7 +22,7 @@ export type FormStep = {
export interface FormStepContentProps {
formHooks: FormHooks;
clanName: string;
clanDir: string;
}
export type FormStepContent = ReactElement<FormStepContentProps>;

View File

@ -1,6 +1,6 @@
import { useListAllFlakes } from "@/api/flake/flake";
import { FlakeListResponse } from "@/api/model";
import { AxiosError, AxiosResponse } from "axios";
// import { useListAllFlakes } from "@/api/flake/flake";
// import { FlakeListResponse } from "@/api/model";
import { AxiosError } from "axios";
import React, {
Dispatch,
ReactNode,
@ -9,7 +9,6 @@ import React, {
useEffect,
useState,
} from "react";
import { KeyedMutator } from "swr";
type AppContextType = {
// data: AxiosResponse<{}, any> | undefined;
@ -19,7 +18,7 @@ type AppContextType = {
error: AxiosError<any> | undefined;
setAppState: Dispatch<SetStateAction<AppState>>;
mutate: KeyedMutator<AxiosResponse<FlakeListResponse, any>>;
// mutate: KeyedMutator<AxiosResponse<FlakeListResponse, any>>;
swrKey: string | false | Record<any, any>;
};
@ -27,28 +26,45 @@ export const AppContext = createContext<AppContextType>({} as AppContextType);
type AppState = {
isJoined?: boolean;
clanName?: string;
flakes?: FlakeListResponse["flakes"];
clanDir?: string;
flakes?: string[]; //FlakeListResponse["flakes"];
};
interface AppContextProviderProps {
children: ReactNode;
}
const mock = {
data: { flakes: [] },
};
// list_clans
export const WithAppState = (props: AppContextProviderProps) => {
const { children } = props;
// const {
// isLoading,
// error,
// swrKey,
// data: flakesResponse,
// mutate,
// } = useListAllFlakes({
// swr: {
// revalidateIfStale: false,
// revalidateOnFocus: false,
// revalidateOnReconnect: false,
// },
// });
const {
isLoading,
error,
swrKey,
data: flakesResponse,
mutate,
} = useListAllFlakes({
swr: {
revalidateIfStale: false,
revalidateOnFocus: false,
revalidateOnReconnect: false,
},
});
} = {
isLoading: false,
error: undefined,
swrKey: "",
data: mock,
};
const [data, setAppState] = useState<AppState>({ isJoined: false });
useEffect(() => {
@ -57,7 +73,7 @@ export const WithAppState = (props: AppContextProviderProps) => {
data: { flakes },
} = flakesResponse;
if (flakes.length >= 1) {
setAppState((c) => ({ ...c, clanName: flakes[0], isJoined: true }));
setAppState((c) => ({ ...c, clanDir: flakes[0], isJoined: true }));
}
setAppState((c) => ({ ...c, flakes }));
}
@ -71,7 +87,7 @@ export const WithAppState = (props: AppContextProviderProps) => {
isLoading,
error,
swrKey,
mutate,
// mutate,
}}
>
{children}

View File

@ -65,7 +65,7 @@ export const MachineContextProvider = (props: MachineContextProviderProps) => {
isValidating,
mutate,
swrKey,
} = useListMachines(flakeName);
} = useListMachines({ flake_dir: flakeName });
const [filters, setFilters] = useState<Filters>([]);
const data = useMemo(() => {

View File

@ -0,0 +1,12 @@
import { HTTPValidationError } from "@/api/model";
import { AxiosError } from "axios";
import { toast } from "react-hot-toast";
export function clanErrorToast(error: AxiosError<HTTPValidationError>) {
console.error({ error });
const detail = error.response?.data.detail?.[0]?.msg;
const cause = error.cause?.message;
const axiosMessage = error.message;
const sanitizedMsg = detail || cause || axiosMessage || "Unexpected error";
toast.error(sanitizedMsg);
}

View File

@ -100,10 +100,14 @@ export default function JoinPrequel() {
onSubmit={handleSubmit(async (values) => {
if (workflow === "create") {
try {
await createFlake({
flake_name: values.dest || "default",
url: values.flakeUrl,
});
await createFlake(
{
url: values.flakeUrl,
},
{
flake_dir: values.dest || "myclan",
},
);
setAppState((s) => ({ ...s, isJoined: true }));
} catch (error) {
toast.error(