Commit d7f73605 authored by charlie-ablett's avatar charlie-ablett
Browse files

Merge branch 'recipe_favourites'

parents 967ba40a d6d4df3f
FROM inkmap/ink-api-base-image:latest
MAINTAINER Vasilis Kefallinos <vasilios.kefallinos@sourcefabric.org>
ENV INSTALL_PATH /ink-api
RUN mkdir -p $INSTALL_PATH
WORKDIR $INSTALL_PATH
COPY . .
FROM ruby:2.2.3
MAINTAINER Vasilis Kefallinos <vkefallinos@gmail.com>
RUN wget https://github.com/jgm/pandoc/releases/download/1.19.2.1/pandoc-1.19.2.1-1-amd64.deb
RUN dpkg -i pandoc-1.19.2.1-1-amd64.deb
RUN apt-get update && apt-get install -qq -y --no-install-recommends \
build-essential libpq-dev git-core netcat-openbsd openjdk-7-jdk \
openjdk-7-jre zip calibre
# Point Bundler at /gems. This will cause Bundler to re-use gems that have already been installed on the gems volume
ENV BUNDLE_PATH /gems
ENV BUNDLE_HOME /gems
# Increase how many threads Bundler uses when installing. Optional!
ENV BUNDLE_JOBS 4
# How many times Bundler will retry a gem download. Optional!
ENV BUNDLE_RETRY 3
# Where Rubygems will look for gems, similar to BUNDLE_ equivalents.
ENV GEM_HOME /gems
ENV GEM_PATH /gems
# You'll need something here. For development, you don't need anything super secret.
ENV SECRET_KEY_BASE development123
# Add /gems/bin to the path so any installed gem binaries are runnable from bash.
ENV PATH /gems/bin:$PATH
ENV DOCKERIZED true
RUN gem install bundler
RUN bundle install --binstubs
# run bundle check to regenerate gemfile.lock file
RUN bundle check
CMD ["/bin/sh" , "docker/init_server.sh"]
# Setup the directory where we will mount the codebase from the host
VOLUME /app
WORKDIR /app
CMD /bin/bash
module Api
module V1
class RecipesController < ApplicationController
before_action :authenticate_account!, only: [:create, :update, :destroy]
before_action :authenticate_account!, only: [:create, :update, :destroy, :favourite, :unfavourite]
before_action :authenticate!, only: [:index, :show, :execute]
respond_to :json
......@@ -33,6 +33,20 @@ module Api
render_error(e)
end
def favourite
recipe.mark_as_favourite!(current_entity.account)
render json: { favourite: recipe.favourited_by?(current_entity.account) }
rescue => e
render_error(e)
end
def unfavourite
recipe.unmark_as_favourite!(current_entity.account)
render json: { favourite: recipe.favourited_by?(current_entity.account) }
rescue => e
render_error(e)
end
def index
render json: recipes, scope: current_entity, scope_name: :current_entity
end
......
......@@ -37,6 +37,7 @@ class Account < ApplicationRecord
has_many :recipes, inverse_of: :account
has_many :process_chains, inverse_of: :account
has_many :account_roles, inverse_of: :account
has_many :recipe_favourites, inverse_of: :account
has_one :service
def roles
......
......@@ -13,6 +13,8 @@ class Recipe < ApplicationRecord
where(account_id: current_entity.account.id).order(created_at: :desc)
}, inverse_of: :recipe, class_name: ProcessChain
has_many :recipe_favourites, inverse_of: :recipe
validates_presence_of :name, :account
validates_inclusion_of :active, :in => [true, false]
validates_inclusion_of :public, :in => [true, false]
......@@ -131,6 +133,22 @@ class Recipe < ApplicationRecord
false
end
def favourited_by?(account)
recipe_favourites.map(&:account_id).include?(account.id)
end
def mark_as_favourite!(account)
favourite = recipe_favourites.new(account: account)
favourite.save
end
def unmark_as_favourite!(account)
favourite = recipe_favourites.where(account: account).first
if favourite
favourite.destroy
end
end
private
def generate_steps_with_positions(recipe_step_data)
......
class RecipeFavourite < ApplicationRecord
belongs_to :recipe, inverse_of: :recipe_favourites
belongs_to :account, inverse_of: :recipe_favourites
validates_presence_of :recipe, :account
validates_uniqueness_of :recipe, { scope: :account, message: "this account already has this recipe favourited" }
end
\ No newline at end of file
......@@ -9,10 +9,14 @@ class RecipeSerializer < ActiveModel::Serializer
end
end
attributes :id, :name, :description, :active, :account_id, :executeRecipeInProgress, :public, :process_chains, :recipe_steps
attributes :id, :name, :description, :active, :account_id, :executeRecipeInProgress, :public, :process_chains, :recipe_steps, :favourite
def executeRecipeInProgress
object.execute_recipe_in_progress?
end
def favourite
object.favourited_by?(scope)
end
end
\ No newline at end of file
docker-compose run --service-ports ink
bin/rails s -b 0.0.0.0
......@@ -19,7 +19,9 @@ staging:
development:
<<: *default
database: ink_development
host: localhost
test:
<<: *default
database: ink_test
host: localhost
......@@ -38,7 +38,7 @@ Rails.application.configure do
config.action_mailer.raise_delivery_errors = false
config.action_mailer.perform_caching = false
# config.web_console.whitelisted_ips = ['172.16.0.0/12', '10.42.0.0/16', '192.168.0.0/16']
config.web_console.whitelisted_ips = ['172.16.0.0/12','172.18.0.0/12', '10.42.0.0/16', '192.168.0.0/16']
# Print deprecation notices to the Rails logger.
config.active_support.deprecation = :log
......
......@@ -38,6 +38,8 @@ Rails.application.routes.draw do
resources :recipes, only: [:index, :show, :create, :update, :destroy] do
member do
post 'execute'
get 'favourite'
get 'unfavourite'
end
end
......
class CreateRecipeFavourites < ActiveRecord::Migration[5.0]
def change
create_table :recipe_favourites do |t|
t.integer :account_id, null: false
t.integer :recipe_id, null: false
t.timestamps
end
add_index :recipe_favourites, [:account_id, :recipe_id]
end
end
......@@ -10,7 +10,7 @@
#
# It's strongly recommended that you check this file into your version control system.
ActiveRecord::Schema.define(version: 20170812063014) do
ActiveRecord::Schema.define(version: 20170826041732) do
# These are extensions that must be enabled in order to support this database
enable_extension "plpgsql"
......@@ -80,6 +80,14 @@ ActiveRecord::Schema.define(version: 20170812063014) do
t.index ["position", "process_chain_id"], name: "index_process_steps_on_position_and_process_chain_id", unique: true, using: :btree
end
create_table "recipe_favourites", force: :cascade do |t|
t.integer "account_id", null: false
t.integer "recipe_id", null: false
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.index ["account_id", "recipe_id"], name: "index_recipe_favourites_on_account_id_and_recipe_id", using: :btree
end
create_table "recipe_steps", force: :cascade do |t|
t.integer "recipe_id", null: false
t.integer "position", null: false
......
......@@ -17,26 +17,19 @@ services:
links:
- postgres
- redis
- slanger
volumes:
- ./:/ink-api
# This will mount your "gems" volume (defined below as your external gem volumes) onto /gems
- gems:/gems
# This will mount ., your app code, into the /app directory within the container
- .:/app
env_file:
- '.env'
depends_on:
- postgres
- slanger
ports:
- "3000:3000"
sidekiq:
build: .
command: '/bin/sh docker/init_sidekiq.sh'
env_file:
- '.env'
links:
- postgres
- redis
volumes:
- ./:/ink-api
depends_on:
- ink
slanger:
image: antillion/slanger
ports:
......@@ -46,28 +39,8 @@ services:
- redis:redis
env_file:
- '.env'
# editoria:
# image: inkmap/editoria:0.1.2
# volumes:
# - ./editoria/api/db/production:/editoria/api/db/production
# environment:
# PUBSWEET_SECRET: 5046a3dd-d178-41ac-bd87-cac327cdf23a
# INK_ENDPOINT: http://ink:3000
# INK_USERNAME: admin@admin.com
# INK_PASSWORD: abc12345
# links:
# - ink:ink
# ports:
# - "3000:3000"
# depends_on:
# - setupdb
# setupdb:
# image: inkmap/editoria:0.1.2
# volumes:
# - ./editoria/api/db/production:/editoria/api/db/production
# environment:
# PUB_USER: admin
# PUB_MAIL: admin@inkmap.com
# PUB_PASS: 12345
# PUB_COL: Collection
# command: sh docker/setupdb
volumes:
db: {}
gems:
# Flagging this as "external" means it will use the volume named "gems" on the host instead of making a new volume specific to this docker-compose file
external: true
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
{"version":3,"sources":[],"names":[],"mappings":"","file":"/styles.css","sourceRoot":""}
\ No newline at end of file
......@@ -752,13 +752,193 @@ RSpec.describe Api::V1::RecipesController do
end
end
describe "GET favourite" do
let!(:recipe) { create(:recipe, account: account) }
context 'with a valid token' do
context 'if recipe exists' do
context 'and it belongs to the user' do
before do
request_with_auth(account.new_jwt) do
perform_favourite_request({id: recipe.id})
end
end
specify do
expect(response.status).to eq 200
end
it 'is favourited' do
expect(recipe.reload.favourited_by?(account)).to be_truthy
end
end
context 'and it belongs to a different user' do
context 'and it is public' do
let!(:other_recipe) { create(:recipe, account: other_account, public: true) }
before do
request_with_auth(account.new_jwt) do
perform_favourite_request({id: other_recipe.id})
end
end
specify do
expect(response.status).to eq 200
end
it 'is favourited' do
expect(other_recipe.reload.favourited_by?(account)).to be_truthy
end
end
context 'and it is private' do
let!(:other_recipe) { create(:recipe, account: other_account, public: false) }
before do
request_with_auth(account.new_jwt) do
perform_favourite_request({id: other_recipe.id})
end
end
specify do
expect(response.status).to eq 404
end
it 'is not favourited' do
expect(other_recipe.reload.favourited_by?(account)).to be_falsey
end
end
end
end
context 'if recipe does not exist' do
specify do
request_with_auth(account.new_jwt) do
perform_favourite_request({id: "LOL"})
end
expect(response.status).to eq 404
expect(assigns[:recipe]).to be_nil
end
end
end
context 'if no valid token is supplied' do
it "does not return anything" do
request_with_auth do
perform_favourite_request({id: recipe.id})
end
expect(response.status).to eq 401
expect(assigns[:recipe]).to be_nil
end
end
end
describe "GET unfavourite" do
let!(:recipe) { create(:recipe, account: account) }
before do
create(:recipe_favourite, recipe: recipe, account: account)
end
context 'with a valid token' do
context 'if recipe exists' do
context 'and it belongs to the user' do
before do
request_with_auth(account.new_jwt) do
perform_unfavourite_request({id: recipe.id})
end
end
specify do
expect(response.status).to eq 200
end
it 'is favourited' do
expect(recipe.reload.favourited_by?(account)).to be_falsey
end
end
context 'and it belongs to a different user' do
context 'and it is public' do
let!(:other_recipe) { create(:recipe, account: other_account, public: true) }
before do
request_with_auth(account.new_jwt) do
perform_unfavourite_request({id: other_recipe.id})
end
end
specify do
expect(response.status).to eq 200
end
it 'is favourited' do
expect(other_recipe.reload.favourited_by?(account)).to be_falsey
end
end
context 'and it is private' do
let!(:other_recipe) { create(:recipe, account: other_account, public: false) }
before do
request_with_auth(account.new_jwt) do
perform_unfavourite_request({id: other_recipe.id})
end
end
specify do
expect(response.status).to eq 404
end
it 'is not favourited' do
expect(other_recipe.reload.favourited_by?(account)).to be_falsey
end
end
end
end
context 'if recipe does not exist' do
specify do
request_with_auth(account.new_jwt) do
perform_unfavourite_request({id: "LOL"})
end
expect(response.status).to eq 404
expect(assigns[:recipe]).to be_nil
end
end
end
context 'if no valid token is supplied' do
it "does not return anything" do
request_with_auth do
perform_unfavourite_request({id: recipe.id})
end
expect(response.status).to eq 401
expect(assigns[:recipe]).to be_nil
end
end
end
# request.headers.merge!(auth_headers)
# this is special for controller tests - you can't just merge them in manually for some reason
# this is special for controller tests - you can't just merge them in manually
def perform_execute_request(data = {})
execute_recipe(version, data)
end
def perform_favourite_request(data = {})
favourite_recipe(version, data)
end
def perform_unfavourite_request(data = {})
unfavourite_recipe(version, data)
end
def perform_create_request(data = {})
post_create_request(version, data)
end
......
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