/* * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. * SPDX-License-Identifier: Apache-2.0 */ import { useProjects } from '@aws/workbench-core-accounts-ui'; import { useDatasets } from '@aws/workbench-core-datasets-ui'; import { nameRegex, BaseLayout } from '@aws/workbench-core-swb-common-ui'; import { Box, BreadcrumbGroupProps, SpaceBetween, Form, Header, ExpandableSection, Input, FormField, Button, Container, Link, Textarea, Select, Multiselect } from '@cloudscape-design/components'; import type { NextPage } from 'next'; import { useRouter } from 'next/router'; import React, { useEffect, useState } from 'react'; import { createEnvironment } from '../../api/environments'; import { useEnvTypeConfigs } from '../../api/environmentTypeConfigs'; import { useEnvironmentType } from '../../api/environmentTypes'; import EnvTypeCards from '../../components/EnvTypeCards'; import EnvTypeConfigCards from '../../components/EnvTypeConfigCards'; import { CreateEnvironmentForm, CreateEnvironmentFormValidation } from '../../models/Environment'; import { EnvTypeItem } from '../../models/EnvironmentType'; import { EnvTypeConfigItem } from '../../models/EnvironmentTypeConfig'; const NewEnvironmentPage: NextPage = () => { // App settings constant const router = useRouter(); const [isSubmitLoading, setIsSubmitLoading] = useState(false); const [disableSubmit, setDisableSubmit] = useState(true); const [selectedEnvType, setSelectedEnvType] = useState(); const [error, setError] = useState(''); const [formData, setFormData] = useState({}); const [formErrors, setFormErrors] = useState({}); const { envTypes, areEnvTypesLoading } = useEnvironmentType(); const { envTypeConfigs, areEnvTypeConfigsLoading } = useEnvTypeConfigs(formData?.envTypeId || ''); const { projects, areProjectsLoading } = useProjects(); const { datasets, areDatasetsLoading } = useDatasets(); const breadcrumbs: BreadcrumbGroupProps.Item[] = [ { text: 'Research Service Workbench', href: '/' }, { text: 'Workspaces', href: '/environments' }, { text: 'Create Workspace', href: '/environments/new' } ]; const validationRules = [ { field: 'name', // eslint-disable-next-line @typescript-eslint/no-explicit-any condition: (a: any) => !!a, message: 'Workspace Name is Required' }, { field: 'name', // eslint-disable-next-line @typescript-eslint/no-explicit-any condition: (a: any) => !!a && nameRegex.test(a), message: 'Workspace Name must start with an alphabetic character and can only contain alphanumeric characters (case sensitive) and hyphens.' }, { field: 'name', // eslint-disable-next-line @typescript-eslint/no-explicit-any condition: (a: any) => !!a && a.length <= 128, message: 'Workspace Name cannot be longer than 128 characters' }, { field: 'projectId', // eslint-disable-next-line @typescript-eslint/no-explicit-any condition: (a: any) => !!a, message: 'Project ID is Required' }, { field: 'envTypeId', // eslint-disable-next-line @typescript-eslint/no-explicit-any condition: (a: any) => !!a, message: 'Compute Platform is Required' }, { field: 'envTypeConfigId', // eslint-disable-next-line @typescript-eslint/no-explicit-any condition: (a: any) => !!a, message: 'Configuration is Required' }, { field: 'description', // eslint-disable-next-line @typescript-eslint/no-explicit-any condition: (a: any) => a && a.length <= 500, message: 'Description cannot be longer than 500 characters' }, { field: 'description', // eslint-disable-next-line @typescript-eslint/no-explicit-any condition: (a: any) => !!a, message: 'Description is Required' } ]; // eslint-disable-next-line @typescript-eslint/no-explicit-any const validateField = (field: keyof CreateEnvironmentForm, value: any): boolean => { for (const rule of validationRules.filter((f) => f.field === field)) { // eslint-disable-next-line security/detect-object-injection if (!rule.condition(value)) { setFormErrors((prevState: CreateEnvironmentFormValidation) => ({ ...prevState, [`${field}Error`]: rule.message })); return false; } } setFormErrors((prevState: CreateEnvironmentFormValidation) => ({ ...prevState, [`${field}Error`]: '' })); return true; }; const onSelectEnvType = async (selection: EnvTypeItem[]): Promise => { const selected = (selection && selection[0]) || undefined; setSelectedEnvType(selected); setFormData({ ...formData, envTypeId: selected?.id, envTypeConfigId: undefined, envType: selected?.type, datasetIds: [] }); validateField('envType', selected?.id); validateField('envTypeConfigId', undefined); }; const onSelectEnvTypeConfig = (selection: EnvTypeConfigItem[]): void => { const selected = (selection && selection[0]) || undefined; setFormData({ ...formData, envTypeConfigId: selected?.id }); validateField('envTypeConfigId', selected?.id); }; const submitForm = async (): Promise => { setIsSubmitLoading(true); try { await createEnvironment(formData); await router.push({ pathname: '/environments', query: { message: 'Workspace Created Successfully', notificationType: 'success' } }); } catch { setError('There was a problem creating a workspace.'); } finally { setIsSubmitLoading(false); } }; useEffect(() => { setDisableSubmit( !validationRules.every((rule) => rule.condition(formData[rule.field as keyof CreateEnvironmentForm])) ); // eslint-disable-next-line react-hooks/exhaustive-deps }, [formData]); const getContent = (): JSX.Element => { return (
e.preventDefault()}> } header={
Create Research Workspace
} > Select Compute Platform ({envTypes.length}) Selected: {selectedEnvType?.name || 'None'} } defaultExpanded > await onSelectEnvType(selected.selectedItems)} /> Select Configurations} >
  • Name can only contain alphanumeric characters (case sensitive) and hyphens.
  • It must start with an alphabetic character.
  • Cannot be longer than 128 characters.
  • } errorText={formErrors?.nameError} > { setFormData({ ...formData, name: value }); validateField('name', value); }} />