• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

alkem-io / client-web / #8646

12 Aug 2024 03:08PM UTC coverage: 5.749%. First build
#8646

Pull #6742

travis-ci

Pull Request #6742: Fix VC name validation

188 of 10047 branches covered (1.87%)

Branch coverage included in aggregate %.

0 of 4 new or added lines in 1 file covered. (0.0%)

1409 of 17734 relevant lines covered (7.95%)

0.19 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

0.0
/src/main/topLevelPages/myDashboard/newVirtualContributorWizard/CreateNewVirtualContributor.tsx
1
import { MouseEvent, useState } from 'react';
2
import { useTranslation } from 'react-i18next';
3
import { Form, Formik } from 'formik';
4
import * as yup from 'yup';
5
import { Box, Button, ButtonProps, DialogContent, Tooltip } from '@mui/material';
6
import LibraryBooksOutlined from '@mui/icons-material/LibraryBooksOutlined';
7
import CloudDownloadOutlinedIcon from '@mui/icons-material/CloudDownloadOutlined';
8
import { FormikInputField } from '@/core/ui/forms/FormikInputField/FormikInputField';
9
import DialogHeader from '@/core/ui/dialog/DialogHeader';
10
import { Caption } from '@/core/ui/typography';
11
import { gutters } from '@/core/ui/grid/utils';
12
import Gutters from '@/core/ui/grid/Gutters';
13
import Loading from '@/core/ui/loading/Loading';
14
import LogoSmallImage from '@/main/ui/logo/logoSmall.svg?react';
15
import GridContainer from '@/core/ui/grid/GridContainer';
16
import GridProvider from '@/core/ui/grid/GridProvider';
17
import GridItem from '@/core/ui/grid/GridItem';
18
import { Actions } from '@/core/ui/actions/Actions';
19
import { theme } from '@/core/ui/themes/default/Theme';
20
import { useColumns } from '@/core/ui/grid/GridContext';
21
import FormikMarkdownField from '@/core/ui/forms/MarkdownInput/FormikMarkdownField';
22
import { TranslatedValidatedMessageWithPayload } from '@/domain/shared/i18n/ValidationMessageTranslation';
23
import FormikVisualUpload from '@/core/ui/upload/FormikVisualUpload/FormikVisualUpload';
24
import { VisualUploadModel } from '@/core/ui/upload/VisualUpload/VisualUpload.model';
25
import {
26
  VisualType,
27
  AiPersonaEngine,
28
  VirtualContributorBodyOfKnowledgeType,
29
} from '@/core/apollo/generated/graphql-schema';
30
import { useScreenSize } from '@/core/ui/grid/constants';
31
import { textLengthValidator } from '@/core/ui/forms/validator/textLengthValidator';
32
import { MID_TEXT_LENGTH, MARKDOWN_TEXT_LENGTH } from '@/core/ui/forms/field-length.constants';
33
import MarkdownValidator from '@/core/ui/forms/MarkdownInput/MarkdownValidator';
34

×
35
type CreateNewVirtualContributorProps = {
×
36
  onClose: () => void;
×
37
  onChangeAvatar: (visual: VisualUploadModel) => void;
×
38
  onCreateKnowledge: (values: VirtualContributorFromProps) => void;
39
  onUseExistingKnowledge: (values: VirtualContributorFromProps) => void;
40
  onUseExternal: (values: VirtualContributorFromProps) => void;
41
  loading?: boolean;
42
  titleId?: string;
43
};
44

45
enum VCSourceOptions {
46
  WRITTEN_KNOWLEDGE = 'createSpace',
×
47
  EXISTING_SPACE = 'existingSpace',
48
  EXTERNAL = 'external',
49
}
50

51
export interface VirtualContributorFromProps {
52
  name: string;
53
  tagline: string;
×
54
  description: string;
55
  externalConfig?: {
56
    apiKey?: string;
57
    assistantId?: string;
58
  };
59
  engine: AiPersonaEngine;
60
  bodyOfKnowledgeType: VirtualContributorBodyOfKnowledgeType;
61
}
62

63
const BigButton = ({
×
64
  tooltipDisabled,
×
65
  selected,
66
  startIcon,
67
  ...props
68
}: ButtonProps & { tooltipDisabled?: string; selected?: boolean }) => {
69
  const button = (
70
    <Box display="flex" flexBasis="50%">
71
      <Button
72
        variant="outlined"
73
        startIcon={startIcon}
×
74
        sx={{
75
          flexDirection: 'column',
76
          justifyContent: 'space-between',
×
77
          flexGrow: 1,
78
          gap: gutters(0.5),
79
          textTransform: 'none',
80
          borderColor: selected ? 'primary.main' : 'divider',
81
          opacity: selected ? 1 : 0.9,
82
          paddingTop: gutters(0.5),
×
83
          '&:active': { border: `1px solid ${theme.palette.text.primary};` },
×
84
        }}
×
85
        {...props}
×
86
      />
87
    </Box>
×
88
  );
×
89

90
  return tooltipDisabled && props.disabled ? <Tooltip title={tooltipDisabled}>{button}</Tooltip> : button;
×
91
};
92

93
const CreateNewVirtualContributor = ({
94
  onClose,
95
  onCreateKnowledge,
96
  onUseExistingKnowledge,
×
97
  onUseExternal,
98
  loading,
99
  onChangeAvatar,
100
  titleId,
101
}: CreateNewVirtualContributorProps) => {
102
  const { t } = useTranslation();
×
103
  const { isSmallScreen } = useScreenSize();
×
104

×
105
  const cols = useColumns();
106
  const isMobile = cols < 5;
107

×
NEW
108
  const initialValues: VirtualContributorFromProps = {
×
NEW
109
    name: '',
×
110
    tagline: '',
×
111
    description: '',
NEW
112
    engine: AiPersonaEngine.Expert,
×
113
    bodyOfKnowledgeType: VirtualContributorBodyOfKnowledgeType.AlkemioKnowledgeBase,
×
114
  };
NEW
115

×
116
  const validationSchema = yup.object().shape({
×
117
    name: yup
118
      .string()
×
119
      .trim()
×
120
      .min(3, ({ min }) => TranslatedValidatedMessageWithPayload('forms.validations.minLength')({ min }))
121
      .required(),
122
    tagline: textLengthValidator({ maxLength: MID_TEXT_LENGTH }),
123
    description: MarkdownValidator(MARKDOWN_TEXT_LENGTH),
×
124
  });
125

126
  const [source, setSource] = useState<VCSourceOptions>();
127
  const selectVCSource = (event: MouseEvent<HTMLButtonElement>) => {
×
128
    setSource(event.currentTarget.value as VCSourceOptions);
×
129
  };
130

131
  const handleSubmit = (values: VirtualContributorFromProps) => {
132
    const name = values.name.trim();
133
    const newValues = { ...values, name };
134

135
    switch (source) {
136
      case VCSourceOptions.WRITTEN_KNOWLEDGE:
137
        onCreateKnowledge(newValues);
138
        break;
139
      case VCSourceOptions.EXISTING_SPACE:
140
        onUseExistingKnowledge(newValues);
×
141
        break;
142
      case VCSourceOptions.EXTERNAL:
×
143
        onUseExternal(newValues);
144
        break;
145
    }
146
  };
147

148
  return (
149
    <>
150
      <DialogHeader id={titleId} onClose={onClose} title={t('createVirtualContributorWizard.initial.title')} />
151
      <DialogContent sx={{ paddingTop: 0 }}>
152
        {loading && <Loading />}
153

154
        {!loading && (
155
          <Gutters disablePadding>
156
            <Caption>{t('createVirtualContributorWizard.initial.profileDescription')}</Caption>
157

158
            <GridContainer disablePadding sx={{ display: 'contents' }}>
159
              <GridProvider columns={12}>
160
                <Formik
161
                  initialValues={initialValues}
162
                  validationSchema={validationSchema}
163
                  enableReinitialize
164
                  onSubmit={handleSubmit}
165
                >
×
166
                  {({ isValid }) => {
167
                    return (
168
                      <Form noValidate>
169
                        <GridItem columns={isMobile ? cols : 8}>
170
                          <Gutters disablePadding>
×
171
                            <Gutters disablePadding flexDirection="row">
172
                              <FormikVisualUpload
173
                                flex={1}
174
                                name="visuals.avatar"
175
                                visualType={VisualType.Avatar}
176
                                onChangeAvatar={onChangeAvatar}
177
                              />
178

179
                              <Gutters disablePadding flex={2}>
180
                                <FormikInputField
181
                                  name="name"
182
                                  title={t('components.nameSegment.name')}
183
                                  placeholder={t('components.nameSegment.name')}
184
                                  required
185
                                />
186

187
                                <FormikInputField
188
                                  name="tagline"
189
                                  title={t('components.profileSegment.tagline.name')}
190
                                  placeholder={t('components.profileSegment.tagline.placeholder')}
191
                                />
192
                              </Gutters>
193
                            </Gutters>
194

195
                            <FormikMarkdownField
196
                              name="description"
197
                              title={t('components.profileSegment.description.name')}
198
                              placeholder={t('components.profileSegment.description.placeholder')}
199
                              rows={10}
200
                              multiline
201
                              hideImageOptions
202
                            />
203
                          </Gutters>
204
                        </GridItem>
205
                        <GridItem columns={isMobile ? cols : 8}>
206
                          <Gutters disablePadding paddingTop={gutters()}>
207
                            <Caption>{t('createVirtualContributorWizard.initial.description')}</Caption>
208
                            <Box
209
                              display="flex"
×
210
                              flexDirection={isSmallScreen ? 'column' : 'row'}
211
                              width="100%"
212
                              gap={gutters()}
213
                            >
214
                              <BigButton
215
                                onClick={selectVCSource}
216
                                value={VCSourceOptions.WRITTEN_KNOWLEDGE}
217
                                startIcon={<LibraryBooksOutlined />}
218
                                selected={source === VCSourceOptions.WRITTEN_KNOWLEDGE}
219
                              >
220
                                {t('createVirtualContributorWizard.initial.createSpace')}
221
                                <Caption fontSize={9}>{t('createVirtualContributorWizard.initial.ownAI')}</Caption>
222
                              </BigButton>
223
                              <BigButton
224
                                onClick={selectVCSource}
225
                                value={VCSourceOptions.EXISTING_SPACE}
226
                                startIcon={
227
                                  <Box sx={{ svg: { height: gutters(1.2) } }}>
228
                                    <LogoSmallImage />
229
                                  </Box>
230
                                }
231
                                selected={source === VCSourceOptions.EXISTING_SPACE}
232
                              >
233
                                {t('createVirtualContributorWizard.initial.useExistingSpace')}
234
                                <Caption fontSize={9}>{t('createVirtualContributorWizard.initial.ownAI')}</Caption>
235
                              </BigButton>
236
                              <BigButton
237
                                onClick={selectVCSource}
238
                                value={VCSourceOptions.EXTERNAL}
239
                                startIcon={<CloudDownloadOutlinedIcon />}
240
                                selected={source === VCSourceOptions.EXTERNAL}
241
                              >
242
                                {t('createVirtualContributorWizard.initial.useExternalAI')}
243
                                <Caption fontSize={9}>{t('createVirtualContributorWizard.initial.externalAI')}</Caption>
244
                              </BigButton>
245
                            </Box>
246
                          </Gutters>
247
                        </GridItem>
248
                        <Actions marginTop={theme.spacing(2)} sx={{ justifyContent: 'end', flexBasis: '100%' }}>
249
                          <Button type="submit" variant="contained" disabled={!isValid || !source}>
250
                            {t('buttons.create')}
251
                          </Button>
252
                        </Actions>
253
                      </Form>
254
                    );
255
                  }}
256
                </Formik>
257
              </GridProvider>
258
            </GridContainer>
259
          </Gutters>
260
        )}
261
      </DialogContent>
262
    </>
263
  );
264
};
265

266
export default CreateNewVirtualContributor;
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc