ui(admin): fix egg variables
This commit is contained in:
parent
f7c824743f
commit
ce0bc477c2
12 changed files with 157 additions and 100 deletions
|
@ -55,8 +55,8 @@ class VariableCreationService
|
||||||
'description' => $data['description'] ?? '',
|
'description' => $data['description'] ?? '',
|
||||||
'env_variable' => $data['env_variable'] ?? '',
|
'env_variable' => $data['env_variable'] ?? '',
|
||||||
'default_value' => $data['default_value'] ?? '',
|
'default_value' => $data['default_value'] ?? '',
|
||||||
'user_viewable' => in_array('user_viewable', $options),
|
'user_viewable' => $data['user_viewable'],
|
||||||
'user_editable' => in_array('user_editable', $options),
|
'user_editable' => $data['user_editable'],
|
||||||
'rules' => $data['rules'] ?? '',
|
'rules' => $data['rules'] ?? '',
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
|
|
@ -2,6 +2,9 @@ import { Model, UUID, WithRelationships, withRelationships } from '@/api/admin/i
|
||||||
import { Nest } from '@/api/admin/nest';
|
import { Nest } from '@/api/admin/nest';
|
||||||
import http, { QueryBuilderParams, withQueryBuilderParams } from '@/api/http';
|
import http, { QueryBuilderParams, withQueryBuilderParams } from '@/api/http';
|
||||||
import { AdminTransformers } from '@/api/admin/transformers';
|
import { AdminTransformers } from '@/api/admin/transformers';
|
||||||
|
import { AxiosError } from 'axios';
|
||||||
|
import { useRouteMatch } from 'react-router-dom';
|
||||||
|
import useSWR, { SWRResponse } from 'swr';
|
||||||
|
|
||||||
export interface Egg extends Model {
|
export interface Egg extends Model {
|
||||||
id: number;
|
id: number;
|
||||||
|
@ -39,16 +42,22 @@ export interface EggVariable extends Model {
|
||||||
defaultValue: string;
|
defaultValue: string;
|
||||||
isUserViewable: boolean;
|
isUserViewable: boolean;
|
||||||
isUserEditable: boolean;
|
isUserEditable: boolean;
|
||||||
isRequired: boolean;
|
// isRequired: boolean;
|
||||||
rules: string;
|
rules: string;
|
||||||
createdAt: Date;
|
createdAt: Date;
|
||||||
updatedAt: Date;
|
updatedAt: Date;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A standard API response with the minimum viable details for the frontend
|
||||||
|
* to correctly render a egg.
|
||||||
|
*/
|
||||||
|
type LoadedEgg = WithRelationships<Egg, 'nest' | 'variables'>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets a single egg from the database and returns it.
|
* Gets a single egg from the database and returns it.
|
||||||
*/
|
*/
|
||||||
export const getEgg = async (id: number | string): Promise<WithRelationships<Egg, 'nest' | 'variables'>> => {
|
export const getEgg = async (id: number | string): Promise<LoadedEgg> => {
|
||||||
const { data } = await http.get(`/api/application/eggs/${id}`, {
|
const { data } = await http.get(`/api/application/eggs/${id}`, {
|
||||||
params: {
|
params: {
|
||||||
include: [ 'nest', 'variables' ],
|
include: [ 'nest', 'variables' ],
|
||||||
|
@ -73,3 +82,16 @@ export const exportEgg = async (eggId: number): Promise<Record<string, any>> =>
|
||||||
const { data } = await http.get(`/api/application/eggs/${eggId}/export`);
|
const { data } = await http.get(`/api/application/eggs/${eggId}/export`);
|
||||||
return data;
|
return data;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns an SWR instance by automatically loading in the server for the currently
|
||||||
|
* loaded route match in the admin area.
|
||||||
|
*/
|
||||||
|
export const useEggFromRoute = (): SWRResponse<LoadedEgg, AxiosError> => {
|
||||||
|
const { params } = useRouteMatch<{ id: string }>();
|
||||||
|
|
||||||
|
return useSWR(`/api/application/eggs/${params.id}`, async () => getEgg(params.id), {
|
||||||
|
revalidateOnMount: false,
|
||||||
|
revalidateOnFocus: false,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
|
@ -1,21 +1,22 @@
|
||||||
import http from '@/api/http';
|
import http from '@/api/http';
|
||||||
import { EggVariable, rawDataToEggVariable } from '@/api/admin/eggs/getEgg';
|
import { EggVariable } from '@/api/admin/egg';
|
||||||
|
import { AdminTransformers } from '@/api/admin/transformers';
|
||||||
|
|
||||||
export default (eggId: number, variable: Omit<EggVariable, 'id' | 'eggId' | 'createdAt' | 'updatedAt'>): Promise<EggVariable> => {
|
export type CreateEggVariable = Omit<EggVariable, 'id' | 'eggId' | 'createdAt' | 'updatedAt' | 'relationships'>;
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
http.post(
|
export default async (eggId: number, variable: CreateEggVariable): Promise<EggVariable> => {
|
||||||
`/api/application/eggs/${eggId}/variables`,
|
const { data } = await http.post(
|
||||||
{
|
`/api/application/eggs/${eggId}/variables`,
|
||||||
name: variable.name,
|
{
|
||||||
description: variable.description,
|
name: variable.name,
|
||||||
env_variable: variable.envVariable,
|
description: variable.description,
|
||||||
default_value: variable.defaultValue,
|
env_variable: variable.environmentVariable,
|
||||||
user_viewable: variable.userViewable,
|
default_value: variable.defaultValue,
|
||||||
user_editable: variable.userEditable,
|
user_viewable: variable.isUserViewable,
|
||||||
rules: variable.rules,
|
user_editable: variable.isUserEditable,
|
||||||
},
|
rules: variable.rules,
|
||||||
)
|
},
|
||||||
.then(({ data }) => resolve(rawDataToEggVariable(data)))
|
);
|
||||||
.catch(reject);
|
|
||||||
});
|
return AdminTransformers.toEggVariable(data);
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,22 +1,21 @@
|
||||||
import http from '@/api/http';
|
import http from '@/api/http';
|
||||||
import { EggVariable, rawDataToEggVariable } from '@/api/admin/eggs/getEgg';
|
import { EggVariable } from '@/api/admin/egg';
|
||||||
|
import { AdminTransformers } from '@/api/admin/transformers';
|
||||||
|
|
||||||
export default (eggId: number, variables: Omit<EggVariable, 'eggId' | 'createdAt' | 'updatedAt'>[]): Promise<EggVariable[]> => {
|
export default async (eggId: number, variables: Omit<EggVariable, 'eggId' | 'createdAt' | 'updatedAt'>[]): Promise<EggVariable[]> => {
|
||||||
return new Promise((resolve, reject) => {
|
const { data } = await http.patch(
|
||||||
http.patch(
|
`/api/application/eggs/${eggId}/variables`,
|
||||||
`/api/application/eggs/${eggId}/variables`,
|
variables.map(variable => ({
|
||||||
variables.map(variable => ({
|
id: variable.id,
|
||||||
id: variable.id,
|
name: variable.name,
|
||||||
name: variable.name,
|
description: variable.description,
|
||||||
description: variable.description,
|
env_variable: variable.environmentVariable,
|
||||||
env_variable: variable.envVariable,
|
default_value: variable.defaultValue,
|
||||||
default_value: variable.defaultValue,
|
user_viewable: variable.isUserViewable,
|
||||||
user_viewable: variable.userViewable,
|
user_editable: variable.isUserEditable,
|
||||||
user_editable: variable.userEditable,
|
rules: variable.rules,
|
||||||
rules: variable.rules,
|
})),
|
||||||
})),
|
);
|
||||||
)
|
|
||||||
.then(({ data }) => resolve((data.data || []).map(rawDataToEggVariable)))
|
return data.data.map(AdminTransformers.toEggVariable);
|
||||||
.catch(reject);
|
|
||||||
});
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -168,7 +168,7 @@ export class AdminTransformers {
|
||||||
defaultValue: attributes.default_value,
|
defaultValue: attributes.default_value,
|
||||||
isUserViewable: attributes.user_viewable,
|
isUserViewable: attributes.user_viewable,
|
||||||
isUserEditable: attributes.user_editable,
|
isUserEditable: attributes.user_editable,
|
||||||
isRequired: attributes.required,
|
// isRequired: attributes.required,
|
||||||
rules: attributes.rules,
|
rules: attributes.rules,
|
||||||
createdAt: new Date(attributes.created_at),
|
createdAt: new Date(attributes.created_at),
|
||||||
updatedAt: new Date(attributes.updated_at),
|
updatedAt: new Date(attributes.updated_at),
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { Egg } from '@/api/admin/eggs/getEgg';
|
import { useEggFromRoute } from '@/api/admin/egg';
|
||||||
import updateEgg from '@/api/admin/eggs/updateEgg';
|
import updateEgg from '@/api/admin/eggs/updateEgg';
|
||||||
import Field from '@/components/elements/Field';
|
import Field from '@/components/elements/Field';
|
||||||
import useFlash from '@/plugins/useFlash';
|
import useFlash from '@/plugins/useFlash';
|
||||||
|
@ -18,9 +18,15 @@ interface Values {
|
||||||
scriptInstall: string;
|
scriptInstall: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function EggInstallContainer ({ egg }: { egg: Egg }) {
|
export default function EggInstallContainer () {
|
||||||
const { clearFlashes, clearAndAddHttpError } = useFlash();
|
const { clearFlashes, clearAndAddHttpError } = useFlash();
|
||||||
|
|
||||||
|
const { data: egg } = useEggFromRoute();
|
||||||
|
|
||||||
|
if (!egg) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
let fetchFileContent: (() => Promise<string>) | null = null;
|
let fetchFileContent: (() => Promise<string>) | null = null;
|
||||||
|
|
||||||
const submit = async (values: Values, { setSubmitting }: FormikHelpers<Values>) => {
|
const submit = async (values: Values, { setSubmitting }: FormikHelpers<Values>) => {
|
||||||
|
|
|
@ -1,10 +1,11 @@
|
||||||
|
import { useEggFromRoute } from '@/api/admin/egg';
|
||||||
import EggInstallContainer from '@/components/admin/nests/eggs/EggInstallContainer';
|
import EggInstallContainer from '@/components/admin/nests/eggs/EggInstallContainer';
|
||||||
import EggVariablesContainer from '@/components/admin/nests/eggs/EggVariablesContainer';
|
import EggVariablesContainer from '@/components/admin/nests/eggs/EggVariablesContainer';
|
||||||
import React from 'react';
|
import useFlash from '@/plugins/useFlash';
|
||||||
|
import React, { useEffect } from 'react';
|
||||||
import { useLocation } from 'react-router';
|
import { useLocation } from 'react-router';
|
||||||
import tw from 'twin.macro';
|
import tw from 'twin.macro';
|
||||||
import { Route, Switch, useRouteMatch } from 'react-router-dom';
|
import { Route, Switch, useRouteMatch } from 'react-router-dom';
|
||||||
import getEgg from '@/api/admin/eggs/getEgg';
|
|
||||||
import AdminContentBlock from '@/components/admin/AdminContentBlock';
|
import AdminContentBlock from '@/components/admin/AdminContentBlock';
|
||||||
import Spinner from '@/components/elements/Spinner';
|
import Spinner from '@/components/elements/Spinner';
|
||||||
import FlashMessageRender from '@/components/FlashMessageRender';
|
import FlashMessageRender from '@/components/FlashMessageRender';
|
||||||
|
@ -13,18 +14,24 @@ import EggSettingsContainer from '@/components/admin/nests/eggs/EggSettingsConta
|
||||||
|
|
||||||
const EggRouter = () => {
|
const EggRouter = () => {
|
||||||
const location = useLocation();
|
const location = useLocation();
|
||||||
const match = useRouteMatch<{ id?: string }>();
|
const match = useRouteMatch();
|
||||||
|
|
||||||
const { data: egg } = getEgg(Number(match.params?.id));
|
const { clearFlashes, clearAndAddHttpError } = useFlash();
|
||||||
|
const { data: egg, error, isValidating, mutate } = useEggFromRoute();
|
||||||
|
|
||||||
if (egg === undefined) {
|
useEffect(() => {
|
||||||
|
mutate();
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (!error) clearFlashes('egg');
|
||||||
|
if (error) clearAndAddHttpError({ error, key: 'egg' });
|
||||||
|
}, [ error ]);
|
||||||
|
|
||||||
|
if (!egg || (error && isValidating)) {
|
||||||
return (
|
return (
|
||||||
<AdminContentBlock>
|
<AdminContentBlock showFlashKey={'egg'}>
|
||||||
<FlashMessageRender byKey={'egg'} css={tw`mb-4`}/>
|
<Spinner size={'large'} centered/>
|
||||||
|
|
||||||
<div css={tw`w-full flex flex-col items-center justify-center`} style={{ height: '24rem' }}>
|
|
||||||
<Spinner size={'base'}/>
|
|
||||||
</div>
|
|
||||||
</AdminContentBlock>
|
</AdminContentBlock>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -62,15 +69,15 @@ const EggRouter = () => {
|
||||||
|
|
||||||
<Switch location={location}>
|
<Switch location={location}>
|
||||||
<Route path={`${match.path}`} exact>
|
<Route path={`${match.path}`} exact>
|
||||||
<EggSettingsContainer egg={egg}/>
|
<EggSettingsContainer/>
|
||||||
</Route>
|
</Route>
|
||||||
|
|
||||||
<Route path={`${match.path}/variables`} exact>
|
<Route path={`${match.path}/variables`} exact>
|
||||||
<EggVariablesContainer egg={egg}/>
|
<EggVariablesContainer/>
|
||||||
</Route>
|
</Route>
|
||||||
|
|
||||||
<Route path={`${match.path}/install`} exact>
|
<Route path={`${match.path}/install`} exact>
|
||||||
<EggInstallContainer egg={egg}/>
|
<EggInstallContainer/>
|
||||||
</Route>
|
</Route>
|
||||||
</Switch>
|
</Switch>
|
||||||
</AdminContentBlock>
|
</AdminContentBlock>
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
import { useEggFromRoute } from '@/api/admin/egg';
|
||||||
import updateEgg from '@/api/admin/eggs/updateEgg';
|
import updateEgg from '@/api/admin/eggs/updateEgg';
|
||||||
import EggDeleteButton from '@/components/admin/nests/eggs/EggDeleteButton';
|
import EggDeleteButton from '@/components/admin/nests/eggs/EggDeleteButton';
|
||||||
import EggExportButton from '@/components/admin/nests/eggs/EggExportButton';
|
import EggExportButton from '@/components/admin/nests/eggs/EggExportButton';
|
||||||
|
@ -13,7 +14,6 @@ import { faDocker } from '@fortawesome/free-brands-svg-icons';
|
||||||
import { faEgg, faFireAlt, faMicrochip, faTerminal } from '@fortawesome/free-solid-svg-icons';
|
import { faEgg, faFireAlt, faMicrochip, faTerminal } from '@fortawesome/free-solid-svg-icons';
|
||||||
import React, { forwardRef, useImperativeHandle, useRef } from 'react';
|
import React, { forwardRef, useImperativeHandle, useRef } from 'react';
|
||||||
import AdminBox from '@/components/admin/AdminBox';
|
import AdminBox from '@/components/admin/AdminBox';
|
||||||
import { Egg } from '@/api/admin/eggs/getEgg';
|
|
||||||
import { useHistory } from 'react-router-dom';
|
import { useHistory } from 'react-router-dom';
|
||||||
import tw from 'twin.macro';
|
import tw from 'twin.macro';
|
||||||
import { object } from 'yup';
|
import { object } from 'yup';
|
||||||
|
@ -45,7 +45,13 @@ export function EggInformationContainer () {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function EggDetailsContainer ({ egg }: { egg: Egg }) {
|
function EggDetailsContainer () {
|
||||||
|
const { data: egg } = useEggFromRoute();
|
||||||
|
|
||||||
|
if (!egg) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<AdminBox icon={faEgg} title={'Egg Details'} css={tw`relative`}>
|
<AdminBox icon={faEgg} title={'Egg Details'} css={tw`relative`}>
|
||||||
<div css={tw`mb-6`}>
|
<div css={tw`mb-6`}>
|
||||||
|
@ -200,12 +206,18 @@ interface Values {
|
||||||
configFiles: string;
|
configFiles: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function EggSettingsContainer ({ egg }: { egg: Egg }) {
|
export default function EggSettingsContainer () {
|
||||||
const history = useHistory();
|
const history = useHistory();
|
||||||
|
|
||||||
|
const ref = useRef<EggProcessContainerRef>();
|
||||||
|
|
||||||
const { clearFlashes, clearAndAddHttpError } = useFlash();
|
const { clearFlashes, clearAndAddHttpError } = useFlash();
|
||||||
|
|
||||||
const ref = useRef<EggProcessContainerRef>();
|
const { data: egg } = useEggFromRoute();
|
||||||
|
|
||||||
|
if (!egg) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
const submit = async (values: Values, { setSubmitting }: FormikHelpers<Values>) => {
|
const submit = async (values: Values, { setSubmitting }: FormikHelpers<Values>) => {
|
||||||
clearFlashes('egg');
|
clearFlashes('egg');
|
||||||
|
@ -240,7 +252,7 @@ export default function EggSettingsContainer ({ egg }: { egg: Egg }) {
|
||||||
<Form>
|
<Form>
|
||||||
<div css={tw`grid grid-cols-1 md:grid-cols-2 gap-x-8 gap-y-6 mb-6`}>
|
<div css={tw`grid grid-cols-1 md:grid-cols-2 gap-x-8 gap-y-6 mb-6`}>
|
||||||
<EggInformationContainer/>
|
<EggInformationContainer/>
|
||||||
<EggDetailsContainer egg={egg}/>
|
<EggDetailsContainer/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<EggStartupContainer css={tw`mb-6`}/>
|
<EggStartupContainer css={tw`mb-6`}/>
|
||||||
|
|
|
@ -5,7 +5,7 @@ import { Form, Formik, FormikHelpers, useFormikContext } from 'formik';
|
||||||
import React, { useState } from 'react';
|
import React, { useState } from 'react';
|
||||||
import tw from 'twin.macro';
|
import tw from 'twin.macro';
|
||||||
import { array, boolean, object, string } from 'yup';
|
import { array, boolean, object, string } from 'yup';
|
||||||
import getEgg, { Egg, EggVariable } from '@/api/admin/eggs/getEgg';
|
import { EggVariable, useEggFromRoute } from '@/api/admin/egg';
|
||||||
import updateEggVariables from '@/api/admin/eggs/updateEggVariables';
|
import updateEggVariables from '@/api/admin/eggs/updateEggVariables';
|
||||||
import NewVariableButton from '@/components/admin/nests/eggs/NewVariableButton';
|
import NewVariableButton from '@/components/admin/nests/eggs/NewVariableButton';
|
||||||
import AdminBox from '@/components/admin/AdminBox';
|
import AdminBox from '@/components/admin/AdminBox';
|
||||||
|
@ -19,10 +19,10 @@ import { TrashIcon } from '@heroicons/react/outline';
|
||||||
export const validationSchema = object().shape({
|
export const validationSchema = object().shape({
|
||||||
name: string().required().min(1).max(191),
|
name: string().required().min(1).max(191),
|
||||||
description: string(),
|
description: string(),
|
||||||
envVariable: string().required().min(1).max(191),
|
environmentVariable: string().required().min(1).max(191),
|
||||||
defaultValue: string(),
|
defaultValue: string(),
|
||||||
userViewable: boolean().required(),
|
isUserViewable: boolean().required(),
|
||||||
userEditable: boolean().required(),
|
isUserEditable: boolean().required(),
|
||||||
rules: string().required(),
|
rules: string().required(),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -47,8 +47,8 @@ export function EggVariableForm ({ prefix }: { prefix: string }) {
|
||||||
|
|
||||||
<FieldRow>
|
<FieldRow>
|
||||||
<Field
|
<Field
|
||||||
id={`${prefix}envVariable`}
|
id={`${prefix}environmentVariable`}
|
||||||
name={`${prefix}envVariable`}
|
name={`${prefix}environmentVariable`}
|
||||||
label={'Environment Variable'}
|
label={'Environment Variable'}
|
||||||
type={'text'}
|
type={'text'}
|
||||||
/>
|
/>
|
||||||
|
@ -63,14 +63,14 @@ export function EggVariableForm ({ prefix }: { prefix: string }) {
|
||||||
|
|
||||||
<div css={tw`flex flex-row mb-6`}>
|
<div css={tw`flex flex-row mb-6`}>
|
||||||
<Checkbox
|
<Checkbox
|
||||||
id={`${prefix}userViewable`}
|
id={`${prefix}isUserViewable`}
|
||||||
name={`${prefix}userViewable`}
|
name={`${prefix}isUserViewable`}
|
||||||
label={'User Viewable'}
|
label={'User Viewable'}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<Checkbox
|
<Checkbox
|
||||||
id={`${prefix}userEditable`}
|
id={`${prefix}isUserEditable`}
|
||||||
name={`${prefix}userEditable`}
|
name={`${prefix}isUserEditable`}
|
||||||
label={'User Editable'}
|
label={'User Editable'}
|
||||||
css={tw`ml-auto`}
|
css={tw`ml-auto`}
|
||||||
/>
|
/>
|
||||||
|
@ -95,7 +95,7 @@ function EggVariableDeleteButton ({ onClick }: { onClick: (success: () => void)
|
||||||
setLoading(true);
|
setLoading(true);
|
||||||
|
|
||||||
onClick(() => {
|
onClick(() => {
|
||||||
setLoading(false);
|
//setLoading(false);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -140,14 +140,18 @@ function EggVariableBox ({ onDeleteClick, variable, prefix }: { onDeleteClick: (
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function EggVariablesContainer ({ egg }: { egg: Egg }) {
|
export default function EggVariablesContainer () {
|
||||||
const { clearAndAddHttpError } = useFlash();
|
const { clearAndAddHttpError } = useFlash();
|
||||||
|
|
||||||
const { mutate } = getEgg(egg.id);
|
const { data: egg, mutate } = useEggFromRoute();
|
||||||
|
|
||||||
|
if (!egg) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
const submit = (values: EggVariable[], { setSubmitting }: FormikHelpers<EggVariable[]>) => {
|
const submit = (values: EggVariable[], { setSubmitting }: FormikHelpers<EggVariable[]>) => {
|
||||||
updateEggVariables(egg.id, values)
|
updateEggVariables(egg.id, values)
|
||||||
.then(async (variables) => await mutate(egg => ({ ...egg!, relations: { variables: variables } })))
|
.then(async () => await mutate())
|
||||||
.catch(error => clearAndAddHttpError({ key: 'egg', error }))
|
.catch(error => clearAndAddHttpError({ key: 'egg', error }))
|
||||||
.then(() => setSubmitting(false));
|
.then(() => setSubmitting(false));
|
||||||
};
|
};
|
||||||
|
@ -155,17 +159,17 @@ export default function EggVariablesContainer ({ egg }: { egg: Egg }) {
|
||||||
return (
|
return (
|
||||||
<Formik
|
<Formik
|
||||||
onSubmit={submit}
|
onSubmit={submit}
|
||||||
initialValues={egg.relations?.variables || []}
|
initialValues={egg.relationships.variables}
|
||||||
validationSchema={array().of(validationSchema)}
|
validationSchema={array().of(validationSchema)}
|
||||||
>
|
>
|
||||||
{({ isSubmitting, isValid }) => (
|
{({ isSubmitting, isValid }) => (
|
||||||
<Form>
|
<Form>
|
||||||
<div css={tw`flex flex-col mb-16`}>
|
<div css={tw`flex flex-col mb-16`}>
|
||||||
{egg.relations?.variables?.length === 0 ?
|
{egg.relationships.variables?.length === 0 ?
|
||||||
<NoItems css={tw`bg-neutral-700 rounded-md shadow-md`}/>
|
<NoItems css={tw`bg-neutral-700 rounded-md shadow-md`}/>
|
||||||
:
|
:
|
||||||
<div css={tw`grid grid-cols-1 lg:grid-cols-2 gap-x-8 gap-y-6`}>
|
<div css={tw`grid grid-cols-1 lg:grid-cols-2 xl:grid-cols-3 gap-x-8 gap-y-6`}>
|
||||||
{egg.relations?.variables?.map((v, i) => (
|
{egg.relationships.variables.map((v, i) => (
|
||||||
<EggVariableBox
|
<EggVariableBox
|
||||||
key={i}
|
key={i}
|
||||||
prefix={`[${i}].`}
|
prefix={`[${i}].`}
|
||||||
|
@ -175,8 +179,9 @@ export default function EggVariablesContainer ({ egg }: { egg: Egg }) {
|
||||||
.then(async () => {
|
.then(async () => {
|
||||||
await mutate(egg => ({
|
await mutate(egg => ({
|
||||||
...egg!,
|
...egg!,
|
||||||
relations: {
|
relationships: {
|
||||||
variables: egg!.relations.variables!.filter(v2 => v.id === v2.id),
|
...egg!.relationships,
|
||||||
|
variables: egg!.relationships.variables!.filter(v2 => v.id === v2.id),
|
||||||
},
|
},
|
||||||
}));
|
}));
|
||||||
success();
|
success();
|
||||||
|
@ -190,7 +195,7 @@ export default function EggVariablesContainer ({ egg }: { egg: Egg }) {
|
||||||
|
|
||||||
<div css={tw`bg-neutral-700 rounded shadow-md py-2 px-4 mt-6`}>
|
<div css={tw`bg-neutral-700 rounded shadow-md py-2 px-4 mt-6`}>
|
||||||
<div css={tw`flex flex-row`}>
|
<div css={tw`flex flex-row`}>
|
||||||
<NewVariableButton eggId={egg.id}/>
|
<NewVariableButton/>
|
||||||
|
|
||||||
<Button type={'submit'} size={'small'} css={tw`ml-auto`} disabled={isSubmitting || !isValid}>
|
<Button type={'submit'} size={'small'} css={tw`ml-auto`} disabled={isSubmitting || !isValid}>
|
||||||
Save Changes
|
Save Changes
|
||||||
|
|
|
@ -1,26 +1,32 @@
|
||||||
import { Form, Formik, FormikHelpers } from 'formik';
|
import { Form, Formik, FormikHelpers, useFormikContext } from 'formik';
|
||||||
import React, { useState } from 'react';
|
import React, { useState } from 'react';
|
||||||
import tw from 'twin.macro';
|
import tw from 'twin.macro';
|
||||||
import createEggVariable from '@/api/admin/eggs/createEggVariable';
|
import createEggVariable, { CreateEggVariable } from '@/api/admin/eggs/createEggVariable';
|
||||||
import getEgg from '@/api/admin/eggs/getEgg';
|
import { useEggFromRoute } from '@/api/admin/egg';
|
||||||
import { EggVariableForm, validationSchema } from '@/components/admin/nests/eggs/EggVariablesContainer';
|
import { EggVariableForm, validationSchema } from '@/components/admin/nests/eggs/EggVariablesContainer';
|
||||||
import Modal from '@/components/elements/Modal';
|
import Modal from '@/components/elements/Modal';
|
||||||
import FlashMessageRender from '@/components/FlashMessageRender';
|
import FlashMessageRender from '@/components/FlashMessageRender';
|
||||||
import Button from '@/components/elements/Button';
|
import Button from '@/components/elements/Button';
|
||||||
import useFlash from '@/plugins/useFlash';
|
import useFlash from '@/plugins/useFlash';
|
||||||
|
|
||||||
export default function NewVariableButton ({ eggId }: { eggId: number }) {
|
export default function NewVariableButton () {
|
||||||
|
const { setValues } = useFormikContext();
|
||||||
const [ visible, setVisible ] = useState(false);
|
const [ visible, setVisible ] = useState(false);
|
||||||
const { clearFlashes, clearAndAddHttpError } = useFlash();
|
const { clearFlashes, clearAndAddHttpError } = useFlash();
|
||||||
|
|
||||||
const { mutate } = getEgg(eggId);
|
const { data: egg, mutate } = useEggFromRoute();
|
||||||
|
|
||||||
const submit = (values: any, { setSubmitting }: FormikHelpers<any>) => {
|
if (!egg) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
const submit = (values: CreateEggVariable, { setSubmitting }: FormikHelpers<CreateEggVariable>) => {
|
||||||
clearFlashes('variable:create');
|
clearFlashes('variable:create');
|
||||||
|
|
||||||
createEggVariable(eggId, values)
|
createEggVariable(egg.id, values)
|
||||||
.then(async (v) => {
|
.then(async (variable) => {
|
||||||
await mutate(egg => ({ ...egg!, relations: { variables: [ ...egg!.relations.variables!, v ] } }));
|
setValues([ ...egg.relationships.variables, variable ]);
|
||||||
|
await mutate(egg => ({ ...egg!, relationships: { ...egg!.relationships, variables: [ ...egg!.relationships.variables, variable ] } }));
|
||||||
setVisible(false);
|
setVisible(false);
|
||||||
})
|
})
|
||||||
.catch(error => {
|
.catch(error => {
|
||||||
|
@ -36,15 +42,15 @@ export default function NewVariableButton ({ eggId }: { eggId: number }) {
|
||||||
initialValues={{
|
initialValues={{
|
||||||
name: '',
|
name: '',
|
||||||
description: '',
|
description: '',
|
||||||
envVariable: '',
|
environmentVariable: '',
|
||||||
defaultValue: '',
|
defaultValue: '',
|
||||||
userViewable: false,
|
isUserViewable: false,
|
||||||
userEditable: false,
|
isUserEditable: false,
|
||||||
rules: '',
|
rules: '',
|
||||||
}}
|
}}
|
||||||
validationSchema={validationSchema}
|
validationSchema={validationSchema}
|
||||||
>
|
>
|
||||||
{({ isSubmitting, resetForm }) => (
|
{({ isSubmitting, isValid, resetForm }) => (
|
||||||
<Modal
|
<Modal
|
||||||
visible={visible}
|
visible={visible}
|
||||||
dismissable={!isSubmitting}
|
dismissable={!isSubmitting}
|
||||||
|
@ -70,7 +76,7 @@ export default function NewVariableButton ({ eggId }: { eggId: number }) {
|
||||||
>
|
>
|
||||||
Cancel
|
Cancel
|
||||||
</Button>
|
</Button>
|
||||||
<Button css={tw`w-full mt-4 sm:w-auto sm:mt-0`} type={'submit'}>
|
<Button css={tw`w-full mt-4 sm:w-auto sm:mt-0`} type={'submit'} disabled={isSubmitting || !isValid}>
|
||||||
Create Variable
|
Create Variable
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -146,7 +146,6 @@ export default () => {
|
||||||
const { clearFlashes, clearAndAddHttpError } = useFlash();
|
const { clearFlashes, clearAndAddHttpError } = useFlash();
|
||||||
|
|
||||||
const submit = (r: CreateServerRequest, { setSubmitting }: FormikHelpers<CreateServerRequest>) => {
|
const submit = (r: CreateServerRequest, { setSubmitting }: FormikHelpers<CreateServerRequest>) => {
|
||||||
console.log(r);
|
|
||||||
clearFlashes('server:create');
|
clearFlashes('server:create');
|
||||||
|
|
||||||
createServer(r)
|
createServer(r)
|
||||||
|
|
|
@ -32,7 +32,7 @@ export default () => {
|
||||||
if (!server || (error && isValidating)) {
|
if (!server || (error && isValidating)) {
|
||||||
return (
|
return (
|
||||||
<AdminContentBlock showFlashKey={'server'}>
|
<AdminContentBlock showFlashKey={'server'}>
|
||||||
<Spinner size={'large'} centered/>;
|
<Spinner size={'large'} centered/>
|
||||||
</AdminContentBlock>
|
</AdminContentBlock>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue