Skip to content

Commit b4d10f9

Browse files
authored
Merge pull request #156 from SolidLabResearch/fix/141-convert-to-custom
Fix/141 convert to custom
2 parents fd61229 + 4013413 commit b4d10f9

File tree

10 files changed

+483
-54
lines changed

10 files changed

+483
-54
lines changed

CHANGELOG.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,15 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
77

88
## [Unreleased]
99

10+
### Added
11+
12+
- The possibility to create a custom query from an existing query and to clone a custom query (#141).
13+
14+
### Changed
15+
16+
### Fixed
17+
18+
1019
## [1.3.0] - 2024-08-07
1120

1221
### Added

README.md

Lines changed: 20 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -224,16 +224,26 @@ Nevertheless, you can use any React component you want, just make sure it's a fu
224224

225225
## Custom queries
226226

227-
Besides the prepared queries in the configuration file, a user can edit custom queries:
228-
229-
- To create a custom query, open "Custom Query Editor" from the menu on the left.
230-
- Complete the custom query editor form and click the "CREATE QUERY" button when ready.
231-
- Your new query is added to the "Custom queries" group and you are redirected to the query's result view.
232-
- If not satisfied with the query result, you can click "EDIT QUERY" to further edit your query.
233-
When saving changes, the result is recalculated.
234-
- Because the custom query only lives as long as your browser remembers it, a "SAVE QUERY LINK" button is provided.
235-
Use it to generate a unique URL for this custom query. Copy that URL to your clipboard and save it.
236-
You can then visit that URL any time later, to recreate this query.
227+
The configuration file contains prepared, fixed queries.
228+
In addition, a user can create and edit custom queries, either from scratch or based on an existing query.
229+
230+
- To create a new custom query from scratch:
231+
- Open "Custom Query Editor" from the menu on the left.
232+
- Complete the custom query editor form and click the "CREATE QUERY" button when ready.
233+
- Your new query is added to the "Custom queries" group and you are redirected to the query's result view.
234+
- If not satisfied with the query result, you can click "EDIT QUERY" to further edit your query.
235+
When saving changes, the result is recalculated.
236+
237+
- To create a new custom query based on an existing query:
238+
- Open the existing query.
239+
- Click "CLONE AS CUSTOM QUERY" (in a normal query) or "CLONE" (in a custom query).
240+
- Make the desired changes in the form and click the "CREATE QUERY" button when ready. The new custom query behaves as if it were created from scratch.
241+
242+
- To reproduce a custom query later, a "SAVE QUERY LINK" button is provided.
243+
Use it to generate a unique URL for this custom query.
244+
Visiting that URL any time later, recreates a custom query with the same specifications.
245+
This may be useful to forward a custom query to another user.
246+
237247
- To clean up an unwanted custom query, there is always a button "DELETE QUERY"...
238248

239249
## Representation Mapper
Lines changed: 208 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,208 @@
1+
describe("Customize existing query", () => {
2+
3+
it("simple query", () => {
4+
cy.visit("/");
5+
cy.contains("General examples").click();
6+
cy.contains("A public list of books I'd love to own").click();
7+
8+
cy.get('button').contains("Clone as custom query").click();
9+
10+
cy.url().should('include', 'customQuery');
11+
12+
13+
cy.get('input[name="name"]').should('have.value', "(Cloned from) A public list of books I'd love to own");
14+
15+
cy.get('textarea[name="queryString"]').should('have.value', `PREFIX schema: <http://schema.org/>
16+
17+
SELECT * WHERE {
18+
?list schema:name ?listTitle;
19+
schema:itemListElement [
20+
schema:name ?bookTitle;
21+
schema:creator [
22+
schema:name ?authorName
23+
]
24+
].
25+
}`);
26+
cy.get('input[name="source"]').should('have.value', "http://localhost:8080/example/wish-list");
27+
28+
})
29+
30+
it("templated query - fixed variables", () => {
31+
cy.visit("/");
32+
cy.contains("General examples").click();
33+
cy.contains("A templated query about musicians").click();
34+
35+
cy.get('form').within(() => {
36+
cy.get('#genre').click();
37+
});
38+
cy.get('li').contains('Baroque').click();
39+
40+
cy.get('button[type="submit"]').click();
41+
42+
cy.get('button').contains("Clone as custom query").click();
43+
cy.url().should('include', 'customQuery');
44+
45+
cy.get('input[name="name"]').should('have.value', "(Cloned from) A templated query about musicians");
46+
47+
cy.get('textarea[name="queryString"]').should('have.value', `PREFIX schema: <http://schema.org/>
48+
49+
SELECT ?name ?sameAs_url WHERE {
50+
?list schema:name ?listTitle;
51+
schema:name ?name;
52+
schema:genre $genre;
53+
schema:sameAs ?sameAs_url;
54+
}`);
55+
56+
cy.get('textarea[name="variables"]').should('have.value', `{"genre":["\\"Romantic\\"","\\"Baroque\\"","\\"Classical\\""]}`)
57+
58+
59+
60+
61+
62+
})
63+
64+
it("templated query - indirect variables", () => {
65+
66+
cy.visit("/");
67+
cy.contains("For testing only").click();
68+
cy.contains("A templated query about musicians, two variables (indirect variables)").click();
69+
70+
cy.get('form').within(() => {
71+
cy.get('#genre').click();
72+
});
73+
cy.get('li').contains('Baroque').click();
74+
75+
cy.get('form').within(() => {
76+
cy.get('#sameAsUrl').click();
77+
});
78+
cy.get('li').contains('Vivaldi').click();
79+
80+
cy.get('button[type="submit"]').click();
81+
82+
cy.get('button').contains("Clone as custom query").click();
83+
cy.url().should('include', 'customQuery');
84+
85+
cy.get('input[name="name"]').should('have.value', "(Cloned from) A templated query about musicians, two variables (indirect variables)");
86+
87+
cy.get('textarea[name="queryString"]').should('have.value', `PREFIX schema: <http://schema.org/>
88+
89+
SELECT ?name WHERE {
90+
?list schema:name ?listTitle;
91+
schema:name ?name;
92+
schema:genre $genre;
93+
schema:sameAs $sameAsUrl;
94+
}
95+
`);
96+
97+
cy.get('textarea[name="indirectQuery1"]').should('have.value', `PREFIX schema: <http://schema.org/>
98+
99+
SELECT DISTINCT ?genre
100+
WHERE {
101+
?list schema:genre ?genre
102+
}
103+
ORDER BY ?genre
104+
`);
105+
106+
cy.get('textarea[name="indirectQuery2"]').should('have.value', `PREFIX schema: <http://schema.org/>
107+
108+
SELECT DISTINCT ?sameAsUrl
109+
WHERE {
110+
?list schema:sameAs ?sameAsUrl
111+
}
112+
ORDER BY ?sameAsUrl
113+
`);
114+
115+
116+
117+
118+
})
119+
120+
it("index file", () => {
121+
cy.visit("/");
122+
cy.contains("General examples").click();
123+
cy.contains("Sources from an index file").click();
124+
125+
cy.get('button').contains("Clone as custom query").click({ force: true }); // Button is out of FoV so we gotta force the click
126+
127+
cy.url().should('include', 'customQuery');
128+
129+
130+
cy.get('input[name="name"]').should('have.value', "(Cloned from) Sources from an index file");
131+
132+
cy.get('textarea[name="queryString"]').should('have.value', `PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
133+
PREFIX o: <https://www.example.com/ont/>
134+
135+
SELECT ?component ?componentName ?material ?materialName ?percentage
136+
WHERE {
137+
?component
138+
a o:Component ;
139+
o:name ?componentName ;
140+
o:has-component-bom [
141+
o:has-component-material-assoc [
142+
o:percentage ?percentage ;
143+
o:has-material ?material ;
144+
];
145+
];
146+
.
147+
?material o:name ?materialName ;
148+
}
149+
ORDER BY ?componentName
150+
`);
151+
152+
cy.get('input[name="indexSourceUrl"]').should('have.value', `http://localhost:8080/example/index-example-texon-only`)
153+
cy.get('textarea[name="indexSourceQuery"]').should('have.value', `PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
154+
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
155+
PREFIX example: <http://localhost:8080/example/index-example-texon-only#>
156+
157+
SELECT ?object
158+
WHERE {
159+
example:index-example rdfs:seeAlso ?object .
160+
}
161+
`)
162+
163+
})
164+
165+
166+
})
167+
168+
describe("Clone and customize existing query, clone the custom after", () => {
169+
170+
it("clone simple query", () => {
171+
cy.visit("/");
172+
cy.contains("General examples").click();
173+
cy.contains("A public list of books I'd love to own").click();
174+
175+
cy.get('button').contains("Clone as custom query").click();
176+
177+
cy.url().should('include', 'customQuery');
178+
179+
180+
cy.get('input[name="name"]').should('have.value', "(Cloned from) A public list of books I'd love to own");
181+
182+
cy.get('textarea[name="queryString"]').should('have.value', `PREFIX schema: <http://schema.org/>
183+
184+
SELECT * WHERE {
185+
?list schema:name ?listTitle;
186+
schema:itemListElement [
187+
schema:name ?bookTitle;
188+
schema:creator [
189+
schema:name ?authorName
190+
]
191+
].
192+
}`
193+
);
194+
cy.get('input[name="source"]').should('have.value', "http://localhost:8080/example/wish-list");
195+
196+
cy.get('button[type="submit"]').click();
197+
198+
cy.contains("Colleen Hoover").should("exist");
199+
200+
cy.get('button').contains("Clone").click();
201+
202+
cy.url().should('include', 'customQuery');
203+
204+
205+
cy.get('input[name="name"]').should('have.value', "(Cloned) (Cloned from) A public list of books I'd love to own");
206+
207+
})
208+
})

src/App.jsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ import InteractionLayout from "./components/InteractionLayout/InteractionLayout"
1515
import TemplatedListResultTable from "./components/ListResultTable/TemplatedListResultTable.jsx";
1616

1717
import { Route } from "react-router-dom";
18-
import CustomEditor from "./components/Dashboard/CustomQueryEditor/customEditor.jsx";
18+
import CustomEditor from "./components/CustomQueryEditor/customEditor.jsx";
1919

2020
import configManager from "./configManager/configManager.js";
2121

src/IconProvider/IconProvider.js

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,9 @@ import TuneIcon from '@mui/icons-material/Tune';
2121
import SaveAsIcon from '@mui/icons-material/SaveAs';
2222
import InfoIcon from '@mui/icons-material/Info';
2323
import CloseIcon from '@mui/icons-material/Close';
24+
import SettingsSuggestIcon from '@mui/icons-material/SettingsSuggest';
25+
import ChevronLeftIcon from '@mui/icons-material/ChevronLeft';
26+
import FilterNoneIcon from '@mui/icons-material/FilterNone';
2427

2528
export default {
2629
BrushIcon,
@@ -45,5 +48,8 @@ export default {
4548
TuneIcon,
4649
SaveAsIcon,
4750
InfoIcon,
48-
CloseIcon
51+
CloseIcon,
52+
SettingsSuggestIcon,
53+
ChevronLeftIcon,
54+
FilterNoneIcon
4955
};

0 commit comments

Comments
 (0)