82 Commits
Author SHA1 Message Date
junv ca3162b631 fix readme 2012-12-06 16:11:31 +08:00
Jeff Xiong 1cc624c10b fix a typo 2012-12-06 14:44:21 +08:00
szpyxlwoni 3709e9206d Merge branch 'master' of https://github.com/wahyd4/ocelots 2012-12-06 14:33:57 +08:00
szpyxlwoni 706699a4b8 add team search 2012-12-06 14:33:30 +08:00
junv c2078f3ca2 Merge branch 'master' of https://github.com/wahyd4/ocelots 2012-12-06 14:24:20 +08:00
szpyxlwoni 7cf845153a Merge remote-tracking branch 'heroku/master' 2012-12-06 14:24:13 +08:00
szpyxlwoni 1376cc92fc fix a bug 2012-12-06 14:23:15 +08:00
junv a4f546210c fix pusher channel 2012-12-06 14:19:41 +08:00
szpyxlwoni 92e3156740 Merge branch 'master' of https://github.com/wahyd4/ocelots 2012-12-06 14:17:46 +08:00
szpyxlwoni a70a948f97 add team search input 2012-12-06 14:17:21 +08:00
junv ec6b5b4bb2 filter blanks of slug when create a team 2012-12-06 14:12:21 +08:00
szpyxlwoni 490476cca2 Merge remote-tracking branch 'heroku/master' 2012-12-06 14:08:35 +08:00
szpyxlwoni 1e009425f7 fix google maps error message and make list of team sort by team name 2012-12-06 14:07:22 +08:00
junv 1fd6d145b4 fix pusher channel bug 2012-12-06 13:00:41 +08:00
junv 0ac6202372 fix readme display bug 2012-12-06 12:19:56 +08:00
junv eb95b7fc13 update readme.md for pusher config 2012-12-06 11:35:58 +08:00
junv 3995c7e239 Merge branch 'master' of https://github.com/wahyd4/ocelots 2012-12-06 11:24:29 +08:00
junv b1cd590a63 change push message to pusher ,before use it we should config it at localhost and heroku 2012-12-06 11:16:41 +08:00
szpyxlwoni c1e4d4ff18 Merge remote-tracking branch 'heroku/master' 2012-12-06 11:15:00 +08:00
szpyxlwoni b6dc5e4e32 Merge branch 'master' of https://github.com/wahyd4/ocelots 2012-12-06 11:12:07 +08:00
szpyxlwoni 68afb37c29 add search people in a team 2012-12-06 11:11:56 +08:00
junv d40596ef06 trying 2012-12-06 09:54:42 +08:00
junv f37d88d84a ddd 2012-12-06 09:30:36 +08:00
junv 46c4fd5081 try to fix 2012-12-06 08:54:38 +08:00
junv 661882f409 try to fix 2012-12-05 18:16:24 +08:00
junv 4bd724079f try to fix 2012-12-05 18:11:58 +08:00
junv 709fbe1a1c try to fix address bug 2012-12-05 18:04:12 +08:00
junv a365c0f436 try 2012-12-05 17:59:31 +08:00
junv 9315f2ad96 fix web socket address port 2012-12-05 17:54:08 +08:00
junv 686fc27126 fix web socket address bind bug 2012-12-05 17:48:30 +08:00
junv 51ba3907d8 Merge branch 'master' of https://github.com/wahyd4/ocelots 2012-12-05 17:15:48 +08:00
junv ea1d27c0ff add antechamber auto-refresh based web-socket,but right now can;t be auto recoverd 2012-12-05 17:15:41 +08:00
szpyxlwoni 72a4102090 Merge remote-tracking branch 'heroku/master' 2012-12-05 16:39:37 +08:00
szpyxlwoni 721c552ce4 add sort of list of teams 2012-12-05 16:36:42 +08:00
junv 408c45f8bf .. 2012-12-05 14:29:32 +08:00
junv f79ad1cc53 qMerge branch 'master' of https://github.com/wahyd4/ocelots 2012-12-05 14:28:56 +08:00
junv 70f89d3d47 add experiment websocket feature 2012-12-05 14:27:34 +08:00
szpyxlwoni f277ab8b9c fix a bug that person add a team with nil name 2012-12-05 11:30:33 +08:00
szpyxlwoni 5c0bf3bd1f Merge branch 'master' of https://github.com/wahyd4/ocelots 2012-12-05 11:04:24 +08:00
szpyxlwoni 9e0899e6b4 add google search to find loction of person\ 2012-12-05 11:04:09 +08:00
junv 7c737fb2f8 modify server to thin 2012-12-05 11:03:40 +08:00
junv 317cb03aff fix bug; 2012-12-05 10:45:51 +08:00
junv 5ae31a5046 add travis config; 2012-12-05 10:40:56 +08:00
junv 1c31cd4618 add dfault task 2012-12-05 10:21:42 +08:00
junv 9ed0a1d780 modify gemfile.lock; 2012-12-05 10:15:06 +08:00
junv 7230c11ab1 add travis 2012-12-05 10:06:53 +08:00
junv 03dce270e5 add code climate 2012-12-05 09:58:28 +08:00
junv 8bdbb5caa8 fix git personal website 2012-12-05 08:53:34 +08:00
szpyxlwoni 1c3d9c246a modify quiz 2012-12-04 17:22:06 +08:00
szpyxlwoni b57c4e92bc select person with facts in quiz page 2012-12-04 17:09:22 +08:00
junv f068ce3eea remove google map js from some unused pages 2012-12-04 16:46:31 +08:00
junv cf3f915488 fix profile page flickr dispaly bug 2012-12-04 15:51:50 +08:00
junv d7245ac9a4 add job title to avatars print page 2012-12-04 15:29:53 +08:00
szpyxlwoni 0025dabc9a add job title to people 2012-12-04 15:17:38 +08:00
szpyxlwoni 89ae1532d1 add job title to people 2012-12-04 15:14:10 +08:00
szpyxlwoni f2610e8b42 Merge branch 'master' of https://github.com/wahyd4/ocelots 2012-12-04 13:36:51 +08:00
szpyxlwoni a1aaf56959 fix a soundcloud bug 2012-12-04 13:36:22 +08:00
junv 409e7e3b20 fix social media display bug 2012-12-04 13:23:17 +08:00
junv 10e41d315f fix readme 2012-11-29 14:01:51 +08:00
junv 11f1f8c7a1 update readme 2012-11-29 14:00:46 +08:00
junv ef78a8fe99 modify readme.md 2012-11-29 13:53:32 +08:00
junv 39f0d2e1df Merge remote-tracking branch 'heroku/master' 2012-11-29 11:15:27 +08:00
szpyxlwoni 383b6164b4 fix soundcloud 2012-11-29 11:13:20 +08:00
szpyxlwoni 03ad1f5809 fix soundcloud 2012-11-29 11:06:15 +08:00
junv 11a791e261 Merge remote-tracking branch 'heroku/master' 2012-11-29 11:04:55 +08:00
szpyxlwoni 6ac344ddfa fix soundcloud 2012-11-29 10:47:03 +08:00
szpyxlwoni 6f1f983c13 fix soundcloud 2012-11-29 10:41:51 +08:00
junv cb8d2ca7f4 avatar ux improved 2012-11-29 10:01:59 +08:00
szpyxlwoni c1b49254ee Merge branch 'master' of https://github.com/wahyd4/ocelots 2012-11-29 09:54:43 +08:00
szpyxlwoni 4ee3aa1215 config soundcloud in diff host 2012-11-29 09:53:09 +08:00
junv ddc96613b2 add css precompile 2012-11-29 09:18:56 +08:00
szpyxlwoni db7dbd6e67 Merge branch 'master' of https://github.com/wahyd4/ocelots 2012-11-28 17:43:04 +08:00
szpyxlwoni fa05b3db73 add local uservoice record 2012-11-28 17:42:28 +08:00
junv da5c63d75e a litte ui improved 2012-11-28 15:05:23 +08:00
junv fcfb53b57c social media ux improved 2012-11-28 10:36:17 +08:00
junv 5f546d98a5 fix app.net url 2012-11-28 09:58:28 +08:00
junv ece31349d1 team member list page ui changed 2012-11-27 17:31:08 +08:00
junv a42e7ffb28 add error message when invite people failed 2012-11-27 15:37:11 +08:00
junv f73932f9a8 fix 2012-11-27 14:45:04 +08:00
junv 32180e0db5 Merge branch 'master' of https://github.com/wahyd4/ocelots 2012-11-27 14:32:21 +08:00
junv 0592347620 a little ux improved 2012-11-27 14:32:00 +08:00
szpyxlwoni 85492000f5 add a test for ensure do not invite someone more than once 2012-11-27 13:53:06 +08:00
46 changed files with 619 additions and 151 deletions
+9
View File
@@ -0,0 +1,9 @@
language: ruby
rvm:
- 1.9.3
env:
- DB=postgresql
script:
- RAILS_ENV=test bundle exec rake ci --trace db:migrate
before_script:
- psql -c 'create database ocelots_test' -U postgres
+2
View File
@@ -14,6 +14,8 @@ gem 'therubyracer'
gem 'google-api-client'
gem 'gravtastic'
gem 'rdiscount'
gem 'thin'
gem 'pusher'
group :assets do
gem 'sass-rails', '~> 3.2.3'
+13 -1
View File
@@ -71,9 +71,11 @@ GEM
capybara (>= 1.1.2)
cucumber (>= 1.1.8)
nokogiri (>= 1.5.0)
daemons (1.1.9)
database_cleaner (0.9.1)
diff-lcs (1.1.3)
erubis (2.7.0)
eventmachine (1.0.0)
execjs (1.4.0)
multi_json (~> 1.0)
extlib (0.9.15)
@@ -136,6 +138,9 @@ GEM
pg (0.14.1)
polyglot (0.3.3)
progressbar (0.11.0)
pusher (0.11.1)
multi_json (~> 1.0)
signature (~> 0.1.6)
rack (1.4.1)
rack-cache (1.2)
rack (>= 0.4)
@@ -166,7 +171,7 @@ GEM
rake (>= 0.8.7)
rdoc (~> 3.4)
thor (>= 0.14.6, < 2.0)
rake (10.0.1)
rake (10.0.2)
rdiscount (1.6.8)
rdoc (3.12)
json (~> 1.4)
@@ -197,6 +202,7 @@ GEM
multi_json (~> 1.0)
rubyzip
sexp_processor (4.1.2)
signature (0.1.6)
signet (0.4.3)
addressable (>= 2.2.3)
faraday (~> 0.8.1)
@@ -226,6 +232,10 @@ GEM
temple (0.4.1)
therubyracer (0.10.2)
libv8 (~> 3.3.10)
thin (1.5.0)
daemons (>= 1.0.9)
eventmachine (>= 0.12.6)
rack (>= 1.0.0)
thor (0.16.0)
tilt (1.3.3)
treetop (1.4.12)
@@ -259,6 +269,7 @@ DEPENDENCIES
machinist
paperclip
pg
pusher
rails (= 3.2.9)
rails_best_practices (~> 1.11.1)
rdiscount
@@ -269,5 +280,6 @@ DEPENDENCIES
slim
tddium
therubyracer
thin
uglifier (>= 1.0.3)
uuidtools
+32 -1
View File
@@ -1,4 +1,6 @@
# Ocelots
[![Build Status](https://secure.travis-ci.org/wahyd4/ocelots.png)](https://travis-ci.org/wahyd4/ocelots)
[![Code Climate](https://codeclimate.com/badge.png)](https://codeclimate.com/github/wahyd4/ocelots)
This is an application to allow members of a team to get to know each other.
@@ -6,6 +8,8 @@ You log in using a mozilla persona id (linked to your email address) and then yo
You can now create a team and invite new members to join by entering their email address (including yourself - you can administer a team without being a member).
Everyone can try it [iocelots.com][1]
To setup your own instance on heroku:
heroku apps:create
@@ -46,6 +50,18 @@ To use google maps, you will need to provide a google api key
heroku config:add GOOGLE_API=your_api_key
To use Pusher to auto-fresh messages,you need to add Pusher addon on heroku,and config it like:
heroku config:add PUSHER_APP_ID=your_pusher_app_id
heroku config:add PUSHER_KEY='your_pusher_key'
heroku config:add PUSHER_SECRET='your_pusher_secret'
To use it in local you need config it like following:
export PUSHER_APP_ID=your_pusher_app_id
export PUSHER_KEY='your_pusher_key'
export PUSHER_SECRET='your_pusher_secret'
## API
You can experiment with the API from the command line
@@ -55,6 +71,18 @@ First, set a couple of environment variables:
export OCELOTS_URL=http://localhost:3000
export OCELOTS_AUTH_TOKEN=f1ac4214-5426-4597-9b74-ea63167f4750
### Google OAuth API Config
You should apply for the API token from [Google API console][2],then set it.
heroku config:add GOOGLE_OAUTH_CLIENT_ID=yourid --app ocelots
heroku config:add GOOGLE_OAUTH_CLIENT_SECRET=yourSecret
heroku config:add GOOGLE_OAUTH_REDIRECT=http://replace to your domain/home/verify_g_callback
To use it in local, you need export variables:
export GOOGLE_OAUTH_CLIENT_ID=yourid --app ocelots
export GOOGLE_OAUTH_CLIENT_SECRET=yourSecret
export GOOGLE_OAUTH_REDIRECT=http://replace to your domain/home/verify_g_callback
### Membership Details
To request information on all the teams you are a member of:
@@ -86,4 +114,7 @@ To request the message contents of the antechamber for a team (with an optional
To add a new message:
export TEAM_SLUG=ateam
curl -H 'Content-Type: application/json' -d '{"content":"message"}' "$OCELOTS_URL/api/antechamber/$TEAM_SLUG?auth_token=$OCELOTS_AUTH_TOKEN"
curl -H 'Content-Type: application/json' -d '{"content":"message"}' "$OCELOTS_URL/api/antechamber/$TEAM_SLUG?auth_token=$OCELOTS_AUTH_TOKEN"
[1]: http://iocelots.com 'iocelots'
[2]: https://code.google.com/apis/console#access "Google API console"
Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.0 KiB

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

+5 -2
View File
@@ -5,8 +5,11 @@ $ ->
beforeSubmit: ->
if $('.message-body').val().replace(/\s+/, "") == ""
false
success: (data) ->
$('.message-list').prepend(data)
$('.submit-mess').click ->
$('.form-inline').ajaxSubmit options
pusher = new Pusher $('#pusher_key').val()
channel = pusher.subscribe $('#team_slug').val()
channel.bind 'new_message', (data) ->
$('.message-list').prepend(data.content).show('slow')
@@ -18,46 +18,4 @@ $ ->
$('.fancybox').fancybox()
$('#view_map').each ->
lat = $(this).data('lat')
lng = $(this).data('lng')
map_options = {
center: new google.maps.LatLng(lat, lng),
zoom: 8,
mapTypeId: google.maps.MapTypeId.ROADMAP
}
map = new google.maps.Map(this, map_options)
marker_options = {
position: new google.maps.LatLng(lat, lng),
map: map
}
marker = new google.maps.Marker(marker_options)
$("#map_canvas").each ->
lat = parseFloat($('#person_lat').val()) || -34.397
lng = parseFloat($('#person_lng').val()) || 150.644
map_options = {
center: new google.maps.LatLng(lat, lng),
zoom: 8,
mapTypeId: google.maps.MapTypeId.ROADMAP
}
map = new google.maps.Map(this, map_options)
marker_options = {
draggable: true,
position: new google.maps.LatLng(lat, lng),
map: map
}
marker = new google.maps.Marker(marker_options)
google.maps.event.addListener marker, 'dragend', (event) ->
point = marker.getPosition()
$('#person_lat').val point.lat()
$('#person_lng').val point.lng()
@@ -0,0 +1,43 @@
$ ->
geocoder = null
map = null
marker = null
$("#map_canvas").each ->
geocoder = new google.maps.Geocoder()
lat = parseFloat($('#person_lat').val()) || -34.397
lng = parseFloat($('#person_lng').val()) || 150.644
latlng = new google.maps.LatLng(lat, lng)
mapOptions = {
zoom: 8
center: latlng
mapTypeId: google.maps.MapTypeId.ROADMAP
}
map = new google.maps.Map(document.getElementById("map_canvas"), mapOptions);
marker_options = {
draggable: true,
position: new google.maps.LatLng(lat, lng),
map: map
}
marker = new google.maps.Marker(marker_options)
google.maps.event.addListener marker, 'dragend', (event) ->
point = marker.getPosition()
$('#person_lat').val point.lat()
$('#person_lng').val point.lng()
$("#address_btn").live "click", (e) ->
address = $("#address").val()
geocoder.geocode { 'address': address}, (results, status) ->
if (status == google.maps.GeocoderStatus.OK)
map.setCenter(results[0].geometry.location)
marker.setMap null
marker = new google.maps.Marker {
map: map,
position: results[0].geometry.location
}
$('#person_lat').val(results[0].geometry.location.$a)
$('#person_lng').val(results[0].geometry.location.ab)
$('.error_maps').addClass 'hidden'
else
$('.error_maps').removeClass 'hidden'
false
@@ -0,0 +1,72 @@
$ ->
getCallback = () ->
switch (window.location.hostname)
when "127.0.0.1" then "http://127.0.0.1:3000/soundcloud_oauth_callback.html"
when "ocelots-staging.herokuapp.com" then "http://ocelots-staging.herokuapp.com/soundcloud_oauth_callback.html"
when "iocelots.com" then "http://iocelots.com/soundcloud_oauth_callback.html"
getClientID = () ->
switch (window.location.hostname)
when "127.0.0.1" then "ee3d987c0fa30e22edd251a7bd046851"
when "ocelots-staging.herokuapp.com" then "40d2c306162dcea94436672679aa6c25"
when "iocelots.com" then "bdb756070f00205c76a9563eafe8ca09"
SC.initialize {
client_id: getClientID()
redirect_uri: getCallback()
}
$("#recorderUI.reset #controlButton").live "click", (e) ->
updateTimer 0
SC.record {
start:() ->
setRecorderUIState("recording")
$('#timer').removeClass("hidden")
progress: (ms, avgPeak) ->
updateTimer ms
}
e.preventDefault
$("#recorderUI.recording #controlButton, #recorderUI.playing #controlButton").live "click", (e) ->
setRecorderUIState "recorded"
SC.recordStop()
e.preventDefault
$("#recorderUI.recorded #controlButton").live "click", (e) ->
updateTimer 0
setRecorderUIState "playing"
SC.recordPlay {
progress: (ms) ->
updateTimer ms
finished: () ->
setRecorderUIState "recorded"
}
e.preventDefault
$("#reset").live "click", (e) ->
SC.recordStop
setRecorderUIState "reset"
e.preventDefault
$("#upload").live "click", (e) ->
setRecorderUIState "uploading"
SC.connect {
connected: () ->
$("#uploadStatus").html "Uploading..."
SC.recordUpload {
track: {
title: $('#full_name').val() + ".voice",
sharing: "public"
}
}, (track) ->
$("#uploadStatus").html("Upload Success!<br>Please update your profile");
$('#track').val(track.id)
$('#secret').val(track.secret_token)
}
e.preventDefault
updateTimer = (ms) ->
$("#timer").text(SC.Helper.millisecondsToHMS(ms))
setRecorderUIState = (state) ->
$("#recorderUI").attr("class", state)
+17
View File
@@ -0,0 +1,17 @@
$ ->
$('#show-filter').keyup (event) ->
switch event.which
when 27 then $('#show-filter').val('')
toggle_hidden_by_search($('#show-filter').val())
toggle_hidden_by_search = (str) ->
reg = new RegExp(str, 'i')
$('.team_name').each (j, v)->
if $(v).text().search(reg) + 1
$(v).parent().parent().parent().parent().removeClass("hidden")
else
$(v).parent().parent().parent().parent().addClass("hidden")
$('#show-filter').keydown (event) ->
event.preventDefault() if event.which == 13
+20 -2
View File
@@ -4,6 +4,7 @@ $ ->
$(selector).removeClass("hidden")
else
$(selector).addClass("hidden")
toggle_hidden_by_search($('#show-filter').val())
$('#show-past').change -> toggle_hidden(this.checked, '.past')
$('#show-current').change -> toggle_hidden(this.checked, '.current')
@@ -13,8 +14,20 @@ $ ->
$('#show-filter').keyup (event) ->
switch event.which
when 27 then $('#show-filter').val('')
toggle_hidden_by_search($('#show-filter').val())
$('#show-filter').keydown (event) -> event.preventDefault() if event.which == 13
toggle_hidden_by_search = (str) ->
reg = new RegExp(str, 'i')
$('.team-fliter input:checked').next().each (i, e) ->
$('.' + $(e).text() + ' .full-name').each (j, v)->
if $(v).text().search(reg) + 1
$(v).parent().parent().parent().removeClass("hidden")
else
$(v).parent().parent().parent().addClass("hidden")
$('#show-filter').keydown (event) ->
event.preventDefault() if event.which == 13
$('#add_new').click ->
$('.team-content').hide 'slow'
@@ -40,6 +53,11 @@ $ ->
setTimeout ()->
node.hide('slow').remove()
,4000
error: ->
node = $('<div></div>').addClass('alert').addClass('alert-error').text 'Sorry,there are some errors occured.'
node.insertBefore('p.alert.alert-info')
setTimeout ()->
node.hide('slow').remove()
,4000
$('.do-add').click ->
$('.add-member-form').ajaxSubmit options
+50 -15
View File
@@ -1,22 +1,11 @@
body {
//background:url('/assets/paper.jpg');
background:url('/assets/paper.jpg');
padding-top: 60px;
padding-bottom: 40px;
}
/*
.highlight {
-webkit-transition: all 1s ease;
-moz-transition: all 1s ease;
-o-transition: all 1s ease;
color: #333;
text-shadow: white 0 1px 0;
font-weight: 100;
}
*/
//.highlight:hover {
// background: #ccc;
// text-decoration: none;
//}
.correct {
background: #090 !important;
@@ -77,4 +66,50 @@ body {
.url-font{
color:#777;
font-weight: bold;
}
}
.avatar-image{
border-radius: 150px;
box-shadow: 0 0 15px #333;
transition:transform 2s;
-moz-transition:-moz-transform 2s;
-webkit-transition:-webkit-transform 2s;
-o-transition:-o-transform 2s;
}
.avatar-image:hover{
transform:rotate(36deg);
-moz-transform:rotate(360deg);
-webkit-transform:rotate(360deg);
-o-transform:rotate(360deg);
}
.join-status-button{
float: left;
margin-left: 36px;
margin-top: 17px;
}
.team-fliter{
margin-left: -29px;
}
.full-name{
}
.sexy-bg{
background: rgba(255,255,255,0.13);
-webkit-box-shadow: 0 0 15px rgba(8, 8, 8, 0.7);
}
.image-gray{
filter: url(filters.svg#grayscale);
filter: gray;
-webkit-filter: grayscale(1);
}
.avatar-img{
margin-right:8px;
}
+94
View File
@@ -0,0 +1,94 @@
.exampleSource {
display: none;
}
#left, #right {
width: 45%;
float: left;
}
#right {
width: 40%;
padding-left: 30px;
margin-left: 30px;
border-left: 1px solid #eee;
}
#right pre {
overflow: scroll;
}
.example {
border-top: 1px solid #eee;
padding-top: 30px;
width: 100%;
}
.big.button {
width: 100%;
margin-bottom: 30px;
padding: 0 0;
}
.fullWidth {
width: 100%;
}
.tab-ui a {
color: black;
}
.tab-ui li.current a {
color: #F60;
}
#recorderUI {
width: 182px;
margin: 0;
}
#recorderUI #timer {
font-weight: bold;
font-size: 10px;
color: #333;
line-height: 60px;
width: 100%;
text-align: center;
display: none;
}
#recorderUI.recording #timer, #recorderUI.playing #timer {
display: block;
}
#recorderUI #otherControls {
display: none;
}
#recorderUI.playing #otherControls, #recorderUI.recorded #otherControls {
display: block;
margin-left: 38px;
}
#reset, #upload {
width: 50px;
margin: 5px;
}
#otherControls {
clear: both;
}
#controlButton { margin: auto !important; padding: 0 !important; border: 0 !important; -moz-border-radius: 0; -webkit-border-radius: 0; -o-border-radius: 0; -ms-border-radius: 0; border-radius: 0; -webkit-transition: none; -moz-transition: none; -o-transition: none; transition: none; display: block; width: 60px; height: 60px; background-color: transparent !important; background-image: url(rec_button_large.png) !important; background-position: 0 0; }
#recorderUI.recording #controlButton, #recorderUI.playing #controlButton {
background-position: 0 -60px;
}
#recorderUI.recorded #controlButton { background-position: 0 -120px; }
#controlButton.pause { background-position: 0 -180px; }
+5 -1
View File
@@ -1,4 +1,5 @@
require 'team_filter'
require 'pusher'
class AntechamberController < ApplicationController
include TeamFilter
@@ -12,7 +13,10 @@ class AntechamberController < ApplicationController
def create
with_team do |team|
message = Message.create team: team, person: current_person, content: params[:content]
render partial: 'shared/one_message', locals: {message: message}
Pusher.trigger(team.slug, 'new_message',{content:render_to_string( partial: 'shared/one_message', locals: {message: message})})
render text:'ok'
end
end
+2 -2
View File
@@ -1,7 +1,7 @@
require 'soundcloud'
require 'soundcloudvalidate'
class MembershipController < ApplicationController
include Soundcloud
include Soundcloudvalidate
def accept_invitation
membership = Membership.find_by_pending_approval_token params[:token]
+2 -2
View File
@@ -1,7 +1,7 @@
require 'soundcloud'
require 'soundcloudvalidate'
class ProfileController < ApplicationController
include Soundcloud
include Soundcloudvalidate
before_filter :current_person
def update
+15 -5
View File
@@ -5,13 +5,17 @@ class TeamsController < ApplicationController
include TeamFilter
def index
@memberships = current_person.memberships.select { |membership| membership.ended==nil }
@memberships = current_person.memberships.select { |membership| membership.ended==nil }.sort_by {|mem| mem.team_name.downcase}
if params[:sortby]== 'CreateDate'
@memberships = @memberships.sort_by {|mem| mem.id}
@sortby = params[:sortby]
end
@team = Team.new
@organisations = Organisation.find(:all)
@view_membership = current_person.viewable_teams
end
def create
@teams = current_person.teams
@team = Team.new params[:team].merge creator: current_person
if @team.save
@@ -23,6 +27,8 @@ class TeamsController < ApplicationController
redirect_to "/teams/#{@team.slug}"
else
@memberships = current_person.memberships
@view_membership = current_person.viewable_teams
render :index
end
end
@@ -55,9 +61,13 @@ class TeamsController < ApplicationController
def quiz
with_team do |team|
@people = team.people.sample 5
@person = @people.sample
@facts = @person.facts.sample 3
render :quiz
@person = team.people.select {|person| !person.facts.empty?}.sample
if @person
@facts = @person.facts.sample 3
render :quiz
else
render :nofacts
end
end
end
+1 -1
View File
@@ -1,6 +1,6 @@
module ApplicationHelper
def image_for person
image_tag person.photo? ? person.photo.url(:square) : person.gravatar_url
image_tag person.photo? ? person.photo.url(:square) : person.gravatar_url ,class:'avatar-image'
end
def phone_link_to phone
+1 -1
View File
@@ -13,7 +13,7 @@ class Person < ActiveRecord::Base
attr_accessible :photo, :phone
attr_accessible :url, :twitter, :facebook, :weibo, :appnet, :github ,:flickr
attr_accessible :lat, :lng
attr_accessible :show_avatar
attr_accessible :job_title, :track, :secret, :show_avatar
validates_uniqueness_of :account
+7
View File
@@ -4,6 +4,7 @@ class Team < ActiveRecord::Base
validates_presence_of :name
validates_presence_of :slug
validates_uniqueness_of :slug
validate :format_slug ,:on => :create
has_many :memberships
has_many :people, through: :memberships
@@ -26,4 +27,10 @@ class Team < ActiveRecord::Base
def add_to (organisation)
organisations << organisation if organisation
end
def format_slug
slug.gsub!(/ /, "_") if slug
end
end
+6 -2
View File
@@ -1,11 +1,15 @@
- content_for :javascript_includes do
= javascript_include_tag 'antechamber'
= javascript_include_tag '/jquery.form.js'
= javascript_include_tag 'http://js.pusher.com/1.12/pusher.min.js'
= javascript_include_tag 'antechamber'
= render partial: 'shared/team_menu_items'
h1 = @team.name
form.form-inline action="/antechamber/#{@team.slug}"
p #{text_area_tag :content, nil, placeholder: 'Enter Message', rows: 4,class:'message-body'}
input type="hidden" id="pusher_key" value="#{ENV['PUSHER_KEY']}"
input type="hidden" id="team_slug" value="#{@team.slug}"
p #{text_area_tag :content, nil, placeholder: 'Enter Message', rows: 4 ,class:'message-body',style:"width:30%"}
a.btn.submit-mess Send
div.message-list
+1 -1
View File
@@ -9,6 +9,7 @@ html
= stylesheet_link_tag '/fancyapps-fancyBox-2bb0da9/source/jquery.fancybox.css'
= csrf_meta_tags
= javascript_include_tag '/ga.js'
= yield :style_includes
body
@@ -31,6 +32,5 @@ html
= javascript_include_tag 'application'
= javascript_include_tag '/bootstrap/js/bootstrap.min.js'
= javascript_include_tag '/fancyapps-fancyBox-2bb0da9/source/jquery.fancybox.pack.js'
= javascript_include_tag "http://maps.googleapis.com/maps/api/js?key=#{ENV['GOOGLE_API']}&sensor=false"
= yield :javascript_includes
= javascript_include_tag '/uservoice.js'
+35 -11
View File
@@ -1,7 +1,13 @@
- content_for :javascript_includes do
= javascript_include_tag 'profile'
= javascript_include_tag 'soundcloud'
= javascript_include_tag 'https://connect.soundcloud.com/sdk.js'
= javascript_include_tag "http://maps.googleapis.com/maps/api/js?key=#{ENV['GOOGLE_API']}&sensor=false"
= javascript_include_tag 'google_map'
- content_for :style_includes do
= stylesheet_link_tag 'soundcloud'
div.hero-unit.highlight
div.hero-unit.highlight.sexy-bg
div.row
div.span4
a href="/profiles/#{@current_person.account}"
@@ -34,6 +40,10 @@ h1 Edit
label.control-label for="photo" Photo
div.controls
= form.file_field :photo
div.controls style="margin-top:8px;"
span Or Set Your
span &nbsp;
a href="http://en.gravatar.com/" target="_blank" Gravatar
div.control-group
label.control-label for="person_account" Profile
div.controls
@@ -45,7 +55,7 @@ h1 Edit
div.control-group
label.control-label for="person_full_name" Full Name
div.controls
= form.text_field :full_name
= form.text_field :full_name, id: "full_name"
div.control-group
label.control-label for="person_chinese_name" Chinese Name
div.controls
@@ -59,17 +69,29 @@ h1 Edit
div.controls
= form.text_field :preferred_name
div.control-group
label.control-label for="person_sc_embed_code" Soundcloud embed code
label.control-label for="person_sc_embed_code" Record Your Voice
div.controls
= text_field_tag :sc_embed_code, nil
= form.text_field :track, id:'track', type:'hidden'
= form.text_field :secret, id:'secret', type:'hidden'
div id="recorderUI" class="reset"
a href="#" id="controlButton" class="record"
span id="timer" class="hidden" 0:00
div id="otherControls"
a href="#" id="reset" class="button" Reset
a href="#" id="upload" class="button" Upload
div id="uploadStatus"
div.control-group
label.control-label for="person_phone" Phone
div.controls
= form.text_field :phone
div.control-group
label.control-label for="person_phone" Job Title
div.controls
= form.text_field :job_title
div.control-group
label.control-label for="person_url" Personal site
div.controls
p #{form.text_field :url,placeholder:'Need http://'}
p #{form.text_field :url,placeholder:'Without http://'}
div.control-group
label.control-label for="person_twitter" Twitter
div.controls
@@ -104,7 +126,7 @@ h1 Edit
div.control-group
label.control-label for="person_appnet" Appnet Preview
div.controls.url-font
span http://alpha.appnet.com/
span http://alpha.app.net/
span.appnet-preview #{@current_person.appnet}
div.control-group
label.control-label for="person_github" Github
@@ -122,14 +144,16 @@ h1 Edit
div.control-group
label.control-label for="person_flickr" Flickr Preview
div.controls.url-font
span http://flickr.com/
span http://flickr.com/photos/
span.flickr-preview #{@current_person.flickr}
div.control-group
label.control-label for="lat" Birthplace
label.control-label for="lat" Location
div.controls
div.label.label-info Please move the pin to choose your location.
p #{form.text_field :lat,:type => 'hidden'} #{form.text_field :lng,:type=> 'hidden'}
div id="map_canvas" style="width: 600px; height: 300px;"
input#address type="text"
button#address_btn style='margin-left:1em' Search
p #{form.text_field :lat,:type => 'hidden', :id => 'person_lat'} #{form.text_field :lng,:type=> 'hidden', :id => 'person_lng'}
div.error_maps.alert.alert-error.hidden style="color:red;margin-left: 13em" The place you just searched does not exist.
div id="map_canvas" style="width: 600px; height: 300px;margin-left: 13em"
div.form-actions
= form.submit 'Update Profile', class: 'btn btn-primary'
div.control-group
+10 -9
View File
@@ -1,20 +1,21 @@
div.hero-unit
- content_for :javascript_includes do
= javascript_include_tag "http://maps.googleapis.com/maps/api/js?key=#{ENV['GOOGLE_API']}&sensor=false"
div.hero-unit.sexy-bg
div.row.person
div.span4
=image_for @person
div.span4
div.span4 style="margin-top:0px"
= render partial: 'shared/person', locals: {person: @person}
p
= phone_link_to @person.phone
= render partial: 'shared/person_social_media', locals: {person: @person}
blockquote
ul.unstyled
- @person.facts.each do |fact|
li
p I #{fact.content}
div.span2
h2 Facts:
ul
- @person.facts.each do |fact|
li
p I #{fact.content}
- if @person.lat and @person.lng
div.row
+2 -1
View File
@@ -1,4 +1,4 @@
h1 = person.full_name
h1.full-name = person.full_name
- if person.chinese_name
h1 = person.chinese_name
@@ -10,4 +10,5 @@ h1 = person.full_name
h2
i = person.preferred_name
i style="font-size:1.2em" = person.job_title
p = person.email
+38 -21
View File
@@ -1,22 +1,39 @@
div.social_media
- unless person.url.blank?
a href="http://#{person.url}"
img src='/assets/url.png'
- unless person.twitter.blank?
a href="http://twitter.com/#{person.twitter}"
img src='/assets/twitter.png'
- unless person.facebook.blank?
a href="http://www.facebook.com/#{person.facebook}"
img src='/assets/facebook.png'
- unless person.weibo.blank?
a href="http://weibo.com/#{person.weibo}"
img src='/assets/weibo-1.png'
- unless person.appnet.blank?
a href="http://alpha.app.net/#{person.appnet}"
img src='/assets/appnet.png'
- unless person.github.blank?
a href="http://github.com/#{person.github}"
img src='/assets/github.png'
- unless person.flickr.blank?
a href="http://flickr.com/photos/#{person.flickr}"
img src='/assets/flickr.png'
- if person.url.blank?
img.image-gray.avatar-img src='/assets/url.png'
- else
a href="http://#{person.url}"
img.avatar-img src='/assets/url.png'
- if person.twitter.blank?
img.image-gray.avatar-img src='/assets/twitter.png'
-else
a href="http://twitter.com/#{person.twitter}"
img.avatar-img src='/assets/twitter.png'
- if person.facebook.blank?
img.image-gray.avatar-img src='/assets/facebook.png'
-else
a href="http://www.facebook.com/#{person.facebook}"
img.avatar-img src='/assets/facebook.png'
- if person.weibo.blank?
img.image-gray src='/assets/weibo-1.png'
-else
a href="http://weibo.com/#{person.weibo}"
img.avatar-img src='/assets/weibo-1.png'
- if person.appnet.blank?
img.image-gray.avatar-img src='/assets/appnet.png'
-else
a href="http://alpha.app.net/#{person.appnet}"
img.avatar-img src='/assets/appnet.png'
- if person.github.blank?
img.image-gray.avatar-img src='/assets/github.png'
-else
a href="http://github.com/#{person.github}"
img.avatar-img src='/assets/github.png'
- if person.flickr.blank?
img.image-gray.avatar-img src='/assets/flickr.png'
-else
a href="http://flickr.com/photos/#{person.flickr}"
img.avatar-img src='/assets/flickr.png'
div.clear
p
@@ -1 +1 @@
iframe height="166" scrolling="no" frameborder="no" src="http://w.soundcloud.com/player/?url=http%3A%2F%2Fapi.soundcloud.com%2Ftracks%2F#{object.track}%3F#{object.secret ? "secret_token%3D#{object.secret}" : ''}&amp;auto_play=false&amp;show_artwork=false&amp;color=ff7700"
iframe height="166" scrolling="no" frameborder="no" src="https://w.soundcloud.com/player/?url=http%3A%2F%2Fapi.soundcloud.com%2Ftracks%2F#{object.track}%3F#{object.secret ? "secret_token%3D#{object.secret}" : ''}&amp;auto_play=false&amp;show_artwork=false&amp;color=ff7700"
@@ -1,4 +1,4 @@
div.hero-unit.highlight class="#{membership.status}"
div.hero-unit.highlight.sexy-bg class="#{membership.status}"
div.row
div.span4
a href="/profiles/#{membership.account}"
@@ -1,4 +1,4 @@
div.hero-unit.pending.hidden
div.hero-unit.pending.hidden.sexy-bg
div.row.person
div.span4
img src="/assets/silhouette.png" width=300
+4 -3
View File
@@ -1,6 +1,7 @@
- @team.people.each do |person|
div.avatar
a href="/profiles/#{person.account}" target="_blank"
=image_for person
h2 #{person.full_name}
- if person.preferred_name
p #{person.preferred_name}
h2 #{person.full_name}
- if person.job_title
i #{person.job_title}
+15 -3
View File
@@ -1,3 +1,5 @@
- content_for :javascript_includes do
= javascript_include_tag 'teams'
- content_for :menu_items do
li
= link_to 'add team', '#add_new', class: 'fancybox'
@@ -16,6 +18,16 @@ div id="add_new" style="display:none;"
div.form-actions
= form.submit 'Create', class: 'btn'
div style="overflow:hidden;margin-bottom:1em"
div.btn-group style="float:left;"
-if @sortby
a.btn href='/teams' Team Name
a.btn.btn-primary href='/teams?sortby=CreateDate' Create Date
-else
a.btn.btn-primary href='/teams' Team Name
a.btn href='/teams?sortby=CreateDate' Create Date
div.btn-group style="float:right;"
input.span2.search-query id="show-filter" type="text" placeholder="search"
- @memberships.each do |membership|
a href="/teams/#{membership.team_slug}"
@@ -24,7 +36,7 @@ div id="add_new" style="display:none;"
div.span4
img src="/assets/team.png"
div.span4
h1 = membership.team_name
h1.team_name = membership.team_name
p = membership.team_description
div.span1
- if membership.pending?
@@ -41,14 +53,14 @@ div.clearfix
div style="margin-top:-30px"
h3 style="text-align:center" Viewable Teams
hr style="margin-top:-30px"
- current_person.viewable_teams.each do |team|
- @view_membership.each do |team|
a href="/teams/#{team.slug}"
div.hero-unit.highlight.viewable-team
div.row
div.span4
img src="/assets/team.png"
div.span4
h1 = team.name
h1.team_name = team.name
p = team.description
div.span1
div.span1 style="margin:60px 0 0 65px"
+7
View File
@@ -0,0 +1,7 @@
= render partial: 'shared/team_menu_items'
div.row
div.span4.offset4
div.alert.alert-block
strong Sorry!
p The people of this team do not seem to have a fact
+2 -1
View File
@@ -1,11 +1,12 @@
= render partial: 'shared/team_menu_items'
h1 I have some facts:
ul
- @facts.each do |fact|
li
h3 = 'I ' + fact.content
h1 am i ...
h1 Guess who am I ...
- @people.each do |person|
a.quiz href="#" data-correct="#{person == @person ? 'true' : 'false'}"
+14 -9
View File
@@ -15,16 +15,18 @@
div.team-content
h1 = @team.name
h1 style="float:left;" = @team.name
- if current_person.approved_teams.include? @team
=form_tag "/teams/#{@team.slug}/quit" do
=submit_tag 'Quit Team',id:"join-team",class:"btn btn-danger "
-else
=form_tag "/teams/#{@team.slug}/join" do
=submit_tag 'Join Team',id:"join-team",class:"btn btn-primary "
div.join-status-button
- if current_person.approved_teams.include? @team
=form_tag "/teams/#{@team.slug}/quit" do
=submit_tag 'Quit Team',id:"join-team",class:"btn btn-danger "
-else
=form_tag "/teams/#{@team.slug}/join" do
=submit_tag 'Join Team',id:"join-team",class:"btn btn-primary "
p
form.form-inline
div.clear
form.form-inline.team-fliter
label.span1.checkbox
input type="checkbox" id="show-past"
span past
@@ -37,7 +39,10 @@ div.team-content
label.span1.checkbox
input type="checkbox" id="show-pending"
span pending
input.span2.search-query id="show-filter" type="text" placeholder="search"
input.span2.search-query id="show-filter" type="text" placeholder="search" style="float:right;margin-bottom: 10px;margin-right: 10px;"
div.clear
- @team.memberships.each do |membership|
= render partial: membership_partial(membership), locals: {membership: membership, current_person: @current_person}
+10
View File
@@ -1,3 +1,5 @@
require 'pusher'
Ocelots::Application.configure do
# Settings specified here will take precedence over those in config/application.rb
@@ -34,6 +36,10 @@ Ocelots::Application.configure do
# Expands the lines which load the assets
config.assets.debug = true
#config.threadsafe! enables allow_concurrency, cache_classes, dependency_loading and preload_frameworks to make the application threadsafe.
config.threadsafe!
# paperclip will save to public/system/[object] when running local
if(ENV['S3_BUCKET'].nil?)
config.paperclip_storage_options = {}
@@ -49,4 +55,8 @@ Ocelots::Application.configure do
path: "/development/:persona_id/photos/:style/:basename.:extension"
}
end
Pusher.app_id = ENV['PUSHER_APP_ID']
Pusher.key = ENV['PUSHER_KEY']
Pusher.secret = ENV['PUSHER_SECRET']
end
+4 -1
View File
@@ -47,7 +47,7 @@ Ocelots::Application.configure do
# Precompile additional assets (application.js, application.css, and all non-JS/CSS are already added)
config.assets.precompile << '*.js'
config.assets.precompile += %w( style.css )
config.assets.precompile << '*.css'
# Disable delivery errors, bad email addresses will be ignored
# config.action_mailer.raise_delivery_errors = false
@@ -62,6 +62,9 @@ Ocelots::Application.configure do
# Send deprecation notices to registered listeners
config.active_support.deprecation = :notify
#config.threadsafe! enables allow_concurrency, cache_classes, dependency_loading and preload_frameworks to make the application threadsafe.
config.threadsafe!
# Log the query plan for queries taking more than this (works
# with SQLite, MySQL, and PostgreSQL)
# config.active_record.auto_explain_threshold_in_seconds = 0.5
@@ -0,0 +1,5 @@
class AddJobTitleToPeople < ActiveRecord::Migration
def change
add_column :people ,:job_title , :string
end
end
+2 -1
View File
@@ -11,7 +11,7 @@
#
# It's strongly recommended to check this file into your version control system.
ActiveRecord::Schema.define(:version => 20121121081226) do
ActiveRecord::Schema.define(:version => 20121204070333) do
create_table "engagements", :force => true do |t|
t.integer "organisation_id"
@@ -81,6 +81,7 @@ ActiveRecord::Schema.define(:version => 20121121081226) do
t.float "lng"
t.boolean "show_avatar", :default => true
t.string "flickr"
t.string "job_title"
end
create_table "teams", :force => true do |t|
@@ -1,4 +1,4 @@
module Soundcloud
module Soundcloudvalidate
def process_sc_embed_code object, owner
return unless object
return unless owner == current_person
+1 -1
View File
@@ -1,6 +1,6 @@
module TeamFilter
def with_team
@team = Team.find_by_slug params[:slug]
@team = Team.find_by_slug params[:slug]
unless current_person.allowed_to_view_team?(@team)
@team = nil
end
+9
View File
@@ -0,0 +1,9 @@
<!DOCTYPE html>
<html lang="en">
<head><meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Connect with SoundCloud</title>
</head>
<body onload="window.opener.setTimeout(window.opener.SC.connectCallback, 1)">
<b style="width: 100%; text-align: center;">This popup should automatically close in a few seconds</b>
</body>
</html>
+42 -1
View File
@@ -11,15 +11,25 @@ describe TeamsController do
describe :index do
it 'fetches all organisations' do
@person.teams.create(name: 'IBM', slug: 'IBM')
get :index
all_organisations = assigns[:organisations]
all_organisations.should_not be_nil
all_organisations.should_not be_empty
all_memberships = assigns[:memberships]
all_memberships[0].team_name.should <= all_memberships[1].team_name
end
it 'fetches teams which sort by create date' do
@person.teams.create(name: 'IBM', slug: 'ibm')
get :index, sortby: 'CreateDate'
all_memberships = assigns[:memberships]
all_memberships[0].team_name.should_not <= all_memberships[1].team_name
assigns[:sortby].should == 'CreateDate'
end
end
describe :show do
it 'shows selected team' do
get :show, :slug => @team.slug
response.should be_success
@@ -54,6 +64,22 @@ describe TeamsController do
new_team.name.should == 'CDI'
new_team.organisations.first.should == @organisation
end
it 'not create team with null name' do
lambda do
post :create, team: {name: nil, slug: 'cdi'}, org_ids: [@organisation.id.to_s]
end.should_not change(Team, :count)
assigns(:memberships).should_not be_nil
end
it 'not create team with null name' do
lambda do
post :create, team: {name: 'CDI', slug: nil}, org_ids: [@organisation.id.to_s]
end.should_not change(Team, :count)
assigns(:memberships).should_not be_nil
assigns[:view_membership].should_not be_nil
end
end
describe :join do
@@ -131,4 +157,19 @@ describe TeamsController do
response.body.should be_include('failed')
end
end
describe :quiz do
it 'ensure select a person with facts' do
@person.facts.create(content: "I like food")
get :quiz, :slug => @team.slug
response.should render_template('quiz')
assigns(:people).should_not be_empty
assigns(:facts).should_not be_empty
end
it 'ensure show nofacts page when people who in a team have not a fact' do
get :quiz, :slug => @team.slug
response.should render_template('nofacts')
end
end
end
+8 -1
View File
@@ -29,7 +29,7 @@ describe Membership do
end.should change(Membership, :count).by(1)
end
it 'ensure do not invite someone who has a pending membership with a team' do
it 'ensure do not invite someone who joined that team' do
@invitee.teams << @team
lambda do
Membership.create_pending_membership(@inviter, @invitee, @team)
@@ -41,5 +41,12 @@ describe Membership do
Membership.create_pending_membership(@inviter, @inviter, @team)
end.should_not change(Membership, :count)
end
it 'ensure do not invite someone more than once' do
Membership.create team: @team, person: @invitee,pending_approval_token: uuid
lambda do
Membership.create_pending_membership(@inviter, @invitee, @team)
end.should_not change(Membership, :count)
end
end
end
-6
View File
@@ -103,12 +103,6 @@ describe Person do
person.organisation.name.should == tw.name
end
#it 'ensure return the accurate orgisation by email when some orgisation has several domains' do
# tw = Organisation.create(name: 'ThoughtWorks',domains:'thoughtworks.com,tw.com')
# person = Person.create_for_email('test@thoughtworks.com')
# person.get_organisation_by_email.name.should == tw.name
#end
end
describe :refresh_auth_token do
+10
View File
@@ -19,4 +19,14 @@ describe Team do
end
describe 'create team' do
it 'ensure when create a team,if team"s slug has blanks, it will be format to url string "' do
@person = Person.create_for_email 'test@thoughworks.com'
@team = @person.teams.create(name: 'LSP', slug: 'l s p')
@team.slug.should == 'l_s_p'
end
end
end