Skip to content

Commit

Permalink
Merge pull request #564 from t3-innovation-network/staging
Browse files Browse the repository at this point in the history
Release 07/12/24
  • Loading branch information
excelsior authored Jul 12, 2024
2 parents 7a96adb + 64b9493 commit 77a2cde
Show file tree
Hide file tree
Showing 106 changed files with 2,923 additions and 1,404 deletions.
18 changes: 9 additions & 9 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,15 @@ DEFAULT_PASS=t3admint3admin
# Secret key used to encode passwords and sensitive information. E.g. 'HS256', 'RS256'
PRIVATE_KEY=a-strong-password-to-use-as-secret-key-to-encode-and-or-decode

# Credentials for sending emails from the application
# These credentials are for the email account from which the emails are going
# to be sent (the sender).
MAIL_PASSWORD=apassword
MAIL_USERNAME=t3@mail.org

# Mailgun configuration
MAILGUN_API_KEY=your-mailgun-api-key
MAILGUN_DOMAIN=the-domain-that-serves-your-emails
# Email configuration.
# Either Mailgun or SMTP settings must be present.
# Mailgun takes precedence over SMTP if both are present.
FROM_EMAIL_ADDRESS=
MAILGUN_API_KEY=
MAILGUN_DOMAIN=
SMTP_ADDRESS=
SMTP_PASSWORD=
SMTP_USERNAME=

# The minimum accepted length for passwords
MIN_PASSWORD_LENGTH=8
Expand Down
3 changes: 3 additions & 0 deletions .overcommit.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@ PreCommit:
BundleCheck:
enabled: true

CapitalizedSubject:
enabled: false

ExecutePermissions:
enabled: true
exclude:
Expand Down
1 change: 1 addition & 0 deletions app/assets/stylesheets/application.scss
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
@import 'components/card';
@import 'components/drag-n-drop';
@import 'components/icon';
@import 'components/multiselect';
@import 'customradio';
@import 'forms';
@import 'navbar';
Expand Down
3 changes: 3 additions & 0 deletions app/assets/stylesheets/components/_multiselect.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
.dropdown-container {
z-index: 9999;
}
24 changes: 24 additions & 0 deletions app/assets/stylesheets/stepper.scss
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,30 @@
top: 0.5vw;
}

.indicator-stepnum {
@include e(link) {
margin-left: -0.3vw;

&:hover {
color: $primary-color-light !important; // stylelint-disable-line
}
}

@include e(num) {
display: inline-block;

@include m(text) {
padding-top: 1px;
}

@include m(link) {
border: 1px solid $primary-color-light;
height: 1rem;
width: 1rem;
}
}
}

.indicator > .indicator-step .indicator-stepnum {
color: $foreground-color;
font-size: 12px;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,15 @@ def call_action

@instance.send(action)
render json: @instance.reload, with_organizations: true
rescue CpState::NotYetReadyForTransition => e
message =
if @instance.incomplete?
ConfigurationProfile.validate_structure(@instance.structure, "complete")
else
e.message
end

render json: { message: }, status: :internal_server_error
end

private
Expand Down
8 changes: 5 additions & 3 deletions app/controllers/api/v1/configuration_profiles_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,11 @@ def show
end

def update
@instance.update(permitted_params)

render json: @instance, with_organizations: true
if @instance.update(permitted_params)
render json: @instance, with_organizations: true
else
render json: { error: @instance.errors.full_messages.join("\\n") }, status: :unprocessable_entity
end
end

def set_current
Expand Down
48 changes: 48 additions & 0 deletions app/controllers/api/v1/mapping_exports_controller.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
# frozen_string_literal: true

###
# @description: Place all the actions related to mappings
###
module API
module V1
class MappingExportsController < BaseController
include ConfigurationProfileQueryable

###
# @description: Returns exported mappings in a given format as binary
###
def index
domains = current_configuration_profile
.domains
.where(id: Array.wrap(params.fetch(:domain_ids, "").split(",")))

mapping = current_configuration_profile
.mappings
.find_by(id: params[:mapping_id])

if domains.empty? && mapping.nil?
render json: { error: "Either domain_ids or mapping_id is required" }, status: :bad_request
return
end

result = ExportMappings.call(
configuration_profile: current_configuration_profile,
domains:,
format: params[:format],
mapping:
)

if result.success?
send_data result.data,
filename: result.filename,
type: result.content_type
else
render json: { error: response.error }, status: :unprocessable_entity
end
rescue StandardError => e
Airbrake.notify(e)
render json: { error: e.message }, status: :internal_server_error
end
end
end
end
8 changes: 7 additions & 1 deletion app/controllers/api/v1/mappings_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,13 @@ def destroy
# mapping JSON-LD version.
###
def export
render json: @instance.export
exporter = Exporters::Mapping.new(@instance)

if params[:format] == "csv"
render plain: exporter.to_csv, content_type: "text/csv"
else
render json: exporter.to_jsonld
end
end

###
Expand Down
25 changes: 21 additions & 4 deletions app/controllers/api/v1/specifications_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ module API
module V1
class SpecificationsController < BaseController
include ConfigurationProfileQueryable
before_action :authorize_with_policy, only: :update

###
# @description: Lists all the specifications
Expand All @@ -19,11 +20,13 @@ def index
Specification.all
end

if (domain = params[:domain]).present?
specifications = specifications.joins(:domain).where(domains: { pref_label: domain })
specifications = specifications.joins(:mappings).where(mappings: { status: "mapped" }).includes(:domain)

if (domain_id = params[:domain_id]).present?
specifications.where!(domain_id:)
end

render json: specifications.joins(:mappings).where(mappings: { status: "mapped" }).distinct.order(name: :asc)
render json: specifications.distinct.order(name: :asc)
end

###
Expand Down Expand Up @@ -56,8 +59,18 @@ def destroy
}
end

def update
spec = Processors::Specifications.update(valid_params, instance: @instance)

render json: spec
end

private

def authorize_with_policy
authorize(instance)
end

###
# @description: Clean the parameters with all needed for specifications creation
# @return [ActionController::Parameters]
Expand All @@ -77,7 +90,11 @@ def valid_params
# @return [ActionController::Parameters]
###
def permitted_params
params.require(:specification).permit(:name, :scheme, :uri, :version)
params.require(:specification).permit(:name, :scheme, :uri, :version, :mapping_id)
end

def instance
@instance ||= policy_scope(Specification).find(params[:id])
end
end
end
Expand Down
2 changes: 1 addition & 1 deletion app/controllers/api/v1/spine_specifications_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ class SpineSpecificationsController < BaseController
# @description: Returns a filtered list of specifications for an organization
###
def index
render json: current_configuration_profile.spines
render json: current_configuration_profile.spines, include: %i(domain)
end

def show
Expand Down
131 changes: 131 additions & 0 deletions app/interactors/export_mappings.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
# frozen_string_literal: true

class ExportMappings
include Interactor

delegate :configuration_profile, :domains, :format, :mapping, to: :context

def call
case format
when "csv" then export_csv
when "jsonld" then export_jsonld
when "ttl" then export_turtle
else context.fail!(error: "Unsupported format: `#{format}`")
end

context.filename = "#{filename}.#{extension}"
end

def bulk_export?
domains.any?
end

def filename
@filename ||=
if bulk_export?
domains.map(&:name).map { _1.tr(" ", "+") }.join("_")
else
mapping.export_filename
end
end

def export_csv
context.content_type = bulk_export? ? "application/zip" : "text/csv"

context.data =
if bulk_export?
io = StringIO.new

Zip::OutputStream.write_buffer(io) do |zip|
mappings.each do |mapping|
zip.put_next_entry("#{mapping.export_filename}.csv")
zip.write(Exporters::Mapping.new(mapping).csv)
end
end

io.rewind
io.string
else
exporter.csv
end
end

def export_jsonld
context.content_type = "application/ld+json"
context.data = jsonld_data
end

def export_turtle
context.content_type = "text/turtle"
context.data = turtle_data
end

def exporter
Exporters::Mapping.new(mapping)
end

def extension
bulk_export? && format == "csv" ? "zip" : format
end

def jsonld_data
@jsonld_data ||= if bulk_export?
{
"@context": Desm::CONTEXT,
"@graph": mappings.map { Exporters::Mapping::JSONLD.new(_1).graph }.flatten.uniq
}.to_json
else
exporter.jsonld.to_json
end
end

def mappings
@mappings ||=
begin
relation = configuration_profile.mappings.mapped.select(:id)

if bulk_export?
relation = relation
.joins(:specification)
.where(specifications: { domain_id: domains })
end

relation.where!(id: mapping) if mapping.present?

mappings = Mapping
.where(id: relation)
.includes(
alignments: [
:predicate,
{ mapped_terms: :property },
{ spine_term: :property }
],
specification: :domain
)

if format == "csv"
mappings.includes(:configuration_profile)
else
mappings
end
end
end

def turtle_data
@turtle_data ||= begin
repository = RDF::Repository.new

JSON::LD::Reader.new(jsonld_data) do |reader|
reader.each_statement do |statement|
repository << statement
end
end

RDF::Writer.for(:turtle).buffer do |writer|
repository.each_statement do |statement|
writer << statement
end
end
end
end
end
Loading

0 comments on commit 77a2cde

Please sign in to comment.