Skip to content

Conversation

jjkoehorst
Copy link
Collaborator

This is a mock-up example mostly helped with Claude as it is something I think is important for SEEK but found it easier to explain by showing what I mean with it I am in no means a seek / ruby backend expert so don't blindly accept this commit ;).

It's "just" another button that brings you to the SEEK sparql endpoint interface that connects with the virtuoso public endpoint (if I did it correctly) as the virtuoso sparql interface is simply horrible.

There are some dummy example queries ( I am now working on the population script to see what ends up in the endpoint but have not got that part working yet....)

It would be great if the query field has some SPARQL syntax knowledge. it currently supports table, json and xml output formats.
Also the links point directly to where they are pointing to. It would be nice if on click it could fire a describe query and a special click (maybe link button) brings them to the link destination. This way people can more easily "browse" the endpoint.

Once populated it would also need a endpoint map UML like to show the structure but that's for later...

jjkoehorst and others added 3 commits August 15, 2025 17:32
- Add SPARQL controller with public endpoint support (no authentication)
- Create responsive web interface with query textarea and result display
- Implement horizontal scrolling tables for wide result sets
- Add example query library with dropdown selection
- Enable click-to-DESCRIBE functionality for URIs in results
- Include auto-resizing textarea and smooth UX interactions
- Add conditional menu visibility based on endpoint configuration
- Support multiple output formats (table, JSON, XML)
- Integrate with existing RDF repository configuration system

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <[email protected]>
Copy link
Member

@stuzart stuzart left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

some refactoring needed, and tests.
Bit confused about the help_documents/index.html, which looks like a cleaner and updated version of what is in sparql/index.html but in the wrong place ??

Occurred to me whilst reviewing, that shoudl probably avoid using virtuoso specifically, as there is the ability implement other subclasses of RdfRepository to support other triple stores

class SparqlController < ApplicationController
layout 'application'

before_action :login_required, if: -> { Seek::Config.respond_to?(:public_seek_enabled) && !Seek::Config.public_seek_enabled }
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

public_seek_enabled isn't a known configuration so the :if-> can be removed

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

also login required might not be needed or do we want it to be available only to people with an account? might make integration more difficult.

def index
# Main SPARQL interface page
unless rdf_repository_configured?
flash.now[:warning] = "SPARQL endpoint is not configured. Please check your virtuoso_settings.yml configuration."
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should be flash[:error], only :notice and :error are used


before_action :login_required, if: -> { Seek::Config.respond_to?(:public_seek_enabled) && !Seek::Config.public_seek_enabled }

def index
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

needs a functional test

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Was your first suggestion to remove this?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it's the def index action that needs a test, I can help with this

@example_queries = load_example_queries
end

def query
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can add integration tests for this (already setup to run with virituoso)

end

@results = execute_sparql_query(@sparql_query)
@result_count = @results.is_a?(Array) ? @results.length : 0
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should make sure execute_sparql_query always returns an array (if it doesn't already)

Comment on lines 5 to 7
<% if flash[:warning] %>
<p style="color: orange;">⚠️ <%= flash[:warning] %></p>
<% else %>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this isn't necessary if using flash[:error], as it's part of the default layout. (views/layouts/application.html.erb)

<p style="color: orange;">⚠️ <%= flash[:warning] %></p>
<% else %>
<p style="color: green;">✅ SPARQL endpoint is configured and ready</p>
<p><small>Endpoint: <%= controller.send(:get_virtuoso_uri) rescue 'N/A' %></small></p>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

shoudn't call the controller directly from the view (especially private). Infact I'm surprised this still works!

can just pass with an @ variable from the controller, or from a view helper method

<%= form.submit "Execute Query", style: "background: #007bff; color: white; padding: 8px 16px; border: none;" %>
<button type="button" onclick="document.querySelector('textarea').value = ''" style="margin-left: 10px; padding: 8px 16px;">Clear</button>

<% if @example_queries && @example_queries.any? %>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

tip: you can just call @example_queries&.any? without checking if it's present. & is a shortcut for .try() which always returns false if the item is nil

Comment on lines 51 to 85
<% if @results && @results.any? %>
<div style="background: #e8f5e8; border: 1px solid #4caf50; padding: 15px; margin-top: 20px;">
<h4 style="color: #4caf50;">Query Results (<%= @result_count %> results):</h4>

<% if @format == 'table' && @results.first.is_a?(Hash) %>
<div style="overflow-x: auto; max-width: 100%;">
<table border="1" style="min-width: 100%; border-collapse: collapse; white-space: nowrap;">
<thead>
<tr>
<% @results.first.keys.each do |key| %>
<th style="background: #f5f5f5; padding: 8px; min-width: 150px;"><%= key %></th>
<% end %>
</tr>
</thead>
<tbody>
<% @results.each do |row| %>
<tr>
<% row.values.each do |value| %>
<td style="padding: 8px; min-width: 150px;">
<% if value.to_s.start_with?('http') %>
<a href="<%= value %>" target="_blank" class="external-link" style="max-width: 300px; overflow: hidden; text-overflow: ellipsis; display: inline-block;"><%= value %></a>
<% else %>
<%= value %>
<% end %>
</td>
<% end %>
</tr>
<% end %>
</tbody>
</table>
</div>
<% else %>
<pre><%= JSON.pretty_generate(@results) %></pre>
<% end %>
</div>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this would be cleaner using a partial, or a view helper.

Infact I'm a little confused, as they are exist as partials and are used from help_documents/index.html - is that the more recent version but in the wrong place ?

<pre><%= JSON.pretty_generate(@results) %></pre>
<% end %>
</div>
<% elsif defined?(@results) && @results && @results.empty? %>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

no need for ?defined - @ variables always are but default to nil

- Remove non-functional validate button and associated JavaScript code as it was only testing bare minimum (should find a js library)
- Move inline styles to stylesheet on suggestions from stuart
- Improve SPARQL controller error handling and query execution, for example ASK did not return a list
- Add SPARQL link to navbar when RDF repository is configured, moved the button to the main menu bar if thats ok?
- Make output format dropdown more compact as it was ridiculously wide
- Clean up form styling and button positioning
@jjkoehorst
Copy link
Collaborator Author

Some new changes based on feedback from @stuzart , working on "tests". I also have another change in the pipeline that has to do with RDF. basically for institutions there is no RDF yet

institutions_controller.rb

      format.rdf { render template: 'rdf/show' }
      format.ttl { render template: 'rdf/show' }

in institution.rb
include Seek::Rdf::RdfGeneration

and the jerm_vocab

Institution => 'https://schema.org/Organization',

which should enable RDF for institutions. shall I push it to this branch as well?

jjkoehorst and others added 20 commits August 30, 2025 08:48
…red due to blank.

What happens now is if you run a sparql query and click on any of the URLS's it will execute a DESCRIBE such as  `DESCRIBE <http://localhost:3000/projects/1>`

Why? This allows users to more easily browse through the graph. TODO, a graphical map to be added once the "test data" has been added and is covering all RDF aspects.
… support checking it is restricting the graph being queried
…. This way users might be more able to understand the schema structure.

The image can / should obviously replaced in the future when the schema changes.
… the most suitable when there is a query error
…ML and JSON responses if a query.

Ultimately, will be much cleaner if split into 2 actions
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants