diff --git a/.ruby-version b/.ruby-version new file mode 100644 index 00000000..4d9d11cf --- /dev/null +++ b/.ruby-version @@ -0,0 +1 @@ +3.4.2 diff --git a/.tool-versions b/.tool-versions new file mode 100644 index 00000000..e15f5d30 --- /dev/null +++ b/.tool-versions @@ -0,0 +1,2 @@ +nodejs 18.20.4 +ruby 3.1.6 diff --git a/app/controllers/api/submissions_controller.rb b/app/controllers/api/submissions_controller.rb index af784ba2..1bef7f4e 100644 --- a/app/controllers/api/submissions_controller.rb +++ b/app/controllers/api/submissions_controller.rb @@ -193,7 +193,7 @@ module Api submitters: [[:send_email, :send_sms, :completed_redirect_url, :uuid, :name, :email, :role, :completed, :phone, :application_key, :external_id, :reply_to, :go_to_last, { metadata: {}, values: {}, roles: [], readonly_fields: [], message: %i[subject body], - fields: [:name, :uuid, :default_value, :value, :title, :description, + fields: [:name, :uuid, :question_id, :default_value, :value, :title, :description, :readonly, :required, :validation_pattern, :invalid_message, { default_value: [], value: [], preferences: {} }] }]] } diff --git a/app/controllers/api/templates_controller.rb b/app/controllers/api/templates_controller.rb index cb79ce9c..ac67f9b6 100644 --- a/app/controllers/api/templates_controller.rb +++ b/app/controllers/api/templates_controller.rb @@ -237,15 +237,16 @@ module Api :external_id, :shared_link, { + external_data_fields: {}, submitters: [%i[name uuid is_requester invite_by_uuid optional_invite_by_uuid linked_to_uuid email]], - fields: [[:uuid, :submitter_uuid, :name, :type, + fields: [[:uuid, :question_id, :submitter_uuid, :name, :type, :required, :readonly, :default_value, :title, :description, { preferences: {}, conditions: [%i[field_uuid value action operation]], - options: [%i[value uuid]], + options: [%i[value uuid answer_id]], validation: %i[message pattern], - areas: [%i[x y w h cell_w attachment_uuid option_uuid page]] }]] + areas: [%i[x y w h cell_w attachment_uuid option_uuid answer_id page]] }]] } ] diff --git a/app/controllers/export_controller.rb b/app/controllers/export_controller.rb new file mode 100644 index 00000000..cfa94cf4 --- /dev/null +++ b/app/controllers/export_controller.rb @@ -0,0 +1,62 @@ +# frozen_string_literal: true + +require 'faraday' + +class ExportController < ApplicationController + skip_authorization_check + skip_before_action :maybe_redirect_to_setup + skip_before_action :verify_authenticity_token + + # Template is sent as JSON already; we're just gonnna send it on to the third party. + def export_template + export_location = ExportLocation.default_location + + data = request.raw_post.present? ? JSON.parse(request.raw_post) : params.to_unsafe_h + response = post_to_api(data, export_location.templates_endpoint, export_location.extra_params) + + if response&.success? + Rails.logger.info("Successfully exported template #{data[:template][:name]} to #{export_location.name}") + head :ok + else + Rails.logger.error("Failed to export template to third party: #{response&.status}") + Rollbar.error("#{export_location.name} template export API error: #{response&.status}") if defined?(Rollbar) + head :unprocessable_entity + end + rescue Faraday::Error => e + Rails.logger.error("Failed to export template Faraday: #{e.message}") + Rollbar.error("Failed to export template: #{e.message}") if defined?(Rollbar) + head :service_unavailable + rescue StandardError => e + Rails.logger.error("Failed to export template: #{e.message}") + Rollbar.error(e) if defined?(Rollbar) + head :internal_server_error + end + + private + + def api_connection + @api_connection ||= Faraday.new(url: ExportLocation.default_location.api_base_url) do |faraday| + faraday.request :json + faraday.response :json + faraday.adapter Faraday.default_adapter + end + rescue StandardError => e + Rails.logger.error("Failed to create API connection: #{e.message}") + Rollbar.error(e) if defined?(Rollbar) + nil + end + + def post_to_api(data, endpoint, extra_params = nil) + connection = api_connection + return nil unless connection + + connection.post(endpoint) do |req| + # req.headers['Authorization'] = "Bearer #{export_location.authorization_token}" lol + + # Merge extra_params into data if provided + data = data.merge(extra_params) if extra_params.present? && data.is_a?(Hash) + + req.body = data.is_a?(String) ? data : data.to_json + end + end +end diff --git a/app/controllers/templates_controller.rb b/app/controllers/templates_controller.rb index 14b36709..2828ce58 100644 --- a/app/controllers/templates_controller.rb +++ b/app/controllers/templates_controller.rb @@ -121,14 +121,15 @@ class TemplatesController < ApplicationController :name, { schema: [[:attachment_uuid, :name, { conditions: [%i[field_uuid value action operation]] }]], submitters: [%i[name uuid is_requester linked_to_uuid invite_by_uuid optional_invite_by_uuid email]], - fields: [[:uuid, :submitter_uuid, :name, :type, + external_data_fields: {}, + fields: [[:uuid, :question_id, :submitter_uuid, :name, :type, :required, :readonly, :default_value, :title, :description, { preferences: {}, conditions: [%i[field_uuid value action operation]], - options: [%i[value uuid]], + options: [%i[value uuid answer_id]], validation: %i[message pattern], - areas: [%i[x y w h cell_w attachment_uuid option_uuid page]] }]] } + areas: [%i[x y w h cell_w attachment_uuid option_uuid answer_id page]] }]] } ) end diff --git a/app/javascript/application.scss b/app/javascript/application.scss index 61d3f645..a9709f8b 100644 --- a/app/javascript/application.scss +++ b/app/javascript/application.scss @@ -56,11 +56,45 @@ button[disabled] .enabled { } .base-button { - @apply btn btn-neutral text-white text-base; + @apply btn btn-primary text-white text-base; +} + +.btn-outline { + border-color: #004FCC; + color: #004FCC; +} + +.btn-outline:hover { + background-color: #004FCC; + border-color: #004FCC; + color: white; +} + +.btn-ghost { + color: #004FCC; +} + +.btn-ghost:hover { + background-color: #004FCC; + color: white; +} + +.btn-neutral { + background-color: #004FCC; + border-color: #004FCC; + color: white; +} + +.btn-neutral:hover { + background-color: #0063FF; + border-color: #0063FF; + color: white; } .white-button { @apply btn btn-outline text-base bg-white border-2; + border-color: #004FCC; + color: #004FCC; } .base-checkbox { diff --git a/app/javascript/form.scss b/app/javascript/form.scss index fb651155..753f53eb 100644 --- a/app/javascript/form.scss +++ b/app/javascript/form.scss @@ -56,11 +56,45 @@ button[disabled] .enabled { } .base-button { - @apply btn btn-neutral text-white text-base; + @apply btn btn-primary text-white text-base; +} + +.btn-outline { + border-color: #004FCC; + color: #004FCC; +} + +.btn-outline:hover { + background-color: #004FCC; + border-color: #004FCC; + color: white; +} + +.btn-ghost { + color: #004FCC; +} + +.btn-ghost:hover { + background-color: #004FCC; + color: white; +} + +.btn-neutral { + background-color: #004FCC; + border-color: #004FCC; + color: white; +} + +.btn-neutral:hover { + background-color: #0063FF; + border-color: #0063FF; + color: white; } .white-button { @apply btn btn-outline text-base bg-white border-2; + border-color: #004FCC; + color: #004FCC; } .base-checkbox { diff --git a/app/javascript/template_builder/builder.vue b/app/javascript/template_builder/builder.vue index df68917a..f14555ab 100644 --- a/app/javascript/template_builder/builder.vue +++ b/app/javascript/template_builder/builder.vue @@ -73,6 +73,25 @@ name="buttons" />