fix: rename time entry form to project time entry form.

This commit is contained in:
elforjani13
2022-07-06 13:42:15 +02:00
parent bcf0ec25b8
commit 7ef7e126e5
14 changed files with 169 additions and 232 deletions

View File

@@ -3,17 +3,19 @@ import intl from 'react-intl-universal';
import { DATATYPES_LENGTH } from 'common/dataTypes';
const Schema = Yup.object().shape({
date: Yup.date().label(intl.get('time_entry.schema.label.date')).required(),
date: Yup.date()
.label(intl.get('project_time_entry.schema.label.date'))
.required(),
projectId: Yup.string()
.label(intl.get('time_entry.schema.label.project_name'))
.label(intl.get('project_time_entry.schema.label.project_name'))
.required(),
taskId: Yup.string()
.label(intl.get('time_entry.schema.label.task_name'))
.label(intl.get('project_time_entry.schema.label.task_name'))
.required(),
description: Yup.string().nullable().max(DATATYPES_LENGTH.TEXT),
duration: Yup.string()
.label(intl.get('time_entry.schema.label.duration'))
.label(intl.get('project_time_entry.schema.label.duration'))
.required(),
});
export const CreateTimeEntryFormSchema = Schema;
export const CreateProjectTimeEntryFormSchema = Schema;

View File

@@ -5,9 +5,9 @@ import intl from 'react-intl-universal';
import { Formik } from 'formik';
import { AppToaster } from 'components';
import TimeEntryFormContent from './TimeEntryFormContent';
import { CreateTimeEntryFormSchema } from './TimeEntryForm.schema';
import { useTimeEntryFormContext } from './TimeEntryFormProvider';
import ProjectTimeEntryFormContent from './ProjectTimeEntryFormContent';
import { CreateProjectTimeEntryFormSchema } from './ProjectTimeEntryForm.schema';
import { useProjectTimeEntryFormContext } from './ProjectTimeEntryFormProvider';
import withDialogActions from 'containers/Dialog/withDialogActions';
import { compose } from 'utils';
@@ -21,15 +21,15 @@ const defaultInitialValues = {
};
/**
* Time entry form.
* Project Time entry form.
* @returns
*/
function TimeEntryForm({
function ProjectTimeEntryForm({
// #withDialogActions
closeDialog,
}) {
// time entry form dialog context.
const { dialogName } = useTimeEntryFormContext();
const { dialogName } = useProjectTimeEntryFormContext();
// Initial form values
const initialValues = {
@@ -58,12 +58,12 @@ function TimeEntryForm({
return (
<Formik
validationSchema={CreateTimeEntryFormSchema}
validationSchema={CreateProjectTimeEntryFormSchema}
initialValues={initialValues}
onSubmit={handleFormSubmit}
component={TimeEntryFormContent}
component={ProjectTimeEntryFormContent}
/>
);
}
export default compose(withDialogActions)(TimeEntryForm);
export default compose(withDialogActions)(ProjectTimeEntryForm);

View File

@@ -0,0 +1,17 @@
import React from 'react';
import { Form } from 'formik';
import ProjectTimeEntryFormFields from './ProjectTimeEntryFormFields';
import ProjectTimeEntryFormFloatingActions from './ProjectTimeEntryFormFloatingActions';
/**
* Time entry form content.
* @returns
*/
export default function TimeEntryFormContent() {
return (
<Form>
<ProjectTimeEntryFormFields />
<ProjectTimeEntryFormFloatingActions />
</Form>
);
}

View File

@@ -0,0 +1,24 @@
import React from 'react';
import { ProjectTimeEntryFormProvider } from './ProjectTimeEntryFormProvider';
import ProjectTimeEntryForm from './ProjectTimeEntryForm';
/**
* Project time entry form dialog content.
* @returns {ReactNode}
*/
export default function ProjectTimeEntryFormDialogContent({
// #ownProps
dialogName,
project,
timeEntry,
}) {
return (
<ProjectTimeEntryFormProvider
projectId={project}
timeEntryId={timeEntry}
dialogName={dialogName}
>
<ProjectTimeEntryForm />
</ProjectTimeEntryFormProvider>
);
}

View File

@@ -18,16 +18,16 @@ import { ProjectSelect, TaskSelect } from './components';
import { momentFormatter } from 'utils';
/**
* Time entry form fields.
* Project time entry form fields.
* @returns
*/
function TimeEntryFormFields() {
function ProjectTimeEntryFormFields() {
return (
<div className={Classes.DIALOG_BODY}>
{/*------------ Project -----------*/}
<FFormGroup
name={'projectId'}
label={<T id={'time_entry.dialog.project'} />}
label={<T id={'project_time_entry.dialog.project'} />}
labelInfo={<FieldRequiredHint />}
className={classNames('form-group--select-list', Classes.FILL)}
>
@@ -40,7 +40,7 @@ function TimeEntryFormFields() {
{/*------------ Task -----------*/}
<FFormGroup
name={'taskId'}
label={<T id={'time_entry.dialog.task'} />}
label={<T id={'project_time_entry.dialog.task'} />}
labelInfo={<FieldRequiredHint />}
className={classNames('form-group--select-list', Classes.FILL)}
>
@@ -53,7 +53,7 @@ function TimeEntryFormFields() {
{/*------------ Duration -----------*/}
<FFormGroup
label={intl.get('time_entry.dialog.duration')}
label={intl.get('project_time_entry.dialog.duration')}
name={'duration'}
labelInfo={<FieldRequiredHint />}
>
@@ -61,7 +61,7 @@ function TimeEntryFormFields() {
</FFormGroup>
{/*------------ Date -----------*/}
<FFormGroup
label={intl.get('time_entry.dialog.date')}
label={intl.get('project_time_entry.dialog.date')}
name={'date'}
className={classNames(CLASSES.FILL, 'form-group--date')}
>
@@ -78,20 +78,13 @@ function TimeEntryFormFields() {
{/*------------ Description -----------*/}
<FFormGroup
name={'description'}
label={intl.get('time_entry.dialog.description')}
label={intl.get('project_time_entry.dialog.description')}
className={'form-group--description'}
>
<FTextArea name={'description'} />
{/* <FEditableText
multiline={true}
// minLines={1.78}
// maxLines={1.78}
name={'description'}
placeholder=""
/> */}
</FFormGroup>
</div>
);
}
export default TimeEntryFormFields;
export default ProjectTimeEntryFormFields;

View File

@@ -3,20 +3,20 @@ import React from 'react';
import { useFormikContext } from 'formik';
import { Intent, Button, Classes } from '@blueprintjs/core';
import { FormattedMessage as T } from 'components';
import { useTimeEntryFormContext } from './TimeEntryFormProvider';
import { useProjectTimeEntryFormContext } from './ProjectTimeEntryFormProvider';
import withDialogActions from 'containers/Dialog/withDialogActions';
import { compose } from 'utils';
/**
* Time entry form floating actions.
* Projcet time entry form floating actions.
* @returns
*/
function TimeEntryFormFloatingActions({
function ProjectTimeEntryFormFloatingActions({
// #withDialogActions
closeDialog,
}) {
// time entry form dialog context.
const { dialogName } = useTimeEntryFormContext();
const { dialogName } = useProjectTimeEntryFormContext();
// Formik context.
const { isSubmitting } = useFormikContext();
@@ -45,4 +45,4 @@ function TimeEntryFormFloatingActions({
);
}
export default compose(withDialogActions)(TimeEntryFormFloatingActions);
export default compose(withDialogActions)(ProjectTimeEntryFormFloatingActions);

View File

@@ -0,0 +1,32 @@
//@ts-nocheck
import React from 'react';
import { DialogContent } from 'components';
const ProjecctTimeEntryFormContext = React.createContext();
/**
* Project time entry form provider.
* @returns
*/
function ProjectTimeEntryFormProvider({
// #ownProps
dialogName,
projectId,
timeEntryId,
...props
}) {
const provider = {
dialogName,
};
return (
<DialogContent>
<ProjecctTimeEntryFormContext.Provider value={provider} {...props} />
</DialogContent>
);
}
const useProjectTimeEntryFormContext = () =>
React.useContext(ProjecctTimeEntryFormContext);
export { ProjectTimeEntryFormProvider, useProjectTimeEntryFormContext };

View File

@@ -0,0 +1,67 @@
import React from 'react';
import styled from 'styled-components';
import { Dialog, DialogSuspense, FormattedMessage as T } from 'components';
import withDialogRedux from 'components/DialogReduxConnect';
import { compose } from 'utils';
const ProjectTimeEntryFormDialogContent = React.lazy(
() => import('./ProjectTimeEntryFormDialogContent'),
);
/**
* Project time entry form dialog.
* @returns
*/
function ProjectTimeEntryFormDialog({
dialogName,
isOpen,
payload: { projectId = null, timeEntryId = null },
}) {
return (
<ProjectTimeEntryFormDialogRoot
name={dialogName}
title={<T id={'project_time_entry.dialog.label'} />}
isOpen={isOpen}
autoFocus={true}
canEscapeKeyClose={true}
style={{ width: '400px' }}
>
<DialogSuspense>
<ProjectTimeEntryFormDialogContent
dialogName={dialogName}
project={projectId}
timeEntry={timeEntryId}
/>
</DialogSuspense>
</ProjectTimeEntryFormDialogRoot>
);
}
export default compose(withDialogRedux())(ProjectTimeEntryFormDialog);
const ProjectTimeEntryFormDialogRoot = styled(Dialog)`
.bp3-dialog-body {
.bp3-form-group {
margin-bottom: 15px;
label.bp3-label {
margin-bottom: 3px;
font-size: 13px;
}
}
.form-group {
&--description {
.bp3-form-content {
textarea {
width: 100%;
min-width: 100%;
font-size: 14px;
}
}
}
}
}
.bp3-dialog-footer {
padding-top: 10px;
}
`;

View File

@@ -1,17 +0,0 @@
import React from 'react';
import { Form } from 'formik';
import TimeEntryFormFields from './TimeEntryFormFields';
import TimeEntryFormFloatingActions from './TimeEntryFormFloatingActions';
/**
* Time entry form content.
* @returns
*/
export default function TimeEntryFormContent() {
return (
<Form>
<TimeEntryFormFields />
<TimeEntryFormFloatingActions />
</Form>
);
}

View File

@@ -1,24 +0,0 @@
import React from 'react';
import { TimeEntryFormProvider } from './TimeEntryFormProvider';
import TimeEntryForm from './TimeEntryForm';
/**
* Time entry form dialog content.
* @returns {ReactNode}
*/
export default function TimeEntryFormDialogContent({
// #ownProps
dialogName,
project,
timeEntry,
}) {
return (
<TimeEntryFormProvider
projectId={project}
timeEntryId={timeEntry}
dialogName={dialogName}
>
<TimeEntryForm />
</TimeEntryFormProvider>
);
}

View File

@@ -1,31 +0,0 @@
//@ts-nocheck
import React from 'react';
import { DialogContent } from 'components';
const TimeEntryFormContext = React.createContext();
/**
* Time entry form provider.
* @returns
*/
function TimeEntryFormProvider({
// #ownProps
dialogName,
projectId,
timeEntryId,
...props
}) {
const provider = {
dialogName,
};
return (
<DialogContent>
<TimeEntryFormContext.Provider value={provider} {...props} />
</DialogContent>
);
}
const useTimeEntryFormContext = () => React.useContext(TimeEntryFormContext);
export { TimeEntryFormProvider, useTimeEntryFormContext };

View File

@@ -1,63 +0,0 @@
import React from 'react';
import intl from 'react-intl-universal';
import { MenuItem, Button } from '@blueprintjs/core';
import { FSelect } from '../../../../../components/Forms';
/**
*
* @param {*} query
* @param {*} project
* @param {*} _index
* @param {*} exactMatch
* @returns
*/
const projectItemPredicate = (query, project, _index, exactMatch) => {
const normalizedTitle = project.name.toLowerCase();
const normalizedQuery = query.toLowerCase();
if (exactMatch) {
return normalizedTitle === normalizedQuery;
} else {
return `${project.name}. ${normalizedTitle}`.indexOf(normalizedQuery) >= 0;
}
};
/**
*
* @param {*} project
* @param {*} param1
* @returns
*/
const projectItemRenderer = (project, { handleClick, modifiers, query }) => {
return (
<MenuItem
active={modifiers.active}
disabled={modifiers.disabled}
key={project.id}
onClick={handleClick}
text={project.name}
/>
);
};
const projectSelectProps = {
// itemPredicate: projectItemPredicate,
itemRenderer: projectItemRenderer,
valueAccessor: 'id',
labelAccessor: 'name',
};
export function ProjectSelect({ projects, ...rest }) {
return (
<FSelect
items={projects}
{...projectSelectProps}
{...rest}
input={ProjectSelectButton}
/>
);
}
function ProjectSelectButton({ label }) {
return <Button text={label ? label : intl.get('find_or_choose_a_project')} />;
}

View File

@@ -1,63 +0,0 @@
import React from 'react';
import intl from 'react-intl-universal';
import { MenuItem, Button } from '@blueprintjs/core';
import { FSelect } from '../../../../../components/Forms';
/**
*
* @param {*} query
* @param {*} task
* @param {*} _index
* @param {*} exactMatch
* @returns
*/
const taskItemPredicate = (query, task, _index, exactMatch) => {
const normalizedTitle = task.name.toLowerCase();
const normalizedQuery = query.toLowerCase();
if (exactMatch) {
return normalizedTitle === normalizedQuery;
} else {
return `${task.name}. ${normalizedTitle}`.indexOf(normalizedQuery) >= 0;
}
};
/**
*
* @param {*} task
* @param {*} param1
* @returns
*/
const taskItemRenderer = (task, { handleClick, modifiers, query }) => {
return (
<MenuItem
active={modifiers.active}
disabled={modifiers.disabled}
key={task.id}
onClick={handleClick}
text={task.name}
/>
);
};
const taskSelectProps = {
itemPredicate: taskItemPredicate,
itemRenderer: taskItemRenderer,
valueAccessor: 'id',
labelAccessor: 'name',
};
export function TaskSelect({ tasks, ...rest }) {
return (
<FSelect
items={tasks}
{...taskSelectProps}
{...rest}
input={TaskSelectButton}
/>
);
}
function TaskSelectButton({ label }) {
return <Button text={label ? label : intl.get('choose_a_task')} />;
}