Commit d1805ee0 by tady

Merge branch 'master' into imagemagick-pdf-slice

Conflicts:
	Gemfile
parents 0892400f 22e5e7ca
......@@ -2,7 +2,6 @@ bundler_args: "--without development --path=~/.bundle"
language: ruby
rvm:
- 2.1.2
- 2.0.0
env:
matrix:
- DB_TEST_DATABASE=rendezvous_test DB_TEST_USER=travis
......
......@@ -4,7 +4,7 @@ source 'https://rubygems.org'
gem 'rails', '~> 4.1'
# Use SCSS for stylesheets
gem 'sass-rails'
gem 'sass-rails', github: 'rails/sass-rails'
# Use Uglifier as compressor for JavaScript assets
gem 'uglifier'
......@@ -141,4 +141,11 @@ gem 'kaminari', github: 'amatsuda/kaminari'
gem 'jwt', '0.1.11'
# Optional
# For notifing to HipChat
gem 'hipchat'
# For PDF upload
gem 'rmagick', :require => 'RMagick'
GIT
remote: git://github.com/amatsuda/kaminari.git
revision: 21ad994d42527fd97c8168b0d0ccdd88cec91251
revision: 5b221e01ea63852a3894c6b0c3c6de50cdace27a
specs:
kaminari (0.15.1)
kaminari (1.0.0.alpha)
actionpack (>= 3.0.0)
activesupport (>= 3.0.0)
......@@ -15,30 +15,40 @@ GIT
activesupport
gmail_xoauth
GIT
remote: git://github.com/rails/sass-rails.git
revision: 57ec3397ff99655890895df29a7bf3f683410256
specs:
sass-rails (5.0.0.dev)
railties (>= 4.0.0, < 5.0)
sass (~> 3.2)
sprockets (~> 2.12)
sprockets-rails (~> 2.0)
GEM
remote: https://rubygems.org/
specs:
actionmailer (4.1.0)
actionpack (= 4.1.0)
actionview (= 4.1.0)
actionmailer (4.1.4)
actionpack (= 4.1.4)
actionview (= 4.1.4)
mail (~> 2.5.4)
actionpack (4.1.0)
actionview (= 4.1.0)
activesupport (= 4.1.0)
actionpack (4.1.4)
actionview (= 4.1.4)
activesupport (= 4.1.4)
rack (~> 1.5.2)
rack-test (~> 0.6.2)
actionview (4.1.0)
activesupport (= 4.1.0)
actionview (4.1.4)
activesupport (= 4.1.4)
builder (~> 3.1)
erubis (~> 2.7.0)
activemodel (4.1.0)
activesupport (= 4.1.0)
activemodel (4.1.4)
activesupport (= 4.1.4)
builder (~> 3.1)
activerecord (4.1.0)
activemodel (= 4.1.0)
activesupport (= 4.1.0)
activerecord (4.1.4)
activemodel (= 4.1.4)
activesupport (= 4.1.4)
arel (~> 5.0.0)
activesupport (4.1.0)
activesupport (4.1.4)
i18n (~> 0.6, >= 0.6.9)
json (~> 1.7, >= 1.7.7)
minitest (~> 5.1)
......@@ -142,7 +152,7 @@ GEM
formatador (0.2.5)
gherkin (2.12.2)
multi_json (~> 1.3)
github-markdown (0.6.5)
github-markdown (0.6.6)
gmail_xoauth (0.4.1)
oauth (>= 0.3.6)
guard (2.6.1)
......@@ -151,7 +161,7 @@ GEM
lumberjack (~> 1.0)
pry (>= 0.9.12)
thor (>= 0.18.1)
guard-rspec (4.2.10)
guard-rspec (4.3.1)
guard (~> 2.1)
rspec (>= 2.14, < 4.0)
guard-rubocop (1.1.0)
......@@ -162,9 +172,14 @@ GEM
teaspoon (>= 0.8.0)
hashie (3.2.0)
hike (1.2.3)
hipchat (1.2.0)
httparty
htmlentities (4.3.2)
http-cookie (1.0.2)
domain_name (~> 0.5)
httparty (0.13.1)
json (~> 1.8)
multi_xml (>= 0.5.2)
i18n (0.6.11)
i18n_generators (1.2.1)
mechanize
......@@ -213,8 +228,8 @@ GEM
net-ssh (>= 2.6.5)
net-ssh (2.9.1)
netrc (0.7.7)
newrelic_rpm (3.9.0.229)
nokogiri (1.6.2.1)
newrelic_rpm (3.9.1.236)
nokogiri (1.6.3.1)
mini_portile (= 0.6.0)
ntlm-http (0.1.1)
oauth (0.4.7)
......@@ -263,19 +278,19 @@ GEM
rack (>= 1.1.3)
rack-test (0.6.2)
rack (>= 1.0)
rails (4.1.0)
actionmailer (= 4.1.0)
actionpack (= 4.1.0)
actionview (= 4.1.0)
activemodel (= 4.1.0)
activerecord (= 4.1.0)
activesupport (= 4.1.0)
rails (4.1.4)
actionmailer (= 4.1.4)
actionpack (= 4.1.4)
actionview (= 4.1.4)
activemodel (= 4.1.4)
activerecord (= 4.1.4)
activesupport (= 4.1.4)
bundler (>= 1.3.0, < 2.0)
railties (= 4.1.0)
railties (= 4.1.4)
sprockets-rails (~> 2.0)
railties (4.1.0)
actionpack (= 4.1.0)
activesupport (= 4.1.0)
railties (4.1.4)
actionpack (= 4.1.4)
activesupport (= 4.1.4)
rake (>= 0.8.7)
thor (>= 0.18.1, < 2.0)
rainbow (2.0.0)
......@@ -287,23 +302,23 @@ GEM
rdoc (4.1.1)
json (~> 1.4)
ref (1.0.5)
request_store (1.0.7)
request_store (1.0.8)
rest-client (1.7.2)
mime-types (>= 1.16, < 3.0)
netrc (~> 0.7)
rmagick (2.13.2)
rmagick (2.13.3)
rspec (3.0.0)
rspec-core (~> 3.0.0)
rspec-expectations (~> 3.0.0)
rspec-mocks (~> 3.0.0)
rspec-core (3.0.2)
rspec-core (3.0.3)
rspec-support (~> 3.0.0)
rspec-expectations (3.0.2)
rspec-expectations (3.0.3)
diff-lcs (>= 1.2.0, < 2.0)
rspec-support (~> 3.0.0)
rspec-mocks (3.0.2)
rspec-mocks (3.0.3)
rspec-support (~> 3.0.0)
rspec-rails (3.0.1)
rspec-rails (3.0.2)
actionpack (>= 3.0)
activesupport (>= 3.0)
railties (>= 3.0)
......@@ -311,7 +326,7 @@ GEM
rspec-expectations (~> 3.0.0)
rspec-mocks (~> 3.0.0)
rspec-support (~> 3.0.0)
rspec-support (3.0.2)
rspec-support (3.0.3)
rubocop (0.24.1)
json (>= 1.7.7, < 2)
parser (>= 2.2.0.pre.3, < 3.0)
......@@ -319,12 +334,7 @@ GEM
rainbow (>= 1.99.1, < 3.0)
ruby-progressbar (~> 1.4)
ruby-progressbar (1.5.1)
sass (3.2.19)
sass-rails (4.0.3)
railties (>= 4.0.0, < 5.0)
sass (~> 3.2.0)
sprockets (~> 2.8, <= 2.11.0)
sprockets-rails (~> 2.0)
sass (3.3.14)
sdoc (0.4.0)
json (~> 1.8)
rdoc (~> 4.0, < 5.0)
......@@ -338,7 +348,7 @@ GEM
temple (~> 0.6.6)
tilt (>= 1.3.3, < 2.1)
slop (3.6.0)
sprockets (2.11.0)
sprockets (2.12.1)
hike (~> 1.2)
multi_json (~> 1.0)
rack (~> 1.0)
......@@ -424,6 +434,7 @@ DEPENDENCIES
guard-rspec
guard-rubocop
guard-teaspoon
hipchat
i18n_generators
jbuilder
jquery-rails
......@@ -444,7 +455,7 @@ DEPENDENCIES
rmagick
rspec-rails
rubocop
sass-rails
sass-rails!
sdoc
settingslogic
slim
......
# guard :rubocop do
# watch(%r{.+\.rb$})
# watch(%r{(?:.+/)?\.rubocop\.yml$}) { |m| File.dirname(m[0]) }
# end
guard :rspec do
# Note: The cmd option is now required due to the increasing number of ways
# rspec may be run, below are examples of the most common uses.
# * bundler: 'bundle exec rspec'
# * bundler binstubs: 'bin/rspec'
# * spring: 'bin/rsspec' (This will use spring if running and you have
# installed the spring binstubs per the docs)
# * zeus: 'zeus rspec' (requires the server to be started separetly)
# * 'just' rspec: 'rspec'
guard :rspec, cmd: 'bundle exec rspec' do
watch(%r{^spec/.+_spec\.rb$})
watch(%r{^spec/spec_helper\.rb$}) { |m| 'spec' }
watch(%r{^lib/(.+)\.rb$}) { |m| "spec/lib/#{m[1]}_spec.rb" }
watch('spec/spec_helper.rb') { "spec" }
# Rails example
watch(%r{^app/(.+)\.rb$}) { |m| "spec/#{m[1]}_spec.rb" }
watch(%r{^lib/(.+)\.rb$}) { |m| "spec/lib/#{m[1]}_spec.rb" }
watch(%r{^app/controllers/(.+)_(controller)\.rb$}) do |m|
%W(spec/routing/#{m[1]}_routing_spec.rb spec/#{m[2]}s/#{m[1]}_#{m[2]}_spec.rb spec/requests/#{m[1]}_spec.rb)
end
watch(%r{^app/(.*)(\.erb|\.haml|\.slim)$}) { |m| "spec/#{m[1]}#{m[2]}_spec.rb" }
watch(%r{^app/controllers/(.+)_(controller)\.rb$}) { |m| ["spec/routing/#{m[1]}_routing_spec.rb", "spec/#{m[2]}s/#{m[1]}_#{m[2]}_spec.rb", "spec/acceptance/#{m[1]}_spec.rb"] }
watch(%r{^spec/support/(.+)\.rb$}) { "spec" }
watch('config/routes.rb') { "spec/routing" }
watch('app/controllers/application_controller.rb') { "spec/controllers" }
watch('spec/rails_helper.rb') { "spec" }
# Capybara features specs
watch(%r{^app/views/(.+)/.*\.(erb|haml|slim)$}) { |m| "spec/features/#{m[1]}_spec.rb" }
# Turnip features and steps
watch(%r{^spec/acceptance/(.+)\.feature$})
watch(%r{^spec/steps/(.+)_steps\.rb$}) { |m| Dir[File.join("**/#{m[1]}.feature")][0] || 'spec/acceptance' }
watch(%r{^spec/acceptance/steps/(.+)_steps\.rb$}) { |m| Dir[File.join("**/#{m[1]}.feature")][0] || 'spec/acceptance' }
end
# guard :rubocop do
# watch(%r{.+\.rb$})
# watch(%r{(?:.+/)?\.rubocop\.yml$}) { |m| File.dirname(m[0]) }
# end
# guard :teaspoon do
# watch(%r{^app/assets/javascripts/(.+).js}) { |m| "spec/javascripts/#{m[1]}_spec.js.coffee" }
# # Implementation files
# watch(%r{^app/assets/javascripts/(.+).js}) { |m| "#{m[1]}_spec" }
# # Specs / Helpers
# watch(%r{^spec/javascripts/(.*)})
# end
......@@ -61,6 +61,14 @@ $ (bundle exec) rake db:seed
And have fun with your team !
# Optional features
## PDF uploading
```
brew install imagemagick ghostscript
```
# Test
......
......@@ -22,7 +22,10 @@ $.extend
uploadingIndex += 1
done: (e, data) ->
settings.$progressWrapper.hide()
setTimeout ->
settings.$progressWrapper.fadeOut()
, 1000
$.each data.result.files, (index, file) ->
# TODO: カーソル位置に挿入
......@@ -44,6 +47,10 @@ $.extend
# $('<p/>').text(file.name).appendTo('#files') # TODO
progressall: (e, data) ->
progress = parseInt(data.loaded / data.total * 100, 10)
if progress >= 99
settings.$progressWrapper.find('.progress-title').text 'Uploading files may task some time for converting.'
settings.$progressBar
.css(width: progress + '%')
.text(progress + '%')
......
# Desc
# open link in newtab
# Usage:
$ ->
$('a[href^=http]')
.not('[href*="' + location.hostname + '"]')
.attr({target:"_blank"})
@import url(http://fonts.googleapis.com/css?family=Flamenco:300,400);
@import url(http://fonts.googleapis.com/css?family=Quicksand:300,400,700);
$set_prefix: -webkit-, -moz-, -ms-, -o-, '';
$main-color: #75b3c8;
@mixin background_color($bg_value: $main-color) {
background-color: $bg_value;
color: #fff;
}
@mixin border_radius($br_value: 4px) {
@each $prefix in $set_prefix {
#{$prefix}border-radius: $br_value
}
}
@mixin transition($transition_value: 0.3s, $move_type: ease-in-out) {
@each $prefix in $set_prefix {
#{$prefix}transition: all $transition_value $move_type
}
}
@import 'values';
@import url(http://fonts.googleapis.com/css?family=Flamenco:300,400);
@import url(http://fonts.googleapis.com/css?family=Quicksand:300,400,700);
p, h1, h2, h3, h4, h5, h6, span {
font-family: 'メイリオ', 'meiryo', hiragino kaku go;
letter-spacing: 2pt;
line-height: 150%;
margin: 0;
padding: 0;
}
.badge {
background-color: transparent;
color: $main-color;
font-family: 'Quicksand';
letter-spacing: 0;
border: 1.5px solid $main-color;
padding: 4px 6px;
}
$set_prefix: -webkit-, -moz-, -ms-, -o-, '';
$main-color: #75b3c8;
@mixin background_color($bg_value: $main-color) {
background-color: $bg_value;
color: #fff;
}
@mixin border_radius($br_value: 4px) {
@each $prefix in $set_prefix {
#{$prefix}border-radius: $br_value
}
}
@mixin transition($transition_value: 0.3s, $move_type: ease-in-out) {
@each $prefix in $set_prefix {
#{$prefix}transition: all $transition_value $move_type
}
}
@import url(http://fonts.googleapis.com/css?family=Flamenco:300,400);
@import url(http://fonts.googleapis.com/css?family=Quicksand:300,400,700);
.btn-original {
background: transparent!important;
border: 1px solid #fff;
font-family: 'Quicksand', sans-serif;
font-weight: 300;
font-size: 24px;
letter-spacing: 0em;
&:hover {
border: 1px solid #75b3c8;
background-color: #75b3c8!important;
@include transition;
}
}
@import 'values';
.panel {
border: 1px solid $main-color;
.panel-heading {
background-color: $main-color;
color: #fff;
}
.panel-body {
.list-group-item {
&:hover {
@include transition;
}
}
}
}
.flow-wrapper {
margin-top: 40px;
h1 {
img {
height: 18px;
margin-right: 10px;
position: relative;
bottom: 2px;
}
font-size: 20px;
small {
color: #f6f6f6;
}
}
h4 {
color: #333!important;
}
.posted-name {
color: $main-color;
font-size: 12px;
}
.numbers-wrapper {
height: 150px;
.col-xs-4 {
text-align: center;
label {
border-bottom: 5px solid #ec0160;
font-weight: 300;
}
p {
font-size: 54px;
font-weight: 300;
font-family: 'Quicksand';
color: #ec0160;
}
}
}
}
.label-date {
background-color: #aaa;
padding-top: 3px;
font-family: 'Quicksand';
}
.label-tag {
background-color: #e67e22;
padding-top: 4px;
font-weight: 300;
}
.post-show-wrapper {
margin-top: 40px;
}
.post-edit-btn,
.watch-btn,
.btn-watched {
@include border_radius;
color: $main-color;
border: 1px solid $main-color;
&:hover {
@include transition;
background-color: #eee;
}
a {
color: $main-color;
}
.dropdown-toggle {
background-color: $main-color;
@include border_radius(0px);
color: #fff;
background-image: none!important;
border: 1px solid transparent;
.caret {
font-size: 20px;
}
}
}
.watch-btn {
height: 36px;
}
.btn-watched {
background-color: $main-color;
color: #fff;
border: 2px solid $main-color;
}
.detail-wrapper {
dt {
padding: 2px 0;
}
dd {
margin-bottom: 10px;
}
.label-tag {
background-color: #e67e22;
padding-top: 4px;
font-weight: 100;
}
}
.comment-wrapper {
.panel-title {
img {
height: 25px;
margin-right: 10px;
position: relative;
bottom: 2px;
}
}
textarea {
border: 1px solid #f6f6f6;
margin: 10px 0;
padding: 10px 15px;
line-height: 1.428571429;
vertical-align: middle;
border: 1px solid #dce4ec;
-webkit-border-radius: 4px;
-moz-border-radius: 4px;
-o-border-radius: 4px;
border-radius: 4px;
-webkit-box-shadow: inset 0 1px 1px rgba(0,0,0,0.075);
box-shadow: inset 0 1px 1px rgba(0,0,0,0.075);
-webkit-transition: border-color ease-in-out 0.15s, box-shadow ease-in-out 0.15s;
transition: border-color ease-in-out 0.15s, box-shadow ease-in-out 0.15s;
&:focus {
border: 1px solid $main-color;
box-shadow: 0px 0px 0px $main-color;
background-color: #f8f8f8;
}
}
.comment-btn {
background-color: transparent;
color: $main-color;
border: 1px solid $main-color;
&:hover {
color: #fff;
background-color: $main-color;
@include transition;
}
&:focus {
background-color: #f8f8f8;
@include transition;
box-shadow: 0px 0px 0px $main-color;
}
}
}
.panel-default {
.panel-heading {
background-color: $main-color;
color: #fff;
background-image: none;
}
}
.btn {
background-color: transparent;
background-image: none;
color: $main-color;
border: 1px solid $main-color;
&:hover {
color: #fff;
background-color: $main-color;
@include transition;
border: 1px solid $main-color;
}
&:focus {
background-color: #f8f8f8;
@include transition;
box-shadow: 0px 0px 0px $main-color;
}
}
.fc-event-inner {
padding: 5px;
span {
width: 85px;
}
&:HOVER {
background-color: #f8f8f8;
@include transition;
}
}
......@@ -16,7 +16,7 @@
.mod-mdEditor-textarea {
width: 100%;
min-height: 400px;
font-size: 9pt;
font-size: 12pt;
padding: 3px;
tab-size: 2;
font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', 'Consolas', 'source-code-pro', 'Ricty', monospace;
......
.odometer.odometer-auto-theme, .odometer.odometer-theme-default {
display: -moz-inline-box;
-moz-box-orient: vertical;
display: inline-block;
vertical-align: middle;
*vertical-align: auto;
position: relative;
}
.odometer.odometer-auto-theme, .odometer.odometer-theme-default {
*display: inline;
}
.odometer.odometer-auto-theme .odometer-digit, .odometer.odometer-theme-default .odometer-digit {
display: -moz-inline-box;
-moz-box-orient: vertical;
display: inline-block;
vertical-align: middle;
*vertical-align: auto;
position: relative;
}
.odometer.odometer-auto-theme .odometer-digit, .odometer.odometer-theme-default .odometer-digit {
*display: inline;
}
.odometer.odometer-auto-theme .odometer-digit .odometer-digit-spacer, .odometer.odometer-theme-default .odometer-digit .odometer-digit-spacer {
display: -moz-inline-box;
-moz-box-orient: vertical;
display: inline-block;
vertical-align: middle;
*vertical-align: auto;
visibility: hidden;
}
.odometer.odometer-auto-theme .odometer-digit .odometer-digit-spacer, .odometer.odometer-theme-default .odometer-digit .odometer-digit-spacer {
*display: inline;
}
.odometer.odometer-auto-theme .odometer-digit .odometer-digit-inner, .odometer.odometer-theme-default .odometer-digit .odometer-digit-inner {
text-align: left;
display: block;
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
overflow: hidden;
}
.odometer.odometer-auto-theme .odometer-digit .odometer-ribbon, .odometer.odometer-theme-default .odometer-digit .odometer-ribbon {
display: block;
}
.odometer.odometer-auto-theme .odometer-digit .odometer-ribbon-inner, .odometer.odometer-theme-default .odometer-digit .odometer-ribbon-inner {
display: block;
-webkit-backface-visibility: hidden;
}
.odometer.odometer-auto-theme .odometer-digit .odometer-value, .odometer.odometer-theme-default .odometer-digit .odometer-value {
display: block;
-webkit-transform: translateZ(0);
}
.odometer.odometer-auto-theme .odometer-digit .odometer-value.odometer-last-value, .odometer.odometer-theme-default .odometer-digit .odometer-value.odometer-last-value {
position: absolute;
}
.odometer.odometer-auto-theme.odometer-animating-up .odometer-ribbon-inner, .odometer.odometer-theme-default.odometer-animating-up .odometer-ribbon-inner {
-webkit-transition: -webkit-transform 2s;
-moz-transition: -moz-transform 2s;
-ms-transition: -ms-transform 2s;
-o-transition: -o-transform 2s;
transition: transform 2s;
}
.odometer.odometer-auto-theme.odometer-animating-up.odometer-animating .odometer-ribbon-inner, .odometer.odometer-theme-default.odometer-animating-up.odometer-animating .odometer-ribbon-inner {
-webkit-transform: translateY(-100%);
-moz-transform: translateY(-100%);
-ms-transform: translateY(-100%);
-o-transform: translateY(-100%);
transform: translateY(-100%);
}
.odometer.odometer-auto-theme.odometer-animating-down .odometer-ribbon-inner, .odometer.odometer-theme-default.odometer-animating-down .odometer-ribbon-inner {
-webkit-transform: translateY(-100%);
-moz-transform: translateY(-100%);
-ms-transform: translateY(-100%);
-o-transform: translateY(-100%);
transform: translateY(-100%);
}
.odometer.odometer-auto-theme.odometer-animating-down.odometer-animating .odometer-ribbon-inner, .odometer.odometer-theme-default.odometer-animating-down.odometer-animating .odometer-ribbon-inner {
-webkit-transition: -webkit-transform 2s;
-moz-transition: -moz-transform 2s;
-ms-transition: -ms-transform 2s;
-o-transition: -o-transform 2s;
transition: transform 2s;
-webkit-transform: translateY(0);
-moz-transform: translateY(0);
-ms-transform: translateY(0);
-o-transform: translateY(0);
transform: translateY(0);
}
.odometer.odometer-auto-theme, .odometer.odometer-theme-default {
font-family: "Helvetica Neue", sans-serif;
line-height: 1.1em;
}
.odometer.odometer-auto-theme .odometer-value, .odometer.odometer-theme-default .odometer-value {
text-align: center;
}
@import 'values';
#post-form {
.row {
margin-top: 20px;
.col-xs-9 {
.field {
margin-bottom: 10px;
.input-group-addon {
background-color: #fff;
border-top: 1px solid $main-color;
border-left: 1px solid $main-color;
border-bottom: 1px solid $main-color;
color: $main-color;
label {
margin-bottom: 0;
font-weight: 300;
}
}
.form-control {
border: 1px solid $main-color;
padding: 10px!important;
height: 50px;
}
.select2-choices {
box-shadow: 0 0 0 #fff;
border: 1px solid $main-color;
background-image: none;
padding: 5px;
}
}
}
}
.btn-toolbar {
> .btn-group > .btn {
color: $main-color;
background-color: #fff;
box-shadow: 0 0 0 #fff;
}
}
textarea {
padding: 10px;
border-top: 0px solid #fff;
&:focus {
box-shadow: 0 0 0 #fff!important;
background-color: #fff;
}
}
.mod-mdEditor-textarea {
&:focus {
box-shadow: 0 0 0 #fff!important;
}
}
.preview-wrapper {
.mod-mdEditor-preview {
}
.panel-body {
padding: 10px;
padding-top: 0;
}
}
#save_button {
margin-bottom: 10px;
}
}
input,
textarea {
border: 1px solid $main-color;
&:focus {
border: 1px solid $main-color;
background-color: #f8f8f8;
box-shadow: 0 0 0 #fff!important;
@include transition;
}
}
@import 'values';
.mod-tag-tree {
.mod-tag-tree-filter {
margin-bottom: 20px;
width: 400px!important;
&:focus {
border: 1px solid $main-color;
box-shadow: 0 0 0 #fff!important;
background-color: #f8f8f8;
@include transition;
}
}
li {
padding: 6px 0!important;
margin-right: 4px!important;
span {
min-height: 10px!important;
min-width: 10px!important;
}
}
}
.stock-wrapper {
margin-top: 15px;
.odometer {
position: relative;
bottom: 2px;
}
h1 {
color: #fff;
small {
color: #f8f8f8;
}
}
.list-group {
box-shadow: 0 0 0 #fff;
}
}
@import 'values';
.template-wrapper {
margin-top: 15px;
}
// Place all the styles related to the templates controller here.
// They will automatically be included in application.css.
// You can use Sass (SCSS) here: http://sass-lang.com/
/*************************************************************************
* app_header
*************************************************************************/
@import 'values';
@import url(http://fonts.googleapis.com/css?family=Flamenco:300,400);
@import url(http://fonts.googleapis.com/css?family=Quicksand:300,400,700);
$main-color: #75b3c8;
.navbar-original {
background-color: $main-color!important;
background-image: none!important;
li:hover {
cursor: pointer;
a {
color: $main-color;
}
}
li.new-post-btn:hover {
background-color: $main-color;
a {
color: #fff;
}
}
a {
color: #fff;
font-family: 'Quciksand', 'meiryo', 'メイリオ','sans-serif';
letter-spacing: .1em;
font-weight: 300;
@include transition;
}
.input-group {
input {
border: 1px solid transparent;
box-shadow: none;
}
button {
background-color: #fff;
border: 1px solid #fff;
.search {
width: 20px;
&:hover {
opacity: .7;
@include transition;
}
}
}
}
.nav-icon {
width: 20px;
margin-right: 5px;
}
li.stock img {
width: 25px;
position: relative;
bottom: 2px;
}
li.flow {
a {
position: relative;
top: 2px;
}
img {
position: relative;
bottom: 2px;
}
}
.navbar-right {
.new-post-btn {
.btn {
position: relative;
background-color: #fafafa;
color: $main-color;
vertical-align: middle;
&:hover {
background-color: #ddd;
@include transition;
}
}
.write {
width: 17px;
vertical-align: middle;
position: relative;
bottom: 1px;
}
}
}
.badge {
background-color: transparent;
color: #fff;
font-family: 'Quicksand';
font-weight: 300;
letter-spacing: 0;
border: 1px solid #fff;
padding: 4px 6px;
margin-left: 5px;
}
}
@import url(http://fonts.googleapis.com/css?family=Quicksand:300,400,700);
$main-color: #75b3c8;
.background-image {
width: 100%;
height: 100%;
position: fixed;
top: 0;
left: 0;
background-image: image-url("compass.jpg");
background-size: cover;
}
.background-mask {
width: 100%;
height: 100%;
background-color: rgba(#000, .6);
position: fixed;
top: 0;
left: 0;
}
.login {
.container.marketing {
h2.title {
font-family: 'Quicksand', sans-serif;
font-weight: 300;
font-size: 62px;
color: #fff;
}
p {
color: #fff;
}
}
.welcome-box {
text-align: center;
.btn-original {
margin-top: 140px;
}
.zigexn {
margin-top: 20px;
}
}
.featurette {
.featurette-heading {
margin-top: 0;
color: #ddd;
line-height: 150%;
font-family: 'Quicksand','メイリオ', 'meiryo', hiragino kaku go;
}
.text-muted {
color: #ccc;
font-family: 'Quicksand','メイリオ', 'meiryo', hiragino kaku go;
}
.featurette-image {
box-shadow: 1px 1px 1px #ccc;
border-radius: 5px;
}
}
}
......@@ -33,13 +33,15 @@ class ApisController < ApplicationController
when /\.(jpe?g|png|gif)\Z/
s3_files << { type: 'image', name: file.original_filename, image: res.public_url.to_s }
when /\.pdf\Z/
cover_image_name = "#{Digest::MD5.file(file.path).to_s}-cover.png"
pdf = Magick::ImageList.new(file.path + '[0]')
cover_tmp = Rails.root.join('tmp', cover_image_name)
pdf[0].write(cover_tmp)
cover_res = s3_uploader.upload!(file: cover_tmp, name: cover_image_name)
s3_files << { type: 'slide', name: cover_image_name, url: res.public_url.to_s, image: cover_res.public_url.to_s }
if Settings.respond_to?(:pdf_uploading) && Settings.pdf_uploading
cover_image_name = "#{Digest::MD5.file(file.path).to_s}-cover.png"
pdf = Magick::ImageList.new(file.path + '[0]')
cover_tmp = Rails.root.join('tmp', cover_image_name)
pdf[0].write(cover_tmp)
cover_res = s3_uploader.upload!(file: cover_tmp, name: cover_image_name)
s3_files << { type: 'slide', name: cover_image_name, url: res.public_url.to_s, image: cover_res.public_url.to_s }
end
end
end
......
class StockController < ApplicationController
def show
end
end
class PostDecorator < Draper::Decorator
delegate_all
def show_url
h.post_url(model)
end
def show_path
h.post_path(model)
end
......
module HipchatIntegration
# Call Hipchat API
def notify_hipchat!
client = HipChat::Client.new(Settings.hipchat.token)
client[Settings.hipchat.room].send('Rendezvous', notify_hipchat_body, message_format:'text', notify: 1)
end
# @return [String] notification body
def notify_hipchat_body
<<EOF
#{author.name}が「#{title}」を投稿しました。
#{self.decorate.show_url}
--
#{body}
EOF
end
end
......@@ -19,11 +19,14 @@ class Notification < ActiveRecord::Base
# Named scope
######################################################################
# 最新のPostを取得
scope :unread, -> {
where(is_read: false)
}
scope :recent, -> {
where(arel_table[:created_at].gt 7.day.ago)
}
######################################################################
# Instance method
######################################################################
......
......@@ -16,6 +16,8 @@
require 'date'
class Post < ActiveRecord::Base
include HipchatIntegration if Settings.respond_to?(:hipchat)
######################################################################
# Associations
######################################################################
......@@ -29,7 +31,7 @@ class Post < ActiveRecord::Base
has_many :watchers, :through => :watches
######################################################################
# validations
# Validations
######################################################################
validates :title, presence: true
validates :body, presence: true
......@@ -39,6 +41,7 @@ class Post < ActiveRecord::Base
######################################################################
after_save :set_watcher!
after_save :notify_watchers!
after_create :notify_hipchat! if Settings.respond_to?(:hipchat)
######################################################################
# Named scope
......
......@@ -115,7 +115,9 @@ class User < ActiveRecord::Base
# push通知を追加
def push_notification(detail_path, body)
notifications.create(detail_path: detail_path, body: body, is_read: false)
unless notifications.where(detail_path: detail_path).unread.exists?
notifications.create(detail_path: detail_path, body: body, is_read: false)
end
end
# record footprint
......
/! view:flow/show
.row
h1
| Flow
small - 最近投稿された記事
.row.flow-wrapper
.numbers-wrapper
.col-xs-4
label.numbers Stocks
p = Post.count
.col-xs-4
label.numbers Users
p = User.count
.col-xs-4
label.numbers Tags
p = Tag.count
.col-xs-8 role="navigation"
.list-group
- @posts.each do |_post|
= render partial: 'posts/large_item', locals: { post: _post }
.panel
.panel-heading
h1
= image_tag 'flow.png'
| Flow
small - 最近投稿された記事
.panel-body.list-group
- @posts.each do |_post|
= render partial: 'posts/large_item', locals: { post: _post }
= paginate(@posts)
.col-xs-4
......@@ -19,7 +31,7 @@
/ - Post.limit(5).each do |_post|
/ = render partial: 'posts/small_item', locals: { post: _post }
.panel.panel-default
.panel
.panel-heading
h2.panel-title 最近投稿されたタグ
.panel-body.list-group
......
......@@ -10,6 +10,7 @@ html lang="ja"
link href="//cdnjs.cloudflare.com/ajax/libs/fullcalendar/1.6.4/fullcalendar.print.css" rel="stylesheet" /
link href="//netdna.bootstrapcdn.com/font-awesome/4.0.3/css/font-awesome.css" rel="stylesheet"
script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"
= render partial: 'partials/google_analytics'
= stylesheet_link_tag "application", media: "all"
= render_style
= csrf_meta_tags
......
nav.navbar.navbar-default.navbar-fixed-top role="navigation"
nav.navbar.navbar-fixed-top.navbar-original role="navigation"
.container
.navbar-header
......@@ -9,17 +9,20 @@ nav.navbar.navbar-default.navbar-fixed-top role="navigation"
.input-group
input.form-control name="q" placeholder="Search" type="text" value=params[:q] /
span.input-group-btn
button.btn.btn-default data-disable-with="Searching..." type="submit"
span.glyphicon.glyphicon-search
button.btn data-disable-with="Searching..." type="submit"
= image_tag 'search.png', class: 'search'
ul.nav.navbar-nav
li class=('active' if current_page?(stock_path))
li.stock class=('active' if current_page?(stock_path))
a href=stock_path title="Stock"
= image_tag "stock.png", class: 'nav-icon stock'
| Stock
li class=('active' if current_page?(flow_path))
li.flow class=('active' if current_page?(flow_path))
a href=flow_path title="Frow"
= image_tag "flow.png", class: 'nav-icon'
| Flow
li class=('active' if current_page?(templates_path))
li.template class=('active' if current_page?(templates_path))
a href=templates_path title="Templates"
= image_tag "template.png", class: 'nav-icon'
| Templates
ul.nav.navbar-nav.navbar-right
......@@ -27,12 +30,12 @@ nav.navbar.navbar-default.navbar-fixed-top role="navigation"
a#notifications data-container="body" data-toggle="popover" data-placement="bottom"
span.glyphicon.glyphicon-flag
- if current_user.notifications.unread.any?
span.badge = current_user.notifications.unread.count
li
span.badge = current_user.notifications.unread.recent.count
li.new-post-btn
form
a.btn.btn-primary.navbar-btn href=new_post_path
| New Post&nbsp;&nbsp;
span.glyphicon.glyphicon-pencil
a.btn.navbar-btn href=new_post_path
| 投稿する
= image_tag 'write.png', class: "write"
li.dropdown
a.dropdown-toggle data-toggle="dropdown"
= current_user.name
......@@ -53,10 +56,10 @@ nav.navbar.navbar-default.navbar-fixed-top role="navigation"
a href=destroy_user_session_path data-method="delete" rel="nofollow" SignOut
script#notification-content type="text/template"
- if current_user.notifications.unread.any?
- if current_user.notifications.unread.recent.any?
h4 通知一覧
.list-group
- current_user.notifications.unread.each do |notification|
- current_user.notifications.unread.recent.each do |notification|
a.list-group-item href=notification_bridge_path(notification.id)
spen.small
| [#{notification.created_at.strftime('%m/%d %H:%M')}]&nbsp;
......
- if Settings.respond_to?(:google_analytics) && Settings.google_analytics.present?
javascript:
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
})(window,document,'script','//www.google-analytics.com/analytics.js','ga');
ga('create', '#{Settings.google_analytics}', 'auto');
ga('send', 'pageview');
......@@ -22,19 +22,13 @@
= hidden_field :post, :tags, class: 'mod-mdEditor-tags', style: 'width:300px', value: @post.tags.map{ |_tag| _tag.name }.join(',')
.col-xs-3
p.actions
= f.submit class: 'btn btn-primary js-disable-confirm-unload', id: 'save_button'
p.actions
= f.check_box :is_draft
= f.label :is_draft, "下書き保存"
p.actions
= f.date_select :specified_date
br/
.row
#progress-wrapper.alert.alert-warning.fade.in style="display:none;"
| Uploading files...
span.progress-title
| Uploading files...
#progress style="height:20px;"
.progress-bar.progress-bar-success.progress-bar-striped.active role="progressbar" aria-valuemin="0" aria-valuemax="100" style="width: 0%;"
| 0%
......@@ -65,11 +59,22 @@
| Upload
.panel-body.panel-body-nopadding
= f.text_area :body, class: 'mod-mdEditor-textarea'
= f.text_area :body, class: 'mod-mdEditor-textarea', placehoder: 'type your text....'
p.actions
= f.submit class: 'btn btn-lg js-disable-confirm-unload', id: 'save_button'
p.actions
= f.check_box :is_draft
= f.label :is_draft, "下書き保存"
p.actions
= f.date_select :specified_date
.col-xs-6
.box-text
.text-box.body.viewer.github.mod-mdEditor-preview
.panel.preview-wrapper
.panel-heading
h5 Preview - 入力した内容がここに表示されます
.panel-body
.box-text
.text-box.body.viewer.github.mod-mdEditor-preview
input#fileupload data-url="/apis/file_receiver" multiple="" name="files[]" style="display:none" type="file" /
......
......@@ -7,16 +7,16 @@ a.list-group-item.post-list.mod-hover-hidden data-post-id=post.id href=post_path
.col-xs-9
h4.text-link #{post.title}
.col-xs-3
span.label.label-danger = post.display_specified_date if post.specified_date
span.label.label-danger.label-date = post.display_specified_date if post.specified_date
small.pull-right ##{post.id}
.row
.col-xs-8
small.text-success
small.text-success.posted-name
| #{post.author.name} posted&nbsp;
abbr.js-time-ago data-time-ago-at=post.updated_at
|.&nbsp;&nbsp;
- post.tags.each do |tag|
span.label.label-success ##{tag.name}
span.label.label-success.label-tag ##{tag.name}
| &nbsp;
.col-xs-4
small.pull-right
......
.row
.row.post-show-wrapper
.col-xs-9
.panel.panel-info
.panel
.panel-heading
h3.panel-title
a href=post_path(@post) = @post.title
......@@ -8,8 +8,8 @@
= MarkdownRenderer.new(@post.body).render
.col-xs-3
.btn-group
a.btn.btn-primary href=edit_post_path(@post)
.btn-group.post-edit-btn
a.btn href=edit_post_path(@post)
| 編集&nbsp;
span.glyphicon.glyphicon-pencil
button.btn.btn-default.dropdown-toggle data-toggle="dropdown" type="button"
......@@ -32,11 +32,11 @@
.btn-group
- if current_user.watching?(post: @post)
= link_to 'Watching <span class="glyphicon glyphicon-eye-open"></span>'.html_safe, watch_post_path, :remote => true, :'data-type' => :html, :class => 'btn btn-warning ajax_link'
= link_to 'Watching <span class="glyphicon glyphicon-eye-open"></span>'.html_safe, watch_post_path, :remote => true, :'data-type' => :html, :class => 'btn ajax_link btn-watched'
- else
= link_to 'Watch <span class="glyphicon glyphicon-eye-open"></span>'.html_safe, watch_post_path, :remote => true, :'data-type' => :html, :class => 'btn btn-default ajax_link'
= link_to 'Watch <span class="glyphicon glyphicon-eye-open"></span>'.html_safe, watch_post_path, :remote => true, :'data-type' => :html, :class => 'btn ajax_link watch-btn'
.well style="margin-top:20px"
.well.detail-wrapper style="margin-top:20px"
dl
dt 作成者
dd
......@@ -46,7 +46,7 @@
dt タグ
dd
- @post.tags.each do |tag|
span.label.label-success
span.label.label-tag
a href=tag.decorate.show_path
| ##{tag.name}
| &nbsp;
......@@ -72,30 +72,33 @@
= @post.comments.count
.row
.panel.panel-success
.panel-heading
h3.panel-title Comments
.panel-body
ul.media-list
- @post.comments.each do |comment|
li.media
a.pull-left href="#"
img.media-object src=comment.author.image_url /
.media-body
h4.media-heading= comment.author.name
= comment.body
= form_tag(comment_post_path, method: :post, data: { 'form-id' => "comment_#{@post.id}" }) do
li.media
a.pull-left href="#"
img.media-object src=current_user.image_url /
.media-body
h4.media-heading= current_user.name
= text_area :comment, :body, class: 'form-control', placeholder: 'コメントする...'
= submit_tag 'Comment', class: 'btn btn-primary', data: { 'disable-with' => '...' }
javascript:
$("form[data-form-id='comment_#{@post.id}']").on('ajax:success', function(event, data, xhr) {
.col-md-12
.panel.comment-wrapper
.panel-heading
h3.panel-title
= image_tag 'comment_w.png'
| Comments
.panel-body
ul.media-list
- @post.comments.each do |comment|
li.media
a.pull-left href="#"
img.media-object src=comment.author.image_url /
.media-body
h4.media-heading= comment.author.name
= comment.body
= form_tag(comment_post_path, method: :post, data: { 'form-id' => "comment_#{@post.id}" }) do
li.media
a.pull-left href="#"
img.media-object src=current_user.image_url /
.media-body
h4.media-heading= current_user.name
= text_area :comment, :body, class: 'form-control', placeholder: 'コメントする...'
= submit_tag "Comment", class: 'btn comment-btn', data: { 'disable-with' => '...' }
javascript:
$("form[data-form-id='comment_#{@post.id}']").on('ajax:success', function(event, data, xhr) {
});
});
/! Button trigger modal
/!
......
/! view:stock/show
.row
h1
| Stock
small - 保存・蓄積された記事
#sidebar.col-xs-12 role="navigation"
#tab-tree.tab-pane
- cache('tag-tree', :expires_in => 1.hour) do
.list-group
= Tag.posts_exist.decorate.tree_view
.col-md-12
.panel.stock-wrapper
.panel-heading
h1
| &nbsp;Stocks
small - 保存・蓄積された記事
.panel-body
#sidebar role="navigation"
#tab-tree.tab-pane
- cache('tag-tree', :expires_in => 1.hour) do
.list-group
= Tag.posts_exist.decorate.tree_view
......@@ -5,7 +5,7 @@
| Templates
small - テンプレートから作成
.panel.panel-info
.panel.template-wrapper
.panel-heading
span.glyphicon.glyphicon-info-sign
| テンプレートの使い方
......
/! view:welcome/login
.background-image
.background-mask
.login
.container.marketing
.row style=("margin-top: 40px")
.col-lg-4
.col-lg-4
img.img-circle alt=("Generic placeholder image") src="http://placehold.it/140x140&amp;text=Rendezvous" /
h2 Rendezvous
.col-lg-12.welcome-box
h2.title Rendezvous
p
| Rendezvousはチームの`Stock`と`Flow`の
br>/
| RendezvousはチームのStockとFlowの
| 2種類の情報を蓄積・検索・共有する
br>/
| オープンソースのソフトウェアです。
p
a.btn.btn-lg.btn-primary href=user_omniauth_authorize_path(:google_oauth2) role="button" Sign up with Google
.col-lg-4
a.btn.btn-lg.btn-primary.btn-original href=user_omniauth_authorize_path(:google_oauth2) role="button" Sign up with Google
p.zigexn powerd by ZIGExN
hr.featurette-divider/
.row.featurette
.col-md-7
h2.featurette-heading
| Stock all you have done.
span.text-muted It may be priceless for others.
p.lead Donec ullamcorper nulla non metus auctor fringilla. Vestibulum id ligula porta felis euismod semper. Praesent commodo cursus magna, vel scelerisque nisl consectetur. Fusce dapibus, tellus ac cursus commodo.
span.text-muted It may be priceless for others.
.col-md-5
img.featurette-image.img-responsive alt="Stock" src="http://placehold.it/500x400&amp;text=Stock" /
= image_tag "font.jpg", class: "featurette-image img-responsive"
hr.featurette-divider/
.row.featurette
.col-md-5
img.featurette-image.img-responsive alt="Flow" src="http://placehold.it/500x400&amp;text=Flow" /
= image_tag "paper.jpg", class: "featurette-image img-responsive"
.col-md-7
h2.featurette-heading
| Flow anything member have come up with.
span.text-muted Which accelerate your PDCA.
p.lead Donec ullamcorper nulla non metus auctor fringilla. Vestibulum id ligula porta felis euismod semper. Praesent commodo cursus magna, vel scelerisque nisl consectetur. Fusce dapibus, tellus ac cursus commodo.
span.text-muted Which accelerate your PDCA.
hr.featurette-divider/
.row.featurette
.col-md-7
h2.featurette-heading
| Collaborate with other team on documents.
span.text-muted Making more and more generic plans.
p.lead Donec ullamcorper nulla non metus auctor fringilla. Vestibulum id ligula porta felis euismod semper. Praesent commodo cursus magna, vel scelerisque nisl consectetur. Fusce dapibus, tellus ac cursus commodo.
span.text-muted Making more and more generic plans.
.col-md-5
img.featurette-image.img-responsive alt="Collaboration" src="http://placehold.it/500x400&amp;text=Collaboration" /
= image_tag "pc.jpg", class: "featurette-image img-responsive"
hr.featurette-divider/
......@@ -19,6 +19,17 @@ defaults: &defaults
secret_access_key: "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
bucket_name: "xxxxxxxxxxxxxxxxxx"
# optional
# hipchat:
# token: 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'
# room: 'xxxxxxxxxxx'
# optional
# google_analytics:
# optional
# pdf_uploading: false
development:
<<: *defaults
......
......@@ -32,6 +32,16 @@ describe Notification do
expect(@bob.notifications.size).to eq(1)
end
it "not duplicated notifies on post edited" do
@bob.watch!(post: @post)
expect(@bob.watching?(post: @post)).to be_truthy
@post.reload
expect(@post.watchers).to include(@bob)
@post.update!(title: @post.title + ' [New!]')
@post.update!(title: @post.title + ' [New!]')
expect(@bob.notifications.size).to eq(1)
end
it "not notifies on post edited by him" do
@bob.watch!(post: @post)
@post.reload
......
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