Skip to content

Commit

Permalink
some features included
Browse files Browse the repository at this point in the history
- id_code gui component form validation
- language selector
- experiment publish action
- some translations included
  • Loading branch information
manoutbar committed May 26, 2022
1 parent c840ef4 commit 24ecf38
Show file tree
Hide file tree
Showing 12 changed files with 101 additions and 24 deletions.
11 changes: 9 additions & 2 deletions src/app/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,6 @@ import CssBaseline from '@mui/material/CssBaseline';
import Typography from '@mui/material/Typography';
import Container from '@mui/material/Container';
import Button from '@mui/material/Button';
import IconButton from '@mui/material/IconButton';
import LogoutIcon from '@mui/icons-material/Logout';
import { styled } from '@mui/system';
import { useTranslation } from "react-i18next";
import 'infrastructure/i18n/config';
Expand All @@ -35,12 +33,17 @@ import UserProfile from 'features/user/Profile';
import Theme from 'styles/theme';
import PrivateRoute from './helpers/PrivateRoute';
import PublicExperimentsList from 'features/experiment/PublicExperimentsList';
import LanguageSelector from 'features/language/languageSelector';

const StyledContainer = styled(Container)(({ theme }) => ({
backgroundColor: theme.palette.background.default,
marginTop: theme.spacing(3)
}))

const LanguageSelectorContainer = styled('div')(({ theme }) => ({
marginRight: theme.spacing(2)
}))

const NotificationsContainer = styled('div')(({ theme }) => ({
position: 'absolute',
top: '64px', // under header bar
Expand Down Expand Up @@ -76,6 +79,10 @@ function App() {
</Button>
<Spacer />

<LanguageSelectorContainer>
<LanguageSelector />
</LanguageSelectorContainer>

{
isAuth ? (
<UserMenu>
Expand Down
Binary file added src/assets/lang-thumbnails/english.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added src/assets/lang-thumbnails/spanish.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
9 changes: 7 additions & 2 deletions src/features/experiment/Details.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -139,15 +139,20 @@ const ExperimentDetails: React.FC = () => {
checked={experiment.isPublic}
onChange={() => {
const experimentData: any = experimentToFormData(experiment);
experimentData.set('public', true);
const newValue = !experiment.isPublic;
experimentData.set('public', newValue);
console.log('experimentToFormData', [...experimentData.entries()]);
dispatch(saveExperiment(experimentData, () => {
const notification = NotificationFactory.success(`Experiment "${experiment.name}" successfully published`)
const notification = NotificationFactory.success(`Experiment "${experiment.name}" successfully ${newValue ? 'published' : 'unpublished'}`)
.dismissible()
.build();

setTimeout(() => {
dispatch(showNotification(notification));
setExperimentInList({
...experiment,
isPublic: newValue
})
}, 0)
}))
}}
Expand Down
4 changes: 2 additions & 2 deletions src/features/experiment/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,8 @@ export function experimentDTOToExperimentType(experiment: ExperimentDTO): Experi
sizeBalance: experiment.size_balance ?? undefined,
specialColnames: experiment.special_colnames ?? '',
status: '',
isPublic: true,
author: 'First Second LastName'
isPublic: experiment.public,
author: experiment.user != null ? `${experiment.user.first_name} ${experiment.user.last_name}` : undefined
}
}

Expand Down
38 changes: 38 additions & 0 deletions src/features/language/languageSelector.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import React from 'react';
import { useTranslation } from 'react-i18next'

import { Avatar, MenuItem, Select } from '@mui/material';

import esThumbnail from 'assets/lang-thumbnails/spanish.png';
import enThumbnail from 'assets/lang-thumbnails/english.png';

const LanguageSelector: React.FC = () => {
const { i18n } = useTranslation();
const changeLanguage = (evt: any) => {
i18n.changeLanguage(evt.target.value);
};

console.log('i18n language', i18n.language)
return (
<Select
labelId="demo-simple-select-label"
id="demo-simple-select"
value={ i18n.language }
label="Age"
onChange={ changeLanguage }
sx={{
'&, & .MuiOutlinedInput-notchedOutline': {
border: 'none',
}
}}
>
<MenuItem value="es">
<Avatar alt="Cindy Baker" src={ esThumbnail } />
</MenuItem>
<MenuItem value="en">
<Avatar alt="Cindy Baker" src={ enThumbnail } />
</MenuItem>
</Select>
)
}
export default LanguageSelector;
37 changes: 25 additions & 12 deletions src/features/user/GUIComponentsCatalog/Form.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import React, { useContext, useState } from 'react';
import { Button, Grid, MenuItem, Select, TextField, Theme } from '@mui/material';
import React, { useContext } from 'react';
import { Button, FormHelperText, Grid, MenuItem, Select, TextField, Theme } from '@mui/material';
import { ThemeContext } from '@mui/styled-engine';
import SaveIcon from '@mui/icons-material/Save';
import { useTranslation } from 'react-i18next';
Expand All @@ -13,20 +13,25 @@ import { objectToFormData } from 'infrastructure/util/form';
import Spacer from 'components/Spacer';

import { GUIComponentCategoryType, GUIComponentType } from './types';
import GUIComponentRepository from 'infrastructure/repositories/gui-component';
import { useSelector } from 'react-redux';
import { authSelector } from 'features/auth/slice';

export interface CreateGUIComponentFormProps {
onSubmit: any
disabled?: boolean,
initialValues?: any,
disabled?: boolean
initialValues?: any
categories: GUIComponentCategoryType[]
repository: GUIComponentRepository
}

const CreateGUIComponentForm: React.FC<CreateGUIComponentFormProps> = ({ onSubmit, disabled = false, initialValues = {}, categories }) => {
const CreateGUIComponentForm: React.FC<CreateGUIComponentFormProps> = ({ onSubmit, disabled = false, initialValues = {}, categories, repository }) => {
const theme = useContext(ThemeContext) as Theme;
const [, updateState] = React.useState();
const forceUpdate = React.useCallback(() => updateState({} as any), []);
const { t } = useTranslation();
const { register, formState, handleSubmit, getValues, setValue, setError } = useForm();
const { token } = useSelector(authSelector);
const { register, formState, handleSubmit, getValues, setValue, setError, clearErrors } = useForm();

const thumbnailField = register('thumbnail');

Expand Down Expand Up @@ -99,12 +104,17 @@ const CreateGUIComponentForm: React.FC<CreateGUIComponentFormProps> = ({ onSubmi
placeholder={t('features.user.gui-components.form.idCode.placeholder')}
inputProps={
register('id_code', {
value: initialValues.idCode
value: initialValues.idCode,
validate: async(value) => {
const existsResponse = await repository.checkIdCode(value, token ?? '');
console.log('validate id_code', value, 'exists', existsResponse);
return !existsResponse.exists || t('features.user.gui-components.form.errors.idCodeMustBeUnique') as string;
}
})
}
error={formState.errors.idCode != null}
helperText={formState.errors.idCode?.message}
disabled={ disabled }
error={formState.errors.id_code != null}
helperText={formState.errors.id_code?.message}
disabled={ initialValues.id_code != null || disabled }
/>
</TextInputContainer>
</FormInput>
Expand Down Expand Up @@ -138,7 +148,8 @@ const CreateGUIComponentForm: React.FC<CreateGUIComponentFormProps> = ({ onSubmi
error={formState.errors.category != null}
value={ (getValues('category') || initialValues.category) ?? '' }
onChange={ (evt) => {
setValue('category', evt.target.value);
setValue('category', evt.target.value, { shouldValidate: true });
clearErrors('category');
forceUpdate();
}}
style={{ width: '100%', maxWidth: '400px', marginRight: theme.spacing(4) }}
Expand All @@ -150,7 +161,9 @@ const CreateGUIComponentForm: React.FC<CreateGUIComponentFormProps> = ({ onSubmi
>{ category.name }</MenuItem>
)) }
</Select>

{ formState.errors.category != null && (
<FormHelperText>{ formState.errors.category?.message }</FormHelperText>
)}
</FormInput>

<FormInput
Expand Down
8 changes: 4 additions & 4 deletions src/features/user/GUIComponentsCatalog/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,13 @@ import AddCircleIcon from '@mui/icons-material/AddCircle';

import { useSelector } from 'react-redux';
import { authSelector } from 'features/auth/slice';
import { guiComponentRepository } from 'features/experiment/wizard/slice';
import CenteredModal from 'components/CenteredModal';

import GUIComponentsList from './List';
import { GUIComponentCategoryType, GUIComponentType } from './types';
import CreateGUIComponentForm from './Form';
import { guiComponentRepository } from 'features/experiment/wizard/slice';
import { guiComponentDTOToGUIComponent } from '../utils';


export interface GUIComponentsCatalogProps {
Expand Down Expand Up @@ -139,10 +140,9 @@ const GUIComponentsCatalog: React.FC<GUIComponentsCatalogProps> = (props) => {
<CreateGUIComponentForm
onSubmit={ async (guiComponentData: any) => {
console.log('TODO: handle gui component creation form submit', guiComponentData);

const isNewComponent = typeof (initialValues as any).id === 'number';
const result = await guiComponentRepository.save(guiComponentData, token ?? '');
const guiComponent = await guiComponentRepository.get(result.id, token ?? '');
const guiComponent = guiComponentDTOToGUIComponent(await guiComponentRepository.get(result.id, token ?? ''));

// temp method to add and display saved gui-component
if (isNewComponent) {
Expand All @@ -153,11 +153,11 @@ const GUIComponentsCatalog: React.FC<GUIComponentsCatalogProps> = (props) => {

setCreationModal(false);
setInitialValues({});

}}
disabled={ guiComponentsLoading }
categories={ categories }
initialValues={ initialValues }
repository={ guiComponentRepository }
/>
</CenteredModal>

Expand Down
2 changes: 2 additions & 0 deletions src/infrastructure/http/dto/experiment.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,12 @@ export interface ExperimentDTO {
last_edition: string
foldername: string
is_active: boolean
public: boolean,
scenarios_conf: any
screenshots_path: string
size_balance: any
status: string
user?: any
}

export interface ExperimentResponse {
Expand Down
3 changes: 2 additions & 1 deletion src/infrastructure/i18n/locales/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -710,7 +710,8 @@
"categoryRequired": "Please select a valida category",
"thumbnailRequired": "Please select an image",
"idCodeRequired": "Please enter an unique identifier",
"idCodeMustNotContainsWhiteSpace": "The unique identifier must not contains white spaces"
"idCodeMustNotContainsWhiteSpace": "The unique identifier must not contains white spaces",
"idCodeMustBeUnique": "This identifier is being used by another component"
}
}
}
Expand Down
3 changes: 2 additions & 1 deletion src/infrastructure/i18n/locales/es.json
Original file line number Diff line number Diff line change
Expand Up @@ -716,7 +716,8 @@
"categoryRequired": "Por favor, seleccione una categoría",
"thumbnailRequired": "Por favor, introduzca una imagen",
"idCodeRequired": "Por favor, introduzca un identificador único",
"idCodeMustNotContainsWhiteSpace": "El identificador no puede contener espacios en blanco"
"idCodeMustNotContainsWhiteSpace": "El identificador no puede contener espacios en blanco",
"idCodeMustBeUnique": "El identificador introducido ya está siendo utilizado"
}
}
}
Expand Down
10 changes: 10 additions & 0 deletions src/infrastructure/repositories/gui-component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,16 @@ export default class GUIComponentRepository {
}
}

async checkIdCode(idCode: string, token: string) {
try {
const params = { id_code: idCode };
return await Http.get<{ exists: boolean }>(Http.buildURL('/gui-component/checkId/', params), Http.authHeader(token))
} catch (ex) {
console.error('error caught checking id_code', ex)
throw ex;
}
}

async get(id: number, token: string) {
try {
return await Http.get<GUIComponentDTO>(Http.buildURL(`/gui-component/${id}/`), Http.authHeader(token))
Expand Down

0 comments on commit 24ecf38

Please sign in to comment.