Commit 4ca0c3cc authored by charlie-ablett's avatar charlie-ablett
Browse files

Merge branch 'recipe_presets'

parents 93b6d0cf 70511793
......@@ -118,7 +118,7 @@ Restart the server on production by running `touch $rails_root/tmp/restart.txt`.
To write a new step, create a gem (you can host it under RubyGems). I've included code so that the step files get autoloaded when Rails is present.
The example I'll use here is `InkStep::RotThirteen` included in the gem `coko_demo_steps`.
The example I'll use here is `InkStep::Coko::RotThirteen` included in the gem `coko_demo_steps`.
You can install in a few ways:
......
module Api
module V1
class RecipeStepPresetsController < ApplicationController
# before_action :authenticate_account!, only: [:create, :update, :destroy, :creat_from_process_chain]
before_action :authenticate!
respond_to :json
def create_from_process_step
process_step = ProcessStep.find(params[:process_step_id])
process_chain = current_entity.account.process_chains.find(process_step.process_chain_id)
if process_chain.recipe.available_to_account?(current_entity.account)
new_recipe_step_preset.execution_parameters = process_step.execution_parameters
new_recipe_step_preset.recipe_step_id = process_chain.recipe.recipe_steps.find_by_position(process_step.position).id
new_recipe_step_preset.save!
render json: new_recipe_step_preset, scope: current_entity, scope_name: :current_entity
else
render json: "Recipe not available", status: 404
return
end
rescue => e
ap e.message
ap e.backtrace
render_error(e)
end
def create
if new_recipe_step_preset.recipe_step.recipe.available_to_account?(current_entity.account)
new_recipe_step_preset.execution_parameters = params[:recipe_step_preset][:execution_parameters]
# not being picked up automatically?
new_recipe_step_preset.save!
render json: new_recipe_step_preset, scope: current_entity, scope_name: :current_entity
else
render json: "Recipe not available", status: 404
return
end
rescue => e
ap e.message
ap e.backtrace
render_error(e)
end
def index
recipe_step = RecipeStep.find(params[:recipe_step_id])
recipe = Recipe.find(recipe_step.recipe_id)
if recipe.available_to_account?(current_entity.account)
render json: recipe_step_presets, scope: current_entity, scope_name: :current_entity
else
render json: "Recipe not available", status: 404 and return
end
end
def show
if recipe_step_preset.recipe_step.recipe.available_to_account?(current_entity.account)
render json: {presets: recipe_step_preset}, scope: current_entity, scope_name: :current_entity
else
render json: "Recipe not available", status: 404
end
rescue => e
ap e.message
ap e.backtrace
render_error(e)
end
def update
if recipe_step_preset.recipe_step.recipe.available_to_account?(current_entity.account)
recipe_step_preset.execution_parameters = params[:recipe_step_preset][:execution_parameters]
recipe_step_preset.update!(recipe_step_preset_params)
render json: recipe_step_preset, root: false, scope: current_entity, scope_name: :current_entity
else
render json: "Recipe not available", status: 404 and return
end
rescue => e
ap e.message
ap e.backtrace
render_error(e)
end
def destroy
recipe_step_preset.destroy
render json: recipe_step_preset, root: false, scope: current_entity, scope_name: :current_entity
rescue => e
render_error(e)
end
private
def recipe_step_preset_params
params.require(:recipe_step_preset).permit(:name, :description, :execution_parameters, :recipe_step_id)
end
def recipe_step_preset
@recipe_step_preset ||= current_entity.account.recipe_step_presets.find(params[:id])
end
def recipe_step_presets
@recipe_step_presets ||= current_entity.account.recipe_step_presets.where(recipe_step_id: params[:recipe_step_id])
end
def new_recipe_step_preset
@new_recipe_step_preset ||= current_entity.account.recipe_step_presets.new(recipe_step_preset_params)
end
end
end
end
\ No newline at end of file
......@@ -2,7 +2,7 @@ module Api
module V1
class RecipesController < ApplicationController
before_action :authenticate_account!, only: [:create, :update, :destroy, :favourite, :unfavourite, :favourites]
before_action :authenticate!, only: [:index, :show, :execute]
before_action :authenticate!, only: [:index, :show, :execute, :index_all]
respond_to :json
......@@ -47,10 +47,15 @@ module Api
render_error(e)
end
def index
def index_all
render json: recipes, scope: current_entity, scope_name: :current_entity
end
def index
@recipes = Recipe.available_to_account(current_entity.account.id, current_entity.admin?)
render json: @recipes, scope: current_entity, scope_name: :current_entity, each_serializer: SimpleRecipeSerializer
end
def favourites
render json: favourite_recipes, scope: current_entity, scope_name: :current_entity
end
......@@ -98,7 +103,12 @@ module Api
end
def execution_params
params[:execution_parameters] || {}
ex_params = params[:execution_parameters] || {}
if ex_params.is_a?(String)
return JSON.parse(ex_params)
else
ex_params
end
end
def callback_url_param
......@@ -114,7 +124,7 @@ module Api
end
def recipes
@recipes ||= Recipe.includes(:recipe_steps, process_chains: :process_steps).available_to_account(current_entity.account.id, current_entity.admin?)
@recipes ||= Recipe.includes(:recipe_steps, :recipe_favourites, process_chains: :process_steps).available_to_account(current_entity.account.id, current_entity.admin?)
end
def favourite_recipes
......
# create_table "accounts", force: :cascade do |t|
# t.string "provider", default: "email", null: false
# t.string "uid", default: "", null: false
# t.string "encrypted_password", default: "", null: false
# t.string "reset_password_token"
# t.datetime "reset_password_sent_at"
# t.datetime "remember_created_at"
# t.integer "sign_in_count", default: 0, null: false
# t.datetime "current_sign_in_at"
# t.datetime "last_sign_in_at"
# t.string "current_sign_in_ip"
# t.string "last_sign_in_ip"
# t.string "confirmation_token"
# t.datetime "confirmed_at"
# t.datetime "confirmation_sent_at"
# t.string "unconfirmed_email"
# t.string "name"
# t.string "nickname"
# t.string "image"
# t.string "email"
# t.json "tokens"
# t.datetime "created_at"
# t.datetime "updated_at"
# end
# needed as Devise uses this class before Rails has a chance to autoload it
require 'rails/generators/rails/app/templates/app/models/application_record'
......@@ -38,6 +13,7 @@ class Account < ApplicationRecord
has_many :process_chains, inverse_of: :account
has_many :account_roles, inverse_of: :account
has_many :recipe_favourites, inverse_of: :account
has_many :recipe_step_presets, inverse_of: :account
has_one :service
def roles
......
......@@ -80,7 +80,12 @@ class Recipe < ApplicationRecord
new_chain = process_chains.new(account: account, execution_parameters: execution_parameters)
recipe_steps.each do |recipe_step|
raw_params = execution_parameters[recipe_step.position.to_s] || {}
ap "Execution parameters"
ap execution_parameters
ap("raw param:", raw_params)
parameters = raw_params["data"] || {}
ap "param"
ap parameters
# Folding the ad-hoc execution parameters into the execution parameters detailed in the recipe step
# The ad-hoc parameters of the same name take precedence.
......@@ -153,6 +158,14 @@ class Recipe < ApplicationRecord
end
end
def available_to_account?(target_account)
return true if target_account.admin?
return true if public?
return true if account == target_account
return false unless active? || account != target_account
false
end
private
def generate_steps_with_positions(recipe_step_data)
......
# create_table "recipe_steps", force: :cascade do |t|
# t.integer "recipe_id", null: false
# t.integer "position", null: false
# t.datetime "created_at", null: false
# t.datetime "updated_at", null: false
# t.string "step_class_name", null: false
# end
class RecipeStep < ApplicationRecord
include ObjectMethods
belongs_to :recipe, inverse_of: :recipe_steps
has_many :recipe_step_presets, inverse_of: :recipe_step
validates_presence_of :recipe, :position, :step_class_name
validates :position, numericality: { greater_than_or_equal_to: 1, only_integer: true }
validates_uniqueness_of :position, { scope: :recipe, message: "Only one step can be in this position for this chain" }
validates_uniqueness_of :position, { scope: :recipe, message: "Only one step can be in this position for this recipe" }
def step_class
class_from_string(step_class_name)
......
class RecipeStepPreset < ApplicationRecord
belongs_to :recipe_step, inverse_of: :recipe_step_presets
belongs_to :account, inverse_of: :recipe_step_presets
validates_presence_of :recipe_step, :name, :account
end
\ No newline at end of file
class Service < ApplicationRecord
belongs_to :account
validates :account, presence: true
......
class RecipeStepSerializer < ActiveModel::Serializer
attributes :id, :position, :recipe_id, :step_class_name, :description, :execution_parameters, :human_readable_name
attributes :id, :position, :recipe_id, :step_class_name, :description, :execution_parameters, :human_readable_name,
:default_parameter_values, :required_parameters, :accepted_parameters
has_many :recipe_step_presets do
if scope.admin?
object.recipe_step_presets
else
object.recipe_step_presets.where(account_id: scope.account.id)
end
end
def execution_parameters
object.execution_parameters || {}
......@@ -20,4 +29,28 @@ class RecipeStepSerializer < ActiveModel::Serializer
object.step_class.human_readable_name
end
end
def default_parameter_values
if object.step_class.nil?
nil
else
object.step_class.default_parameter_values
end
end
def required_parameters
if object.step_class.nil?
nil
else
object.step_class.required_parameters
end
end
def accepted_parameters
if object.step_class.nil?
nil
else
object.step_class.accepted_parameters
end
end
end
class SimpleRecipeSerializer < ActiveModel::Serializer
attributes :id, :name, :description, :active, :account_id, :public, :recipe_steps, :favourite
def favourite
object.favourited_by?(scope)
end
end
\ No newline at end of file
......@@ -7,7 +7,7 @@ lock '3.4.1'
set :application, 'ink-api'
set :repo_url, 'git@gitlab.coko.foundation:INK/ink-api.git'
set :linked_files, fetch(:linked_files, []).push('config/database.yml', 'config/secrets.yml', 'config/ink_api.yml', '.env', 'StepGemfile')
set :linked_files, fetch(:linked_files, []).push('config/database.yml', 'config/secrets.yml', '.env', 'StepGemfile')#'config/ink_api.yml',
set :linked_dirs, fetch(:linked_dirs, []).push('log', 'tmp/pids', 'tmp/cache', 'tmp/sockets', 'vendor/bundle', 'public/system', 'public/uploads')
set :bundle_binstubs, nil
......
set :stage, :production
set :rails_env, 'production'
server '162.243.148.158', user: 'admin', roles: %w{web app}
set :deploy_to, '/home/admin/ink-api/production'
# server '162.243.148.158', user: 'admin', roles: %w{web app} #discourse
server '46.101.192.238', user: 'charlie', roles: %w{web app} #ink
set :deploy_to, '/home/ink-api/production'
set :branch, 'production'
# server-based syntax
......
......@@ -38,6 +38,7 @@ Rails.application.routes.draw do
resources :recipes, only: [:index, :show, :create, :update, :destroy] do
collection do
get 'favourites'
get 'index-all'
end
member do
......@@ -66,6 +67,15 @@ Rails.application.routes.draw do
end
end
resources :recipe_steps, only: [] do #ha
resources :recipe_step_presets, only: [:index]
end
resources :recipe_step_presets, only: [:create, :update, :show, :destroy] do
collection do
post 'create_from_process_step'
end
end
end
# scope module: :v2, constraints: ApiConstraints.new(version: 2, default: true) do
......
class AddRecipeStepPresets < ActiveRecord::Migration[5.0]
def change
create_table :recipe_step_presets do |t|
t.string :name, null: false
t.integer :recipe_step_id, null: false
t.text :description
t.json "execution_parameters", default: {}, null: false
t.integer :account_id, null: false
t.timestamps
end
end
end
......@@ -10,7 +10,7 @@
#
# It's strongly recommended that you check this file into your version control system.
ActiveRecord::Schema.define(version: 20170826041732) do
ActiveRecord::Schema.define(version: 20170911083743) do
# These are extensions that must be enabled in order to support this database
enable_extension "plpgsql"
......@@ -88,6 +88,16 @@ ActiveRecord::Schema.define(version: 20170826041732) do
t.index ["account_id", "recipe_id"], name: "index_recipe_favourites_on_account_id_and_recipe_id", using: :btree
end
create_table "recipe_step_presets", force: :cascade do |t|
t.string "name", null: false
t.integer "recipe_step_id", null: false
t.text "description"
t.json "execution_parameters", default: {}, null: false
t.integer "account_id", null: false
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
create_table "recipe_steps", force: :cascade do |t|
t.integer "recipe_id", null: false
t.integer "position", null: false
......
......@@ -7,19 +7,22 @@ end
account = Account.create(name: "Demo User", password: "password", password_confirmation: "password", email: "inkdemo@example.com")
service = Service.create(name: "Demo Service", description: "A sample service", auth_key: "abc123", account: account)
public_recipe1 = Recipe.new(name: "Rot 13 and SHOUTIFIED", description: "Basic obfuscation via ROT-13, and then EVERYTHING IN CAPS", active: true, public: true, account: account)
public_recipe_step1 = public_recipe1.recipe_steps.new(position: 1, step_class_name: InkStep::Coko::RotThirteenStep.to_s)
public_recipe_step2 = public_recipe1.recipe_steps.new(position: 2, step_class_name: InkStep::Coko::ShoutifierStep.to_s)
public_recipe1.save!
if defined? InkStep::Coko
editoria_recipe = Recipe.new(name: "Editoria Typescript", description: "Convert a docx file to HTML using Coko's own XSweet pipeline and get it ready for Editoria", active: true, public: true, account: account)
editoria_recipe_step1 = editoria_recipe.recipe_steps.new(position: 1, step_class_name: InkStep::Coko::XsweetPipeline::DocxExtract::DocxToHtmlExtractStep.to_s)
editoria_recipe_step2 = editoria_recipe.recipe_steps.new(position: 2, step_class_name: InkStep::Coko::XsweetPipeline::DocxExtract::HandleNotesStep.to_s)
editoria_recipe_step3 = editoria_recipe.recipe_steps.new(position: 3, step_class_name: InkStep::Coko::XsweetPipeline::DocxExtract::ScrubStep.to_s)
editoria_recipe_step4 = editoria_recipe.recipe_steps.new(position: 4, step_class_name: InkStep::Coko::XsweetPipeline::DocxExtract::JoinElementsStep.to_s)
editoria_recipe_step5 = editoria_recipe.recipe_steps.new(position: 5, step_class_name: InkStep::Coko::XsweetPipeline::DocxExtract::CollapseParagraphsStep.to_s)
editoria_recipe_step6 = editoria_recipe.recipe_steps.new(position: 6, step_class_name: InkStep::Coko::XsweetPipeline::HandleLists::HandleListsStep.to_s)
editoria_recipe_step7 = editoria_recipe.recipe_steps.new(position: 7, step_class_name: InkStep::Coko::XsweetPipeline::HeaderPromote::HeaderPromotionStep.to_s)
editoria_recipe_step8 = editoria_recipe.recipe_steps.new(position: 8, step_class_name: InkStep::Coko::XsweetPipeline::FinaliseTypescript::FinalRinseStep.to_s)
editoria_recipe_step9 = editoria_recipe.recipe_steps.new(position: 9, step_class_name: InkStep::Coko::XsweetPipeline::PrepareForEditoria::EditoriaPrepareStep.to_s)
editoria_recipe.save!
\ No newline at end of file
public_recipe1 = Recipe.new(name: "Rot 13 and SHOUTIFIED", description: "Basic obfuscation via ROT-13, and then EVERYTHING IN CAPS", active: true, public: true, account: account)
public_recipe_step1 = public_recipe1.recipe_steps.new(position: 1, step_class_name: InkStep::Coko::RotThirteenStep.to_s)
public_recipe_step2 = public_recipe1.recipe_steps.new(position: 2, step_class_name: InkStep::Coko::ShoutifierStep.to_s)
public_recipe1.save!
editoria_recipe = Recipe.new(name: "Editoria Typescript", description: "Convert a docx file to HTML using Coko's own XSweet pipeline and get it ready for Editoria", active: true, public: true, account: account)
editoria_recipe_step1 = editoria_recipe.recipe_steps.new(position: 1, step_class_name: InkStep::Coko::XsweetPipeline::DocxExtract::DocxToHtmlExtractStep.to_s)
editoria_recipe_step2 = editoria_recipe.recipe_steps.new(position: 2, step_class_name: InkStep::Coko::XsweetPipeline::DocxExtract::HandleNotesStep.to_s)
editoria_recipe_step3 = editoria_recipe.recipe_steps.new(position: 3, step_class_name: InkStep::Coko::XsweetPipeline::DocxExtract::ScrubStep.to_s)
editoria_recipe_step4 = editoria_recipe.recipe_steps.new(position: 4, step_class_name: InkStep::Coko::XsweetPipeline::DocxExtract::JoinElementsStep.to_s)
editoria_recipe_step5 = editoria_recipe.recipe_steps.new(position: 5, step_class_name: InkStep::Coko::XsweetPipeline::DocxExtract::CollapseParagraphsStep.to_s)
editoria_recipe_step6 = editoria_recipe.recipe_steps.new(position: 6, step_class_name: InkStep::Coko::XsweetPipeline::HandleLists::HandleListsStep.to_s)
editoria_recipe_step7 = editoria_recipe.recipe_steps.new(position: 7, step_class_name: InkStep::Coko::XsweetPipeline::HeaderPromote::HeaderPromotionStep.to_s)
editoria_recipe_step8 = editoria_recipe.recipe_steps.new(position: 8, step_class_name: InkStep::Coko::XsweetPipeline::FinaliseTypescript::FinalRinseStep.to_s)
editoria_recipe_step9 = editoria_recipe.recipe_steps.new(position: 9, step_class_name: InkStep::Coko::XsweetPipeline::PrepareForEditoria::EditoriaPrepareStep.to_s)
editoria_recipe.save!
end
\ No newline at end of file
This diff is collapsed.
This diff is collapsed.
<!DOCTYPE html>
<html lang="en">
<head><link rel="stylesheet" href="/styles.css">
<meta http-equiv="X-UA-Compatible" content="IE=edge" charset="utf-8">
<script src="https://code.jquery.com/jquery-2.2.1.min.js"></script>
<link rel="stylesheet" href="http://fortawesome.github.io/Font-Awesome/assets/font-awesome/css/font-awesome.css">
<title>INK - Ingest &apos;n&apos; Konvert</title>
</head>
<body>
<div id="app"></div>
<script src="/bundle.js"></script>
</body>
</html>
.Select{position:relative}.Select,.Select div,.Select input,.Select span{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.Select.is-disabled>.Select-control{background-color:#f9f9f9}.Select.is-disabled>.Select-control:hover{box-shadow:none}.Select.is-disabled .Select-arrow-zone{cursor:default;pointer-events:none;opacity:.35}.Select-control{background-color:#fff;border-color:#d9d9d9 #ccc #b3b3b3;border-radius:4px;border:1px solid #ccc;color:#333;cursor:default;display:table;border-spacing:0;border-collapse:separate;height:36px;outline:none;overflow:hidden;position:relative;width:100%}.Select-control:hover{box-shadow:0 1px 0 rgba(0,0,0,.06)}.Select-control .Select-input:focus{outline:none}.is-searchable.is-open>.Select-control{cursor:text}.is-open>.Select-control{border-bottom-right-radius:0;border-bottom-left-radius:0;background:#fff;border-color:#b3b3b3 #ccc #d9d9d9}.is-open>.Select-control .Select-arrow{top:-2px;border-color:transparent transparent #999;border-width:0 5px 5px}.is-searchable.is-focused:not(.is-open)>.Select-control{cursor:text}.is-focused:not(.is-open)>.Select-control{border-color:#007eff;box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 0 3px rgba(0,126,255,.1)}.Select--single>.Select-control .Select-value,.Select-placeholder{bottom:0;color:#aaa;left:0;line-height:34px;padding-left:10px;padding-right:10px;position:absolute;right:0;top:0;max-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.has-value.is-pseudo-focused.Select--single>.Select-control .Select-value .Select-value-label,.has-value.Select--single>.Select-control .Select-value .Select-value-label{color:#333}.has-value.is-pseudo-focused.Select--single>.Select-control .Select-value a.Select-value-label,.has-value.Select--single>.Select-control .Select-value a.Select-value-label{cursor:pointer;text-decoration:none}.has-value.is-pseudo-focused.Select--single>.Select-control .Select-value a.Select-value-label:focus,.has-value.is-pseudo-focused.Select--single>.Select-control .Select-value a.Select-value-label:hover,.has-value.Select--single>.Select-control .Select-value a.Select-value-label:focus,.has-value.Select--single>.Select-control .Select-value a.Select-value-label:hover{color:#007eff;outline:none;text-decoration:underline}.Select-input{height:34px;padding-left:10px;padding-right:10px;vertical-align:middle}.Select-input>input{width:100%;background:none transparent;border:0 none;box-shadow:none;cursor:default;display:inline-block;font-family:inherit;font-size:inherit;margin:0;outline:none;line-height:14px;padding:8px 0 12px;-webkit-appearance:none}.is-focused .Select-input>input{cursor:text}.has-value.is-pseudo-focused .Select-input{opacity:0}.Select-control:not(.is-searchable)>.Select-input{outline:none}.Select-loading-zone{cursor:pointer;display:table-cell;text-align:center}.Select-loading,.Select-loading-zone{position:relative;vertical-align:middle;width:16px}.Select-loading{-webkit-animation:Select-animation-spin .4s infinite linear;-o-animation:Select-animation-spin .4s infinite linear;animation:Select-animation-spin .4s infinite linear;height:16px;box-sizing:border-box;border-radius:50%;border:2px solid #ccc;border-right-color:#333;display:inline-block}.Select-clear-zone{-webkit-animation:Select-animation-fadeIn .2s;-o-animation:Select-animation-fadeIn .2s;animation:Select-animation-fadeIn .2s;color:#999;cursor:pointer;display:table-cell;position:relative;text-align:center;vertical-align:middle;width:17px}.Select-clear-zone:hover{color:#d0021b}.Select-clear{display:inline-block;font-size:18px;line-height:1}.Select--multi .Select-clear-zone{width:17px}.Select-arrow-zone{cursor:pointer;display:table-cell;position:relative;text-align:center;vertical-align:middle;width:25px;padding-right:5px}.Select-arrow{border-color:#999 transparent transparent;border-style:solid;border-width:5px 5px 2.5px;display:inline-block;height:0;width:0;position:relative}.is-open .Select-arrow,.Select-arrow-zone:hover>.Select-arrow{border-top-color:#666}.Select--multi .Select-multi-value-wrapper{display:inline-block}.Select .Select-aria-only{display:inline-block;height:1px;width:1px;margin:-1px;clip:rect(0,0,0,0);overflow:hidden;float:left}@-webkit-keyframes Select-animation-fadeIn{0%{opacity:0}to{opacity:1}}@keyframes Select-animation-fadeIn{0%{opacity:0}to{opacity:1}}.Select-menu-outer{border-bottom-right-radius:4px;border-bottom-left-radius:4px;background-color:#fff;border:1px solid #ccc;border-top-color:#e6e6e6;box-shadow:0 1px 0 rgba(0,0,0,.06);box-sizing:border-box;margin-top:-1px;max-height:200px;position:absolute;top:100%;width:100%;z-index:1;-webkit-overflow-scrolling:touch}.Select-menu{max-height:198px;overflow-y:auto}.Select-option{box-sizing:border-box;background-color:#fff;color:#666;cursor:pointer;display:block;padding:8px 10px}.Select-option:last-child{border-bottom-right-radius:4px;border-bottom-left-radius:4px}.Select-option.is-selected{background-color:#f5faff;background-color:rgba(0,126,255,.04);color:#333}.Select-option.is-focused{background-color:#ebf5ff;background-color:rgba(0,126,255,.08);color:#333}.Select-option.is-disabled{color:#ccc;cursor:default}.Select-noresults{box-sizing:border-box;color:#999;cursor:default;display:block;padding:8px 10px}.Select--multi .Select-input{vertical-align:middle;margin-left:10px;padding:0}.Select--multi.has-value .Select-input{margin-left:5px}.Select--multi .Select-value{background-color:#ebf5ff;background-color:rgba(0,126,255,.08);border-radius:2px;border:1px solid #c2e0ff;border:1px solid rgba(0,126,255,.24);color:#007eff;display:inline-block;font-size:.9em;line-height:1.4;margin-left:5px;margin-top:5px;vertical-align:top}.Select--multi .Select-value-icon,.Select--multi .Select-value-label{display:inline-block;vertical-align:middle}.Select--multi .Select-value-label{border-bottom-right-radius:2px;border-top-right-radius:2px;cursor:default;padding:2px 5px}.Select--multi a.Select-value-label{color:#007eff;cursor:pointer;text-decoration:none}.Select--multi a.Select-value-label:hover{text-decoration:underline}.Select--multi .Select-value-icon{cursor:pointer;border-bottom-left-radius:2px;border-top-left-radius:2px;border-right:1px solid #c2e0ff;border-right:1px solid rgba(0,126,255,.24);padding:1px 5px 3px}.Select--multi .Select-value-icon:focus,.Select--multi .Select-value-icon:hover{background-color:#d8eafd;background-color:rgba(0,113,230,.08);color:#0071e6}.Select--multi .Select-value-icon:active{background-color:#c2e0ff;background-color:rgba(0,126,255,.24)}.Select--multi.is-disabled .Select-value{background-color:#fcfcfc;border:1px solid #e3e3e3;color:#333}.Select--multi.is-disabled .Select-value-icon{cursor:not-allowed;border-right:1px solid #e3e3e3}.Select--multi.is-disabled .Select-value-icon:active,.Select--multi.is-disabled .Select-value-icon:focus,.Select--multi.is-disabled .Select-value-icon:hover{background-color:#fcfcfc}@keyframes Select-animation-spin{to{transform:rotate(1turn)}}@-webkit-keyframes Select-animation-spin{to{-webkit-transform:rotate(1turn)}}@font-face{font-family:Fira Sans;src:url("/fonts/FiraSans-Light.woff") format("woff"),url("/fonts/FiraSans-Light.woff2") format("woff2");font-weight:300;font-style:normal}@font-face{font-family:Fira Sans;src:url("/fonts/FiraSans-LightItalic.woff") format("woff"),url("/fonts/FiraSans-LightItalic.woff2") format("woff2");font-weight:300;font-style:italic}@font-face{font-family:Fira Sans;src:url("/fonts/FiraSans-Regular.woff") format("woff"),url("/fonts/FiraSans-Regular.woff2") format("woff2");font-weight:400;font-style:normal}@font-face{font-family:Fira Sans;src:url("/fonts/FiraSans-Italic.woff") format("woff"),url("/fonts/FiraSans-Italic.woff2") format("woff2");font-weight:400;font-style:italic}@font-face{font-family:Fira Sans;src:url("/fonts/FiraSans-Bold.woff") format("woff"),url("/fonts/FiraSans-Bold.woff2") format("woff2");font-weight:700;font-style:normal}@font-face{font-family:Fira Sans;src:url("/fonts/FiraSans-BoldItalic.woff") format("woff"),url("/fonts/FiraSans-BoldItalic.woff2") format("woff2");font-weight:700;font-style:italic}@font-face{font-family:Montserrat;src:url("/fonts/Montserrat-Black.woff") format("woff"),url("/fonts/Montserrat-Black.woff2") format("woff2");font-weight:800;font-style:bold}body,html{font-family:Fira Sans,sans-serif;font-size:14px;font-weight:400;line-height:30px;background-color:#fff;-webkit-text-size-adjust:none;touch-action:manipulation}.vertical-center{min-height:100%;min-height:100vh;display:flex;align-items:center}.horizontal-center{margin-left:auto;margin-right:auto}a{text-decoration:none}a:link,a:visited{color:#804da6}.italic{font-style:italic}.button{border:0;padding:5px}.action-button{padding:10px 30px;font-size:.875rem;text-transform:uppercase;font-weight:700;font-style:italic;color:#804da6;border-radius:5px;border:2px solid #804da6;background-color:#fff;cursor:pointer;outline:none}.action-button--clear{padding:20px;background-color:transparent}.action-button--disabled{color:rgba(128,77,166,.7);background-color:hsla(0,0%,75%,.3)}.action-button--cancel{background-color:silver;border-color:silver;margin-left:1rem;margin-right:1rem}.confirmation-button{padding:10px 30px;font-size:.875rem;text-transform:uppercase;font-weight:700;color:#fff;border-radius:0;background-color:#804da6;cursor:pointer;outline:none}.confirmation-button--clear{padding:20px;border:none;background-color:transparent}.inline-action-button{font-family:Fira Sans;background-color:#804da6;color:#fff;border:0;padding:5px 4px;display:inline-block;margin-left:10px;margin-bottom:30px}.inline-action-button--disabled{color:silver;background-color:rgba(128,77,166,.7)}.curved-button{font-family:Fira Sans;padding:1rem 3rem;border:none;background-color:#60c1c0;color:#fff;font-size:1.5rem;border-radius:2rem}.curved-button:link,.curved-button:visited{color:#fff}.input{display:block;margin:20px 0;padding:7.5px 15px;line-height:20px;font-weight:300}.input::placeholder{opacity:1}.input--inline-box{width:15rem;font-family:Courier;font-weight:700;display:inline-block}.input--inline-box,.input--single-line-box{border:1px solid #60c1c0;background-color:#fff;color:#804da6;padding:5px;margin-bottom:30px}.input--single-line-box{margin-top:30px;width:45rem}.input--single-line-box:focus{border-color:rgba(96,193,192,.8);box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(96,193,192,.6);outline:0 none}.input--single-line-box::placeholder{color:silver}.input--single-line-box:focus::placeholder{color:hsla(0,0%,75%,.3)}.input--multi-line-box{border:1px solid #60c1c0;background-color:#fff;color:#804da6;padding:5px;margin-top:30px;margin-bottom:30px;width:45rem}.input--multi-line-box:focus{border-color:rgba(96,193,192,.8);box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(96,193,192,.6);outline:0 none}.input--multi-line-box::placeholder{color:silver}.input--multi-line-box:focus::placeholder{color:hsla(0,0%,75%,.3)}.input--sign-in{border:1px solid #60c1c0;background-color:#fff;color:#804da6;font-weight:700;padding:5px;margin-top:30px;margin-bottom:30px;width:12rem}.input--sign-in:focus{border-color:rgba(96,193,192,.8);box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(96,193,192,.6);outline:0 none}.input--sign-in::placeholder{color:silver}.input--sign-in:focus::placeholder{color:hsla(0,0%,75%,.3)}.form-label{display:block;padding:5px;margin:30px;text-align:right;color:#60c1c0;font-weight:700;font-style:italic}span.left-pad{padding-left:10px}.hr{height:6px;width:400px;margin-top:20px;margin-bottom:20px;border:0;background-color:silver}.hr__sign-in{margin-top:2px}ul{list-style-type:none;padding-left:0}.list-item--step-class-name{font-family:Courier;font-weight:700;margin-left:1rem}.file-list{list-style-type:none;padding-left:1.5rem;margin:0;border:0}h1{font-size:3.5rem;color:#565859;font-weight:700}h2{line-height:3rem}h2,h3{font-size:2.5rem;color:#60c1c0;font-weight:400}h4{font-size:1.25rem;color:#804da6;font-style:italic;font-weight:700}h4,h5{font-weight:400}h5{font-size:1.5rem;color:#565859}h6{font-size:.8rem;color:silver;font-weight:400}p{font-size:inherit;color:#565859}.step{font-size:1rem}.step--blue{color:#60c1c0}.step--white{color:#fff;font-weight:700}.small-info-text{font-style:italic}.small-info,.small-info-text{font-size:1rem;color:silver}.left-indent{margin-left:1.5rem}.monospace{font-family:Courier}.bold{font-weight:700;color:#000}table{width:100%;border-spacing:0;border-collapse:collapse}td{border:1px solid silver;margin:0}.cell{vertical-align:top}tr.success{color:#90b85b}.fail{color:#df3c21}td.centered{text-align:center}td.success{background-color:rgba(144,184,91,.3)}td.fail{background-color:rgba(223,60,33,.2)}td.text{padding:.5rem}.account-item,td.text{border:1px solid silver}.account-item{border-radius:1rem;padding-left:.5rem;padding-right:.5rem;margin-bottom:.2rem}.alert{border:1px solid;border-radius:10px;padding-left:10px}.alert--success{border-color:#206f1b;background-color:#c1eebe;color:#206f1b}.alert--error{border-color:#df3c21;color:#df3c21;background-color:rgba(223,60,33,.2)}.alert--info,.alert--warning{border-color:#bd9d00;color:#bd9d00;background-color:#fff1ad}.alerts-list{max-width:1000px}.alerts-list--sign-in-page{max-width:400px}.breadcrumb{color:#804da6;padding:10px}.breadcrumb-divider{color:#000}.env-info-header{background-color:green;color:#fff;text-align:center}.successful{color:#90b85b}.failed{color:#df3c21}.execution-result-border{border-bottom:1px solid #804da6;padding:20px}.execution-result-border__top{border-top:1px solid #804da6}.execution-step-border{border-top:1px solid #60c1c0}.choose-file-container{border:2px dashed #804da6;border-radius:10px;padding:20px;margin-bottom:2px}.choose-file-container input[type=file]::-webkit-file-upload-button{border:none;font-size:1.5rem;background-color:#60c1c0;font-family:Fira Sans;color:#fff}.file-picker{font-family:Fira Sans}.file-picker--disabled{color:silver;background-color:rgba(96,193,192,.3)}.file-button{font-family:Fira Sans;background-color:#804da6;color:#fff;font-size:1.5rem;border:none}.file-button--disabled{color:silver;background-color:rgba(128,77,166,.7)}.action-button-container{margin-top:4rem}.loading-centered{text-align:center;padding-top:10rem;padding-bottom:10rem}.processing-centered{padding-top:2rem;padding-bottom:2rem}.processing-centered,.step-processing-centered{text-align:center;color:silver}.logo{font-family:Montserrat,sans-serif;font-weight:800;color:#804da6}.logo__large{font-size:5rem}.logo__small{font-size:2.3rem}.recipe-item{position:relative;margin:20px 20px 20px 0;width:200px;cursor:pointer}.recipe-item__header{color:#fff;font-weight:700;padding:0 0 0 10px}.recipe-item__selected{background-color:#804da6}.recipe-item__unselected{background-color:#60c1c0}.recipe-item__body{padding:0 0 0 10px;border:3px solid #60c1c0;border-top:0}.recipe-item__private:before{content:"";position:absolute;top:0;right:0;border-width:0 16px 16px 0;border-style:solid;border-color:#804da6 #fff}.form-input-container{display:flex;flex-direction:row}.steps-container{border-top:1px solid #60c1c0;border-bottom:1px solid #60c1c0;padding:20px;margin-right:40px;width:300px}.step__description{font-size:1rem;padding-left:10px;margin-bottom:40px}.step__number{font-size:3rem;margin-top:20px;margin-bottom:10px;border-radius:10px}.step__number,.step__title{font-weight:700;text-align:center}.step__title{font-size:1.5rem}.step-module-container{text-align:center}.step-module{font-weight:400;margin-right:.5rem;border:1px dotted silver;padding:4px;border-radius:4px;color:silver}.step__admin-description{font-size:1rem;padding-left:10px;margin-bottom:20px}ol>li.stepClassListItem{font-weight:700}.status-report-container{margin-right:20px}.content-container{padding:20px;margin:auto;width:80%}.logo-container{display:block;align-items:baseline;padding-top:5rem;padding-bottom:2rem}.home-page-content-container,.logo-container{text-align:center}.main-nav{display:flex;justify-content:space-between;padding:20px}.main-nav__logo{margin-right:auto}.recipe-detail-view-container{display:flex;justify-content:space-around;margin-top:30px}.recipe-list-container{display:flex;flex-wrap:wrap}.secondary-text{font-style:italic;font-size:1.25rem;color:#565859}.sign-in-logo-container{display:flex;justify-content:space-between;align-items:baseline}.sign-in-button-container{display:flex;justify-content:center}
/*# sourceMappingURL=styles.css.map*/
\ No newline at end of file
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment