Skip to content

Commit

Permalink
Merge pull request #19 from lexis-solutions/110-bugfixes-improvements…
Browse files Browse the repository at this point in the history
…-dev-36

110 bugfixes improvements dev 36
  • Loading branch information
bmestanov authored Feb 16, 2022
2 parents c100db8 + dcd34d6 commit 754c514
Show file tree
Hide file tree
Showing 9 changed files with 95 additions and 86 deletions.
1 change: 1 addition & 0 deletions .github/workflows/release.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ jobs:
runs-on: ubuntu-latest
env:
PUBLIC_URL: __PUBLIC_URL_PLACEHOLDER__
PUBLIC_DIR_NAME: client
steps:
- name: Checkout
uses: actions/checkout@v2
Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,14 +61,14 @@ app.listen(4000);

### Docker usage

The docker container exposes port 4000

```
docker run -p 4000:4000 \
--env CONNECTION_STRING=mongo://username:password@host/database \
--env COLLECTION=collection lexissolutions/agenda-admin:latest
```

If MongoDB is installed directly on your machine, you can run the command with `--network=host`

#### Docker environment configuration

| name | description | required | default value |
Expand Down
5 changes: 3 additions & 2 deletions build.sh
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
directory=${PUBLIC_DIR_NAME:-public}
yarn --cwd client build --prod
yarn --cwd api build
mkdir ./api/client
cp -R ./client/build/* ./api/client
mkdir ./api/$directory
cp -R ./client/build/* ./api/$directory
cp ./README.md ./api/README.md
10 changes: 5 additions & 5 deletions client/src/components/Footer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ const Footer: React.FC = () => {
if (!data) return null;

return (
<div className="fixed px-4 bottom-0 z-10 flex flex-row items-center justify-between w-full max-w-screen-xl p-2 mx-auto border-t bg-base-100">
<div className="fixed bottom-0 z-10 flex flex-row items-center justify-between w-full max-w-screen-xl p-2 px-4 mx-auto border-t bg-base-100">
<div className="flex flex-row items-center space-x-1">
<div>{jobsMsg} selected</div>
<button
Expand All @@ -89,7 +89,7 @@ const Footer: React.FC = () => {
{selectedJobsCount > 0 && (
<a
href="#bulk-requeue"
className="btn btn-sm btn-ghost text-secondary"
className="btn btn-sm btn-ghost text-warning"
onClick={() => setRenderModals(true)}
>
Requeue Selected
Expand All @@ -98,7 +98,7 @@ const Footer: React.FC = () => {
{selectedJobsCount > 0 && (
<a
href="#bulk-delete"
className="btn btn-sm btn-ghost text-warning"
className="btn btn-sm btn-ghost text-error"
onClick={() => setRenderModals(true)}
>
Delete Selected
Expand All @@ -112,7 +112,7 @@ const Footer: React.FC = () => {
<div className="modal-action">
<a
href="#!"
className="btn btn-primary"
className="btn btn-warning"
onClick={() => {
handleBulkRequeue();
setRenderModals(false);
Expand All @@ -135,7 +135,7 @@ const Footer: React.FC = () => {
<div className="modal-action">
<a
href="#!"
className="btn btn-warning"
className="btn btn-error"
onClick={() => {
handleBulkDelete();
setRenderModals(false);
Expand Down
134 changes: 67 additions & 67 deletions client/src/components/Header.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,13 @@
import { useState } from 'react';
import { useFormik } from 'formik';
import * as Yup from 'yup';
import cx from 'classnames';

import JobFilters from 'src/components/JobFilters';
import JobNamesAutocomplete from 'src/components/JobNamesAutocomplete';
import Modal from 'src/components/Modal';
import Plus from 'src/svgs/Plus';
import { createNewJob } from 'src/api';
import humanInterval from 'human-interval';
import { isUndefined } from 'lodash';
import { useFormik } from 'formik';
import { useState } from 'react';

interface FormValuesType {
name: string;
Expand All @@ -17,48 +16,25 @@ interface FormValuesType {
data?: string;
}

const cronRegex = new RegExp(
/^(\*|([0-9]|1[0-9]|2[0-9]|3[0-9]|4[0-9]|5[0-9])|\*\/([0-9]|1[0-9]|2[0-9]|3[0-9]|4[0-9]|5[0-9])) (\*|([0-9]|1[0-9]|2[0-3])|\*\/([0-9]|1[0-9]|2[0-3])) (\*|([1-9]|1[0-9]|2[0-9]|3[0-1])|\*\/([1-9]|1[0-9]|2[0-9]|3[0-1])) (\*|([1-9]|1[0-2])|\*\/([1-9]|1[0-2])) (\*|([0-6])|\*\/([0-6]))$/
);

const createJobSchema = Yup.object().shape({
name: Yup.string().required('Job name is required!'),
schedule: Yup.string()
.test('valid-human-interval', 'Invalid time format', (value) => {
const time = humanInterval(value);
return !isNaN(Number(value)) || isUndefined(time) || !isNaN(time);
})
.when('repeatInterval', {
is: (repeatInterval: string | undefined) => !repeatInterval,
then: Yup.string().required(
'Either a schedule or a repeat interval must be provided!'
),
}),
repeatInterval: Yup.string().test(
'valid-human-interval',
'Invalid time format',
(value) => {
if (isUndefined(value)) {
return true;
}

const time = humanInterval(value);
return (
!isNaN(Number(value)) ||
cronRegex.test(value) ||
isUndefined(time) ||
!isNaN(time)
);
}
),
schedule: Yup.string().when('repeatInterval', {
is: (repeatInterval: string | undefined) => !repeatInterval,
then: Yup.string().required(
'Either a schedule or a repeat interval must be provided!'
),
}),
repeatInterval: Yup.string(),
data: Yup.string().test(
'validate-data-format',
'Invalid JSON format!',
(value) => {
if (!value) {
return false;
}

try {
if (value) {
JSON.parse(value);
}
JSON.parse(value);
} catch (e) {
return false;
}
Expand All @@ -71,21 +47,16 @@ const Header: React.FC = () => {
const [renderModal, setRenderModal] = useState(false);
const [renderAlert, setRenderAlert] = useState(false);

const showAlert = () => {
setRenderAlert(true);
setTimeout(() => setRenderAlert(false), 5000);
};

const formik = useFormik<FormValuesType>({
initialValues: {
name: '',
schedule: '',
repeatInterval: '',
data: 'null',
data: '{}',
},
onSubmit: async (values) => {
await createNewJob(values);
showAlert();
setRenderAlert(true);
},
validationSchema: createJobSchema,
});
Expand All @@ -104,21 +75,31 @@ const Header: React.FC = () => {
</a>
</div>
{renderModal && (
<Modal id="create-job" onClose={() => setRenderModal(false)}>
<Modal
id="create-job"
onClose={() => {
setRenderModal(false);
setRenderAlert(false);
}}
>
<div className="text-xl">Create Job</div>
<form className="flex flex-col" onSubmit={formik.handleSubmit}>
<label className="label" htmlFor="name">
Name
</label>
{formik.errors.name && formik.touched.name ? (
<div className="text-error">{formik.errors.name}</div>
) : null}
<JobNamesAutocomplete
menuStyle={{ top: 155, left: 20 }}
menuStyle={{
top: 155,
left: 20,
maxWidth: 350,
maxHeight: 400,
}}
renderInput={(props) => (
<input
{...props}
className="w-full input input-bordered"
className={cx('w-full input input-bordered', {
'border-red-500': formik.errors.name && formik.touched.name,
})}
id="name"
name="name"
type="text"
Expand All @@ -128,20 +109,29 @@ const Header: React.FC = () => {
onChange={formik.handleChange}
onSelect={(value) => formik.setFieldValue('name', value)}
/>

<div className="text-xs text-error">
{formik.errors.name && formik.touched.name
? formik.errors.name
: ''}
</div>
<label className="label" htmlFor="schedule">
<div className="flex flex-row items-center">Schedule</div>
</label>
{formik.errors.schedule && formik.touched.schedule ? (
<div className="text-error">{formik.errors.schedule}</div>
) : null}
<input
className="input input-bordered"
className={cx('input input-bordered', {
'border-red-500':
formik.errors.schedule && formik.touched.schedule,
})}
id="schedule"
name="schedule"
type="text"
onChange={formik.handleChange}
value={formik.values.schedule}
/>
{formik.errors.schedule && formik.touched.schedule ? (
<div className="text-xs text-error">{formik.errors.schedule}</div>
) : null}
<span className="my-2 text-xs text-base-content">
Number or{' '}
<a
Expand All @@ -156,17 +146,22 @@ const Header: React.FC = () => {
<label className="label" htmlFor="repeatInterval">
<div className="flex flex-row items-center">Repeat Interval</div>
</label>
{formik.errors.repeatInterval && formik.touched.repeatInterval ? (
<div className="text-error">{formik.errors.repeatInterval}</div>
) : null}
<input
className="input input-bordered"
className={cx('input input-bordered', {
'border-red-500':
formik.errors.repeatInterval && formik.touched.repeatInterval,
})}
id="repeatInterval"
name="repeatInterval"
type="text"
onChange={formik.handleChange}
value={formik.values.repeatInterval}
/>
{formik.errors.repeatInterval && formik.touched.repeatInterval ? (
<div className="text-xs text-error">
{formik.errors.repeatInterval}
</div>
) : null}
<span className="my-2 text-xs text-base-content">
Number,{' '}
<a
Expand All @@ -190,18 +185,20 @@ const Header: React.FC = () => {
<label className="label" htmlFor="data">
Data
</label>
{formik.errors.data && formik.touched.data ? (
<div className="text-error">{formik.errors.data}</div>
) : null}
<textarea
className="font-mono textarea textarea-bordered"
className={cx('font-mono textarea textarea-bordered', {
'border-red-500': formik.errors.data && formik.touched.data,
})}
id="data"
name="data"
onChange={formik.handleChange}
value={formik.values.data}
/>
{formik.errors.data && formik.touched.data ? (
<div className="text-xs text-error">{formik.errors.data}</div>
) : null}
{renderAlert && (
<div className="sticky left-0 right-0 m-2 alert alert-success">
<div className="sticky left-0 right-0 mt-4 -mb-2 alert alert-success">
<label>Job successfully created!</label>
</div>
)}
Expand All @@ -211,10 +208,13 @@ const Header: React.FC = () => {
</button>
<a
href="#!"
onClick={() => setRenderModal(false)}
onClick={() => {
setRenderModal(false);
setRenderAlert(false);
}}
className="btn"
>
Cancel
Close
</a>
</div>
</form>
Expand Down
13 changes: 10 additions & 3 deletions client/src/components/JobFilters.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ const JobFilters: React.FC = () => {
return (
<div className="flex flex-col w-full space-y-4">
<div className="flex flex-row items-end space-x-4">
<div className="form-control">
<div className="flex-1 form-control">
<label className="label">
<span>Job Name</span>
</label>
Expand All @@ -131,12 +131,19 @@ const JobFilters: React.FC = () => {
}}
/>
)}
menuStyle={{
top: 85,
left: 0,
maxWidth: 500,
maxHeight: 600,
overflowY: 'scroll',
}}
value={term}
onChange={(e) => setTerm(e.target.value)}
onSelect={setJobName}
/>
</div>
<div className="form-control">
<div className="flex-1 form-control">
<label className="label">Form Value</label>
<div className="flex flex-row">
<InputField
Expand Down Expand Up @@ -168,7 +175,7 @@ const JobFilters: React.FC = () => {
/>
</div>
</div>
<div className="form-control">
<div className="flex-1 form-control">
<label className="label">Refresh Interval (seconds)</label>
<InputField
className="input input-bordered"
Expand Down
5 changes: 3 additions & 2 deletions client/src/components/JobNamesAutocomplete.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,9 @@ const JobNamesAutocomplete: React.FC<PropsType> = ({

const defaultMenuStyle: React.CSSProperties = useMemo(
() => ({
position: 'fixed',
overflow: 'hidden',
position: 'absolute',
cursor: 'pointer',
overflow: 'auto',
zIndex: 999,
borderWidth: 2,
borderRadius: 8,
Expand Down
4 changes: 2 additions & 2 deletions client/src/components/JobsTable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,7 @@ const JobsTable: React.FC = () => {
<div className="modal-action">
<a
href="#!"
className="btn btn-primary"
className="btn btn-warning"
onClick={() => {
if (modalJob) {
handleRequeueJobs([modalJob.job._id]);
Expand All @@ -178,7 +178,7 @@ const JobsTable: React.FC = () => {
<div className="modal-action">
<a
href="#!"
className="btn btn-warning"
className="btn btn-error"
onClick={() => {
if (modalJob) {
handleDeleteJobs([modalJob.job._id]);
Expand Down
Loading

0 comments on commit 754c514

Please sign in to comment.