Skip to content
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
3 changes: 2 additions & 1 deletion public/locales/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -270,7 +270,8 @@
"properFormattingLowercase": "Use lowercase a-z, 0-9, hyphen (-), and period (.), but note that whitespace (spaces, tabs, etc.) is not allowed for proper compatibility.",
"maxChars": "Max length is {{maxLength}} characters.",
"userExists": "User with this email already exists!",
"atLeastOneUser": "You need to have at least one member assigned."
"atLeastOneUser": "You need to have at least one member assigned.",
"notValidChargingTargetFormat": "Use lowercase letters a-f, numbers 0-9, and hyphens (-) in the format: aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa"
},
"common": {
"documentation": "Documentation",
Expand Down
42 changes: 12 additions & 30 deletions src/components/Dialogs/CreateProjectDialog.cy.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,5 @@
import React, { useState, useRef } from 'react';
import {
CreateProjectWorkspaceDialog,
OnCreatePayload,
} from './CreateProjectWorkspaceDialog';
import { CreateProjectWorkspaceDialog, OnCreatePayload } from './CreateProjectWorkspaceDialog';
import { MemberRoles } from '../../lib/api/types/shared/members';
import { ErrorDialogHandle } from '../Shared/ErrorMessageBox';

Expand Down Expand Up @@ -31,18 +28,12 @@ export const CreateProjectWorkspaceDialogWrapper: React.FC<{
name: '',
displayName: '',
chargingTarget: '',
members: [
{ name: 'user1@example.com', roles: [MemberRoles.admin], kind: 'User' },
],
members: [{ name: 'user1@example.com', roles: [MemberRoles.admin], kind: 'User' }],
chargingTargetType: 'btp',
},
});

const handleCreate = async ({
name,
displayName,
chargingTarget,
members,
}: OnCreatePayload) => {
const handleCreate = async ({ name, displayName, chargingTarget, members }: OnCreatePayload) => {
const payload: OnCreatePayload = {
name: name,
displayName: displayName,
Expand All @@ -55,6 +46,7 @@ export const CreateProjectWorkspaceDialogWrapper: React.FC<{
};
return (
<CreateProjectWorkspaceDialog
watch={watch}
type={'workspace'}
isOpen={isOpen}
setIsOpen={setIsOpen}
Expand All @@ -76,16 +68,12 @@ describe('CreateProjectWorkspaceDialog', () => {
.contains('user1@example.com')
.should('be.visible');
cy.get('ui5-button[icon="delete"]').find('button').click({ force: true });
cy.get('span[id="members-error"]')
.contains('You need to have at least one member assigned.')
.should('be.visible');
cy.get('span[id="members-error"]').contains('You need to have at least one member assigned.').should('be.visible');
});

it('should add a new member and display it in the table', () => {
cy.mount(<CreateProjectWorkspaceDialogWrapper />, {});
cy.get('ui5-input[id*="member-email-input"]')
.find('input[id*="inner"]')
.type('user2@example.com', { force: true });
cy.get('ui5-input[id*="member-email-input"]').find('input[id*="inner"]').type('user2@example.com', { force: true });
cy.get('ui5-button:contains("Add")').click({ force: true });
cy.get('div[data-component-name="AnalyticalTableContainerWithScrollbar"]')
.contains('user2@example.com')
Expand All @@ -96,25 +84,21 @@ describe('CreateProjectWorkspaceDialog', () => {
const stubFn = cy.stub().as('stubFn');
cy.mount(<CreateProjectWorkspaceDialogWrapper spyFormBody={stubFn} />, {});

cy.get('ui5-input[id*="name"]')
.find('input[id*="inner"]')
.type('brand--01', { force: true });
cy.get('ui5-input[id*="name"]').find('input[id*="inner"]').type('brand--01', { force: true });
cy.get('ui5-input[id*="displayName"]')
.find('input[id*="inner"]')
.type('Brand new workspace number one', { force: true });
cy.get('ui5-input[id*="chargingTarget"]')
.find('input[id*="inner"]')
.type('Charging target 1000', { force: true });
cy.get('ui5-input[id*="email"]')
.find('input[id*="inner"]')
.type('user2@example.com', { force: true });
.type('aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa', { force: true });
cy.get('ui5-input[id*="email"]').find('input[id*="inner"]').type('user2@example.com', { force: true });
cy.get('ui5-button:contains("Add")').click({ force: true });
cy.get('ui5-button:contains("Create")').click({ force: true });

cy.get('@stubFn').should('have.been.calledWith', {
name: 'brand--01',
displayName: 'Brand new workspace number one',
chargingTarget: 'Charging target 1000',
chargingTarget: 'aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa',
members: [
{
name: 'user1@example.com',
Expand Down Expand Up @@ -143,9 +127,7 @@ describe('CreateProjectWorkspaceDialog', () => {
});

newMembers.forEach((email) => {
cy.get('div[data-component-name="AnalyticalTableContainerWithScrollbar"]')
.contains(email)
.should('be.visible');
cy.get('div[data-component-name="AnalyticalTableContainerWithScrollbar"]').contains(email).should('be.visible');
});
});

Expand Down
26 changes: 7 additions & 19 deletions src/components/Dialogs/CreateProjectDialogContainer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,7 @@ import { useCallback, useEffect, useRef } from 'react';
import { useApiResourceMutation } from '../../lib/api/useApiResource';
import { ErrorDialogHandle } from '../Shared/ErrorMessageBox.tsx';
import { APIError } from '../../lib/api/error';
import {
CreateProjectWorkspaceDialog,
OnCreatePayload,
} from './CreateProjectWorkspaceDialog.tsx';
import { CreateProjectWorkspaceDialog, OnCreatePayload } from './CreateProjectWorkspaceDialog.tsx';

import { useToast } from '../../context/ToastContext.tsx';
import { useAuthOnboarding } from '../../spaces/onboarding/auth/AuthContextOnboarding.tsx';
Expand All @@ -14,11 +11,7 @@ import { MemberRoles } from '../../lib/api/types/shared/members.ts';
import { useTranslation } from 'react-i18next';
import { zodResolver } from '@hookform/resolvers/zod';
import { useForm } from 'react-hook-form';
import {
CreateProject,
CreateProjectResource,
CreateProjectType,
} from '../../lib/api/types/crate/createProject.ts';
import { CreateProject, CreateProjectResource, CreateProjectType } from '../../lib/api/types/crate/createProject.ts';
import { validationSchemaProjectWorkspace } from '../../lib/api/validations/schemas.ts';
import { CreateDialogProps } from './CreateWorkspaceDialogContainer.tsx';

Expand All @@ -30,12 +23,12 @@ export function CreateProjectDialogContainer({
setIsOpen: (isOpen: boolean) => void;
}) {
const {
watch,
register,
handleSubmit,
resetField,
setValue,
formState: { errors },
watch,
} = useForm<CreateDialogProps>({
resolver: zodResolver(validationSchemaProjectWorkspace),
defaultValues: {
Expand All @@ -59,9 +52,7 @@ export function CreateProjectDialogContainer({

useEffect(() => {
if (username) {
setValue('members', [
{ name: username, roles: [MemberRoles.admin], kind: 'User' },
]);
setValue('members', [{ name: username, roles: [MemberRoles.admin], kind: 'User' }]);
}
if (!isOpen) {
clearForm();
Expand All @@ -70,9 +61,7 @@ export function CreateProjectDialogContainer({

const toast = useToast();

const { trigger } = useApiResourceMutation<CreateProjectType>(
CreateProjectResource(),
);
const { trigger } = useApiResourceMutation<CreateProjectType>(CreateProjectResource());

const errorDialogRef = useRef<ErrorDialogHandle>(null);

Expand All @@ -99,9 +88,7 @@ export function CreateProjectDialogContainer({
console.error(e);
if (e instanceof APIError) {
if (errorDialogRef.current) {
errorDialogRef.current.showErrorDialog(
`${e.message}: ${JSON.stringify(e.info)}`,
);
errorDialogRef.current.showErrorDialog(`${e.message}: ${JSON.stringify(e.info)}`);
}
}
return false;
Expand All @@ -110,6 +97,7 @@ export function CreateProjectDialogContainer({

return (
<CreateProjectWorkspaceDialog
watch={watch}
isOpen={isOpen}
setIsOpen={setIsOpen}
errorDialogRef={errorDialogRef}
Expand Down
28 changes: 9 additions & 19 deletions src/components/Dialogs/CreateProjectWorkspaceDialog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import { EditMembers } from '../Members/EditMembers.tsx';
import { useTranslation } from 'react-i18next';

import { CreateDialogProps } from './CreateWorkspaceDialogContainer.tsx';
import { FieldErrors, UseFormRegister, UseFormSetValue } from 'react-hook-form';
import { FieldErrors, UseFormWatch, UseFormRegister, UseFormSetValue } from 'react-hook-form';
import { MetadataForm } from './MetadataForm.tsx';

export type OnCreatePayload = {
Expand All @@ -36,6 +36,7 @@ export interface CreateProjectWorkspaceDialogProps {
setValue: UseFormSetValue<CreateDialogProps>;
projectName?: string;
type: 'workspace' | 'project';
watch: UseFormWatch<CreateDialogProps>;
}

export function CreateProjectWorkspaceDialog({
Expand All @@ -50,6 +51,7 @@ export function CreateProjectWorkspaceDialog({
setValue,
projectName,
type,
watch,
}: CreateProjectWorkspaceDialogProps) {
const { t } = useTranslation();
const [isKubectlDialogOpen, setIsKubectlDialogOpen] = useState(false);
Expand All @@ -71,13 +73,9 @@ export function CreateProjectWorkspaceDialog({
<Bar
design="Footer"
endContent={
<div
style={{ display: 'flex', alignItems: 'center', gap: '8px' }}
>
<div style={{ display: 'flex', alignItems: 'center', gap: '8px' }}>
<KubectlInfoButton onClick={openKubectlDialog} />
<Button onClick={() => setIsOpen(false)}>
{t('CreateProjectWorkspaceDialog.cancelButton')}
</Button>
<Button onClick={() => setIsOpen(false)}>{t('CreateProjectWorkspaceDialog.cancelButton')}</Button>
<Button design="Emphasized" onClick={() => onCreate()}>
{t('CreateProjectWorkspaceDialog.createButton')}
</Button>
Expand All @@ -88,19 +86,14 @@ export function CreateProjectWorkspaceDialog({
onClose={() => setIsOpen(false)}
>
<MetadataForm
watch={watch}
register={register}
errors={errors}
setValue={setValue}
requireChargingTarget={type === 'project'}
sideFormContent={
<FormGroup
headerText={t('CreateProjectWorkspaceDialog.membersHeader')}
>
<EditMembers
members={members}
isValidationError={!!errors.members}
onMemberChanged={setMembers}
/>
<FormGroup headerText={t('CreateProjectWorkspaceDialog.membersHeader')}>
<EditMembers members={members} isValidationError={!!errors.members} onMemberChanged={setMembers} />
</FormGroup>
}
/>
Expand All @@ -110,10 +103,7 @@ export function CreateProjectWorkspaceDialog({
isOpen={isKubectlDialogOpen && !!projectName}
onClose={closeKubectlDialog}
/>
<KubectlCreateProjectDialog
isOpen={isKubectlDialogOpen && !projectName}
onClose={closeKubectlDialog}
/>
<KubectlCreateProjectDialog isOpen={isKubectlDialogOpen && !projectName} onClose={closeKubectlDialog} />
<ErrorDialog ref={errorDialogRef} />
</>
);
Expand Down
23 changes: 6 additions & 17 deletions src/components/Dialogs/CreateWorkspaceDialogContainer.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,8 @@
import { useCallback, useEffect, useRef } from 'react';
import {
useApiResourceMutation,
useRevalidateApiResource,
} from '../../lib/api/useApiResource';
import { useApiResourceMutation, useRevalidateApiResource } from '../../lib/api/useApiResource';
import { ErrorDialogHandle } from '../Shared/ErrorMessageBox.tsx';
import { APIError } from '../../lib/api/error';
import {
CreateProjectWorkspaceDialog,
OnCreatePayload,
} from './CreateProjectWorkspaceDialog.tsx';
import { CreateProjectWorkspaceDialog, OnCreatePayload } from './CreateProjectWorkspaceDialog.tsx';
import {
CreateWorkspace,
CreateWorkspaceResource,
Expand Down Expand Up @@ -73,9 +67,7 @@ export function CreateWorkspaceDialogContainer({

useEffect(() => {
if (username) {
setValue('members', [
{ name: username, roles: [MemberRoles.admin], kind: 'User' },
]);
setValue('members', [{ name: username, roles: [MemberRoles.admin], kind: 'User' }]);
}
if (!isOpen) {
clearForm();
Expand All @@ -84,9 +76,7 @@ export function CreateWorkspaceDialogContainer({
const namespace = projectnameToNamespace(project);
const toast = useToast();

const { trigger } = useApiResourceMutation<CreateWorkspaceType>(
CreateWorkspaceResource(namespace),
);
const { trigger } = useApiResourceMutation<CreateWorkspaceType>(CreateWorkspaceResource(namespace));
const revalidate = useRevalidateApiResource(ListWorkspaces(project));
const errorDialogRef = useRef<ErrorDialogHandle>(null);

Expand All @@ -112,9 +102,7 @@ export function CreateWorkspaceDialogContainer({
console.error(e);
if (e instanceof APIError) {
if (errorDialogRef.current) {
errorDialogRef.current.showErrorDialog(
`${e.message}: ${JSON.stringify(e.info)}`,
);
errorDialogRef.current.showErrorDialog(`${e.message}: ${JSON.stringify(e.info)}`);
}
}
return false;
Expand All @@ -123,6 +111,7 @@ export function CreateWorkspaceDialogContainer({

return (
<CreateProjectWorkspaceDialog
watch={watch}
isOpen={isOpen}
setIsOpen={setIsOpen}
errorDialogRef={errorDialogRef}
Expand Down
Loading
Loading