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
54 changes: 27 additions & 27 deletions Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -82,30 +82,30 @@ GEM
public_suffix (>= 2.0.2, < 7.0)
ast (2.4.3)
aws-eventstream (1.4.0)
aws-partitions (1.1148.0)
aws-sdk-core (3.229.0)
aws-partitions (1.1154.0)
aws-sdk-core (3.232.0)
aws-eventstream (~> 1, >= 1.3.0)
aws-partitions (~> 1, >= 1.992.0)
aws-sigv4 (~> 1.9)
base64
bigdecimal
jmespath (~> 1, >= 1.6.1)
logger
aws-sdk-kms (1.110.0)
aws-sdk-core (~> 3, >= 3.228.0)
aws-sdk-kms (1.112.0)
aws-sdk-core (~> 3, >= 3.231.0)
aws-sigv4 (~> 1.5)
aws-sdk-lambda (1.158.0)
aws-sdk-core (~> 3, >= 3.228.0)
aws-sdk-lambda (1.160.0)
aws-sdk-core (~> 3, >= 3.231.0)
aws-sigv4 (~> 1.5)
aws-sdk-s3 (1.197.0)
aws-sdk-core (~> 3, >= 3.228.0)
aws-sdk-s3 (1.198.0)
aws-sdk-core (~> 3, >= 3.231.0)
aws-sdk-kms (~> 1)
aws-sigv4 (~> 1.5)
aws-sdk-secretsmanager (1.119.0)
aws-sdk-core (~> 3, >= 3.228.0)
aws-sdk-secretsmanager (1.120.0)
aws-sdk-core (~> 3, >= 3.231.0)
aws-sigv4 (~> 1.5)
aws-sdk-ses (1.88.0)
aws-sdk-core (~> 3, >= 3.228.0)
aws-sdk-ses (1.90.0)
aws-sdk-core (~> 3, >= 3.231.0)
aws-sigv4 (~> 1.5)
aws-sigv4 (1.12.1)
aws-eventstream (~> 1, >= 1.0.2)
Expand All @@ -116,7 +116,7 @@ GEM
erubi (>= 1.0.0)
rack (>= 0.9.0)
rouge (>= 1.0.0)
bigdecimal (3.2.2)
bigdecimal (3.2.3)
bindex (0.8.1)
bootsnap (1.18.6)
msgpack (~> 1.2)
Expand All @@ -143,7 +143,7 @@ GEM
childprocess (5.1.0)
logger (~> 1.5)
concurrent-ruby (1.3.5)
connection_pool (2.5.3)
connection_pool (2.5.4)
crass (1.0.6)
cssbundling-rails (1.4.3)
railties (>= 6.0.0)
Expand Down Expand Up @@ -186,7 +186,7 @@ GEM
zeitwerk (~> 2.6)
erb (5.0.2)
erubi (1.13.1)
factory_bot (6.5.4)
factory_bot (6.5.5)
activesupport (>= 6.1.0)
factory_bot_rails (6.5.0)
factory_bot (~> 6.5)
Expand Down Expand Up @@ -254,7 +254,7 @@ GEM
ruby2_keywords (~> 0.0.1)
mustermann-grape (1.1.0)
mustermann (>= 1.0.0)
net-imap (0.5.9)
net-imap (0.5.10)
date
net-protocol
net-pop (0.1.2)
Expand Down Expand Up @@ -292,13 +292,13 @@ GEM
parser (3.3.9.0)
ast (~> 2.4.1)
racc
pg (1.6.1)
pg (1.6.1-aarch64-linux)
pg (1.6.1-aarch64-linux-musl)
pg (1.6.1-arm64-darwin)
pg (1.6.1-x86_64-darwin)
pg (1.6.1-x86_64-linux)
pg (1.6.1-x86_64-linux-musl)
pg (1.6.2)
pg (1.6.2-aarch64-linux)
pg (1.6.2-aarch64-linux-musl)
pg (1.6.2-arm64-darwin)
pg (1.6.2-x86_64-darwin)
pg (1.6.2-x86_64-linux)
pg (1.6.2-x86_64-linux-musl)
pp (0.6.2)
prettyprint
prettyprint (0.2.0)
Expand All @@ -314,7 +314,7 @@ GEM
puma (6.6.1)
nio4r (~> 2.0)
racc (1.8.1)
rack (3.2.0)
rack (3.2.1)
rack-session (2.1.1)
base64 (>= 0.1.0)
rack (>= 3.0.0)
Expand Down Expand Up @@ -374,7 +374,7 @@ GEM
responders (3.1.1)
actionpack (>= 5.2)
railties (>= 5.2)
rexml (3.4.1)
rexml (3.4.2)
rouge (4.6.0)
rspec (3.13.1)
rspec-core (~> 3.13.0)
Expand All @@ -396,7 +396,7 @@ GEM
rspec-expectations (~> 3.13)
rspec-mocks (~> 3.13)
rspec-support (~> 3.13)
rspec-support (3.13.4)
rspec-support (3.13.5)
rubocop (1.75.8)
json (~> 2.3)
language_server-protocol (~> 3.17.0.2)
Expand Down Expand Up @@ -486,7 +486,7 @@ GEM
railties (>= 7.1.0)
tzinfo (2.0.6)
concurrent-ruby (~> 1.0)
unicode-display_width (3.1.4)
unicode-display_width (3.1.5)
unicode-emoji (~> 4.0, >= 4.0.4)
unicode-emoji (4.0.4)
uri (1.0.3)
Expand Down
118 changes: 56 additions & 62 deletions app/api/asap_pdf/api.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,44 +6,60 @@ class API < Grape::API::Instance
format :json

http_basic do |email, password|
user = User.find_by(email: email)
user&.valid_password?(password)
@user = User.find_by(email: email)
@user&.valid_password?(password)
end

rescue_from ActiveRecord::RecordNotFound do |e|
error!({error: e.message}, 404)
end

desc "Return list of sites" do
detail "Returns a list of all sites in the system"
detail "Returns a list of all sites the user has access to."
tags ["Sites"]
produces ["application/json"]
failure [[401, "Unauthorized"], [403, "Forbidden"]]
security [{basic_auth: []}]
end
get "/sites" do
Site.all
if @user.is_site_admin
Site.all
else
@user.site.present? ? [@user.site] : []
end
end

desc "Return a specific site" do
detail "Returns detailed information about a specific site"
tags ["Sites"]
desc "List documents related to site." do
detail "A paginated list of documents related to a site."
tags ["Documents"]
produces ["application/json"]
consumes ["application/json"]
failure [
[400, "Bad Request - Invalid parameters"],
[401, "Unauthorized"],
[403, "Forbidden"],
[404, "Site not found"]
]
named "List documents"
end
params do
requires :id, type: Integer, desc: "Site ID"
optional :page, type: Integer, desc: "Page number for pagination", default: 0
optional :items_per_page, type: Integer, desc: "Items per page", default: 25
end
get "/sites/:id" do
Site.find(params[:id])
get "/sites/:id/documents" do
items_per_page = params[:items_per_page].nil? ? 25 : params[:items_per_page].to_i
page = params[:page].nil? ? 0 : params[:page].to_i
unless @user.is_site_admin || params[:id] == @user.site_id
error!("Unauthorized", 401)
end
site = Site.find(params[:id])
{documents: site.documents.limit(items_per_page).offset(page * items_per_page).order(id: :asc)}
end

desc "Discover documents for a site" do
detail "Creates or updates documents for a specific site based on the provided URLs and timestamps"
tags ["Documents"]
desc "List document inferences for a document." do
detail "List LLM document inferences (summary or exception check) for a document."
tags ["Document Inferences"]
produces ["application/json"]
consumes ["application/json"]
failure [
Expand All @@ -52,28 +68,16 @@ class API < Grape::API::Instance
[403, "Forbidden"],
[404, "Site not found"]
]
named "Create Documents"
end
params do
requires :id, type: Integer, desc: "Site ID"
requires :documents, type: Array do
requires :url, type: String, desc: "Document URL"
requires :modification_date, type: DateTime, desc: "Document's last modified timestamp"
end
requires :id, type: Integer, desc: "Document ID"
end
post "/sites/:id/documents" do
site = Site.find(params[:id])
documents = site.discover_documents!(params[:documents], true)

status 201
{documents: documents.map { |doc|
{
id: doc.id,
url: doc.url,
document_status: doc.document_status,
s3_path: doc.s3_path
}
}}
get "/documents/:id/document_inference" do
document = Document.find(params[:id])
unless @user.is_site_admin || document.site_id == @user.site_id
error!("Unauthorized", 401)
end
{document_inferences: document.document_inferences.order(id: :asc)}
end

desc "Adds or updates a document inference with type" do
Expand All @@ -91,67 +95,57 @@ class API < Grape::API::Instance
params do
requires :id, type: Integer, desc: "Document ID"
requires :inference_type, type: String, desc: "Document inference type", values: ["summary", "exception"]
requires :result, type: Hash, desc: "Value of document inference"
optional :result, type: Hash, desc: "Value of document inference" do
optional "summary", type: String, desc: "For inference_type summary, generated summary"
optional "is_<exception type>", type: String, desc: "For inference_type exception, the exception type"
optional "why_<exception type>", type: String, desc: "For inference_type exception, the LLM explanation"
end
end
post "/documents/:id/inference" do
status 201
document = Document.find(params[:id])
unless @user.is_site_admin || document.site_id == @user.site_id
error!("Unauthorized", 401)
end
if params[:inference_type] == "summary"
inference = DocumentInference.create(document_id: params[:id], inference_type: "summary")
inference = document.document_inferences.new(inference_type: "summary")
inference.inference_value = params[:result]["summary"]
inference.is_active = true
inference.inference_model_name = params[:result]["inference_model"]
inference.token_details = params[:result]["usage"]
inference.save!
end
if params[:inference_type] == "exception"
["individualized", "archival", "application", "third_party"].each do |type|
result_boolean = "is_#{type}"
unless params[:result][result_boolean].nil?
inference = DocumentInference.create(document_id: params[:id], inference_type: "exception:#{result_boolean}")
inference = document.document_inferences.new(inference_type: "exception:#{result_boolean}")
inference.inference_value = params[:result][result_boolean] ? "True" : "False"
inference.inference_confidence = params[:result]["#{result_boolean}_confidence"]
inference.inference_reason = params[:result]["why_#{type}"]
inference.is_active = true
inference.inference_model_name = params[:result]["inference_model"]
inference.token_details = params[:result]["usage"]
inference.save!
end
end
end
end

add_swagger_documentation(
doc_version: "1.0.0",
mount_path: "/swagger_doc",
openapi_version: "3.0.1",
info: {
title: "ASAP PDF API",
description: "API for managing ASAP PDF resources and document processing",
description: "API for managing ASAP PDF resources and document processing. <strong>Note: Basic authentication is required for all endpoints.</strong>",
version: "1.0.0"
},
tags: [
{name: "Sites", description: "Site management operations"},
{name: "Documents", description: "Document processing operations"}
{name: "Sites", description: "Site operations"},
{name: "Documents", description: "Document operations"},
{name: "Document Inferences", description: "Document Inference operations"}
],
components: {
schemas: {
Site: {
type: "object",
properties: {
id: {type: "integer", description: "Site ID"},
name: {type: "string", description: "Site name"},
location: {type: "string", description: "Site location"},
primary_url: {type: "string", description: "Primary URL of the site"}
},
required: ["id", "name", "location", "primary_url"]
},
Document: {
type: "object",
properties: {
id: {type: "integer", description: "Document ID"},
url: {type: "string", description: "Document URL"},
document_status: {type: "string", description: "Current status of the document"},
s3_path: {type: "string", description: "S3 storage path"}
},
required: ["id", "url", "document_status", "s3_path"]
}
}
}
models: []
)
end
end
19 changes: 19 additions & 0 deletions app/assets/stylesheets/application.tailwind.css
Original file line number Diff line number Diff line change
Expand Up @@ -136,3 +136,22 @@
@apply m-0 p-2 text-sm h-10;
}
}


.feedback-wrapper {
.sentiment-wrapper {
.sentiment:hover i,
.sentiment.active i {
@apply text-gray-500;
}
}

.additional-feedback {
transition: max-height 0.5s ease;
max-height: 200px;

&.collapsed {
@apply max-h-0 overflow-hidden
}
}
}
Loading