diff --git a/Gemfile b/Gemfile index 42ee84aea..97908758d 100644 --- a/Gemfile +++ b/Gemfile @@ -11,6 +11,8 @@ gem 'turbolinks' gem 'simple_form' gem 'draper' gem 'font-awesome-rails' +gem 'github-markdown' +gem 'premailer-rails' gem 'omniauth' gem 'omniauth-github' diff --git a/Gemfile.lock b/Gemfile.lock index 91dab7363..c5a203e35 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -51,6 +51,8 @@ GEM simplecov (>= 0.7) term-ansicolor thor + css_parser (1.3.5) + addressable debugger (1.6.6) columnize (>= 0.3.1) debugger-linecache (~> 1.2.0) @@ -79,10 +81,12 @@ GEM foundation-rails (5.2.2.0) railties (>= 3.1.0) sass (>= 3.2.0) + github-markdown (0.5.5) haml (4.0.5) tilt hashie (2.1.1) hike (1.2.3) + htmlentities (4.3.1) i18n (0.6.9) jbuilder (2.0.6) activesupport (>= 3.0.0, < 5) @@ -126,6 +130,12 @@ GEM omniauth (~> 1.2) pg (0.17.1) polyglot (0.3.4) + premailer (1.8.0) + css_parser (>= 1.3.5) + htmlentities (>= 4.0.0) + premailer-rails (1.7.0) + actionmailer (>= 3, < 5) + premailer (~> 1.7, >= 1.7.9) pry (0.9.12.6) coderay (~> 1.0) method_source (~> 0.8) @@ -236,6 +246,7 @@ DEPENDENCIES faker font-awesome-rails foundation-rails + github-markdown haml jbuilder jquery-rails @@ -243,6 +254,7 @@ DEPENDENCIES omniauth omniauth-github pg + premailer-rails pry-debugger puma rails (= 4.1.0) diff --git a/app/assets/stylesheets/email.css b/app/assets/stylesheets/email.css new file mode 100644 index 000000000..09e60f856 --- /dev/null +++ b/app/assets/stylesheets/email.css @@ -0,0 +1,225 @@ +/* ------------------------------------- + GLOBAL +------------------------------------- */ +* { + margin:0; + padding:0; +} +* { font-family: "Helvetica Neue", "Helvetica", Helvetica, Arial, sans-serif; } + +img { + max-width: 100%; +} +.collapse { + margin:0; + padding:0; +} +body { + #fdfdfd + -webkit-font-smoothing:antialiased; + -webkit-text-size-adjust:none; + width: 100%!important; + height: 100%; +} + + +/* ------------------------------------- + ELEMENTS +------------------------------------- */ +a { color: #2BA6CB;} + +.btn { + text-decoration:none; + color: #FFF; + background-color: #666; + padding:10px 16px; + font-weight:bold; + margin-right:10px; + text-align:center; + cursor:pointer; + display: inline-block; +} + +p.callout { + padding:15px; + background-color:#ECF8FF; + margin-bottom: 15px; +} +.callout a { + font-weight:bold; + color: #2BA6CB; +} + +table.social { +/* padding:15px; */ + background-color: #ebebeb; + +} +.social .soc-btn { + padding: 3px 7px; + font-size:12px; + margin-bottom:10px; + text-decoration:none; + color: #FFF;font-weight:bold; + display:block; + text-align:center; +} +a.fb { background-color: #3B5998!important; } +a.tw { background-color: #1daced!important; } +a.gp { background-color: #DB4A39!important; } +a.ms { background-color: #000!important; } + +.sidebar .soc-btn { + display:block; + width:100%; +} + +/* ------------------------------------- + HEADER +------------------------------------- */ +table.head-wrap { width: 100%;} + +.header.container table td.logo { padding: 15px; } +.header.container table td.label { padding: 15px; padding-left:0px;} + + +/* ------------------------------------- + BODY +------------------------------------- */ +table.body-wrap { width: 100%;} + + +/* ------------------------------------- + FOOTER +------------------------------------- */ +table.footer-wrap { width: 100%; clear:both!important; +} +.footer-wrap .container td.content p { border-top: 1px solid rgb(253,253,253); padding-top:15px;} +.footer-wrap .container td.content p { + font-size:10px; + font-weight: bold; + +} + + +/* ------------------------------------- + TYPOGRAPHY +------------------------------------- */ +h1,h2,h3,h4,h5,h6 { +font-family: "HelveticaNeue-Light", "Helvetica Neue Light", "Helvetica Neue", Helvetica, Arial, "Lucida Grande", sans-serif; line-height: 1.1; margin-bottom:15px; color:#000; +} +h1 small, h2 small, h3 small, h4 small, h5 small, h6 small { font-size: 60%; color: #6f6f6f; line-height: 0; text-transform: none; } + +h1 { font-weight:200; font-size: 44px;} +h2 { font-weight:200; font-size: 37px;} +h3 { font-weight:500; font-size: 27px;} +h4 { font-weight:500; font-size: 23px;} +h5 { font-weight:900; font-size: 17px;} +h6 { font-weight:900; font-size: 14px; text-transform: uppercase; color:#444;} + +.collapse { margin:0!important;} + +p, ul { + margin-bottom: 10px; + font-weight: normal; + font-size:14px; + line-height:1.6; +} +p.lead { font-size:17px; } +p.last { margin-bottom:0px;} + +ul li { + margin-left:5px; + list-style-position: inside; +} + +/* ------------------------------------- + SIDEBAR +------------------------------------- */ +ul.sidebar { + background:#ebebeb; + display:block; + list-style-type: none; +} +ul.sidebar li { display: block; margin:0;} +ul.sidebar li a { + text-decoration:none; + color: #666; + padding:10px 16px; +/* font-weight:bold; */ + margin-right:10px; +/* text-align:center; */ + cursor:pointer; + border-bottom: 1px solid #777777; + border-top: 1px solid #FFFFFF; + display:block; + margin:0; +} +ul.sidebar li a.last { border-bottom-width:0px;} +ul.sidebar li a h1,ul.sidebar li a h2,ul.sidebar li a h3,ul.sidebar li a h4,ul.sidebar li a h5,ul.sidebar li a h6,ul.sidebar li a p { margin-bottom:0!important;} + + + +/* --------------------------------------------------- + RESPONSIVENESS + Nuke it from orbit. It's the only way to be sure. +------------------------------------------------------ */ + +/* Set a max-width, and make it display as block so it will automatically stretch to that width, but will also shrink down on a phone or something */ +.container { + display:block!important; + max-width:600px!important; + margin:0 auto!important; /* makes it centered */ + clear:both!important; +} + +/* This should also be a block element, so that it will fill 100% of the .container */ +.content { + padding:15px; + max-width:600px; + margin:0 auto; + display:block; +} + +/* Let's make sure tables in the content area are 100% wide */ +.content table { width: 100%; } + + +/* Odds and ends */ +.column { + width: 300px; + float:left; +} +.column tr td { padding: 15px; } +.column-wrap { + padding:0!important; + margin:0 auto; + max-width:600px!important; +} +.column table { width:100%;} +.social .column { + width: 280px; + min-width: 279px; + float:left; +} + +/* Be sure to place a .clear element after each set of columns, just to be safe */ +.clear { display: block; clear: both; } + + +/* ------------------------------------------- + PHONE + For clients that support media queries. + Nothing fancy. +-------------------------------------------- */ +@media only screen and (max-width: 600px) { + + a[class="btn"] { display:block!important; margin-bottom:10px!important; background-image:none!important; margin-right:0!important;} + + div[class="column"] { width: auto!important; float:none!important;} + + table.social div[class="column"] { + width:auto!important; + } + +} diff --git a/app/controllers/admin/feedback_controller.rb b/app/controllers/admin/feedback_controller.rb index 1d8936b16..6a259db5a 100644 --- a/app/controllers/admin/feedback_controller.rb +++ b/app/controllers/admin/feedback_controller.rb @@ -1,8 +1,6 @@ class Admin::FeedbackController < Admin::ApplicationController - def index @feedback = Feedback.all end - end diff --git a/app/controllers/admin/jobs_controller.rb b/app/controllers/admin/jobs_controller.rb new file mode 100644 index 000000000..092c06fd9 --- /dev/null +++ b/app/controllers/admin/jobs_controller.rb @@ -0,0 +1,21 @@ +class Admin::JobsController < Admin::ApplicationController + + def index + @jobs = Job.where(approved: false, submitted: true).order('created_at ASC') + end + + def show + @job = Job.find(params[:id]) + end + + def approve + @job = Job.find(params[:job_id]) + @job.update_attribute(:approved, true) + + JobMailer.job_approved(@job).deliver! + + flash[:notice] = "Job #{@job.title} at #{@job.company} has been approved and #{@job.created_by.full_name} has been sent an email." + + redirect_to admin_jobs_path + end +end diff --git a/app/controllers/admin/portal_controller.rb b/app/controllers/admin/portal_controller.rb index 3016112ac..93cdc29bc 100644 --- a/app/controllers/admin/portal_controller.rb +++ b/app/controllers/admin/portal_controller.rb @@ -1,5 +1,6 @@ class Admin::PortalController < Admin::ApplicationController def index + @jobs_pending_approval = Job.where(approved: false, submitted: true).count end end diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 0b4250dbf..e099bd825 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -64,7 +64,7 @@ def admin? helper_method :admin? def is_verified_coach_or_admin? - current_member.is_admin? or (current_member.is_coach? and current_member.verified?) + current_member and (current_member.is_admin? or (current_member.is_coach? and current_member.verified?)) end helper_method :is_verified_coach_or_admin? diff --git a/app/controllers/jobs_controller.rb b/app/controllers/jobs_controller.rb new file mode 100644 index 000000000..2d861b811 --- /dev/null +++ b/app/controllers/jobs_controller.rb @@ -0,0 +1,63 @@ +class JobsController < ApplicationController + before_filter :set_job, only: [:show, :preview, :edit, :update, :submit] + before_filter :has_access?, only: [ :new, :create, :edit, :update, :submit] + + def index + @jobs = Job.where(approved: true, submitted: true) + end + + def pending + @jobs = current_member.jobs.where(submitted: false) + end + + def new + @job = Job.new + end + + def create + @job = Job.new(job_params) + @job.created_by_id = current_member.id + if @job.save + redirect_to job_preview_path(@job) + else + render 'new' + end + end + + def preview + end + + def edit + end + + def show + redirect_to jobs_path unless @job.approved? and @job.submitted? + end + + def submit + @job.update_attribute(:submitted, true) + + flash[:notice] = "Job submitted. You will receive an email when the job has ben approved." + redirect_to root_path + end + + def update + @job.update_attributes(job_params) + redirect_to job_preview_path(@job) + end + + private + + def job_params + params.require(:job).permit(:title, :description, :location, :expiry_date, :email, :link_to_job, :company) + end + + def set_job + job_id = params[:job_id] || params[:id] + @job = Job.find(job_id) + end + + def has_access? + redirect_to root_path unless logged_in? and is_verified_coach_or_admin? + end +end diff --git a/app/controllers/portal_controller.rb b/app/controllers/portal_controller.rb index 56fc8b89a..4287fe3f4 100644 --- a/app/controllers/portal_controller.rb +++ b/app/controllers/portal_controller.rb @@ -2,5 +2,6 @@ class PortalController < ApplicationController before_action :logged_in? def index + @pending_jobs = current_member.jobs.where(submitted: false) end end diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index e281df4f4..a545d8310 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -11,4 +11,8 @@ def humanize_date_with_time(date) human_date << " at #{I18n.l(date, format: :time)}" end + def dot_markdown(text) + GitHub::Markdown.render_gfm(text).html_safe + end + end diff --git a/app/mailers/job_mailer.rb b/app/mailers/job_mailer.rb new file mode 100644 index 000000000..f7eb6288a --- /dev/null +++ b/app/mailers/job_mailer.rb @@ -0,0 +1,21 @@ +class JobMailer < ActionMailer::Base + + def job_approved(job) + @job = job + @member = @job.created_by + mail(mail_args(@member, "Job #{@job.title} at #{@job.company} approved")) + end + + private + def mail_args(member, subject) + { :from => "Codebar.io ", + :to => member.email, + :subject => subject } + end + + helper do + def full_url_for path + "#{@host}#{path}" + end + end +end diff --git a/app/models/job.rb b/app/models/job.rb new file mode 100644 index 000000000..584cdf4d2 --- /dev/null +++ b/app/models/job.rb @@ -0,0 +1,4 @@ +class Job < ActiveRecord::Base + belongs_to :created_by, class_name: "Member", foreign_key: :created_by_id + +end diff --git a/app/models/member.rb b/app/models/member.rb index 9d2235486..d84124865 100644 --- a/app/models/member.rb +++ b/app/models/member.rb @@ -3,6 +3,7 @@ class Member < ActiveRecord::Base has_many :session_invitations has_many :auth_services has_many :feedbacks, foreign_key: :coach_id + has_many :jobs, foreign_key: :created_by_id validates :auth_services, presence: true validates :name, :surname, :email, :about_you, presence: true, if: :can_log_in? diff --git a/app/views/admin/jobs/index.html.haml b/app/views/admin/jobs/index.html.haml new file mode 100644 index 000000000..9e1e2b267 --- /dev/null +++ b/app/views/admin/jobs/index.html.haml @@ -0,0 +1,16 @@ += render partial: 'shared/title', locals: { title: "Manage Jobs ", date: nil } + +- @jobs.each do |job| + .row + .large-12.columns + .panel.callout + %h4 + =link_to admin_job_path(job) do + #{job.title} at #{job.company} + %small.fa.fa-location-arrow + = job.location + =link_to admin_job_path(job) do + %p + =truncate(sanitize(dot_markdown(job.description), tags: { }), length: 200) + %p.text-right + Posted by #{job.created_by.full_name} on #{l(job.created_at, format: :date)} diff --git a/app/views/admin/jobs/show.html.haml b/app/views/admin/jobs/show.html.haml new file mode 100644 index 000000000..87e801fba --- /dev/null +++ b/app/views/admin/jobs/show.html.haml @@ -0,0 +1,29 @@ += render partial: 'admin/shared/title', locals: { title: "#{@job.title} at #{@job.company}", date: nil } +.row + .large-12.columns + %h2 Review job +.row + .large-12.columns.panel + .row + .large-12.columns + %h1 + #{@job.title} at #{link_to(@job.company, @job.link_to_job)} + %small.fa.fa-location-arrow + = @job.location + + .row + .large-12.columns + = dot_markdown(@job.description) + %p + %em posted by #{@job.created_by.full_name} on #{l(@job.created_at, format: :date)} + + %p + %b This job will expire in #{distance_of_time_in_words(Time.now, @job.expiry_date)} + + .row + .large-12.columns.text-right + =mail_to @job.email, "Apply", class: 'button alert round' + + .row + .large-12.columns.text-right + =link_to "Approve", admin_job_approve_path(@job), class: 'button round alert' diff --git a/app/views/admin/portal/index.html.haml b/app/views/admin/portal/index.html.haml index 56b2dc376..9e1ce35b4 100644 --- a/app/views/admin/portal/index.html.haml +++ b/app/views/admin/portal/index.html.haml @@ -8,3 +8,7 @@ .large-4.columns .panel =link_to "View feedback", admin_feedback_index_path, class: 'button round expand' + + .large-4.columns + .panel + =link_to "Approve jobs (#{@jobs_pending_approval})", admin_jobs_path, class: 'button round expand' diff --git a/app/views/job_mailer/job_approved.html.haml b/app/views/job_mailer/job_approved.html.haml new file mode 100644 index 000000000..2e1b31487 --- /dev/null +++ b/app/views/job_mailer/job_approved.html.haml @@ -0,0 +1,49 @@ +=render partial: 'shared_mailers/header', locals: { title: "Job post approved" } + +%body{ bgcolor: "#FFFFFF" } + + =render partial: 'shared_mailers/body_header', locals: { title: "Job post Approved" } + + %table{ class: "body-wrap"} + %tr + %td + %td{ class: "container", bgcolor: "#FFFFFF" } + + .content + %table + %tr + %td + %h3 Hi, #{@member.name} + %p.lead + The + %a{ href: full_url_for(job_url(@job)) }#{@job.title} at #{@job.company} + job you submitted has been approved. + %p.callout + It is now available to all members at + %a{ href: full_url_for(jobs_url) }Codebar's jobs section » + + %table.social{ width: "100%" } + %tr + %td + + %table{ align: "left", class: "column"} + %tr + %td + + %h5 Connect with Us: + %p + %a{ href: "https://www.facebook.com/codebarHQ", class: 'soc-btn fb'} Like us on facebook + %a{ href: "http://twitter.com/by_codebar", class: "soc-btn tw" }Follow us on twitter + %a{ href: "https://www.facebook.com/groups/codebarcommunity", class: 'soc-btn fb'} Join our facebook community + + + %table.column{ align: "left" } + %tr + %td + %h5 Contact Info: + %p Email: hello@codebar.io + + %span.clear + %td + + = render partial: 'shared_mailers/footer' diff --git a/app/views/jobs/_form.html.haml b/app/views/jobs/_form.html.haml new file mode 100644 index 000000000..d4a3611a7 --- /dev/null +++ b/app/views/jobs/_form.html.haml @@ -0,0 +1,28 @@ +.row + .medium-12.columns + %p.panel Jobs will appear after they are reviewed and authorised. Please think twice before posting a job, as we want to create a job board that our community trusts. + = simple_form_for @job do |f| + .row + .large-6.columns + = f.input :title, label: "Job title", required: true, placeholder: "e.g. Internship" + .row + .large-6.columns + = f.input :company, required: true, placeholder: "e.g. Codebar", required: true + .row + .large-6.columns + = f.input :location, required: true, placeholder: "e.g. London or Remote", required: true + .row + .large-12.columns + = f.input :description, placeholder: 'Use text or markdown for the job description', input_html: { rows: 10 }, required: true + .row + .large-6.columns + = f.input :email, label: "Job application email", required: true + .row + .large-6.columns + = f.input :link_to_job, required: true + .row + .large-6.columns + = f.input :expiry_date, as: :date, order: [:day, :month, :year], start_year: Date.today.year, start_month: Date.today.month, end_year: (Date.today+2.months).year, default: Date.today+2.weeks, input_html: { class: 'medium-3 columns' }, required: true + .row + .large-12.columns.text-right + = f.submit "Update", class: "button round tiny" diff --git a/app/views/jobs/edit.html.haml b/app/views/jobs/edit.html.haml new file mode 100644 index 000000000..eb1cbf1f7 --- /dev/null +++ b/app/views/jobs/edit.html.haml @@ -0,0 +1,2 @@ += render partial: 'shared/title', locals: { title: "Review job", date: nil } += render partial: 'form' diff --git a/app/views/jobs/index.html.haml b/app/views/jobs/index.html.haml new file mode 100644 index 000000000..0c9258a87 --- /dev/null +++ b/app/views/jobs/index.html.haml @@ -0,0 +1,26 @@ += render partial: 'shared/title', locals: { title: "Jobs ", date: nil } +- if is_verified_coach_or_admin? + .row + .large-12.columns.text-right + =link_to "List a job", new_job_path, class: 'button round alert' + +- unless @jobs.any? + .row + .large-12.columns + %p + There are no jobs available at the moment + +- @jobs.each do |job| + .row + .large-12.columns + .panel.callout + %h4 + =link_to job do + #{job.title} at #{job.company} + %small.fa.fa-location-arrow + = job.location + =link_to job do + %p + =truncate(sanitize(dot_markdown(job.description), tags: { }), length: 200) + %p.text-right + Posted by #{job.created_by.full_name} on #{l(job.created_at, format: :date)} diff --git a/app/views/jobs/new.html.haml b/app/views/jobs/new.html.haml new file mode 100644 index 000000000..558c6cb62 --- /dev/null +++ b/app/views/jobs/new.html.haml @@ -0,0 +1,4 @@ +- if @pending_jobs + %p You have #{@pending_jobs.count} += render partial: 'shared/title', locals: { title: "Add a job", date: nil } += render partial: 'form' diff --git a/app/views/jobs/pending.html.haml b/app/views/jobs/pending.html.haml new file mode 100644 index 000000000..3d783356c --- /dev/null +++ b/app/views/jobs/pending.html.haml @@ -0,0 +1,22 @@ += render partial: 'shared/title', locals: { title: "Pending Jobs ", date: nil } + +- unless @jobs.any? + .row + .large-12.columns + %p + There are no jobs available at the moment + +- @jobs.each do |job| + .row + .large-12.columns + .panel.callout + %h4 + =link_to job_preview_path(job) do + #{job.title} at #{job.company} + %small.fa.fa-location-arrow + = job.location + =link_to job_preview_path(job) do + %p + =truncate(sanitize(dot_markdown(job.description), tags: { }), length: 200) + %p.text-right + Posted by #{job.created_by.full_name} on #{l(job.created_at, format: :date)} diff --git a/app/views/jobs/preview.html.haml b/app/views/jobs/preview.html.haml new file mode 100644 index 000000000..e2f671b66 --- /dev/null +++ b/app/views/jobs/preview.html.haml @@ -0,0 +1,30 @@ += render partial: 'shared/title', locals: { title: "Preview ", date: nil } +.row + .large-12.columns + %p Submit to verify your job post. + .row + .large-12.columns.panel + .row + .large-12.columns + %h1 + #{@job.title} at #{link_to(@job.company, @job.link_to_job)} + %small.fa.fa-location-arrow + = @job.location + + .row + .large-12.columns + = dot_markdown(@job.description) + %p + %em posted by #{@job.created_by.full_name} on #{l(@job.created_at, format: :date)} + + %p + %b This job will expire in #{distance_of_time_in_words(Time.now, @job.expiry_date)} + + .row + .large-12.columns.text-right + =mail_to @job.email, "Apply", class: 'button alert round' + + .row + .large-12.columns.text-right + = link_to "Edit", edit_job_path(@job), class: 'button round' + = link_to "Submit", job_submit_path(@job), class: 'button round alert', method: :post diff --git a/app/views/jobs/show.html.haml b/app/views/jobs/show.html.haml new file mode 100644 index 000000000..29cd6f471 --- /dev/null +++ b/app/views/jobs/show.html.haml @@ -0,0 +1,22 @@ += render partial: 'shared/title', locals: { title: "Jobs / #{@job.title} at #{@job.company}", date: nil } +.row + .large-12.columns + .row + .large-12.columns + %h1 + #{@job.title} at #{link_to(@job.company, @job.link_to_job)} + %small.fa.fa-location-arrow + = @job.location + + .row + .large-12.columns + = dot_markdown(@job.description) + %p + %em posted by #{@job.created_by.full_name} on #{l(@job.created_at, format: :date)} + + %p + %b This job will expire in #{distance_of_time_in_words(Time.now, @job.expiry_date)} + + .row + .large-12.columns.text-right + =mail_to @job.email, "Apply", class: 'button alert round' diff --git a/app/views/layouts/_navigation.html.haml b/app/views/layouts/_navigation.html.haml index 04c646236..28c65e660 100644 --- a/app/views/layouts/_navigation.html.haml +++ b/app/views/layouts/_navigation.html.haml @@ -13,7 +13,12 @@ = link_to "Admin", admin_root_path, class: 'button alert' - if logged_in? %li.has-form - = link_to "My account", portal_index_path, class: 'button' + = link_to "My account", portal_index_path, class: 'button success' + %li + - if current_page?(jobs_path) + %li.active= link_to "Jobs", jobs_path + - else + = link_to "Jobs", jobs_path - if current_page?(events_path) %li.active= link_to "Events", events_path diff --git a/app/views/portal/index.html.haml b/app/views/portal/index.html.haml index a74892238..867a1182e 100644 --- a/app/views/portal/index.html.haml +++ b/app/views/portal/index.html.haml @@ -22,3 +22,14 @@ Student feedback for the workshops %br =link_to "View Feedback", coach_feedback_index_path, class: 'button round expand' + - if is_verified_coach_or_admin? + .large-4.columns + .panel + %h4 List a job + -if @pending_jobs.any? + =link_to pending_jobs_path, class: 'button alert round tiny' do + #{@pending_jobs.count} job(s) pending submission + %p + Help codebar students find trusted jobs. + %br + =link_to "Add Job", new_job_path, class: 'button round expand' diff --git a/app/views/shared_mailers/_body_header.html.haml b/app/views/shared_mailers/_body_header.html.haml new file mode 100644 index 000000000..a74aa10cc --- /dev/null +++ b/app/views/shared_mailers/_body_header.html.haml @@ -0,0 +1,13 @@ +%table.head-wrap{ bgcolor: "#fdfdfd" } + %tr + %td + %td.header.container + + .content + %table{ bgcolor: "#fdfdfd" } + %tr + %td + %img{ src: "https://dl.dropboxusercontent.com/u/108831317/codebar.png" } + %td{ align: "right"} + %h6.collapse= title + %td diff --git a/app/views/shared_mailers/_footer.html.haml b/app/views/shared_mailers/_footer.html.haml new file mode 100644 index 000000000..2fe02ff34 --- /dev/null +++ b/app/views/shared_mailers/_footer.html.haml @@ -0,0 +1,12 @@ +%table.footer-wrap + %tr + %td + %td.container + .content + %table + %tr + %td{ align: "center" } + %p + %a{ href: full_url_for(unsubscribe_member_url(@member)) } + %unsubscribe Unsubscribe + %td diff --git a/app/views/shared_mailers/_header.html.haml b/app/views/shared_mailers/_header.html.haml new file mode 100644 index 000000000..abed8e021 --- /dev/null +++ b/app/views/shared_mailers/_header.html.haml @@ -0,0 +1,9 @@ +!!!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd" +%html{ xmlns: "http://www.w3.org/1999/xhtml" } +%head + %meta{name: "viewport", content: "width=device-width" } + + %meta{ 'http-equiv' => "Content-Type", content: "text/html; charset=UTF-8" } + %title=title + + %link{rel: "stylesheet", type: "text/css", href: "/assets/email.css"} diff --git a/config/initializers/premailer.rb b/config/initializers/premailer.rb new file mode 100644 index 000000000..7257df900 --- /dev/null +++ b/config/initializers/premailer.rb @@ -0,0 +1 @@ +Premailer::Rails.config.merge!(preserve_styles: true) diff --git a/config/routes.rb b/config/routes.rb index 94ea6b6ab..4548e686c 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -48,9 +48,19 @@ end end + resources :jobs, except: [:destroy] do + get 'preview' + get 'submit' + get 'pending', on: :collection + end + namespace :admin do root "portal#index" + resources :jobs, only: [ :index, :show] do + get 'approve' + end + resources :invitation, only: [] do get :attended get :not_attending diff --git a/db/migrate/20140504143819_create_job.rb b/db/migrate/20140504143819_create_job.rb new file mode 100644 index 000000000..91fdb7504 --- /dev/null +++ b/db/migrate/20140504143819_create_job.rb @@ -0,0 +1,17 @@ +class CreateJob < ActiveRecord::Migration + def change + create_table :jobs do |t| + t.string :title + t.text :description + t.string :location + t.datetime :expiry_date + t.string :email + t.string :link_to_job + t.references :created_by, index: true + t.boolean :approved, default: false + t. boolean :submitted, default: false + + t.timestamps + end + end +end diff --git a/db/migrate/20140504171455_add_company_to_job.rb b/db/migrate/20140504171455_add_company_to_job.rb new file mode 100644 index 000000000..7b1372927 --- /dev/null +++ b/db/migrate/20140504171455_add_company_to_job.rb @@ -0,0 +1,5 @@ +class AddCompanyToJob < ActiveRecord::Migration + def change + add_column :jobs, :company, :string + end +end diff --git a/db/schema.rb b/db/schema.rb index f4c326ad8..486cd23e5 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -11,7 +11,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 20140501015844) do +ActiveRecord::Schema.define(version: 20140504171455) do create_table "addresses", force: true do |t| t.string "flat" @@ -98,6 +98,23 @@ add_index "feedbacks", ["coach_id"], name: "index_feedbacks_on_coach_id" add_index "feedbacks", ["tutorial_id"], name: "index_feedbacks_on_tutorial_id" + create_table "jobs", force: true do |t| + t.string "title" + t.text "description" + t.string "location" + t.datetime "expiry_date" + t.string "email" + t.string "link_to_job" + t.integer "created_by_id" + t.boolean "approved", default: false + t.boolean "submitted", default: false + t.datetime "created_at" + t.datetime "updated_at" + t.string "company" + end + + add_index "jobs", ["created_by_id"], name: "index_jobs_on_created_by_id" + create_table "meeting_talks", force: true do |t| t.integer "meeting_id" t.string "title" diff --git a/spec/mailers/feedback_request_mailer_spec.rb b/spec/mailers/feedback_request_mailer_spec.rb index 1f5a4e9b1..7b604e3f3 100644 --- a/spec/mailers/feedback_request_mailer_spec.rb +++ b/spec/mailers/feedback_request_mailer_spec.rb @@ -13,6 +13,5 @@ FeedbackRequestMailer.request_feedback(session, member, feedback_request).deliver expect(email.subject).to eq(email_subject) - expect(email.parts.first.body.raw_source).to include feedback_url(feedback_request.token) end end