mirror of
https://github.com/plan-player-analytics/Plan.git
synced 2024-11-01 00:10:12 +01:00
Add 'Edit Query' button to Query Results
This allows easier editing of existing query results
This commit is contained in:
parent
e021162729
commit
20b8ab9baa
@ -336,6 +336,7 @@ public enum HtmlLang implements Lang {
|
||||
QUERY_SERVERS_TWO("html.query.label.servers.two", "using data of 2 servers"),
|
||||
QUERY_SERVERS_MANY("html.query.label.servers.many", "using data of {number} servers"),
|
||||
QUERY_SHOW_FULL_QUERY("html.query.label.showFullQuery", "Show Full Query"),
|
||||
QUERY_EDIT_QUERY("html.query.label.editQuery", "Edit Query"),
|
||||
|
||||
HELP_TEST_RESULT("html.label.help.testResult", "Test result"),
|
||||
HELP_TEST_IT_OUT("html.label.help.testPrompt", "Test it out:"),
|
||||
|
@ -794,6 +794,7 @@ html:
|
||||
generic:
|
||||
are: "`是`"
|
||||
label:
|
||||
editQuery: "Edit Query"
|
||||
from: ">从 </label>"
|
||||
makeAnother: "进行另一个查询"
|
||||
servers:
|
||||
|
@ -794,6 +794,7 @@ html:
|
||||
generic:
|
||||
are: "` jsou`"
|
||||
label:
|
||||
editQuery: "Edit Query"
|
||||
from: ">od</label>"
|
||||
makeAnother: "Vytvořit další dotaz"
|
||||
servers:
|
||||
|
@ -794,6 +794,7 @@ html:
|
||||
generic:
|
||||
are: "`are`"
|
||||
label:
|
||||
editQuery: "Edit Query"
|
||||
from: ">from</label>"
|
||||
makeAnother: "Make another query"
|
||||
servers:
|
||||
|
@ -794,6 +794,7 @@ html:
|
||||
generic:
|
||||
are: "`are`"
|
||||
label:
|
||||
editQuery: "Edit Query"
|
||||
from: ">from</label>"
|
||||
makeAnother: "Make another query"
|
||||
servers:
|
||||
|
@ -794,6 +794,7 @@ html:
|
||||
generic:
|
||||
are: "`are`"
|
||||
label:
|
||||
editQuery: "Edit Query"
|
||||
from: ">de</label>"
|
||||
makeAnother: "Realiza otra consulta"
|
||||
servers:
|
||||
|
@ -794,6 +794,7 @@ html:
|
||||
generic:
|
||||
are: "`ovat`"
|
||||
label:
|
||||
editQuery: "Edit Query"
|
||||
from: ">tästä</label>"
|
||||
makeAnother: "Tee toinen kysely"
|
||||
servers:
|
||||
|
@ -794,6 +794,7 @@ html:
|
||||
generic:
|
||||
are: "`sont`"
|
||||
label:
|
||||
editQuery: "Edit Query"
|
||||
from: ">de</label>"
|
||||
makeAnother: "Faire une autre Requête"
|
||||
servers:
|
||||
|
@ -794,6 +794,7 @@ html:
|
||||
generic:
|
||||
are: "`are`"
|
||||
label:
|
||||
editQuery: "Edit Query"
|
||||
from: ">from</label>"
|
||||
makeAnother: "Make another query"
|
||||
servers:
|
||||
|
@ -794,6 +794,7 @@ html:
|
||||
generic:
|
||||
are: "`それは`"
|
||||
label:
|
||||
editQuery: "Edit Query"
|
||||
from: ">から</label>"
|
||||
makeAnother: "別のクエリを作る"
|
||||
servers:
|
||||
|
@ -794,6 +794,7 @@ html:
|
||||
generic:
|
||||
are: "`are`"
|
||||
label:
|
||||
editQuery: "Edit Query"
|
||||
from: ">from</label>"
|
||||
makeAnother: "Make another query"
|
||||
servers:
|
||||
|
@ -794,6 +794,7 @@ html:
|
||||
generic:
|
||||
are: "`zijn`"
|
||||
label:
|
||||
editQuery: "Edit Query"
|
||||
from: ">van</label>"
|
||||
makeAnother: "Maak nog een query"
|
||||
servers:
|
||||
|
@ -794,6 +794,7 @@ html:
|
||||
generic:
|
||||
are: "`are`"
|
||||
label:
|
||||
editQuery: "Edit Query"
|
||||
from: ">from</label>"
|
||||
makeAnother: "Make another query"
|
||||
servers:
|
||||
|
@ -794,6 +794,7 @@ html:
|
||||
generic:
|
||||
are: "``"
|
||||
label:
|
||||
editQuery: "Edit Query"
|
||||
from: ">с</label>"
|
||||
makeAnother: "Сделать другой запрос"
|
||||
servers:
|
||||
|
@ -794,6 +794,7 @@ html:
|
||||
generic:
|
||||
are: "`vardır`"
|
||||
label:
|
||||
editQuery: "Edit Query"
|
||||
from: ">dan</label>"
|
||||
makeAnother: "Başka bir sorgu yap"
|
||||
servers:
|
||||
|
@ -794,6 +794,7 @@ html:
|
||||
generic:
|
||||
are: "``"
|
||||
label:
|
||||
editQuery: "Edit Query"
|
||||
from: ">з</label>"
|
||||
makeAnother: "Зробити інший запит"
|
||||
servers:
|
||||
|
@ -794,6 +794,7 @@ html:
|
||||
generic:
|
||||
are: "`是`"
|
||||
label:
|
||||
editQuery: "Edit Query"
|
||||
from: ">從 </label>"
|
||||
makeAnother: "進行另一個查詢"
|
||||
servers:
|
||||
|
@ -3,13 +3,14 @@ import {useQueryResultContext} from "../../hooks/queryResultContext";
|
||||
import {FontAwesomeIcon} from "@fortawesome/react-fontawesome";
|
||||
import {faFilter} from "@fortawesome/free-solid-svg-icons";
|
||||
import {useTranslation} from "react-i18next";
|
||||
import {Link} from "react-router-dom";
|
||||
|
||||
const QueryPath = () => {
|
||||
const QueryPath = ({newQuery}) => {
|
||||
const {t} = useTranslation();
|
||||
const {result} = useQueryResultContext();
|
||||
const hasResults = result && result.data;
|
||||
const hasResults = Boolean(result?.data);
|
||||
const path = result?.path;
|
||||
if (!path || !path.length) return <></>;
|
||||
if (!path?.length || (newQuery && hasResults)) return <></>;
|
||||
|
||||
|
||||
const getReadableFilterName = kind => {
|
||||
@ -48,6 +49,7 @@ const QueryPath = () => {
|
||||
|
||||
return (
|
||||
<aside id={"result-path"} className={"alert shadow " + (hasResults ? "alert-success" : "alert-warning")}>
|
||||
{!newQuery && <Link className={"link float-end"} to={"/query/new"}>{t('html.query.label.editQuery')}</Link>}
|
||||
{path.map((step, i) => <p key={step.kind + step.size}
|
||||
style={{marginBottom: 0, marginLeft: i * 0.7 + "rem"}}>
|
||||
<FontAwesomeIcon
|
||||
|
@ -17,6 +17,7 @@ import FilterDropdown from "./FilterDropdown";
|
||||
import FilterList from "./FilterList";
|
||||
import {useQueryResultContext} from "../../../hooks/queryResultContext";
|
||||
import {useNavigate} from "react-router-dom";
|
||||
import {useNavigation} from "../../../hooks/navigationHook.jsx";
|
||||
|
||||
const parseTime = (dateString, timeString) => {
|
||||
const d = dateString.match(
|
||||
@ -37,7 +38,8 @@ const parseTime = (dateString, timeString) => {
|
||||
const QueryOptionsCard = () => {
|
||||
const {t} = useTranslation();
|
||||
const navigate = useNavigate()
|
||||
const {setResult} = useQueryResultContext();
|
||||
const {result, setResult} = useQueryResultContext();
|
||||
const {setCurrentTab} = useNavigation();
|
||||
|
||||
const [loadingResults, setLoadingResults] = useState(false);
|
||||
|
||||
@ -52,6 +54,7 @@ const QueryOptionsCard = () => {
|
||||
|
||||
// View & filter data
|
||||
const {data: options, loadingError} = useDataRequest(fetchFilters, []);
|
||||
|
||||
const [graphData, setGraphData] = useState(undefined);
|
||||
useEffect(() => {
|
||||
if (options) {
|
||||
@ -71,24 +74,22 @@ const QueryOptionsCard = () => {
|
||||
if (invalidFields.length || !options) return;
|
||||
if (!fromDate && !fromTime && !toDate && !toTime) return;
|
||||
|
||||
const newMin = parseTime(
|
||||
fromDate ? fromDate : options.view.afterDate,
|
||||
fromTime ? fromTime : options.view.afterTime
|
||||
);
|
||||
const newMax = parseTime(
|
||||
toDate ? toDate : options.view.beforeDate,
|
||||
toTime ? toTime : options.view.beforeTime
|
||||
);
|
||||
setExtremes({
|
||||
min: newMin,
|
||||
max: newMax
|
||||
min: parseTime(
|
||||
fromDate || options.view.afterDate,
|
||||
fromTime || options.view.afterTime
|
||||
),
|
||||
max: parseTime(
|
||||
toDate || options.view.beforeDate,
|
||||
toTime || options.view.beforeTime
|
||||
)
|
||||
});
|
||||
}, [invalidFields, options]);
|
||||
/* eslint-enable react-hooks/exhaustive-deps */
|
||||
useEffect(updateExtremes, [invalidFields, updateExtremes]);
|
||||
useEffect(updateExtremes, [updateExtremes]);
|
||||
|
||||
const onSetExtremes = useCallback((event) => {
|
||||
if (event && event.trigger) {
|
||||
if (event?.trigger) {
|
||||
const afterDate = Highcharts.dateFormat('%d/%m/%Y', event.min);
|
||||
const afterTime = Highcharts.dateFormat('%H:%M', event.min);
|
||||
const beforeDate = Highcharts.dateFormat('%d/%m/%Y', event.max);
|
||||
@ -100,6 +101,33 @@ const QueryOptionsCard = () => {
|
||||
}
|
||||
}, [setFromTime, setFromDate, setToTime, setToDate]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!options || !result) return;
|
||||
|
||||
setSelectedServers(result.view.servers.map(server => options.view.servers.findIndex(s => s.serverUUID === server.serverUUID)).filter(i => i !== -1))
|
||||
|
||||
setFromDate(result.view.afterDate);
|
||||
setFromTime(result.view.afterTime);
|
||||
setToDate(result.view.beforeDate);
|
||||
setToTime(result.view.beforeTime);
|
||||
|
||||
const existingFilters = result.filters;
|
||||
existingFilters.forEach(f => f.options = options.filters.find(fo => fo.kind === f.kind).options);
|
||||
setFilters(existingFilters);
|
||||
|
||||
setExtremes({
|
||||
min: parseTime(
|
||||
result.view.afterDate || options.view.afterDate,
|
||||
result.view.afterTime || options.view.afterTime
|
||||
),
|
||||
max: parseTime(
|
||||
result.view.beforeDate || options.view.beforeDate,
|
||||
result.view.beforeTime || options.view.beforeTime
|
||||
)
|
||||
});
|
||||
setCurrentTab('html.query.label.editQuery')
|
||||
}, [options, result, setFromDate, setFromTime, setToDate, setToTime, setFilters, setSelectedServers, setExtremes]);
|
||||
|
||||
const getServerSelectorMessage = () => {
|
||||
const selected = selectedServers.length;
|
||||
const available = options.view.servers.length;
|
||||
@ -117,10 +145,10 @@ const QueryOptionsCard = () => {
|
||||
const performQuery = async () => {
|
||||
const inputDto = {
|
||||
view: {
|
||||
afterDate: fromDate ? fromDate : options.view.afterDate,
|
||||
afterTime: fromTime ? fromTime : options.view.afterTime,
|
||||
beforeDate: toDate ? toDate : options.view.beforeDate,
|
||||
beforeTime: toTime ? toTime : options.view.beforeTime,
|
||||
afterDate: fromDate || options.view.afterDate,
|
||||
afterTime: fromTime || options.view.afterTime,
|
||||
beforeDate: toDate || options.view.beforeDate,
|
||||
beforeTime: toTime || options.view.beforeTime,
|
||||
servers: selectedServers.map(index => options.view.servers[index])
|
||||
},
|
||||
filters
|
||||
|
@ -12,10 +12,10 @@ const BetweenDatesFilter = ({index, label, filter, removeFilter, setFilterOption
|
||||
|
||||
const options = filter.options;
|
||||
|
||||
const [fromDate, setFromDate] = useState(options.after[0]);
|
||||
const [fromTime, setFromTime] = useState(options.after[1]);
|
||||
const [toDate, setToDate] = useState(options.before[0]);
|
||||
const [toTime, setToTime] = useState(options.before[1]);
|
||||
const [fromDate, setFromDate] = useState(filter.parameters?.afterDate || options.after[0]);
|
||||
const [fromTime, setFromTime] = useState(filter.parameters?.afterTime || options.after[1]);
|
||||
const [toDate, setToDate] = useState(filter.parameters?.beforeDate || options.before[0]);
|
||||
const [toTime, setToTime] = useState(filter.parameters?.beforeTime || options.before[1]);
|
||||
useEffect(() => {
|
||||
setFilterOptions({
|
||||
...filter,
|
||||
|
@ -9,7 +9,12 @@ const MultipleChoiceFilter = ({index, label, filter, removeFilter, setFilterOpti
|
||||
const {t} = useTranslation();
|
||||
const select = index === 0 ? t('html.query.filter.generic.start') : t('html.query.filter.generic.and');
|
||||
|
||||
const [selectedIndexes, setSelectedIndexes] = useState([]);
|
||||
const parameterSelected = filter.parameters?.selected
|
||||
? JSON.parse(filter.parameters.selected)
|
||||
.map(option => filter.options.options.indexOf(option))
|
||||
: undefined;
|
||||
|
||||
const [selectedIndexes, setSelectedIndexes] = useState(parameterSelected || []);
|
||||
useEffect(() => {
|
||||
setFilterOptions({
|
||||
...filter,
|
||||
|
@ -12,7 +12,7 @@ const NewQueryView = () => {
|
||||
{hasPermission('access.query') && <section className={"query-options-view"}>
|
||||
<Row>
|
||||
<Col md={12}>
|
||||
<QueryPath/>
|
||||
<QueryPath newQuery/>
|
||||
<QueryOptionsCard/>
|
||||
</Col>
|
||||
</Row>
|
||||
|
Loading…
Reference in New Issue
Block a user