Skip to content
Browse files

Tweaked the startup/proposal list page, proposal review page and limi…

…ted the number of proposals per startup to 1. Closes #17.
  • Loading branch information...
1 parent d901bd5 commit 5be56ec572d46718b6ad004af8b236dcd87d8f29 @fredwu committed Jul 19, 2011
View
6 app/assets/javascripts/private_message.js.coffee
@@ -0,0 +1,6 @@
+jQuery ->
+ $('#contact_founder').hide()
+ $('input[rel=contact_founder]').click((e) ->
+ $('#contact_founder').slideDown()
+ e.preventDefault()
+ )
View
3 app/assets/javascripts/startup_photos.js.coffee
@@ -1,3 +0,0 @@
-# Place all the behaviors and hooks related to the matching controller here.
-# All this logic will automatically be available in application.js.
-# You can use CoffeeScript in this file: http://jashkenas.github.com/coffee-script/
View
37 app/assets/stylesheets/style.css.scss
@@ -416,11 +416,16 @@ nav.pagination {
margin-left: $avatar_size + 10px;
min-height: $avatar_size;
- .message_meta {
+ .message_meta,
+ .message_meta_secondary {
color: $secondary_colour_h;
font-size: $font_size_small;
margin-bottom: 5px;
}
+
+ .message_meta_secondary {
+ color: $secondary_colour;
+ }
}
}
}
@@ -558,7 +563,7 @@ nav.pagination {
}
}
- .grid_6 ul.resource_list {
+ #profile_team ul.resource_list {
li.mini_profile {
$profile_width: grid_cells(3);
@@ -653,6 +658,34 @@ form.read_only {
}
/* ------------------------------
+ private message
+------------------------------ */
+
+#business_proposal_private_message {
+ > h2 {
+ border-bottom: 1px dotted $secondary_colour_h;
+ padding-bottom: 10px;
+ margin-bottom: 10px;
+ }
+
+ ul#messages {
+ li:first-child hr {
+ display: none;
+ }
+ }
+}
+
+#action_buttons {
+ > form {
+ float: left;
+
+ input {
+ margin: 0 20px 10px 0;
+ }
+ }
+}
+
+/* ------------------------------
footer
------------------------------ */
View
14 app/controllers/messages_controller.rb
@@ -20,7 +20,7 @@ def create
end
def send_private_message
- result = current_user.send_private_message(User.find(params[:users]), params[:message][:content])
+ result = current_user.send_private_message(User.find(params[:message][:users] || params[:users]), params[:message][:content])
respond_to do |format|
format.json { render :json => result }
@@ -41,4 +41,16 @@ def reply_private_message
format.html { redirect_to :back }
end
end
+
+ def archive_private_message
+ Message.topics.find(params[:id]).mark_as_archived!
+
+ respond_to do |format|
+ format.json { render :json => result }
+ format.html do
+ flash[:success] = t('text.message_is_archived')
+ redirect_to :back
+ end
+ end
+ end
end
View
2 app/models/startup.rb
@@ -112,6 +112,8 @@ def user_role(user)
end
def create_proposal(investors = [], attributes = {}, stage = 'draft', private_message = I18n.t('text.default_text_for_proposal_review'))
+ raise Exceptions::NotAllowed if proposals.count >= Settings.startup.proposal.limit
+
proposal = proposals.create(attributes)
update_and_submit_proposal(proposal, investors, attributes, stage)
send_private_message_to_investors(proposal, investors, private_message) if stage == 'submitted'
View
2 app/views/messages/_index.html.slim
@@ -11,5 +11,5 @@
- if collection.any?
ul#messages
- collection.each do |resource|
- li.message= render 'messages/show', :resource => resource, :meta => meta
+ li.message= render "messages/#{meta[:show_view] || 'show'}", :resource => resource, :meta => meta
= show_pagination collection, :param_name => :p
View
17 app/views/messages/_show_with_startup.html.slim
@@ -0,0 +1,17 @@
+hr
+.message_user
+ = render 'startups/avatar', :startup => resource.proposal.startup
+.message_container
+ .message_meta
+ =' link_to resource.proposal.startup.name, startup_path(resource.proposal.startup)
+ = time_ago(resource.created_at)
+ .message_meta_secondary
+ = "#{t('label.founder')}: "
+ =' link_to resource.user.name, username_path(resource.user.username)
+ = "#{t('label.from')}: #{resource.user.location}, #{t('label.raise')}: #{number_to_currency(resource.proposal.startup.funds_to_raise)}, #{t('label.stage')}: #{resource.proposal.startup.stage}"
+ .message_content
+ - if meta[:linkable]
+ = link_to resource.content, my_private_message_path(resource)
+ - else
+ = resource.content
+
View
25 app/views/messages/show_private_message.html.slim
@@ -3,15 +3,36 @@
= render 'users/proposal_inboxes'
- else
= render 'users/message_inboxes'
-.grid_9
+.grid_9#business_proposal_private_message
- if @topic.is_with_proposal?
h1= t('label.business_proposal')
ul
li= "#{t('label.submitted_by')}: #{link_to @topic.user.name, user_path(@topic.user)} (#{link_to @topic.proposal.startup.name, startup_path(@topic.proposal.startup)})".html_safe
li= "#{t('label.submitted_to')}: #{link_to @topic.target.name, user_path(@topic.target)}".html_safe
hr
- .read_only= render 'proposals/read_only', :resource => @topic.proposal
+ h2= "#{t('label.startup')} #{t('label.details')}"
+ = render 'startups/mini_profile', :startup => @topic.proposal.startup, :meta => { :hide_team_members => true, :hide_editable => true }
+ hr
+ h2= "#{t('label.business_proposal')} #{t('label.details')}"
+ = render 'proposals/read_only', :resource => @topic.proposal
+
+ hr
+ h2= t('label.actions')
+ #action_buttons
+ = form_tag do |f|
+ = submit_tag t('label.contact_founder'), :rel => 'contact_founder'
+ = simple_form_for @topic, :url => my_private_message_path(@topic), :method => :delete do |f|
+ = f.button :submit, t('label.not_interested')
+ .clear
+
+ #contact_founder
+ = simple_form_for Message.new, :url => my_private_messages_path do |f|
+ = f.input :users, :as => :hidden, :input_html => { :value => @topic.user.id }
+ = f.input :content
+ = f.button :submit
+ .clear
+ hr
h2= t('label.comments')
ul#messages
li.message= render 'show', :resource => @topic, :meta => {}
View
24 app/views/proposals/_read_only.html.slim
@@ -1,5 +1,6 @@
ul#proposal_section_selector.multistage_selector
li= link_to t('label.product'), '#product'
+ li= link_to t('label.team'), '#team'
li= link_to t('label.market'), '#market'
li= link_to t('label.competition'), '#competition'
li= link_to t('label.investment'), '#investment', :class => 'last'
@@ -14,8 +15,16 @@ ul#proposal_section_selector.multistage_selector
.attribute= resource.pitch
= f.label :introduction
.attribute= resource.introduction
- .grouped_buttons
- = submit_tag t('label.next'), :class => 'navigation next'
+ fieldset#team
+ #profile_team
+ = f.label t('label.members')
+ .attribute= render 'users/index', :collection => resource.startup.members, :meta => { :parent => resource.startup, :role_identifier => 'member' }
+ = f.label t('label.investors')
+ .attribute= render 'users/index', :collection => resource.startup.investors, :meta => { :parent => resource.startup, :role_identifier => 'investors' }
+ = f.label t('label.advisors')
+ .attribute= render 'users/index', :collection => resource.startup.advisors, :meta => { :parent => resource.startup, :role_identifier => 'advisors' }
+ = f.label t('label.incubators')
+ .attribute= render 'users/index', :collection => resource.startup.incubators, :meta => { :parent => resource.startup, :role_identifier => 'incubators' }
fieldset#market
legend= t('label.market')
h2= t('label.one_year_market')
@@ -39,9 +48,6 @@ ul#proposal_section_selector.multistage_selector
= f.label :five_year_marketing_strategy
.attribute= resource.five_year_marketing_strategy
= f.input :five_year_gross_profit_margin
- .grouped_buttons
- = submit_tag t('label.prev'), :class => 'navigation prev'
- = submit_tag t('label.next'), :class => 'navigation next'
fieldset#competition
legend= t('label.competition')
= f.label :competitors_details
@@ -50,9 +56,6 @@ ul#proposal_section_selector.multistage_selector
.attribute= resource.competitive_edges
= f.label :competing_strategy
.attribute= resource.competing_strategy
- .grouped_buttons
- = submit_tag t('label.prev'), :class => 'navigation prev'
- = submit_tag t('label.next'), :class => 'navigation next'
fieldset#investment
legend= t('label.investment')
= f.input :investment_amount
@@ -62,8 +65,3 @@ ul#proposal_section_selector.multistage_selector
= f.label :spending_plan
.attribute= resource.spending_plan
= f.input :next_investment_round
- .grouped_buttons
- = submit_tag t('label.prev'), :class => 'navigation prev'
- - unless resource.proposal_stage_identifier == 'submitted'
- = submit_tag t('label.save_draft')
- = submit_tag t('label.submit_proposal')
View
2 app/views/startups/_avatar.html.slim
@@ -1,2 +1,2 @@
div style="height: 50px; width: 50px; overflow: hidden;"
- = link_to image_tag(startup.logo_avatar, :alt => startup.name), resource_path(startup)
+ = link_to image_tag(startup.logo_avatar, :alt => startup.name), startup_path(startup)
View
11 app/views/startups/_mini_profile.html.slim
@@ -1,11 +1,12 @@
-- if startup.founder == current_user
+- if startup.founder == current_user && !meta[:hide_editable]
= render 'shared/editable', :edit_target => '#profile_details'
.mini_profile.inline_edtiable_container
#profile_details data-target_link="#{startup_profile_details_path(startup)}"
- = render 'profile_details', :startup => startup
+ = render 'startups/profile_details', :startup => startup
.clear
- hr
- #profile_team
- = render 'profile_team', :startup => startup
+ - unless meta[:hide_team_members]
+ hr
+ #profile_team
+ = render 'startups/profile_team', :startup => startup
View
8 app/views/startups/_profile_team.html.slim
@@ -1,23 +1,23 @@
.team
h2= t('label.members')
- = render 'add_user_link', :startup => startup, :role_identifier => 'member'
+ = render 'startups/add_user_link', :startup => startup, :role_identifier => 'member'
= render 'users/index', :collection => startup.members, :meta => { :removable => true, :editable => true, :parent => startup, :role_identifier => 'member' }
.clear
.team
h2= t('label.investors')
- = render 'add_user_link', :startup => startup, :role_identifier => 'investor'
+ = render 'startups/add_user_link', :startup => startup, :role_identifier => 'investor'
= render 'users/index', :collection => startup.investors, :meta => { :removable => true, :editable => true, :parent => startup, :role_identifier => 'investor' }
.clear
.team
h2= t('label.advisors')
- = render 'add_user_link', :startup => startup, :role_identifier => 'advisor'
+ = render 'startups/add_user_link', :startup => startup, :role_identifier => 'advisor'
= render 'users/index', :collection => startup.advisors, :meta => { :removable => true, :editable => true, :parent => startup, :role_identifier => 'advisor' }
.clear
.team
h2= t('label.incubators')
- = render 'add_user_link', :startup => startup, :role_identifier => 'incubator'
+ = render 'startups/add_user_link', :startup => startup, :role_identifier => 'incubator'
= render 'users/index', :collection => startup.incubators, :meta => { :removable => true, :editable => true, :parent => startup, :role_identifier => 'incubator' }
.clear
View
7 app/views/startups/index.html.slim
@@ -4,13 +4,16 @@ ul.resource_list.startup_list
hr
.profile_pic
- = render 'avatar', :startup => startup, :meta => {}
+ = render 'avatar', :startup => startup
.profile_meta
h2= link_to startup.name, startup_path(startup)
ul
li= startup.pitch
- li.secondary= startup.location
+ li.secondary
+ = "#{t('label.founder')}: "
+ =' link_to startup.founder.name, username_path(startup.founder.username)
+ = "#{t('label.from')}: #{startup.founder.location}, #{t('label.raise')}: #{number_to_currency(startup.funds_to_raise)}, #{t('label.stage')}: #{startup.stage}"
.profile_metrics
.follow_button= follow_button(startup)
View
11 app/views/startups/show.html.slim
@@ -1,5 +1,5 @@
.grid_6
- = render 'mini_profile', :startup => resource
+ = render 'mini_profile', :startup => resource, :meta => {}
.grid_6.inline_edtiable_container
- if resource.founder == current_user
= render 'shared/editable', :edit_target => '#gallery', :url => startup_upload_photos_path(resource)
@@ -12,7 +12,8 @@
hr
h2= t('label.business_proposals')
ul
- - resource.proposals.each_with_index do |proposal, index|
- li
- = link_to "#{t('label.business_proposal')} #{index + 1} (#{t("startup.proposal_stage_identifiers.#{proposal.proposal_stage_identifier}")})", edit_startup_proposal_path(resource, proposal)
- li.create_new= link_to t('label.create_new'), new_startup_proposal_path(resource)
+ - if resource.proposals.any?
+ - resource.proposals.each_with_index do |proposal, index|
+ li= link_to "#{t('label.business_proposal')} #{index + 1} (#{t("startup.proposal_stage_identifiers.#{proposal.proposal_stage_identifier}")})", edit_startup_proposal_path(resource, proposal)
+ - else
+ li.create_new= link_to t('label.create_new'), new_startup_proposal_path(resource)
View
2 app/views/users/proposal_inboxes.html.slim
@@ -1,4 +1,4 @@
.grid_3
= render 'users/proposal_inboxes'
.grid_9
- = render 'messages/index', :collection => @messages, :meta => { :linkable => true }
+ = render 'messages/index', :collection => @messages, :meta => { :linkable => true, :show_view => 'show_with_startup' }
View
9 config/locales/en.yml
@@ -57,13 +57,15 @@ en:
label:
home: Home
loading: Loading
+ actions: Actions
create: Create
update: Update
add: Add
edit: Edit
update: Update
delete: Delete
remove: Remove
+ archive: Archive
cancel: Cancel
close: Close
confirm: Confirm
@@ -139,6 +141,12 @@ en:
messages_inbox: Messages inbox
proposals_inbox: Proposals inbox
delete_the_image_below: Delete the image below
+ contact_founder: Contact founder
+ details: Details
+ not_interested: Not interested
+ from: From
+ raise: Raise
+ stage: Stage
message:
proposal_saved: The proposal has been saved!
proposal_submitted: The proposal has been submitted to the investors!
@@ -150,3 +158,4 @@ en:
enter_recipient_names: Recipient name ...
enter_investor_names: Investor names ...
no_more_selections_allowed: No more selections are allowed.
+ message_is_archived: The message is archived.
View
35 config/routes.rb
@@ -23,23 +23,24 @@
end
end
- match 'startups/:id/profile_details' => 'startups#profile_details', :via => :get, :as => :startup_profile_details
- match 'startups/:id/profile_team' => 'startups#profile_team', :via => :get, :as => :startup_profile_team
- match 'startups/:id/photos' => 'startups#photos', :via => :get, :as => :startup_photos
- match 'startups/:id/upload_photos' => 'startups#upload_photos', :via => :get, :as => :startup_upload_photos
-
- match 'u/:username' => 'users#show', :via => :get, :as => :username
-
- match 'my/profile' => 'users#show', :via => :get
- match 'my/home' => 'users#home', :via => :get
- match 'my/private_messages' => 'messages#send_private_message', :via => :post, :as => :my_private_messages
- match 'my/private_messages/:id' => 'messages#show_private_message', :via => :get, :as => :my_private_message
- match 'my/private_messages/:id' => 'messages#reply_private_message', :via => :post, :as => :my_private_message
- match 'my/message_inboxes(/:type)' => 'users#message_inboxes', :via => :get, :as => :my_message_inbox
- match 'my/micro_posts' => 'users#add_micro_post', :via => :post
-
- match 'my/follow/:target_id' => 'users#follow_target', :via => :post, :as => :follow_target
- match 'my/unfollow/:target_id' => 'users#unfollow_target', :via => :post, :as => :unfollow_target
+ match 'startups/:id/profile_details' => 'startups#profile_details', :via => :get, :as => :startup_profile_details
+ match 'startups/:id/profile_team' => 'startups#profile_team', :via => :get, :as => :startup_profile_team
+ match 'startups/:id/photos' => 'startups#photos', :via => :get, :as => :startup_photos
+ match 'startups/:id/upload_photos' => 'startups#upload_photos', :via => :get, :as => :startup_upload_photos
+
+ match 'u/:username' => 'users#show', :via => :get, :as => :username
+
+ match 'my/profile' => 'users#show', :via => :get
+ match 'my/home' => 'users#home', :via => :get
+ match 'my/private_messages' => 'messages#send_private_message', :via => :post, :as => :my_private_messages
+ match 'my/private_messages/:id' => 'messages#show_private_message', :via => :get, :as => :my_private_message
+ match 'my/private_messages/:id' => 'messages#reply_private_message', :via => :post, :as => :my_private_message
+ match 'my/private_messages/:id' => 'messages#archive_private_message', :via => :delete, :as => :my_private_message
+ match 'my/message_inboxes(/:type)' => 'users#message_inboxes', :via => :get, :as => :my_message_inbox
+ match 'my/micro_posts' => 'users#add_micro_post', :via => :post
+
+ match 'my/follow/:target_id' => 'users#follow_target', :via => :post, :as => :follow_target
+ match 'my/unfollow/:target_id' => 'users#unfollow_target', :via => :post, :as => :unfollow_target
# The priority is based upon order of creation:
# first created -> highest priority.
View
1 config/settings.yml
@@ -20,6 +20,7 @@ group:
height: 50
startup:
proposal:
+ limit: 1
questions:
en:
- Product or service introduction.
View
40 db/seeds_for_dev.rb
@@ -1,25 +1,30 @@
require File.dirname(__FILE__) + '/../spec/support/blueprints'
+p 'Cleaning up temp data ...'
+
+FileUtils.rm_rf(File.join(Rails.root, 'public', 'uploads'))
+
+p 'Finished cleaning up temp data.'
+
p 'Creating seeds data for development ...'
# primary user
+p ' > users ...'
user = User.make!({
:username => 'fredwu',
:name => 'Fred Wu',
:email => 'ifredwu@gmail.com',
:password => 'password',
})
-user.confirm!
# more users
-40.times do
- u = User.make!
- u.confirm!
-end
+User.make!(40)
+User.all.each { |u| u.confirm! }
# investors and startups
+p ' > investors and startups ...'
10.times { InvestorProfile.make! }
20.times { Startup.make! }
@@ -34,22 +39,22 @@
user.investor_profile = InvestorProfile.make!
# startup founders and proposals
+p ' > startup founders and proposals ...'
Startup.all.each do |startup|
u = User.new_users.first
startup.attach_user(u, :member, Faker::Lorem.word)
startup.confirm_user(u)
- 2.times { startup.create_proposal(User.investors.sample, Proposal.make.attributes, 'draft') }
- 3.times { startup.create_proposal(User.investors.sample, Proposal.make.attributes, 'submitted', Faker::Lorem.sentence) }
- startup.create_proposal(user, Proposal.make.attributes, 'submitted', Faker::Lorem.sentence) if rand(5) == 0
- if rand(10) == 0
- startup.create_proposal(user, Proposal.make.attributes, 'submitted', Faker::Lorem.sentence)
- Message.last.mark_as_archived!
+ if rand(2) == 0
+ startup.create_proposal(User.investors.sample, Proposal.make.attributes, 'draft')
+ else
+ startup.create_proposal(user, Proposal.make.attributes, 'submitted')
end
end
# follow/unfollow
+p ' > follow/unfollow ...'
User.limit(10).each do |u|
user.follow(u)
@@ -60,27 +65,30 @@
end
# micro posts
+p ' > micro posts ...'
-(5 + rand(5)).times do
+(3 + rand(3)).times do
User.order('RAND()').each do |u|
u.add_micro_post(Faker::Lorem.sentence)
end
end
# private messages
+p ' > private messages ...'
User.all.each do |u|
- 20.times do
+ 3.times do
target_user = User.order('RAND()').first
+ u.send_private_message(user, Faker::Lorem.sentence) if rand(5) == 0
u.send_private_message(target_user, Faker::Lorem.sentence)
- (2 + rand(2)).times do
+ (1 + rand(1)).times do
rand(2).times { target_user.reply_private_message(Message.topics.last, Faker::Lorem.sentence) }
rand(2).times { u.reply_private_message(Message.topics.last, Faker::Lorem.sentence) }
end
end
- u.sent_messages.order('RAND()').limit(5).each { |msg| msg.mark_as_read! }
- u.sent_messages.order('RAND()').limit(5).each { |msg| msg.mark_as_archived! }
+ u.sent_messages.order('RAND()').limit(3).each { |msg| msg.mark_as_read! }
+ u.sent_messages.order('RAND()').limit(3).each { |msg| msg.mark_as_archived! }
end
p 'Finished creating seeds data for development.'
View
3 lib/exceptions/not_allowed.rb
@@ -0,0 +1,3 @@
+module Exceptions
+ class NotAllowed < Exception; end
+end
View
6 spec/controllers/messages_controller_spec.rb
@@ -53,5 +53,11 @@
assigns(:topic).should == topic
topic.replies.first.content.should == 'Yes dear!'
end
+
+ it "archives a topic" do
+ post :archive_private_message, :id => 1
+
+ Message.topics.find(1).is_archived.should == true
+ end
end
end
View
8 spec/models/proposal_spec.rb
@@ -85,6 +85,14 @@
startup.founder.sent_proposals.first.content.should == 'Hey man!'
end
+ it "submits no more than allowed to" do
+ Settings.startup.proposal.limit.times do
+ startup.create_proposal(investor1, proposal.attributes, 'submitted')
+ end
+
+ expect { startup.create_proposal(investor1, proposal.attributes, 'submitted') }.to raise_exception(Exceptions::NotAllowed)
+ end
+
it "edits a proposal" do
startup.create_proposal(investor1, proposal.attributes)
startup.update_proposal(Proposal.last, investor2, Proposal.make(:pitch => 'Hello world').attributes)

0 comments on commit 5be56ec

Please sign in to comment.
Something went wrong with that request. Please try again.