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