Add and update custom queries

This commit is contained in:
unknown 2021-10-11 13:55:53 +02:00
parent a885440fef
commit 38ffdf1bff
8 changed files with 159 additions and 25 deletions

View File

@ -7,6 +7,10 @@
color: var(--color-primary);
}
.QueriesGrid span:last-child {
margin-bottom: 10px;
}
.ActionIcons {
display: flex;
}

View File

@ -3,11 +3,9 @@ import { connect } from 'react-redux';
import classes from './CustomQueries.module.css';
import ModalForm from '../../../UI/Forms/ModalForm/ModalForm';
import Modal from '../../../UI/Modal/Modal';
import Icon from '../../../UI/Icons/Icon/Icon';
import { GlobalState, Query } from '../../../../interfaces';
import InputGroup from '../../../UI/Forms/InputGroup/InputGroup';
import QueriesForm from './QueriesForm';
import { deleteQuery } from '../../../../store/actions';
import Button from '../../../UI/Buttons/Button/Button';
@ -21,6 +19,12 @@ const CustomQueries = (props: Props): JSX.Element => {
const { customQueries, deleteQuery } = props;
const [modalIsOpen, setModalIsOpen] = useState(false);
const [editableQuery, setEditableQuery] = useState<Query | null>(null);
const updateHandler = (query: Query) => {
setEditableQuery(query);
setModalIsOpen(true);
};
const deleteHandler = (query: Query) => {
if (window.confirm(`Are you sure you want to delete this provider?`)) {
@ -34,7 +38,14 @@ const CustomQueries = (props: Props): JSX.Element => {
isOpen={modalIsOpen}
setIsOpen={() => setModalIsOpen(!modalIsOpen)}
>
<QueriesForm modalHandler={() => setModalIsOpen(!modalIsOpen)} />
{editableQuery ? (
<QueriesForm
modalHandler={() => setModalIsOpen(!modalIsOpen)}
query={editableQuery}
/>
) : (
<QueriesForm modalHandler={() => setModalIsOpen(!modalIsOpen)} />
)}
</Modal>
<div>
@ -54,7 +65,7 @@ const CustomQueries = (props: Props): JSX.Element => {
<span>{q.name}</span>
<span>{q.prefix}</span>
<span className={classes.ActionIcons}>
<span>
<span onClick={() => updateHandler(q)}>
<Icon icon="mdiPencil" />
</span>
<span onClick={() => deleteHandler(q)}>
@ -65,7 +76,12 @@ const CustomQueries = (props: Props): JSX.Element => {
))}
</div>
<Button click={() => setModalIsOpen(true)}>
<Button
click={() => {
setEditableQuery(null);
setModalIsOpen(true);
}}
>
Add new search provider
</Button>
</div>

View File

@ -1,20 +1,70 @@
import { useState } from 'react';
import { ChangeEvent, FormEvent, useState, useEffect } from 'react';
import { Query } from '../../../../interfaces';
import Button from '../../../UI/Buttons/Button/Button';
import InputGroup from '../../../UI/Forms/InputGroup/InputGroup';
import ModalForm from '../../../UI/Forms/ModalForm/ModalForm';
import { connect } from 'react-redux';
import { addQuery, updateQuery } from '../../../../store/actions';
interface Props {
modalHandler: () => void;
// addApp: (formData: NewApp | FormData) => any;
// updateApp: (id: number, formData: NewApp | FormData) => any;
// app?: App;
addQuery: (query: Query) => {};
updateQuery: (query: Query, Oldprefix: string) => {};
query?: Query;
}
const QueriesForm = (props: Props): JSX.Element => {
const [formData, setFormData] = useState();
const { modalHandler, addQuery, updateQuery, query } = props;
const [formData, setFormData] = useState<Query>({
name: '',
prefix: '',
template: '',
});
const inputChangeHandler = (e: ChangeEvent<HTMLInputElement>) => {
const { name, value } = e.target;
setFormData({
...formData,
[name]: value,
});
};
const formHandler = (e: FormEvent) => {
e.preventDefault();
if (query) {
updateQuery(formData, query.prefix);
} else {
addQuery(formData);
}
// close modal
modalHandler();
// clear form
setFormData({
name: '',
prefix: '',
template: '',
});
};
useEffect(() => {
if (query) {
setFormData(query);
} else {
setFormData({
name: '',
prefix: '',
template: '',
});
}
}, [query]);
return (
<ModalForm modalHandler={props.modalHandler} formHandler={() => {}}>
<ModalForm modalHandler={modalHandler} formHandler={formHandler}>
<InputGroup>
<label htmlFor="name">Name</label>
<input
@ -23,37 +73,37 @@ const QueriesForm = (props: Props): JSX.Element => {
id="name"
placeholder="Google"
required
// value={formData.name}
// onChange={(e) => inputChangeHandler(e)}
value={formData.name}
onChange={(e) => inputChangeHandler(e)}
/>
</InputGroup>
<InputGroup>
<label htmlFor="name">Prefix</label>
<input
type="text"
name="name"
id="name"
name="prefix"
id="prefix"
placeholder="g"
required
// value={formData.name}
// onChange={(e) => inputChangeHandler(e)}
value={formData.prefix}
onChange={(e) => inputChangeHandler(e)}
/>
</InputGroup>
<InputGroup>
<label htmlFor="name">Query Template</label>
<input
type="text"
name="name"
id="name"
name="template"
id="template"
placeholder="https://www.google.com/search?q="
required
// value={formData.name}
// onChange={(e) => inputChangeHandler(e)}
value={formData.template}
onChange={(e) => inputChangeHandler(e)}
/>
</InputGroup>
<Button>Add provider</Button>
{query ? <Button>Update provider</Button> : <Button>Add provider</Button>}
</ModalForm>
);
};
export default QueriesForm;
export default connect(null, { addQuery, updateQuery })(QueriesForm);

View File

@ -32,6 +32,7 @@ import {
AddQueryAction,
DeleteQueryAction,
FetchQueriesAction,
UpdateQueryAction,
} from './config';
export enum ActionTypes {
@ -71,6 +72,7 @@ export enum ActionTypes {
fetchQueries = 'FETCH_QUERIES',
addQuery = 'ADD_QUERY',
deleteQuery = 'DELETE_QUERY',
updateQuery = 'UPDATE_QUERY',
}
export type Action =
@ -104,4 +106,5 @@ export type Action =
| UpdateConfigAction
| FetchQueriesAction
| AddQueryAction
| DeleteQueryAction;
| DeleteQueryAction
| UpdateQueryAction;

View File

@ -110,3 +110,26 @@ export const deleteQuery =
console.log(err);
}
};
export interface UpdateQueryAction {
type: ActionTypes.updateQuery;
payload: Query[];
}
export const updateQuery =
(query: Query, oldPrefix: string) =>
async (dispatch: Dispatch<UpdateQueryAction>) => {
try {
const res = await axios.put<ApiResponse<Query[]>>(
`/api/queries/${oldPrefix}`,
query
);
dispatch<UpdateQueryAction>({
type: ActionTypes.updateQuery,
payload: res.data.data,
});
} catch (err) {
console.log(err);
}
};

View File

@ -48,6 +48,13 @@ const deleteQuery = (state: State, action: Action): State => {
};
};
const updateQuery = (state: State, action: Action): State => {
return {
...state,
customQueries: action.payload,
};
};
const configReducer = (state: State = initialState, action: Action) => {
switch (action.type) {
case ActionTypes.getConfig:
@ -60,6 +67,8 @@ const configReducer = (state: State = initialState, action: Action) => {
return addQuery(state, action);
case ActionTypes.deleteQuery:
return deleteQuery(state, action);
case ActionTypes.updateQuery:
return updateQuery(state, action);
default:
return state;
}

View File

@ -34,6 +34,34 @@ exports.getQueries = asyncWrapper(async (req, res, next) => {
});
});
// @desc Update query
// @route PUT /api/queries/:prefix
// @access Public
exports.updateQuery = asyncWrapper(async (req, res, next) => {
const file = new File(QUERIES_PATH);
let content = JSON.parse(file.read());
let queryIdx = content.queries.findIndex(
(q) => q.prefix == req.params.prefix
);
// query found
if (queryIdx > -1) {
content.queries = [
...content.queries.slice(0, queryIdx),
req.body,
...content.queries.slice(queryIdx + 1),
];
}
file.write(content, true);
res.status(200).json({
success: true,
data: content.queries,
});
});
// @desc Delete query
// @route DELETE /api/queries/:prefix
// @access Public

View File

@ -5,9 +5,10 @@ const {
getQueries,
addQuery,
deleteQuery,
updateQuery,
} = require('../controllers/queries/');
router.route('/').post(addQuery).get(getQueries);
router.route('/:prefix').delete(deleteQuery);
router.route('/:prefix').delete(deleteQuery).put(updateQuery);
module.exports = router;