From 107f861705f2920024ceb78412cbd0d1e7d042e7 Mon Sep 17 00:00:00 2001 From: Eric Pugh Date: Fri, 8 Mar 2024 09:22:58 -0500 Subject: [PATCH 01/19] boom! Wrapped the Angular1 app into a end point that can be called by anyone. --- Gemfile | 2 + Gemfile.lock | 6 + app/assets/javascripts/app_stripped.js | 13 ++ .../javascripts/controllers/mainCtrl.js | 30 ++-- .../controllers/queriesStrippedCtrl.js | 62 +++++++ .../javascripts/controllers/queryParams.js | 1 + .../javascripts/controllers/strippedCtrl.js | 169 ++++++++++++++++++ app/assets/javascripts/core.js | 1 - app/assets/javascripts/core_stripped.js | 41 +++++ .../javascripts/directives/queriesStripped.js | 14 ++ .../javascripts/factories/TryFactory.js | 1 + app/assets/javascripts/routes.js | 5 + app/assets/javascripts/services/queriesSvc.js | 4 + .../javascripts/services/querySnapshotSvc.js | 22 ++- .../templates/views/devQueryParams.html | 30 +++- .../templates/views/queries-stripped.html | 22 +++ .../templates/views/queriesStripped.html | 28 +++ app/controllers/api/v1/agent_q_controller.rb | 87 +++++++++ app/controllers/api/v1/queries_controller.rb | 6 +- app/controllers/core_controller.rb | 13 ++ app/controllers/core_stripped_controller.rb | 36 ++++ app/views/core_stripped/index.html.erb | 17 ++ app/views/layouts/core_stripped.html.erb | 35 ++++ config/initializers/assets.rb | 4 +- config/routes.rb | 5 + 25 files changed, 632 insertions(+), 22 deletions(-) create mode 100644 app/assets/javascripts/app_stripped.js create mode 100644 app/assets/javascripts/controllers/queriesStrippedCtrl.js create mode 100644 app/assets/javascripts/controllers/strippedCtrl.js create mode 100644 app/assets/javascripts/core_stripped.js create mode 100644 app/assets/javascripts/directives/queriesStripped.js create mode 100644 app/assets/templates/views/queries-stripped.html create mode 100644 app/assets/templates/views/queriesStripped.html create mode 100644 app/controllers/api/v1/agent_q_controller.rb create mode 100755 app/controllers/core_stripped_controller.rb create mode 100755 app/views/core_stripped/index.html.erb create mode 100755 app/views/layouts/core_stripped.html.erb diff --git a/Gemfile b/Gemfile index 28b89130d..71d5529e9 100755 --- a/Gemfile +++ b/Gemfile @@ -91,3 +91,5 @@ group :test do end gem 'importmap-rails', '~> 2.0' + +gem "ferrum", "~> 0.15" diff --git a/Gemfile.lock b/Gemfile.lock index 84be5ac2f..8375582ab 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -168,6 +168,11 @@ GEM faraday (>= 1, < 3) faraday-net_http (3.1.0) net-http + ferrum (0.15) + addressable (~> 2.5) + concurrent-ruby (~> 1.1) + webrick (~> 1.7) + websocket-driver (~> 0.7) ffi (1.16.3) font-awesome-sass (6.5.1) sassc (~> 2.0) @@ -508,6 +513,7 @@ DEPENDENCIES derailed_benchmarks devise (>= 4.6.2) devise_invitable (~> 2.0) + ferrum (~> 0.15) font-awesome-sass gabba importmap-rails (~> 2.0) diff --git a/app/assets/javascripts/app_stripped.js b/app/assets/javascripts/app_stripped.js new file mode 100644 index 000000000..07979c1fb --- /dev/null +++ b/app/assets/javascripts/app_stripped.js @@ -0,0 +1,13 @@ +'use strict'; + +angular.module('QuepidApp', [ + 'UtilitiesModule', + 'ngRoute', + 'ngCookies', + 'ngSanitize', + 'ui.bootstrap', + 'o19s.splainer-search', + 'angular-flash.service', + 'angular-flash.flash-alert-directive', + 'templates' +]); diff --git a/app/assets/javascripts/controllers/mainCtrl.js b/app/assets/javascripts/controllers/mainCtrl.js index 85c16c2ca..3b856b4da 100644 --- a/app/assets/javascripts/controllers/mainCtrl.js +++ b/app/assets/javascripts/controllers/mainCtrl.js @@ -106,15 +106,25 @@ angular.module('QuepidApp') flash.to('search-error').error = ''; bootstrapped = true; - return queriesSvc.searchAll() - .then(function() { - flash.success = 'All queries finished successfully!'; - }, function(errorMsg) { - var mainErrorMsg = 'Some queries failed to resolve!'; - - flash.error = mainErrorMsg; - flash.to('search-error').error = errorMsg; - }); + + console.log(queriesSvc.queryArray().length) + if (queriesSvc.queryArray().length <= 410) { + console.log("About to call queriesSvc.searchAll") + return queriesSvc.searchAll() + .then(function() { + flash.success = 'All queries finished successfully!'; + }, function(errorMsg) { + var mainErrorMsg = 'Some queries failed to resolve!'; + + flash.error = mainErrorMsg; + flash.to('search-error').error = errorMsg; + }); + } + else { + queriesSvc.requireManualTrigger = true; + flash.success = 'You have ' + queriesSvc.queryArray().length + ' queries in this case and must manually trigger running this!'; + return + } } }); }); @@ -143,7 +153,7 @@ angular.module('QuepidApp') } else if ( caseNo > 0 ) { queriesSvc.querySearchPromiseReset(); - + console.log("about to bootstrapCase") bootstrapCase() .then(function() { loadQueries(); diff --git a/app/assets/javascripts/controllers/queriesStrippedCtrl.js b/app/assets/javascripts/controllers/queriesStrippedCtrl.js new file mode 100644 index 000000000..ab8a2f6ee --- /dev/null +++ b/app/assets/javascripts/controllers/queriesStrippedCtrl.js @@ -0,0 +1,62 @@ +'use strict'; +/*jslint latedef:false*/ + +angular.module('QuepidApp') + .controller('QueriesStrippedCtrl', [ + '$scope', + 'queriesSvc', + 'querySnapshotSvc', + 'caseSvc', + function ( + $scope, + queriesSvc, + querySnapshotSvc, + caseSvc + ) { + $scope.queriesSvc = queriesSvc; + $scope.caseSvc = caseSvc; + + console.log("HI THERE") + + $scope.queries = {}; + + $scope.queries.queriesChanged = function() { + return queriesSvc.version(); + }; + + + // get all the queries for this case for the query service + $scope.queriesList = []; + $scope.$watch(function(){ + // only call if the query service has new information! + return queriesSvc.version(); + }, function(){ + $scope.queriesList = queriesSvc.queryArray(); + updateBatchInfo(); + }); + + $scope.snapshotPayload = function() { + if (!$scope.searching()){ + return querySnapshotSvc.createSnapshotPayload("", true, false, queriesSvc.queryArray()); + } + } + + $scope.searching = function() { + return queriesSvc.hasUnscoredQueries(); + }; + $scope.batchPosition = 0; + $scope.batchSize = 0; + function getBatchPosition() { + return queriesSvc.scoredQueryCount(); + } + + function updateBatchInfo() { + $scope.batchSize = queriesSvc.queryCount(); + $scope.batchPosition = queriesSvc.scoredQueryCount(); + } + $scope.$watch(getBatchPosition, updateBatchInfo); + + + + } + ]); diff --git a/app/assets/javascripts/controllers/queryParams.js b/app/assets/javascripts/controllers/queryParams.js index 0764f3c51..c207ea17f 100644 --- a/app/assets/javascripts/controllers/queryParams.js +++ b/app/assets/javascripts/controllers/queryParams.js @@ -102,6 +102,7 @@ angular.module('QuepidApp') args: $scope.settings.selectedTry.args, curator_vars: $scope.settings.selectedTry.curatorVarsDict(), escape_query: $scope.settings.selectedTry.escapeQuery, + background_queries: $scope.settings.selectedTry.backgroundQueries, api_method: $scope.settings.selectedTry.apiMethod, custom_headers: $scope.settings.selectedTry.customHeaders, field_spec: $scope.settings.selectedTry.fieldSpec, diff --git a/app/assets/javascripts/controllers/strippedCtrl.js b/app/assets/javascripts/controllers/strippedCtrl.js new file mode 100644 index 000000000..e0a2e0d63 --- /dev/null +++ b/app/assets/javascripts/controllers/strippedCtrl.js @@ -0,0 +1,169 @@ +'use strict'; + +angular.module('QuepidApp') + // there's a lot of dependencies here, but this guy + // is responsible for bootstrapping everyone so... + .controller('StrippedCtrl', [ + '$scope', '$routeParams', '$log', + 'flash', + 'caseSvc', 'settingsSvc', 'caseTryNavSvc', + 'queryViewSvc', 'queriesSvc', 'docCacheSvc', + function ( + $scope, $routeParams, $log, + flash, + caseSvc, settingsSvc, caseTryNavSvc, + queryViewSvc, queriesSvc, docCacheSvc + ) { + $log.debug('NEW MAIN CTRL STRIPPED VERSION'); + + var caseNo = parseInt($routeParams.caseNo, 10); + var tryNo = parseInt($routeParams.tryNo, 10); + + var initialCaseNo = angular.copy(caseTryNavSvc.getCaseNo()); + + var caseChanged = function() { + return initialCaseNo !== caseNo; + }; + + var getSearchEngine = function(tryNo) { + var settings = settingsSvc.editableSettings(); + if (settings.hasOwnProperty('getTry')) { + var aTry = settings.getTry(tryNo); + if (aTry) { + return aTry.searchUrl; + } + } + return null; + }; + + var searchEngineChanged = function() { + return getSearchEngine(caseTryNavSvc.getTryNo()) !== getSearchEngine(tryNo); + }; + + var init = function() { + // Make sure we empty stuff from the previous case + if ( caseChanged() ) { + queriesSvc.reset(); + } + + angular.forEach(queriesSvc.queries, function(query) { + query.reset(); + }); + }; + + var bootstrapCase = function() { + return caseSvc.get(caseNo) + .then(function(acase) { + if (angular.isUndefined(acase)){ + throw new Error('Could not retrieve case ' + caseNo + '. Confirm that the case has been shared with you via a team you are a member of!'); + } + + caseSvc.selectTheCase(acase); + settingsSvc.setCaseTries(acase.tries); + if ( isNaN(tryNo) ) { // If we didn't specify a tryNo via the URL + tryNo = acase.lastTry; + } + + settingsSvc.setCurrentTry(tryNo); + if (!settingsSvc.isTrySelected()){ + flash.to('search-error').error = 'The try that was specified for the case does not actually exist!'; + } + else { + if (settingsSvc.editableSettings().proxyRequests === true){ + $scope.showTLSChangeWarning = false; + } + else if (caseTryNavSvc.needToRedirectQuepidProtocol(settingsSvc.editableSettings().searchUrl)){ + $log.info('Need to redirect browser to different TLS'); + throw new Error('Need to change to different TLS'); // Signal that we need to change TLS. + } + } + }); + }; + + var loadQueries = function() { + var newSettings = settingsSvc.editableSettings(); + if ( caseChanged() || searchEngineChanged() ) { + if ( caseChanged() ) { + queryViewSvc.reset(); + docCacheSvc.empty(); + } + docCacheSvc.invalidate(); + } + + return docCacheSvc.update(newSettings) + .then(function() { + var bootstrapped = false; + + return queriesSvc.changeSettings(caseNo, newSettings) + .then(function() { + if (!bootstrapped) { + flash.error = ''; + flash.success = ''; + flash.to('search-error').error = ''; + + bootstrapped = true; + + console.log(queriesSvc.queryArray().length) + if (queriesSvc.queryArray().length <= 410) { + console.log("About to call queriesSvc.searchAll") + return queriesSvc.searchAll() + .then(function() { + flash.success = 'All queries finished successfully!'; + }, function(errorMsg) { + var mainErrorMsg = 'Some queries failed to resolve!'; + + flash.error = mainErrorMsg; + flash.to('search-error').error = errorMsg; + }); + } + else { + queriesSvc.requireManualTrigger = true; + flash.success = 'You have ' + queriesSvc.queryArray().length + ' queries in this case and must manually trigger running this!'; + return + } + } + }); + }); + }; + + init(); + + caseTryNavSvc.navigationCompleted({ + caseNo: caseNo, + tryNo: tryNo + }); + + // While not perfect, at least the site doesn't blow up if you don't + // have any cases. + if ( caseNo === 0 ) { + flash.error = 'You don\'t have any Cases created in Quepid. Click \'Create a Case\' from the Relevancy Cases dropdown to get started.'; + } + else if ( caseNo > 0 ) { + queriesSvc.querySearchPromiseReset(); + console.log("about to bootstrapCase") + bootstrapCase() + .then(function() { + loadQueries(); + }).catch(function(error) { + // brittle logic, but check if we throw the TLS error or if it's from something else.' + var message = error.message; + if (message === 'Need to change to different TLS'){ + var resultsTuple = caseTryNavSvc.swapQuepidUrlTLS(); + + var quepidUrlToSwitchTo = resultsTuple[0]; + var protocolToSwitchTo = resultsTuple[1]; + + flash.to('search-error').error = 'Click Here to Reload Quepid in ' + protocolToSwitchTo + ' Protocol!'; + } + else if (message.startsWith('Could not retrieve case')){ + flash.to('search-error').error = message; + } + else { + flash.to('search-error').error = 'Could not load the case ' + caseNo + ' due to: ' + message; + } + }); + + + } + } + ]); diff --git a/app/assets/javascripts/core.js b/app/assets/javascripts/core.js index cc7ebb001..d9c482b04 100644 --- a/app/assets/javascripts/core.js +++ b/app/assets/javascripts/core.js @@ -78,7 +78,6 @@ //= require_tree ./services //= require_tree ./values //= require_tree ../templates -//= require_tree ./components //= require footer //= require tether-shepherd/dist/js/tether //= require tether-shepherd/dist/js/shepherd diff --git a/app/assets/javascripts/core_stripped.js b/app/assets/javascripts/core_stripped.js new file mode 100644 index 000000000..80fd30a3c --- /dev/null +++ b/app/assets/javascripts/core_stripped.js @@ -0,0 +1,41 @@ +// This is a manifest file that'll be compiled into core.js, which will include all the files +// listed below. +// +// Any JavaScript/Coffee file within this directory, lib/assets/javascripts, vendor/assets/javascripts, +// or any plugin's vendor/assets/javascripts directory can be referenced here using a relative path. +// +// It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the +// compiled file. +// +// Read Sprockets README (https://github.com/rails/sprockets#sprockets-directives) for details +// about supported directives. +// +// This file loads all the below JavaScript files and can be very slow in the dev mode. +// +// This file is meant for the stripped down Angular Core app used by AgentQ. +// +//= require jquery + + +//= require angular/angular + +//= require angular-resource/angular-resource +//= require angular-cookies/angular-cookies +//= require angular-route/angular-route +//= require angular-sanitize/angular-sanitize +//= require angular-ui-bootstrap/dist/ui-bootstrap +//= require angular-rails-templates +//= require splainer-search/splainer-search +//= require angular-flash/dist/angular-flash +//= require utilitiesModule +//= require app_stripped +//= require routes +//= require_tree ./components +//= require_tree ./controllers +//= require_tree ./directives +//= require_tree ./factories +//= require_tree ./filters +//= require_tree ./services +//= require_tree ./values +//= require_tree ../templates +//= require_tree ./components diff --git a/app/assets/javascripts/directives/queriesStripped.js b/app/assets/javascripts/directives/queriesStripped.js new file mode 100644 index 000000000..26cf1e02d --- /dev/null +++ b/app/assets/javascripts/directives/queriesStripped.js @@ -0,0 +1,14 @@ +'use strict'; + +angular.module('QuepidApp') + .directive('queriesStripped', [ + function () { + return { + restrict: 'E', + transclude: true, + controller: 'QueriesStrippedCtrl', + templateUrl: 'views/queries-stripped.html', + replace: true + }; + } + ]); diff --git a/app/assets/javascripts/factories/TryFactory.js b/app/assets/javascripts/factories/TryFactory.js index f764d0bf6..7aa2a1a80 100644 --- a/app/assets/javascripts/factories/TryFactory.js +++ b/app/assets/javascripts/factories/TryFactory.js @@ -40,6 +40,7 @@ self.args = data.args; self.deleted = false; self.escapeQuery = data.escape_query; + self.backgroundQueries = data.background_queries self.apiMethod = data.api_method; self.customHeaders = data.custom_headers; self.fieldSpec = data.field_spec; diff --git a/app/assets/javascripts/routes.js b/app/assets/javascripts/routes.js index 974b61e84..5352189e4 100644 --- a/app/assets/javascripts/routes.js +++ b/app/assets/javascripts/routes.js @@ -33,6 +33,11 @@ angular.module('QuepidApp') controller: 'MainCtrl', reloadOnSearch: false }) + .when('/case/:caseNo/query/:queryNo', { + templateUrl: 'views/queriesStripped.html', + controller: 'StrippedCtrl', + reloadOnSearch: false + }) .when('/cases', { templateUrl: 'views/cases/index.html', controller: 'CasesCtrl' diff --git a/app/assets/javascripts/services/queriesSvc.js b/app/assets/javascripts/services/queriesSvc.js index f279f1ba6..52e43278d 100644 --- a/app/assets/javascripts/services/queriesSvc.js +++ b/app/assets/javascripts/services/queriesSvc.js @@ -100,6 +100,10 @@ angular.module('QuepidApp') // custom parser... passedInSettings.searchEngine = 'solr'; } + + if (passedInSettings.backgroundQueries) { + // Similar to how 'static' works, if we have + } else if (passedInSettings.searchEngine === 'searchapi'){ /*jshint evil:true */ eval(passedInSettings.mapperCode); diff --git a/app/assets/javascripts/services/querySnapshotSvc.js b/app/assets/javascripts/services/querySnapshotSvc.js index 15c58477e..51fb6e012 100644 --- a/app/assets/javascripts/services/querySnapshotSvc.js +++ b/app/assets/javascripts/services/querySnapshotSvc.js @@ -108,7 +108,8 @@ angular.module('QuepidApp') }); }; - this.addSnapshot = function(name, recordDocumentFields, queries) { + + this.createSnapshotPayload = function(name, recordDocumentFields, recordExplain, queries) { // we may want to refactor the payload structure in the future. var docs = {}; var queriesPayload = {}; @@ -129,8 +130,12 @@ angular.module('QuepidApp') // Save all matches angular.forEach(query.docs, function(doc) { - - var docPayload = {'id': doc.id, 'explain': doc.explain().rawStr(), 'rated_only': false}; + let explain = null; + if (recordExplain) { + explain = doc.explain().rawStr(); + } + var docPayload = {'id': doc.id, 'explain': explain, 'rated_only': false}; + if (recordDocumentFields) { var fields = {}; angular.forEach(Object.values(doc.subsList), function(field) { @@ -161,15 +166,22 @@ angular.module('QuepidApp') }); }); - var saved = { + var payload = { 'snapshot': { 'name': name, 'docs': docs, 'queries': queriesPayload } }; + + return payload; + }; + + this.addSnapshot = function(name, recordDocumentFields, queries) { + + payload = createSnapshotPayload(name, recordDocumentFields, recordMatch, queries); - return $http.post('api/cases/' + caseNo + '/snapshots', saved) + return $http.post('api/cases/' + caseNo + '/snapshots', payload) .then(function(response) { return addSnapshotResp([response.data]) .then(function() { diff --git a/app/assets/templates/views/devQueryParams.html b/app/assets/templates/views/devQueryParams.html index aa434cb06..7d84fce32 100644 --- a/app/assets/templates/views/devQueryParams.html +++ b/app/assets/templates/views/devQueryParams.html @@ -252,7 +252,35 @@

Tuning Knobs

- + + + +
+
+ Run Queries in Background +
+ +
+
+ + + diff --git a/app/assets/templates/views/queries-stripped.html b/app/assets/templates/views/queries-stripped.html new file mode 100644 index 000000000..90d570fa9 --- /dev/null +++ b/app/assets/templates/views/queries-stripped.html @@ -0,0 +1,22 @@ +
+
+
+ +
+ Number of Queries: {{ queriesList.length }} +
+ +
+ + + + + + +
+
+
diff --git a/app/assets/templates/views/queriesStripped.html b/app/assets/templates/views/queriesStripped.html new file mode 100644 index 000000000..fa1e42b2e --- /dev/null +++ b/app/assets/templates/views/queriesStripped.html @@ -0,0 +1,28 @@ +
+
+
+
+
+

+ STRIPPED Current case +
+ + {{ caseModel.selectedCase().caseName }} + + + — + + {{ currentTry.selectedTry().formattedName() }} + + + +

+
+
+
+ + + + +
+
diff --git a/app/controllers/api/v1/agent_q_controller.rb b/app/controllers/api/v1/agent_q_controller.rb new file mode 100644 index 000000000..4fbfdde69 --- /dev/null +++ b/app/controllers/api/v1/agent_q_controller.rb @@ -0,0 +1,87 @@ +# frozen_string_literal: true + +require 'ferrum' +require 'benchmark' + +# Note: Auto reloading this file appears to not work. If you change the file, quit Rails and restart it. +# I suspect something about how we are talking to Ferrum/Chrome. +# +# Also browser.quit causes Rails to quit too! +# +# rubocop:disable Layout/LineLength +# rubocop:disable Metrics/MethodLength +module Api + module V1 + class AgentQController < Api::ApiController + #skip_before_action :require_login + skip_before_action :verify_authenticity_token, only: [ :fetch ] + @browser = nil + + def fetch + + api_key = nil + if @current_user.api_keys.empty? + api_key = @current_user.api_keys.create! token: SecureRandom.hex + puts "we made a api" + else + api_key = @current_user.api_keys.first + end + + puts "api_key is #{api_key.token_digest}" + + + if @browser.nil? + puts 'creating Ferrum Browser' + # Launch Ferrum browser + @browser = Ferrum::Browser.new({ + process_timeout: 5, headless: true, + window_size: [ 1280, 800 ], + browser_options: { 'no-sandbox': nil }, + timeout: 60, + pending_connection_errors: false + + }) + end + @browser.headers.set({ 'Authorization' => "Bearer #{api_key.token_digest}" }) + page = @browser.create_page + page.headers.set({ 'Authorization' => "Bearer #{api_key.token_digest}" }) + + Benchmark.measure do + # Perform a GET request + page.go_to('http://localhost:3000/case/4/query/5') + # page.network.wait_for_idle + end + + start_time = Time.zone.now + + counter = 30 + # Run the loop for a maximum of 5 seconds + # Timeout.timeout(60) do + loop do + break unless page.at_css('.snapshot-payload').nil? + break if counter.zero? + + # Sleep for a short duration before checking the condition again + + counter -= 1 + sleep 1 + end + + puts "Condition met after #{Time.zone.now - start_time} seconds." + + node = page.at_css('.snapshot-payload') + + # @@browser.quit + + if node + render json: node.text, status: :ok + else + render json: { agentq_error: 'boom', counter: counter }, status: :internal_server_error + end + # Close the browser + end + end + end +end +# rubocop:enable Layout/LineLength +# rubocop:enable Metrics/MethodLength diff --git a/app/controllers/api/v1/queries_controller.rb b/app/controllers/api/v1/queries_controller.rb index 6b2d695de..91d1ae7b6 100644 --- a/app/controllers/api/v1/queries_controller.rb +++ b/app/controllers/api/v1/queries_controller.rb @@ -35,7 +35,7 @@ def create if @query.save @query.insert_at(params[:position].to_i) if params[:position] - @case.save + # @case.save # Having this line made inserting a new case trigger a bunch of updates which was slow. Analytics::Tracker.track_query_created_event current_user, @query @@ -82,8 +82,8 @@ def destroy # Make sure queries have the right `arranged_next` and `arranged_at` # values after the query has been removed - @case.rearrange_queries - @case.save + # @case.rearrange_queries // super slow with lots of queires + # @case.save head :no_content end diff --git a/app/controllers/core_controller.rb b/app/controllers/core_controller.rb index ff38171fa..229b99210 100755 --- a/app/controllers/core_controller.rb +++ b/app/controllers/core_controller.rb @@ -6,6 +6,19 @@ class CoreController < ApplicationController before_action :populate_from_params, except: :new skip_before_action :check_for_announcement + def require_login + @current_user = User.find(3) + end + + # Spiking out can we make an API public? + def authenticate_api! + set_case + return true if @case&.public? || current_user + + render json: { reason: 'Unauthorized!' }, + status: :unauthorized + end + def index end diff --git a/app/controllers/core_stripped_controller.rb b/app/controllers/core_stripped_controller.rb new file mode 100755 index 000000000..e72ea55d8 --- /dev/null +++ b/app/controllers/core_stripped_controller.rb @@ -0,0 +1,36 @@ +# frozen_string_literal: true + +# This hosts the stripped down version Angular 1 application that runs in the client. +# It is meant to wrap up the business logic used in interacting with a search endpoint +# and abstract that all away from the caller. We create a HTML page that is populated +# with the resulting query/docs. Currently using the "snapshot" JSON format. +# It is meant to be called by agent_q_controller.rb. +# +class CoreStrippedController < ApplicationController + include ApiKeyAuthenticatable + skip_before_action :check_for_announcement + before_action :authenticate_with_api_key! # , only: [:index] + + def require_login + if request.headers['Authorization'] + token = request.headers['Authorization'] + token = token[7..] # chop off 'Bearer ' portion of the header + current_api_key = ApiKey.find_by token_digest: token + + @current_user = current_api_key.user + end + end + + # Spiking out can we make an API public? + def authenticate_api! + set_case + return true if @case&.public? || current_user + + render json: { reason: 'Unauthorized!' }, + status: :unauthorized + end + + def index + end + +end diff --git a/app/views/core_stripped/index.html.erb b/app/views/core_stripped/index.html.erb new file mode 100755 index 000000000..38a2c9b3f --- /dev/null +++ b/app/views/core_stripped/index.html.erb @@ -0,0 +1,17 @@ + + +
+
+
+
+ + + Loading... + +
+
+
+
+
+
+
diff --git a/app/views/layouts/core_stripped.html.erb b/app/views/layouts/core_stripped.html.erb new file mode 100755 index 000000000..6f8e10803 --- /dev/null +++ b/app/views/layouts/core_stripped.html.erb @@ -0,0 +1,35 @@ + + + + +Quepid -- Relevant Search Solved + +<%= csrf_meta_tags %> + + + + + + +
+ <%= yield %> +
+ + + <%= javascript_include_tag 'core_stripped' %> + + + + + diff --git a/config/initializers/assets.rb b/config/initializers/assets.rb index 2c20284dc..584d77af2 100755 --- a/config/initializers/assets.rb +++ b/config/initializers/assets.rb @@ -15,8 +15,8 @@ # Precompile additional assets. # application.js, application.css, and all non-JS/CSS in the app/assets # folder are already added. -Rails.application.config.assets.precompile += %w[ core.css core.js admin.css admin_users.css admin.js admin_users.js - analytics.js ] +Rails.application.config.assets.precompile += %w[ core.css core.js core_stripped.js ] +Rails.application.config.assets.precompile += %w[ admin.css admin_users.css admin.js admin_users.js analytics.js ] Rails.application.config.assets.precompile += %w[ application_spec.js ] # CSS from node modules diff --git a/config/routes.rb b/config/routes.rb index 43425bc2e..3d80520c1 100755 --- a/config/routes.rb +++ b/config/routes.rb @@ -11,6 +11,7 @@ get 'proxy/fetch' post 'proxy/fetch' + mount ActiveStorageDB::Engine => '/active_storage_db' # Define your application routes per the DSL in https://guides.rubyonrails.org/routing.html @@ -119,6 +120,9 @@ get 'test_exception' => 'api#test_exception' scope module: :v1, constraints: ApiConstraint.new(version: 1, default: true) do + + get '/agent_q/fetch' => 'agent_q#fetch' + resources :users, only: [ :index, :show, :update ] do get '/current' => 'current_user#show', on: :collection end @@ -241,6 +245,7 @@ # Routes handled by angular get '/case/:id(/try/:try_number)' => 'core#index', as: :case_core + get '/case/:id(/query/:queryNo)' => 'core_stripped#index' get '/cases/new' => 'core#new', as: :case_new get '/cases' => 'core#index' get '/case' => 'core#index' From c2ddde4543d345192a607802f62d2ae6d3731646 Mon Sep 17 00:00:00 2001 From: Eric Pugh Date: Fri, 8 Mar 2024 11:45:09 -0500 Subject: [PATCH 02/19] lint --- .../javascripts/controllers/mainCtrl.js | 7 ++--- .../controllers/queriesStrippedCtrl.js | 4 +-- .../javascripts/controllers/strippedCtrl.js | 28 ++++++------------- .../javascripts/factories/TryFactory.js | 2 +- .../javascripts/services/querySnapshotSvc.js | 2 +- 5 files changed, 15 insertions(+), 28 deletions(-) diff --git a/app/assets/javascripts/controllers/mainCtrl.js b/app/assets/javascripts/controllers/mainCtrl.js index 3b856b4da..2b9ecfd5b 100644 --- a/app/assets/javascripts/controllers/mainCtrl.js +++ b/app/assets/javascripts/controllers/mainCtrl.js @@ -107,9 +107,9 @@ angular.module('QuepidApp') bootstrapped = true; - console.log(queriesSvc.queryArray().length) + console.log(queriesSvc.queryArray().length); if (queriesSvc.queryArray().length <= 410) { - console.log("About to call queriesSvc.searchAll") + console.log('About to call queriesSvc.searchAll'); return queriesSvc.searchAll() .then(function() { flash.success = 'All queries finished successfully!'; @@ -123,7 +123,7 @@ angular.module('QuepidApp') else { queriesSvc.requireManualTrigger = true; flash.success = 'You have ' + queriesSvc.queryArray().length + ' queries in this case and must manually trigger running this!'; - return + return; } } }); @@ -153,7 +153,6 @@ angular.module('QuepidApp') } else if ( caseNo > 0 ) { queriesSvc.querySearchPromiseReset(); - console.log("about to bootstrapCase") bootstrapCase() .then(function() { loadQueries(); diff --git a/app/assets/javascripts/controllers/queriesStrippedCtrl.js b/app/assets/javascripts/controllers/queriesStrippedCtrl.js index ab8a2f6ee..5d7ce9500 100644 --- a/app/assets/javascripts/controllers/queriesStrippedCtrl.js +++ b/app/assets/javascripts/controllers/queriesStrippedCtrl.js @@ -16,8 +16,6 @@ angular.module('QuepidApp') $scope.queriesSvc = queriesSvc; $scope.caseSvc = caseSvc; - console.log("HI THERE") - $scope.queries = {}; $scope.queries.queriesChanged = function() { @@ -37,7 +35,7 @@ angular.module('QuepidApp') $scope.snapshotPayload = function() { if (!$scope.searching()){ - return querySnapshotSvc.createSnapshotPayload("", true, false, queriesSvc.queryArray()); + return querySnapshotSvc.createSnapshotPayload('', true, false, queriesSvc.queryArray()); } } diff --git a/app/assets/javascripts/controllers/strippedCtrl.js b/app/assets/javascripts/controllers/strippedCtrl.js index e0a2e0d63..2befa371b 100644 --- a/app/assets/javascripts/controllers/strippedCtrl.js +++ b/app/assets/javascripts/controllers/strippedCtrl.js @@ -103,24 +103,15 @@ angular.module('QuepidApp') bootstrapped = true; - console.log(queriesSvc.queryArray().length) - if (queriesSvc.queryArray().length <= 410) { - console.log("About to call queriesSvc.searchAll") - return queriesSvc.searchAll() - .then(function() { - flash.success = 'All queries finished successfully!'; - }, function(errorMsg) { - var mainErrorMsg = 'Some queries failed to resolve!'; - - flash.error = mainErrorMsg; - flash.to('search-error').error = errorMsg; - }); - } - else { - queriesSvc.requireManualTrigger = true; - flash.success = 'You have ' + queriesSvc.queryArray().length + ' queries in this case and must manually trigger running this!'; - return - } + return queriesSvc.searchAll() + .then(function() { + flash.success = 'All queries finished successfully!'; + }, function(errorMsg) { + var mainErrorMsg = 'Some queries failed to resolve!'; + + flash.error = mainErrorMsg; + flash.to('search-error').error = errorMsg; + }); } }); }); @@ -140,7 +131,6 @@ angular.module('QuepidApp') } else if ( caseNo > 0 ) { queriesSvc.querySearchPromiseReset(); - console.log("about to bootstrapCase") bootstrapCase() .then(function() { loadQueries(); diff --git a/app/assets/javascripts/factories/TryFactory.js b/app/assets/javascripts/factories/TryFactory.js index 7aa2a1a80..48de322bf 100644 --- a/app/assets/javascripts/factories/TryFactory.js +++ b/app/assets/javascripts/factories/TryFactory.js @@ -40,7 +40,7 @@ self.args = data.args; self.deleted = false; self.escapeQuery = data.escape_query; - self.backgroundQueries = data.background_queries + self.backgroundQueries = data.background_queries; self.apiMethod = data.api_method; self.customHeaders = data.custom_headers; self.fieldSpec = data.field_spec; diff --git a/app/assets/javascripts/services/querySnapshotSvc.js b/app/assets/javascripts/services/querySnapshotSvc.js index 51fb6e012..9c9e93de1 100644 --- a/app/assets/javascripts/services/querySnapshotSvc.js +++ b/app/assets/javascripts/services/querySnapshotSvc.js @@ -179,7 +179,7 @@ angular.module('QuepidApp') this.addSnapshot = function(name, recordDocumentFields, queries) { - payload = createSnapshotPayload(name, recordDocumentFields, recordMatch, queries); + let payload = this.createSnapshotPayload(name, recordDocumentFields, true, queries); return $http.post('api/cases/' + caseNo + '/snapshots', payload) .then(function(response) { From 1f9a3c158fdd87a95ffe0179752c6d860608299c Mon Sep 17 00:00:00 2001 From: Eric Pugh Date: Wed, 17 Apr 2024 06:19:16 -0400 Subject: [PATCH 03/19] associate search end point with team! --- app/assets/javascripts/controllers/mainCtrl.js | 2 +- lib/tasks/sample_data.thor | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/app/assets/javascripts/controllers/mainCtrl.js b/app/assets/javascripts/controllers/mainCtrl.js index 2b9ecfd5b..b28b09918 100644 --- a/app/assets/javascripts/controllers/mainCtrl.js +++ b/app/assets/javascripts/controllers/mainCtrl.js @@ -108,7 +108,7 @@ angular.module('QuepidApp') bootstrapped = true; console.log(queriesSvc.queryArray().length); - if (queriesSvc.queryArray().length <= 410) { + if (queriesSvc.queryArray().length <= 29) { console.log('About to call queriesSvc.searchAll'); return queriesSvc.searchAll() .then(function() { diff --git a/lib/tasks/sample_data.thor b/lib/tasks/sample_data.thor index b3b6814f6..182fbab47 100644 --- a/lib/tasks/sample_data.thor +++ b/lib/tasks/sample_data.thor @@ -227,6 +227,8 @@ class SampleData < Thor osc.members << osc_member_user unless osc.members.include?(osc_member_user) osc.members << realistic_activity_user unless osc.members.include?(realistic_activity_user) osc.cases << tens_of_queries_case unless osc.members.include?(tens_of_queries_case) + osc.search_endpoints << statedecoded_solr_endpoint unless osc.search_endpoints.include?(statedecoded_solr_endpoint) + print_step 'End of seeding teams................' # Books From 7baab3966712f79056d2a9ee727937930acc3a2e Mon Sep 17 00:00:00 2001 From: Eric Pugh Date: Wed, 17 Apr 2024 06:19:30 -0400 Subject: [PATCH 04/19] position is good --- app/assets/javascripts/components/export_case/_modal.html | 2 +- app/assets/javascripts/services/caseCSVSvc.js | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/app/assets/javascripts/components/export_case/_modal.html b/app/assets/javascripts/components/export_case/_modal.html index 87c50f1d6..48ab1964a 100644 --- a/app/assets/javascripts/components/export_case/_modal.html +++ b/app/assets/javascripts/components/export_case/_modal.html @@ -29,7 +29,7 @@