Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Fixed

- Avoided (infinite) display of "The list is loading. Just a moment please." for queries that should show "The result list is empty.", in cases where the user does not have the right to read the involved source(s) (#209).
- Result list sorting works again and the behavior is improved - see the issue for details (#216).

## [1.7.0] - 2025-04-09

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ function QueryResultList(props) {
<List
{...props}
disableAuthentication={true} // needed to overrule the default, which is to force logging in
storeKey={false} // do not remember pagination, sorting, ...
title=" "
actions={ <ActionBar />}
empty={false}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Link, TableCell, TableHead, TableRow } from "@mui/material";
import { Link, TableCell, TableHead, TableRow, Tooltip } from "@mui/material";
import React from "react";
import { useListContext } from "react-admin";
import "./TableHeader.css";
Expand All @@ -24,8 +24,8 @@ function TableHeader({ children }) {
* @param {string} target - the source of the column that was clicked
*/
function handleHeaderClick(target) {
const newSort = { field: target, order: "DESC" };
if (sort) {
const newSort = { field: target, order: "ASC" };
if (sort && sort.field == target) {
if (sort.order === "ASC") {
newSort.order = "DESC";
} else {
Expand All @@ -37,23 +37,28 @@ function TableHeader({ children }) {

const query = configManager.getQueryWorkingCopyById(resource);
const variableOntology = query.variableOntology;

const sortingAllowed = query.queryText.startsWith("# Custom sorting is allowed.");

return (
<TableHead>
<TableRow>
{React.Children.map(children, (child) => (
<>
<TableCell
key={child.props.source}
sx={{ height: "100%", "& > *": { verticalAlign: "middle" } }}
sx={{ height: "100%", "font-weight": "bold", "& > *": { verticalAlign: "middle" } }}
>
<span
{sortingAllowed ? <span
role="button"
className="header-button"
onClick={() => handleHeaderClick(child.props.source)}
>
{child.props.label}
</span>
</span> : <Tooltip title="Custom sorting is disabled for queries containing an ORDER clause.">
<span>
{child.props.label}
</span>
</Tooltip>}
{!!variableOntology && variableOntology[child.props.source] && (
<Link
target="_blank"
Expand Down
27 changes: 16 additions & 11 deletions main/src/dataProvider/SparqlDataProvider.js
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ export default {
query.variableValues = meta.variableValues;
}

const hash = JSON.stringify({ resource, variableValues: query.variableValues });
const hash = JSON.stringify({ resource, sort, variableValues: query.variableValues });
// LOG console.log(`hash: ${hash}`);
if (hash == listCache.hash) {
// LOG console.log(`reusing listCache.results: ${JSON.stringify(listCache.results, null, 2)}`);
Expand Down Expand Up @@ -151,17 +151,22 @@ async function buildQueryText(query) {
if (!query.variableOntology) {
query.variableOntology = findPredicates(parsedQuery);
}
if (!parsedQuery.order && query.sort && query.sort.field !== "id") {
const { field, order } = query.sort;
parsedQuery.order = [
{
expression: { termType: "Variable", value: field },
descending: order === "DESC",
},
];
}
let comments = "";
if (!parsedQuery.order) {
comments = "Custom sorting is allowed.";
if (query.sort && query.sort.field !== "id") {
const { field, order } = query.sort;
parsedQuery.order = [
{
expression: { termType: "Variable", value: field },
descending: order === "DESC",
},
];
}
}
const generator = new Generator();
return generator.stringify(parsedQuery);
let result = generator.stringify(parsedQuery);
return `# ${comments}\n${result}`;
} catch (error) {
throw new Error(error.message);
}
Expand Down
22 changes: 22 additions & 0 deletions test/cypress/e2e/sorting.cy.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
describe("Table sorting", () => {
it("Should respond to sorting", () => {
cy.visit("/");
cy.contains("Example queries").click();
cy.contains("A query about musicians").click();
cy.contains("Finished in:");
cy.get(':nth-child(1) > .column-name > span').contains("Antonio Caldara").should("not.exist");
cy.contains("name").click();
cy.get(':nth-child(1) > .column-name > span').contains("Antonio Caldara");
cy.contains("name").click();
cy.get(':nth-child(1) > .column-name > span').contains("Wolfgang Amadeus Mozart");
});

it("Should show that sorting is disabled on queries with an ORDER clause", () => {
cy.visit("/");
cy.contains("Project related examples").click();
cy.contains("Components").click();
cy.contains("Finished in:");
cy.contains(/^component$/).click();
cy.contains("Custom sorting is disabled for queries containing an ORDER clause.").should('exist');
});
});