-<%else%>
-
-<%end%>
-
- <%if @margin_notes.size<1%>
-
There are currently no notes.
- <%end%>
-<%=draw_note_tree(@margin_notes,uniq)%>
-
-
-
-
-
-
-
-
-<%# need seperate forms for if its a modal window%>
-<% if @modal%>
-
-<%else%>
-
-<%end%>
-
-
diff --git a/app/views/margin_notes/_update.html.erb b/app/views/margin_notes/_update.html.erb
deleted file mode 100644
index 46ef7556b6..0000000000
--- a/app/views/margin_notes/_update.html.erb
+++ /dev/null
@@ -1,2 +0,0 @@
-
-<%=draw_note_tree(@margin_notes,@key)%>
diff --git a/app/views/ontologies/sections/_sparql.html.haml b/app/views/ontologies/sections/_sparql.html.haml
new file mode 100644
index 0000000000..3d2921c141
--- /dev/null
+++ b/app/views/ontologies/sections/_sparql.html.haml
@@ -0,0 +1,2 @@
+= render TurboFrameComponent.new(id: "sparql", data: {"turbo-frame-target": "frame"} ) do
+ = sparql_query_container(graph: @submission_latest.id )
\ No newline at end of file
diff --git a/app/views/statistics/index.html.haml b/app/views/statistics/index.html.haml
new file mode 100644
index 0000000000..8f802870d1
--- /dev/null
+++ b/app/views/statistics/index.html.haml
@@ -0,0 +1,33 @@
+%div.px-3.py-3.pt-md-5.pb-md-4.text-center
+ %h1.display-4
+ #{portal_name} Statistics
+ %p.lead (last #{Date.today.year - Date.parse(@merged_data[:labels].first).year} years)
+
+%div.container
+ %div
+ = chart_component(title: nil, type: 'line', show_legend: true,
+ labels: @merged_data[:labels],
+ datasets: visits_chart_dataset_array({ 'Ontologies': @merged_data[:visits][2] , 'Users': @merged_data[:visits][0], 'Projects': @merged_data[:visits][1]}, fill: false))
+
+ %div.pb-3.pb-md-4
+ - size = @merged_data[:labels].size - 1
+ - visits = @year_month_visits
+ = render TableComponent.new(id: 'statistics_table') do |t|
+ - t.header do |h|
+ - h.th {'Date'}
+ - h.th {'Ontologies'}
+ - h.th {'Users'}
+ - h.th {'Projects'}
+ - h.th {'Ontology Visits'}
+
+ - @merged_data[:labels].reverse.each_with_index do |year_month, i|
+ - t.row do |r|
+ - r.td {year_month}
+ - r.td {@merged_data[:visits][2][size - i].to_s}
+ - r.td {@merged_data[:visits][0][size - i].to_s}
+ - r.td {@merged_data[:visits][1][size - i].to_s}
+ - r.td do
+ - year = Date.parse(year_month).year
+ - month = Date.parse(year_month).month
+ = visits[[year, month]] || 0
+
diff --git a/config/routes.rb b/config/routes.rb
index 6b97430db3..f9a68ad721 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -40,8 +40,6 @@
resources :mappings
get 'mappings/:id', to: 'mappings#show', constraints: { id: /.+/ }
- resources :margin_notes
-
resources :concepts
get 'ontologies/:ontology_id/concepts', to: 'concepts#show_concept'
@@ -94,12 +92,15 @@
get '' => 'home#index'
+ match 'sparql_proxy', to: 'admin#sparql_endpoint', via: [:get, :post]
+
# Top-level pages
match '/feedback', to: 'home#feedback', via: [:get, :post]
get '/account' => 'home#account'
get '/site_config' => 'home#site_config'
post '/annotator_recommender_form' => 'home#annotator_recommender_form'
match '/visits', to: 'visits#index', via: :get
+ get 'statistics/index'
# Error pages
match "/404", to: "errors#not_found", via: :all
diff --git a/package.json b/package.json
index d5003c910e..f33c80df4a 100644
--- a/package.json
+++ b/package.json
@@ -4,6 +4,8 @@
"dependencies": {
"@hotwired/stimulus": "^3.0.1",
"@hotwired/turbo-rails": "^7.1.1",
+ "@triply/yasgui": "^4.2.28",
+ "chart.js": "^4.4.1",
"debounce": "^1.2.1",
"esbuild": "^0.14.41",
"flatpickr": "^4.6.13",
diff --git a/vendor/assets/images/fg-menu/spinner_bar.gif b/vendor/assets/images/fg-menu/spinner_bar.gif
deleted file mode 100644
index 656ae30fc2..0000000000
Binary files a/vendor/assets/images/fg-menu/spinner_bar.gif and /dev/null differ
diff --git a/vendor/assets/images/rating/delete.gif b/vendor/assets/images/rating/delete.gif
deleted file mode 100755
index 43c6ca8763..0000000000
Binary files a/vendor/assets/images/rating/delete.gif and /dev/null differ
diff --git a/vendor/assets/images/rating/star.gif b/vendor/assets/images/rating/star.gif
deleted file mode 100755
index d0948a7084..0000000000
Binary files a/vendor/assets/images/rating/star.gif and /dev/null differ
diff --git a/vendor/assets/images/split/horizontal.png b/vendor/assets/images/split/horizontal.png
deleted file mode 100755
index cbe7da77dd..0000000000
Binary files a/vendor/assets/images/split/horizontal.png and /dev/null differ
diff --git a/vendor/assets/images/split/vertical.png b/vendor/assets/images/split/vertical.png
deleted file mode 100755
index 0ac8fa1e03..0000000000
Binary files a/vendor/assets/images/split/vertical.png and /dev/null differ
diff --git a/vendor/assets/images/splitter/hgrabber.gif b/vendor/assets/images/splitter/hgrabber.gif
deleted file mode 100644
index 6a59bf83c6..0000000000
Binary files a/vendor/assets/images/splitter/hgrabber.gif and /dev/null differ
diff --git a/vendor/assets/images/splitter/vdockbar.gif b/vendor/assets/images/splitter/vdockbar.gif
deleted file mode 100644
index c2742ac6af..0000000000
Binary files a/vendor/assets/images/splitter/vdockbar.gif and /dev/null differ
diff --git a/vendor/assets/images/splitter/vgrabber.gif b/vendor/assets/images/splitter/vgrabber.gif
deleted file mode 100644
index 990fd1e098..0000000000
Binary files a/vendor/assets/images/splitter/vgrabber.gif and /dev/null differ
diff --git a/vendor/assets/images/splitter/vgrabber2-active.gif b/vendor/assets/images/splitter/vgrabber2-active.gif
deleted file mode 100644
index 55ce07bb38..0000000000
Binary files a/vendor/assets/images/splitter/vgrabber2-active.gif and /dev/null differ
diff --git a/vendor/assets/images/splitter/vgrabber2-normal.gif b/vendor/assets/images/splitter/vgrabber2-normal.gif
deleted file mode 100644
index abfd0577c1..0000000000
Binary files a/vendor/assets/images/splitter/vgrabber2-normal.gif and /dev/null differ
diff --git a/vendor/assets/javascripts/ajax-chosen.js b/vendor/assets/javascripts/ajax-chosen.js
deleted file mode 100644
index 8d9b4ae5be..0000000000
--- a/vendor/assets/javascripts/ajax-chosen.js
+++ /dev/null
@@ -1,164 +0,0 @@
-
-/*
-ajax-chosen
-A complement to the jQuery library Chosen that adds ajax autocomplete
-Contributors:
-https://github.com/jobvite/ajax-chosen
-https://github.com/bicouy0/ajax-chosen
-*/
-
-(function() {
-
- (function($) {
- return $.fn.ajaxChosen = function(options, callback) {
- var clickSelector, container, defaultedOptions, field, inputSelector, multiple, search, select, currentSearchId,
- _this = this;
- defaultedOptions = {
- minLength: 3,
- queryLimit: 10,
- delay: 100,
- chosenOptions: {},
- searchingText: "Searching...",
- noresultsText: "No results.",
- initialQuery: false
- };
- $.extend(defaultedOptions, options);
- defaultedOptions.chosenOptions.no_results_text = defaultedOptions.searchingText;
- select = this;
- multiple = select.attr('multiple') != null;
- if (multiple) {
- inputSelector = ".search-field > input";
- clickSelector = ".chzn-choices";
- } else {
- inputSelector = ".chzn-search > input";
- clickSelector = ".chzn-single";
- }
- select.chosen(defaultedOptions.chosenOptions);
- select.data('chosen').winnow_results = function(){};
- container = select.next('.chzn-container');
- field = container.find(inputSelector);
- if (defaultedOptions.initialQuery) {
- field.bind('focus', function(evt) {
- if (this.previousSearch || !container.hasClass('chzn-container-active')) {
- return;
- }
- return search(evt);
- });
- }
- field.bind('keyup', function(evt) {
- if (this.previousSearch) clearTimeout(this.previousSearch);
- return this.previousSearch = setTimeout((function() {
- return search(evt);
- }), defaultedOptions.delay);
- });
- return search = function(evt) {
- var clearSearchingLabel, currentOptions, prevVal, response, val, _ref, thisSearchId;
- val = $.trim(field.attr('value'));
- prevVal = (_ref = field.data('prevVal')) != null ? _ref : false;
- field.data('prevVal', val);
- thisSearchId = new Date().getTime() + val;
- currentSearchId = thisSearchId;
- var resultsDiv;
- if (multiple) {
- resultsDiv = field.parent().parent().siblings();
- } else {
- resultsDiv = field.parent().parent();
- }
- clearSearchingLabel = function(val) {
- if (typeof val === "undefined" || val === null || val === "") val = $(_this).attr('value');
- return resultsDiv.find('.no-results').html(defaultedOptions.noresultsText + " '" + val + "'");
- };
- if (val === prevVal || (val.length < defaultedOptions.minLength && evt.type === 'keyup')) {
- clearSearchingLabel(val);
- return false;
- }
- if (resultsDiv.find(".no-results").length < 1) {
- resultsDiv.find(".no-results").remove();
- resultsDiv.find(".chzn-results").prepend($("
").addClass("no-results"));
- }
- resultsDiv.find(".active-result").remove();
- resultsDiv.find('.no-results').addClass("searching").html(defaultedOptions.searchingText + " '" + val + "'");
- currentOptions = select.find('option');
- defaultedOptions.term = val;
- response = function(items, success) {
- var currentOpt, keydownEvent, latestVal, newOpt, newOptions, noResult, _fn, _fn2, _i, _j, _len, _len2;
- if (!field.is(':focus') && evt.type === 'keyup') return;
- if (thisSearchId !== currentSearchId) return;
- newOptions = [];
- $.each(items, function(value, text) {
- var newOpt;
- newOpt = $('