Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Close #529 Supported lambda backend type in UI #558

Merged
merged 1 commit into from
Jul 13, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
58 changes: 58 additions & 0 deletions hub/src/components/form/Multiselect/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import React from 'react';
import { Controller, FieldValues } from 'react-hook-form';
import FormField from '@cloudscape-design/components/form-field';
import MultiselectCSD from '@cloudscape-design/components/multiselect';
import { MultiselectProps } from '@cloudscape-design/components/multiselect/interfaces';

import { FormMultiselectProps } from './types';

export const FormMultiselect = <T extends FieldValues>({
name,
rules,
control,
label,
info,
constraintText,
description,
secondaryControl,
stretch,
onChange: onChangeProp,
...props
}: FormMultiselectProps<T>) => {
return (
<Controller
name={name}
control={control}
rules={rules}
render={({ field: { onChange, ...fieldRest }, fieldState: { error } }) => {
const selectedOptions = props.options?.filter((i) => fieldRest.value.includes(i.value)) ?? null;

const onChangeSelect: MultiselectProps['onChange'] = (event) => {
const value = event.detail.selectedOptions.map((item) => item.value);
onChange(value);
onChangeProp && onChangeProp(event);
};

return (
<FormField
description={description}
label={label}
info={info}
stretch={stretch}
constraintText={constraintText}
secondaryControl={secondaryControl}
errorText={error?.message}
>
<MultiselectCSD
selectedOptions={selectedOptions}
onChange={onChangeSelect}
{...fieldRest}
{...props}
invalid={!!error}
/>
</FormField>
);
}}
/>
);
};
15 changes: 15 additions & 0 deletions hub/src/components/form/Multiselect/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { ControllerProps, FieldValues } from 'react-hook-form';
import { FormFieldProps } from '@cloudscape-design/components/form-field';
import { MultiselectProps } from '@cloudscape-design/components/multiselect';

export type FormMultiselectOption = MultiselectProps.Option;
export type FormMultiselectOptions = ReadonlyArray<FormMultiselectOption>;

export type FormMultiselectProps<T extends FieldValues> = Omit<
MultiselectProps,
'value' | 'name' | 'selectedOptions' | 'options'
> &
Omit<FormFieldProps, 'errorText'> &
Pick<ControllerProps<T>, 'control' | 'name' | 'rules'> & {
options: ReadonlyArray<FormMultiselectOption>;
};
2 changes: 2 additions & 0 deletions hub/src/components/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,10 +44,12 @@ export { ListEmptyMessage } from './ListEmptyMessage';
export { DetailsHeader } from './DetailsHeader';
export { Loader } from './Loader';
export { FormInput } from './form/Input';
export { FormMultiselect } from './form/Multiselect';
export { FormSelect } from './form/Select';
export { FormTextarea } from './form/Textarea';
export { FormRadioButtons } from './form/RadioButtons';
export type { FormSelectOptions, FormSelectProps } from './form/Select/types';
export type { FormMultiselectOptions, FormMultiselectProps } from './form/Multiselect/types';
export { FormS3BucketSelector } from './form/S3BucketSelector';
export type { FormTilesProps } from './form/Tiles/types';
export { FormTiles } from './form/Tiles';
Expand Down
22 changes: 22 additions & 0 deletions hub/src/locale/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,8 @@
"gcp_description": "Run workflows and store data in Google Cloud Platform",
"azure": "Azure",
"azure_description": "Run workflows and store data in Microsoft Azure",
"lambda": "Lambda",
"lambda_description": "Run workflows and store data in Lambda",
"local": "Local",
"local_description": "Run workflows and store data locally via Docker"
},
Expand Down Expand Up @@ -145,6 +147,26 @@
"subnet_description": "Select a subnet to run workflows in",
"subnet_placeholder": "Not selected"
},
"lambda": {
"api_key": "Api key",
"api_key_description": "Specify the Lambda api key",
"regions": "Regions",
"regions_description": "Select regions to run workflows and store artifacts",
"regions_placeholder": "Select regions",
"storage_backend": {
"type": "Type",
"type_description": "Type of backend storage",
"type_placeholder": "Select type",
"credentials": {
"access_key_id": "Access key ID",
"access_key_id_description": "Specify the AWS access key ID",
"secret_key_id": "Secret access key",
"secret_key_id_description": "Specify the AWS secret access key"
},
"s3_bucket_name": "Bucket",
"s3_bucket_name_description": "Select an S3 bucket to store artifacts"
}
},
"local": {
"path": "Files path"
},
Expand Down
39 changes: 36 additions & 3 deletions hub/src/pages/Project/Details/Settings/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ import { selectAuthToken, selectUserData } from 'App/slice';
import { ProjectMembers } from '../../Members';
import { getProjectRoleByUserName } from '../../utils';

import { BackendTypesEnum } from '../../Form/types';

import styles from './styles.module.scss';

export const ProjectSettings: React.FC = () => {
Expand Down Expand Up @@ -170,6 +172,34 @@ export const ProjectSettings: React.FC = () => {
);
};

const renderLambdaBackendDetails = (): React.ReactNode => {
if (!data) return null;

return (
<ColumnLayout columns={4} variant="text-grid">
<div>
<Box variant="awsui-key-label">{t('projects.edit.backend_type')}</Box>
<div>{t(`projects.backend_type.${data.backend.type}`)}</div>
</div>

<div>
<Box variant="awsui-key-label">{t('projects.edit.lambda.regions')}</Box>
<div>{data.backend.regions.join(', ')}</div>
</div>

<div>
<Box variant="awsui-key-label">{t('projects.edit.lambda.storage_backend.type')}</Box>
<div>{data.backend.storage_backend.type}</div>
</div>

<div>
<Box variant="awsui-key-label">{t('projects.edit.lambda.storage_backend.s3_bucket_name')}</Box>
<div>{data.backend.storage_backend.bucket_name}</div>
</div>
</ColumnLayout>
);
};

const renderLocalBackendDetails = (): React.ReactNode => {
if (!data) return null;

Expand All @@ -190,15 +220,18 @@ export const ProjectSettings: React.FC = () => {

const renderBackendDetails = () => {
switch (data?.backend.type) {
case 'aws': {
case BackendTypesEnum.AWS: {
return renderAwsBackendDetails();
}
case 'azure': {
case BackendTypesEnum.AZURE: {
return renderAzureBackendDetails();
}
case 'gcp': {
case BackendTypesEnum.GCP: {
return renderGCPBackendDetails();
}
case BackendTypesEnum.LAMBDA: {
return renderLambdaBackendDetails();
}
case 'local': {
return renderLocalBackendDetails();
}
Expand Down
35 changes: 35 additions & 0 deletions hub/src/pages/Project/Form/Lambda/constants.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import React from 'react';

export const FIELD_NAMES = {
API_KEY: 'api_key',
REGIONS: 'regions',
STORAGE_BACKEND: {
TYPE: 'storage_backend.type',
BUCKET_NAME: 'storage_backend.bucket_name',
CREDENTIALS: {
ACCESS_KEY: 'storage_backend.credentials.access_key',
SECRET_KEY: 'storage_backend.credentials.secret_key',
},
},
};

export const DEFAULT_HELP = {
header: <h2>HELP TITLE</h2>,
body: (
<>
<p>Help description</p>
</>
),

footer: (
<>
<h3>Help footer</h3>

<ul>
<li>
<a href="/">Help link</a>
</li>
</ul>
</>
),
};
Loading
Loading