mirror of
https://github.com/pawelmalak/flame.git
synced 2025-07-19 03:29:37 +02:00
Add and update custom queries
This commit is contained in:
parent
a885440fef
commit
38ffdf1bff
8 changed files with 159 additions and 25 deletions
|
@ -7,6 +7,10 @@
|
||||||
color: var(--color-primary);
|
color: var(--color-primary);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.QueriesGrid span:last-child {
|
||||||
|
margin-bottom: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
.ActionIcons {
|
.ActionIcons {
|
||||||
display: flex;
|
display: flex;
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,11 +3,9 @@ import { connect } from 'react-redux';
|
||||||
|
|
||||||
import classes from './CustomQueries.module.css';
|
import classes from './CustomQueries.module.css';
|
||||||
|
|
||||||
import ModalForm from '../../../UI/Forms/ModalForm/ModalForm';
|
|
||||||
import Modal from '../../../UI/Modal/Modal';
|
import Modal from '../../../UI/Modal/Modal';
|
||||||
import Icon from '../../../UI/Icons/Icon/Icon';
|
import Icon from '../../../UI/Icons/Icon/Icon';
|
||||||
import { GlobalState, Query } from '../../../../interfaces';
|
import { GlobalState, Query } from '../../../../interfaces';
|
||||||
import InputGroup from '../../../UI/Forms/InputGroup/InputGroup';
|
|
||||||
import QueriesForm from './QueriesForm';
|
import QueriesForm from './QueriesForm';
|
||||||
import { deleteQuery } from '../../../../store/actions';
|
import { deleteQuery } from '../../../../store/actions';
|
||||||
import Button from '../../../UI/Buttons/Button/Button';
|
import Button from '../../../UI/Buttons/Button/Button';
|
||||||
|
@ -21,6 +19,12 @@ const CustomQueries = (props: Props): JSX.Element => {
|
||||||
const { customQueries, deleteQuery } = props;
|
const { customQueries, deleteQuery } = props;
|
||||||
|
|
||||||
const [modalIsOpen, setModalIsOpen] = useState(false);
|
const [modalIsOpen, setModalIsOpen] = useState(false);
|
||||||
|
const [editableQuery, setEditableQuery] = useState<Query | null>(null);
|
||||||
|
|
||||||
|
const updateHandler = (query: Query) => {
|
||||||
|
setEditableQuery(query);
|
||||||
|
setModalIsOpen(true);
|
||||||
|
};
|
||||||
|
|
||||||
const deleteHandler = (query: Query) => {
|
const deleteHandler = (query: Query) => {
|
||||||
if (window.confirm(`Are you sure you want to delete this provider?`)) {
|
if (window.confirm(`Are you sure you want to delete this provider?`)) {
|
||||||
|
@ -34,7 +38,14 @@ const CustomQueries = (props: Props): JSX.Element => {
|
||||||
isOpen={modalIsOpen}
|
isOpen={modalIsOpen}
|
||||||
setIsOpen={() => setModalIsOpen(!modalIsOpen)}
|
setIsOpen={() => setModalIsOpen(!modalIsOpen)}
|
||||||
>
|
>
|
||||||
<QueriesForm modalHandler={() => setModalIsOpen(!modalIsOpen)} />
|
{editableQuery ? (
|
||||||
|
<QueriesForm
|
||||||
|
modalHandler={() => setModalIsOpen(!modalIsOpen)}
|
||||||
|
query={editableQuery}
|
||||||
|
/>
|
||||||
|
) : (
|
||||||
|
<QueriesForm modalHandler={() => setModalIsOpen(!modalIsOpen)} />
|
||||||
|
)}
|
||||||
</Modal>
|
</Modal>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
|
@ -54,7 +65,7 @@ const CustomQueries = (props: Props): JSX.Element => {
|
||||||
<span>{q.name}</span>
|
<span>{q.name}</span>
|
||||||
<span>{q.prefix}</span>
|
<span>{q.prefix}</span>
|
||||||
<span className={classes.ActionIcons}>
|
<span className={classes.ActionIcons}>
|
||||||
<span>
|
<span onClick={() => updateHandler(q)}>
|
||||||
<Icon icon="mdiPencil" />
|
<Icon icon="mdiPencil" />
|
||||||
</span>
|
</span>
|
||||||
<span onClick={() => deleteHandler(q)}>
|
<span onClick={() => deleteHandler(q)}>
|
||||||
|
@ -65,7 +76,12 @@ const CustomQueries = (props: Props): JSX.Element => {
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<Button click={() => setModalIsOpen(true)}>
|
<Button
|
||||||
|
click={() => {
|
||||||
|
setEditableQuery(null);
|
||||||
|
setModalIsOpen(true);
|
||||||
|
}}
|
||||||
|
>
|
||||||
Add new search provider
|
Add new search provider
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -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 Button from '../../../UI/Buttons/Button/Button';
|
||||||
import InputGroup from '../../../UI/Forms/InputGroup/InputGroup';
|
import InputGroup from '../../../UI/Forms/InputGroup/InputGroup';
|
||||||
import ModalForm from '../../../UI/Forms/ModalForm/ModalForm';
|
import ModalForm from '../../../UI/Forms/ModalForm/ModalForm';
|
||||||
|
import { connect } from 'react-redux';
|
||||||
|
import { addQuery, updateQuery } from '../../../../store/actions';
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
modalHandler: () => void;
|
modalHandler: () => void;
|
||||||
// addApp: (formData: NewApp | FormData) => any;
|
addQuery: (query: Query) => {};
|
||||||
// updateApp: (id: number, formData: NewApp | FormData) => any;
|
updateQuery: (query: Query, Oldprefix: string) => {};
|
||||||
// app?: App;
|
query?: Query;
|
||||||
}
|
}
|
||||||
|
|
||||||
const QueriesForm = (props: Props): JSX.Element => {
|
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 (
|
return (
|
||||||
<ModalForm modalHandler={props.modalHandler} formHandler={() => {}}>
|
<ModalForm modalHandler={modalHandler} formHandler={formHandler}>
|
||||||
<InputGroup>
|
<InputGroup>
|
||||||
<label htmlFor="name">Name</label>
|
<label htmlFor="name">Name</label>
|
||||||
<input
|
<input
|
||||||
|
@ -23,37 +73,37 @@ const QueriesForm = (props: Props): JSX.Element => {
|
||||||
id="name"
|
id="name"
|
||||||
placeholder="Google"
|
placeholder="Google"
|
||||||
required
|
required
|
||||||
// value={formData.name}
|
value={formData.name}
|
||||||
// onChange={(e) => inputChangeHandler(e)}
|
onChange={(e) => inputChangeHandler(e)}
|
||||||
/>
|
/>
|
||||||
</InputGroup>
|
</InputGroup>
|
||||||
<InputGroup>
|
<InputGroup>
|
||||||
<label htmlFor="name">Prefix</label>
|
<label htmlFor="name">Prefix</label>
|
||||||
<input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
name="name"
|
name="prefix"
|
||||||
id="name"
|
id="prefix"
|
||||||
placeholder="g"
|
placeholder="g"
|
||||||
required
|
required
|
||||||
// value={formData.name}
|
value={formData.prefix}
|
||||||
// onChange={(e) => inputChangeHandler(e)}
|
onChange={(e) => inputChangeHandler(e)}
|
||||||
/>
|
/>
|
||||||
</InputGroup>
|
</InputGroup>
|
||||||
<InputGroup>
|
<InputGroup>
|
||||||
<label htmlFor="name">Query Template</label>
|
<label htmlFor="name">Query Template</label>
|
||||||
<input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
name="name"
|
name="template"
|
||||||
id="name"
|
id="template"
|
||||||
placeholder="https://www.google.com/search?q="
|
placeholder="https://www.google.com/search?q="
|
||||||
required
|
required
|
||||||
// value={formData.name}
|
value={formData.template}
|
||||||
// onChange={(e) => inputChangeHandler(e)}
|
onChange={(e) => inputChangeHandler(e)}
|
||||||
/>
|
/>
|
||||||
</InputGroup>
|
</InputGroup>
|
||||||
<Button>Add provider</Button>
|
{query ? <Button>Update provider</Button> : <Button>Add provider</Button>}
|
||||||
</ModalForm>
|
</ModalForm>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default QueriesForm;
|
export default connect(null, { addQuery, updateQuery })(QueriesForm);
|
||||||
|
|
|
@ -32,6 +32,7 @@ import {
|
||||||
AddQueryAction,
|
AddQueryAction,
|
||||||
DeleteQueryAction,
|
DeleteQueryAction,
|
||||||
FetchQueriesAction,
|
FetchQueriesAction,
|
||||||
|
UpdateQueryAction,
|
||||||
} from './config';
|
} from './config';
|
||||||
|
|
||||||
export enum ActionTypes {
|
export enum ActionTypes {
|
||||||
|
@ -71,6 +72,7 @@ export enum ActionTypes {
|
||||||
fetchQueries = 'FETCH_QUERIES',
|
fetchQueries = 'FETCH_QUERIES',
|
||||||
addQuery = 'ADD_QUERY',
|
addQuery = 'ADD_QUERY',
|
||||||
deleteQuery = 'DELETE_QUERY',
|
deleteQuery = 'DELETE_QUERY',
|
||||||
|
updateQuery = 'UPDATE_QUERY',
|
||||||
}
|
}
|
||||||
|
|
||||||
export type Action =
|
export type Action =
|
||||||
|
@ -104,4 +106,5 @@ export type Action =
|
||||||
| UpdateConfigAction
|
| UpdateConfigAction
|
||||||
| FetchQueriesAction
|
| FetchQueriesAction
|
||||||
| AddQueryAction
|
| AddQueryAction
|
||||||
| DeleteQueryAction;
|
| DeleteQueryAction
|
||||||
|
| UpdateQueryAction;
|
||||||
|
|
|
@ -110,3 +110,26 @@ export const deleteQuery =
|
||||||
console.log(err);
|
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);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
|
@ -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) => {
|
const configReducer = (state: State = initialState, action: Action) => {
|
||||||
switch (action.type) {
|
switch (action.type) {
|
||||||
case ActionTypes.getConfig:
|
case ActionTypes.getConfig:
|
||||||
|
@ -60,6 +67,8 @@ const configReducer = (state: State = initialState, action: Action) => {
|
||||||
return addQuery(state, action);
|
return addQuery(state, action);
|
||||||
case ActionTypes.deleteQuery:
|
case ActionTypes.deleteQuery:
|
||||||
return deleteQuery(state, action);
|
return deleteQuery(state, action);
|
||||||
|
case ActionTypes.updateQuery:
|
||||||
|
return updateQuery(state, action);
|
||||||
default:
|
default:
|
||||||
return state;
|
return state;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
// @desc Delete query
|
||||||
// @route DELETE /api/queries/:prefix
|
// @route DELETE /api/queries/:prefix
|
||||||
// @access Public
|
// @access Public
|
||||||
|
|
|
@ -5,9 +5,10 @@ const {
|
||||||
getQueries,
|
getQueries,
|
||||||
addQuery,
|
addQuery,
|
||||||
deleteQuery,
|
deleteQuery,
|
||||||
|
updateQuery,
|
||||||
} = require('../controllers/queries/');
|
} = require('../controllers/queries/');
|
||||||
|
|
||||||
router.route('/').post(addQuery).get(getQueries);
|
router.route('/').post(addQuery).get(getQueries);
|
||||||
router.route('/:prefix').delete(deleteQuery);
|
router.route('/:prefix').delete(deleteQuery).put(updateQuery);
|
||||||
|
|
||||||
module.exports = router;
|
module.exports = router;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue