From 8e222ae5677415f4833e13d7acb08e97792a9c98 Mon Sep 17 00:00:00 2001 From: Luke Barratt <luke@barratt.me> Date: Sun, 13 Apr 2014 12:16:51 +0100 Subject: [PATCH] Added basic teams pages styling --- app/assets/images/flags/FX.png | Bin 0 -> 851 bytes app/assets/images/flags/SU.png | Bin 0 -> 520 bytes app/assets/images/flags/UK.png | Bin 0 -> 1132 bytes app/assets/images/layout/forum-bg-pattern.png | Bin 0 -> 7433 bytes .../images/layout/forum-bg-pattern@2x.png | Bin 0 -> 8033 bytes app/assets/stylesheets/_variables.scss | 4 +- app/assets/stylesheets/application.css.scss | 4 + app/assets/stylesheets/components/_forms.scss | 21 +++ app/assets/stylesheets/components/_tabs.scss | 56 ++++++ app/assets/stylesheets/layout/_body.scss | 32 ++++ app/assets/stylesheets/layout/_header.scss | 4 +- .../stylesheets/layout/_navigation.scss | 2 +- app/assets/stylesheets/mixins/_buttons.scss | 2 +- app/assets/stylesheets/pages/_forums.scss | 1 + app/assets/stylesheets/pages/_matches.scss | 22 +++ app/assets/stylesheets/pages/_teams.scss | 94 ++++++++++ app/assets/stylesheets/pages/_users.scss | 21 +++ app/controllers/comments_controller.rb | 2 +- app/controllers/forums_controller.rb | 9 +- app/models/concerns/extra.rb | 124 ++++++------- app/models/topic.rb | 18 +- app/models/user.rb | 6 +- app/views/application/_header.html.erb | 2 +- app/views/forums/show.html.erb | 10 +- app/views/matches/_list.html.erb | 26 +-- app/views/posts/_post.html.erb | 11 +- app/views/teamers/_list.html.erb | 32 ++-- app/views/teams/_list.html.erb | 30 +-- app/views/teams/index.html.erb | 9 +- app/views/teams/show.html.erb | 173 ++++++++---------- app/views/topics/show.html.erb | 12 +- app/views/users/edit.html.erb | 10 +- app/views/users/index.html.erb | 54 +++--- config/application.rb | 9 +- config/deploy/staging.rb | 2 +- config/environments/development.rb | 6 + config/environments/production.rb | 2 +- config/environments/staging.rb | 2 +- config/environments/test.rb | 7 +- config/initializers/phpcookies.rb | 11 -- config/initializers/secret_token.rb | 1 - config/initializers/session_store.rb | 4 - 42 files changed, 547 insertions(+), 288 deletions(-) create mode 100644 app/assets/images/flags/FX.png create mode 100644 app/assets/images/flags/SU.png create mode 100644 app/assets/images/flags/UK.png create mode 100644 app/assets/images/layout/forum-bg-pattern.png create mode 100644 app/assets/images/layout/forum-bg-pattern@2x.png create mode 100644 app/assets/stylesheets/components/_tabs.scss create mode 100644 app/assets/stylesheets/pages/_matches.scss create mode 100644 app/assets/stylesheets/pages/_teams.scss create mode 100644 app/assets/stylesheets/pages/_users.scss delete mode 100644 config/initializers/phpcookies.rb delete mode 100644 config/initializers/secret_token.rb delete mode 100644 config/initializers/session_store.rb diff --git a/app/assets/images/flags/FX.png b/app/assets/images/flags/FX.png new file mode 100644 index 0000000000000000000000000000000000000000..f27f41143d610efa5b680fec0e2ee82de147cf96 GIT binary patch literal 851 zcmeAS@N?(olHy`uVBq!ia0vp^5+KaM3?#3wJbQ|PfoX1lPlzj!`~Uxc21Z6?q?RyE zEpdig(k!*)*=osi)Kcc&zkmO7sL!QPpNk<r=R>^D1bd$d@=}YNRJ-(a$-+}L%g;5h zxzw@#O4r7#|6t(z@<rd5E%>&0?w7gKKTezQZqBsBfu2mx^%>I-h4t(Y?>!LScQCx~ z5K#H&#>!8Pl^+@_-!)Xc>S^6!qQ&G~7t^=Lzhh58=RPpn|M&0TPc<bUYl=Tq7r(12 zdeKz9-B^pssm{HAi(BIkx2BzLO}l{T_wU~yN^;(pWWOuPc~hMIv?yyENLh_-#X6g+ z%{J9r!D!phpFiK`qyW*Ioa9&8$&a#<wg8nm))*J8G%8wWRJ`7(c!Oc_hHu}#y-JCC znH=>ZIqF$*)cvH$%^+pf8W~H}vsS2QuTsxmt)8>`%a<?Dql2DD2R@4qd>j>cCo*88 zktUNvrE2Oz^~~k!Su54ESE^;L`t<43v#7wQ(Sc8*10O~O+zRtuZwOK*8aYEWW}ay5 z0uYK@`2PL-hdxdZe4Ot4INkMey5i}u&QOENzFaVDnqb6i!N|D+Kom9a&6_v(J?!p! z*xm84yX9_s+0|w(P?=pBZ_p&3kQqE-vv|X1zk2oRj;qyeSF7vJmgk);RvUm6aQO9e z1Wx4)n$8(Kog;Y0ix)3$Ihx;eG{50!cGbb`jGf6UpfcMMR_`8Gzlp5=Q&|0{vIb0j z`t<2_JCkd6##il(FWMTNvNBkqug+>;%I?#{;Wt4bbedSyEa|wpGV$}C!NAP`x0`;h z*Ss9AxLTjHGdW>nw8Bu6$E{kxvsTc%LC~j3(5G3@w*`of967Sn-fV}x*>-!gt#)Rc zY)#i$8?Uu6Xis<>08F6lB|(0{3=Awh0xAZIs*O=Vp*T+$#}JK)S0^~~H7M|~q%WMu z!~XBTM{VO*1`fjt!;cT<-I{6QE4HuyP?L%$@03(y)vXNgHlEq7DP9qKMOxXH^}h&D zlh(EA_U}}ap7d3}buu(DImXZG+v;!VQ1M`nO*Hr6HGNqin;1M@{an^LB{Ts5JeqlR literal 0 HcmV?d00001 diff --git a/app/assets/images/flags/SU.png b/app/assets/images/flags/SU.png new file mode 100644 index 0000000000000000000000000000000000000000..d9624ca1c19a7acc7c7f26702c7a4458662e46b2 GIT binary patch literal 520 zcmeAS@N?(olHy`uVBq!ia0vp^5+KaM3?#3wJbQ|Pfzd0#C&U%V{r~?z10y3cx_tTa z_3PJf-MV$>&YgSr?%ltC|J=EAU%!6+`Sa(WKY#xI{re9U96562^XJb$e*F0T`!_`P z@ZrOsK79g;K-3>Pbm+r}58uCk2b%Ef*Ds(lCZ+?nwr_20zS`J)x3T$QWAl@VX}_`Y zYa^piMn+$ajJ_Efeq&<VtD*5iUHyZ)`e$|ZFF?e^v|Cm6nY#Kru;52EwNFe;yF^7F zii*Ax6@4oz`c72z{SGFk2ZDkx1O;CS3ceN)cq1UNjfv?lFYi+xo)<hkuXuU4GBMrc z;CRfz@r;x6IVa}}4vx)COxIai@3XQ#W@UZC%KDU*bu%mLRd)8<92^e?1RjftJ(HGx zDkJkuUjCVa!ZSt19Xvcc1qAjA3LX#?JR~T1SWxhYpy104k*mPaWG@Nw3ua(o;So?V zP*iP<0t%&hx;Tbt1fT77<Z3YBVJXkP<oy4CxZ}|q9??-N#2pLzj8m9v_?w&jjGrZl zyM?VP<x7;}_ljZtnRHz-$1tCB%D!vtTdj}0yrR!k<#nMv*fdJD{Yp-G!ULgW=a<go gnZq_aOWmd-W|3&z>R1T|J)n&Yp00i_>zopr0Fe6Rpa1{> literal 0 HcmV?d00001 diff --git a/app/assets/images/flags/UK.png b/app/assets/images/flags/UK.png new file mode 100644 index 0000000000000000000000000000000000000000..02fa2a15cce16934a135922553fd2f058b280182 GIT binary patch literal 1132 zcmV-y1e5!TP)<h;3K|Lk000e1NJLTq000;O000;W1^@s6;CDUv000CtNkl<ZNQv!~ zYe>~+9LGx%dSReJ2vJyK+Fmr4ppK@4L8)7d?8Rtl6Xz_}iYB8?iy2LFE%UZ{so50M zhK2VGIv%xSYG>LZZ|SKlkDWSKwJh_Jsr&4C{+Xv(Z#Ig(*&n_y&hPU1K9}El=FR*6 z`|rQ`^B2_b*g=<0M~kkDh<(L)f0T*$#w?-iIT;N7)U92M+S{AH?rz@Op8rBVOX&&Q zQ$&46Hs}5Q(Pm{K+0wwJX7_H4X=#l1_cJ{`P0KYK#|k@0KGi`=Q3q+KJDHjJ6MIe$ zwu}sBCMGypu2*uh=4e4XjjeYWEG@;9p3aEbOj}!<G;omyuD+X-xua>~R!j^-6%_(D zgTefW*p$m`jjvTC4Gd9H+}^sC>CsWXI?|-Xzx=TgeN!jK*jVg^g*+J>!#*@j(5GqA zz*RADdh0uOCaU?Pp$lVtJogSA;_2`(W8;(jT--_6H!88S8E%J%(;F7X)Z@o|k=VeI z{Hxf?DlkMxGa`<7YHEu1>o)crsY5bfF!+{`U8Mx?swDIGcFcMC^lsb6qbpaGrux>q zJbgOF%`IEF9vsZ%!-v$>bz|JWA7fk`69WT0nVclAqFZ4|mSj2%R_`Mys+hpfO9+fE zB{HFwn-?x|U98reoz0}!_M`ylLqg~d3}oWL19~GOuoV<2aiirSI}cw}dL=`$By-N- zqDI5u;2<L-Ba8{y`1trM)fp5-yO^X=QTwXA?3E13(g^09LGGeOG_GDvi;oXigmnK> zvR5)B>x7e&!yrfe(5za8cDA5Z7K?fRCu*JTl?=%`Ar?JnpjN9f8jTEy%esI6J`cnh z4~r>!QA2m{(zIj=T2Ifv<)mbf?3E13su4`bCHs7h+qzWT0)G+8<b#-EI`l?{hK9J2 zlthc49|Ph~*x>3))AHp?e9&s8M~w7kaU9x$5&|NMlwO4)Sd!^5@ZQTJ|D(7Bq!E`| zi`8bw+|xsAXeg~4H}YGa8f#x4^<vu%OP6A|50GD`Q&!toUQVNz7aei&?Ec}r!jLS< ze96FLeL7{THY^qky=TtQuwn&Q4;^On-V!`N{1wZsThuOG$VG8XR;!JLe(7xAUx}gL zgjuggD@M3kOj%LxIo#h*dD-CIEs5fx>%`F8i%z^t8gWsT$Ir5SLpIL7DR>0uaPP(q zRL;)SE?$huWLDx*KAUo>ZSD~<6YU8JTyS?s{ZlG$haPkoR99Eiu2NCs>x(url7q=r z3VfN6ga?G5!X$Q}S-Fx+Yt~>kTUZf#T*)alAvq+U)F_vGt*VN1;>hwp-sCVSIdFhn z4-ZbqC$R35W4QT!KdS^qt2QLjD5j#o&5gok%V=tDp36Pcv-<U)rBiWEg-Vzdio1Jm y;3DKD^v-LR*YoFk!K{hvYnF?`2HvRNxWQkMms8xr{65bB0000<MNUMnLSTYg051Ii literal 0 HcmV?d00001 diff --git a/app/assets/images/layout/forum-bg-pattern.png b/app/assets/images/layout/forum-bg-pattern.png new file mode 100644 index 0000000000000000000000000000000000000000..9b0f1718741ad73f21351561bf62f4586c24bc44 GIT binary patch literal 7433 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 Hu0mjfYt7nh literal 0 HcmV?d00001 diff --git a/app/assets/images/layout/forum-bg-pattern@2x.png b/app/assets/images/layout/forum-bg-pattern@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..cad04a3d842d9bd78ae118acb8dbc40afb253561 GIT binary patch literal 8033 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 literal 0 HcmV?d00001 diff --git a/app/assets/stylesheets/_variables.scss b/app/assets/stylesheets/_variables.scss index a0529f1..9ab65f4 100644 --- a/app/assets/stylesheets/_variables.scss +++ b/app/assets/stylesheets/_variables.scss @@ -24,11 +24,11 @@ $large-screen-up: new-breakpoint(min-width $large-screen 8); */ $open-sans: "Open Sans", sans-serif; -$monserrat: "Montserrat", sans-serif; +$montserrat: "Montserrat", sans-serif; $sans-serif: $open-sans; $base-font-family: $sans-serif; -$header-font-family: $monserrat; +$header-font-family: $montserrat; /* Sizes diff --git a/app/assets/stylesheets/application.css.scss b/app/assets/stylesheets/application.css.scss index d926447..2f0d4e8 100644 --- a/app/assets/stylesheets/application.css.scss +++ b/app/assets/stylesheets/application.css.scss @@ -26,6 +26,7 @@ @import "components/gather"; @import "components/breadcrumbs"; @import "components/pagination"; +@import "components/tabs"; /* Layout @@ -46,3 +47,6 @@ @import "pages/news"; @import "pages/contests"; @import "pages/forums"; +@import "pages/teams"; +@import "pages/users"; +@import "pages/matches"; diff --git a/app/assets/stylesheets/components/_forms.scss b/app/assets/stylesheets/components/_forms.scss index e2c9149..25c04ac 100644 --- a/app/assets/stylesheets/components/_forms.scss +++ b/app/assets/stylesheets/components/_forms.scss @@ -138,3 +138,24 @@ form.square { @include shift(3); } } + +form.search { + + .query { + @include span-columns(9); + + input { + width: 100%; + } + } + + .controls { + @include span-columns(3); + @include shift(0); + @include omega; + + input { + width: 100%; + } + } +} \ No newline at end of file diff --git a/app/assets/stylesheets/components/_tabs.scss b/app/assets/stylesheets/components/_tabs.scss new file mode 100644 index 0000000..3843abc --- /dev/null +++ b/app/assets/stylesheets/components/_tabs.scss @@ -0,0 +1,56 @@ +/* + Breadcrumbs +*/ + +.tabbed { + $tabs-border-width: em(1); + $tabs-padding-vertical: em(8); + $tabs-padding-horizontal: em(16); + + ul.tabs { + @include span-columns(12); + display: block; + font-family: $montserrat; + height: em(40); + max-height: em(40); + position: relative; + + li { + float: left; + display: block; + background-color: $background-primary; + + a { + border: $tabs-border-width solid $navbar-border; + padding: $tabs-padding-vertical $tabs-padding-horizontal; + float: left; + display: block; + color: white; + } + + &.activeli { + z-index: 100; + background-color: $blue; + + a { + padding-bottom: $tabs-padding-vertical + $tabs-border-width; + border-bottom: 0; + } + } + } + } + + .tabbed-contents { + @include span-columns(12); + border: $tabs-border-width solid $navbar-border; + padding: em(20); + } + + @for $i from 1 through $grid-columns { + ul.tabs-#{$i} { + li { + @include span-columns($i); + } + } + } +} diff --git a/app/assets/stylesheets/layout/_body.scss b/app/assets/stylesheets/layout/_body.scss index 39a496a..b6ad05b 100644 --- a/app/assets/stylesheets/layout/_body.scss +++ b/app/assets/stylesheets/layout/_body.scss @@ -49,3 +49,35 @@ body { @include span-columns(3); @include omega(); } + +/* + Heading styles +*/ + +h1, h2, h3, h4, h5, h6 { + + &.fancy { + text-align: center; + position: relative; + background-color: $light-blue; + + &:before { + content: ""; + display: block; + border-top: 2px solid $blue; + width: 100%; + height: 2px; + position: absolute; + top: 50%; + z-index: 1; + } + + span { + background: inherit; + padding: 0 .5em; + position: relative; + display: inline-block; + z-index: 1; + } + } +} \ No newline at end of file diff --git a/app/assets/stylesheets/layout/_header.scss b/app/assets/stylesheets/layout/_header.scss index 318efc3..90e557f 100644 --- a/app/assets/stylesheets/layout/_header.scss +++ b/app/assets/stylesheets/layout/_header.scss @@ -6,7 +6,7 @@ nav.top { background-color: $navigation-background; border-bottom: 1px solid $medium-gray; - font-family: $monserrat; + font-family: $montserrat; height: $navigation-height; width: 100%; z-index: 999; @@ -23,7 +23,7 @@ nav.top { cursor: pointer; display: block; float: right; - font-family: $monserrat; + font-family: $montserrat; font-weight: 700; line-height: $navigation-height; margin: 0; diff --git a/app/assets/stylesheets/layout/_navigation.scss b/app/assets/stylesheets/layout/_navigation.scss index 65f94da..fdb26d1 100644 --- a/app/assets/stylesheets/layout/_navigation.scss +++ b/app/assets/stylesheets/layout/_navigation.scss @@ -3,7 +3,7 @@ */ #menu { - font-family: "Montserrat", sans-serif; + font-family: $montserrat; background-color: $background-primary; height: em(60); max-height: em(60); diff --git a/app/assets/stylesheets/mixins/_buttons.scss b/app/assets/stylesheets/mixins/_buttons.scss index ccd74f4..a5e8908 100644 --- a/app/assets/stylesheets/mixins/_buttons.scss +++ b/app/assets/stylesheets/mixins/_buttons.scss @@ -3,7 +3,7 @@ */ @mixin button($background: $button-primary, $text: $button-text) { - font-family: $monserrat; + font-family: $montserrat; font-size: em(16); background-color: $background; color: $text; diff --git a/app/assets/stylesheets/pages/_forums.scss b/app/assets/stylesheets/pages/_forums.scss index 5c646ff..ebb9c3c 100644 --- a/app/assets/stylesheets/pages/_forums.scss +++ b/app/assets/stylesheets/pages/_forums.scss @@ -141,6 +141,7 @@ div#categories { .content { @include span-columns(9); @include omega; + background: image-url('images/layout/forum-bg-pattern.png') top left; .text, .signature { diff --git a/app/assets/stylesheets/pages/_matches.scss b/app/assets/stylesheets/pages/_matches.scss new file mode 100644 index 0000000..b999667 --- /dev/null +++ b/app/assets/stylesheets/pages/_matches.scss @@ -0,0 +1,22 @@ +/* + Matches Listing +*/ + +#matches { + table-layout: auto; + margin-bottom: em(20); + + .opponent { + width: 30%; + } + + .date, + .maps { + width: 20%; + } + + .score { + width: 10%; + text-align: right; + } +} \ No newline at end of file diff --git a/app/assets/stylesheets/pages/_teams.scss b/app/assets/stylesheets/pages/_teams.scss new file mode 100644 index 0000000..4b9c1bc --- /dev/null +++ b/app/assets/stylesheets/pages/_teams.scss @@ -0,0 +1,94 @@ +/* + Teams Listing +*/ + +#teams { + table { + table-layout: auto; + } + + .country { + width: 5%; + } + + .name { + width: 45%; + } + + .irc { + width: 20%; + } + + .members { + width: 10%; + } + + .actions { + width: 20%; + text-align: right; + } +} + +/* + Team Profiles +*/ + +#team-profile { + + .logo { + @include span-columns(12); + margin: em(20) 0; + text-align: center; + + img { + display: inline-block; + float: none; + width: auto; + } + } + + .controls { + @include span-columns(12); + margin: em(20) 0; + } +} + + +#members { + table-layout: auto; + + .country, + .age { + width: 5%; + } + + .member { + width: 20%; + } + + .steamid { + width: 15%; + } + + .rank { + width: 10%; + } + + .note { + width: 30%; + } + + .joined { + width: 10%; + } + + .joined { + text-align: right; + } + + &.short { + .rank { + width: 40%; + } + } +} \ No newline at end of file diff --git a/app/assets/stylesheets/pages/_users.scss b/app/assets/stylesheets/pages/_users.scss new file mode 100644 index 0000000..557a12c --- /dev/null +++ b/app/assets/stylesheets/pages/_users.scss @@ -0,0 +1,21 @@ +#users { + table-layout: auto; + + .country, + .age { + width: 5%; + } + + .username, + .name { + width: 25%; + } + + .steamid { + width: 20%; + } + + .actions { + text-align: right; + } +} \ No newline at end of file diff --git a/app/controllers/comments_controller.rb b/app/controllers/comments_controller.rb index bb9d523..f066092 100644 --- a/app/controllers/comments_controller.rb +++ b/app/controllers/comments_controller.rb @@ -7,7 +7,7 @@ class CommentsController < ApplicationController end def show - @comments = Comment.recent5.all conditions: {commentable_id: params[:id2], commentable_type: params[:id]} + @comments = Comment.recent5.all conditions: { commentable_id: params[:id2], commentable_type: params[:id] } render partial: 'list', layout: false end diff --git a/app/controllers/forums_controller.rb b/app/controllers/forums_controller.rb index bf13ad8..09faf4f 100644 --- a/app/controllers/forums_controller.rb +++ b/app/controllers/forums_controller.rb @@ -8,7 +8,14 @@ class ForumsController < ApplicationController def show raise AccessError unless @forum.can_show? cuser - @topics = @forum.topics.all + + @topics = Topic.where(forum_id: @forum.id) + .joins(:posts, :user, :users_who_read) + .includes(:lock) + .group('topics.id') + .order('state DESC, posts.id DESC') + .paginate(page: params[:page], per_page: 30) + @forum.read_by! cuser if cuser @nobody = true end diff --git a/app/models/concerns/extra.rb b/app/models/concerns/extra.rb index 55093b9..be784b8 100644 --- a/app/models/concerns/extra.rb +++ b/app/models/concerns/extra.rb @@ -1,76 +1,76 @@ module Extra - extend ActiveSupport::Concern + extend ActiveSupport::Concern - CODING_HTML = 0 - CODING_BBCODE = 1 - CODING_MARKDOWN = 2 + CODING_HTML = 0 + CODING_BBCODE = 1 + CODING_MARKDOWN = 2 included do - def codings - { - CODING_HTML => "Plain HTML", - CODING_BBCODE => "BBCode", - CODING_MARKDOWN => "Markdown" - } - end + def codings + { + CODING_HTML => "Plain HTML", + CODING_BBCODE => "BBCode", + CODING_MARKDOWN => "Markdown" + } + end - def check_params(params, filter) - (params.instance_of?(Array) ? params : params.keys).each do |key| - return false unless filter.include? key.to_sym - end - return true - end + def check_params(params, filter) + (params.instance_of?(Array) ? params : params.keys).each do |key| + return false unless filter.include? key.to_sym + end + return true + end - def error_messages - self.errors.full_messages.uniq - end + def error_messages + self.errors.full_messages.uniq + end - def bbcode_to_html(text) - Sanitize.clean(text.to_s).bbcode_to_html.gsub(/\n|\r\n/, "<br>").html_safe - end + def bbcode_to_html(text) + Sanitize.clean(text.to_s).bbcode_to_html.gsub(/\n|\r\n/, "<br>").html_safe + end - def move_up(scope, column = "position") - n = 0 - objects = self.class.all(conditions: scope, order: column) - binding.pry - objects.each do |item| - if item.id == id and n > 0 - old_position = item.read_attribute(:column) - item.update_attribute(column, objects.fetch(n-1).read_attribute(:column)) - objects.fetch(n-1).update_attribute(column, old_position) - end - n = n + 1 - end - end + def move_up(scope, column = "position") + n = 0 + objects = self.class.all(conditions: scope, order: column) + binding.pry + objects.each do |item| + if item.id == id and n > 0 + old_position = item.read_attribute(:column) + item.update_attribute(column, objects.fetch(n-1).read_attribute(:column)) + objects.fetch(n-1).update_attribute(column, old_position) + end + n = n + 1 + end + end - def move_down(scope, column = "position") - n = 0 - objects = self.class.all(conditions: scope, order: column) - binding.pry - objects.each do |item| - if item.id == id and n < (objects.length-1) - old_position = item.read_attribute(:column) - item.update_attribute(column, objects.fetch(n+1).read_attribute(:column)) - objects.fetch(n+1).update_attribute(column, old_position) - end - n = n + 1 - end - end + def move_down(scope, column = "position") + n = 0 + objects = self.class.all(conditions: scope, order: column) + binding.pry + objects.each do |item| + if item.id == id and n < (objects.length-1) + old_position = item.read_attribute(:column) + item.update_attribute(column, objects.fetch(n+1).read_attribute(:column)) + objects.fetch(n+1).update_attribute(column, old_position) + end + n = n + 1 + end + end - def can_show? cuser - true - end + def can_show? cuser + true + end - def can_create? cuser - true - end + def can_create? cuser + true + end - def can_update? cuser - true - end + def can_update? cuser + true + end - def can_destroy? cuser - true - end - end + def can_destroy? cuser + true + end + end end \ No newline at end of file diff --git a/app/models/topic.rb b/app/models/topic.rb index fc405ca..b13001f 100644 --- a/app/models/topic.rb +++ b/app/models/topic.rb @@ -57,7 +57,23 @@ class Topic < ActiveRecord::Base end def view_count - self.view_counts.length + view_counts.length + end + + def cache_key(key) + "/topics/#{id}/#{key}" + end + + def cached_view_count + Rails.cache.fetch(cache_key('view_count'), expires_in: 24.hours) do + view_count + end + end + + def cached_posts_count + Rails.cache.fetch(cache_key('posts'), expires_in: 12.hours) do + posts.count - 1 + end end def make_post diff --git a/app/models/user.rb b/app/models/user.rb index 7190a16..e54396b 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -163,7 +163,11 @@ class User < ActiveRecord::Base end def from - profile.town ? "#{profile.town}, #{country_s}" : "#{country_s}" + if profile.town.length > 0 + "#{profile.town}, #{country_s}" + else + "#{country_s}" + end end def age diff --git a/app/views/application/_header.html.erb b/app/views/application/_header.html.erb index 6a73a1c..9576d02 100644 --- a/app/views/application/_header.html.erb +++ b/app/views/application/_header.html.erb @@ -34,7 +34,7 @@ </nav> <div class="wrapper banner"> <div id="logo"> - <%= image_tag "logo.png" %> + <%= link_to image_tag("logo.png"), root_path %> </div> <div id="authentication"> <% if cuser %> diff --git a/app/views/forums/show.html.erb b/app/views/forums/show.html.erb index 86f5a22..8ba7312 100644 --- a/app/views/forums/show.html.erb +++ b/app/views/forums/show.html.erb @@ -6,6 +6,8 @@ <h2><%=h @forum.title %></h2> +<%= will_paginate @topics %> + <table id="topics"> <tr> <th class="topic">Topic</th> @@ -14,7 +16,7 @@ <th class="views">Views</th> <th class="last">Last Post</th> </tr> - <% @forum.topics.basic.ordered.each do |topic| %> + <% @topics.each do |topic| %> <tr> <td> <h5> @@ -36,8 +38,8 @@ <% end %> </td> <td><%= namelink(topic.user) %></td> - <td><%=h topic.posts.count-1 %></td> - <td><%=h topic.view_count %></td> + <td><%=h topic.cached_posts_count %></td> + <td><%=h topic.cached_view_count %></td> <td> <%= link_to lastpost(topic) do %> <%=h topic.posts.last.user %><br> @@ -48,4 +50,6 @@ <% end %> </table> +<%= will_paginate @topics %> + <%= render partial: 'controls', locals: { forum: @forum } %> diff --git a/app/views/matches/_list.html.erb b/app/views/matches/_list.html.erb index 08b4c48..109bdd1 100644 --- a/app/views/matches/_list.html.erb +++ b/app/views/matches/_list.html.erb @@ -1,18 +1,18 @@ -<table class="data"> +<table id="matches" class="<%= 'contest' if contest %>"> <tr> <% if contest %> - <th width="20%">Contest</th> - <th width="20%">Opponent</th> + <th class="contest">Contest</th> + <th class="opponent">Opponent</th> <% else %> - <th width="30%">Opponent</th> + <th class="opponent">Opponent</th> <% end %> - <th width="20%">Date</th> + <th class="date">Date</th> <% unless defined? exclude_maps %> - <th width="20%">Maps</th> + <th class="maps">Maps</th> <% end %> - <th width="5%">Score</th> + <th class="score">Score</th> <% if matches.first and matches.first.contest.contest_type == Contest::TYPE_LADDER %> - <th width="5%">Points</th> + <th class="points">Points</th> <% end %> </tr> @@ -35,21 +35,21 @@ <%= match.map1 %>, <%= match.map2 %> </td> <% end %> - <td> + <td class="score"> <%= link_to match, :class => "bold #{match.score_color}" do %> <% if friendly == match.contester1.team %> - <%= h match.score1 %> - <%= h match.score2 %> + <%=h match.score1 %> - <%=h match.score2 %> <% else %> - <%= h match.score2 %> - <%= h match.score1 %> + <%=h match.score2 %> - <%=h match.score1 %> <% end %> <% end %> </td> <% if match.contest.contest_type == Contest::TYPE_LADDER %> <td> <% if match.get_friendly(:points) > 0 %> - <%= image_tag "icons/up.gif" %> + <%= icon 'chevron-up' %> <% elsif match.get_friendly(:points) < 0 %> - <%= image_tag "icons/down.gif" %> + <%= icon 'chevron-down' %> <% end %> <%= match.get_friendly(:points) %> </td> diff --git a/app/views/posts/_post.html.erb b/app/views/posts/_post.html.erb index 3e388a4..7c2adb9 100644 --- a/app/views/posts/_post.html.erb +++ b/app/views/posts/_post.html.erb @@ -9,10 +9,17 @@ </div> <% if post.user.team %> - <%= namelink post.user.team %> + <strong><%= namelink post.user.team %></strong> <% end %> - <%= cascade post.user, [["Posts", "posts.count"], "from", "joined"] %> + <dl> + <dt>Posts</dt> + <dd><%= post.user.posts.count %></dd> + <dt>Location</dt> + <dd><%= post.user.from %></dd> + <dt>Joined</dt> + <dd><%= post.user.joined %></dd> + </dl> </div> <div class="content"> diff --git a/app/views/teamers/_list.html.erb b/app/views/teamers/_list.html.erb index 69f009c..8ed86c0 100644 --- a/app/views/teamers/_list.html.erb +++ b/app/views/teamers/_list.html.erb @@ -1,38 +1,30 @@ -<table class="data"> +<table id="members" class="<%= 'short' if !comment %>"> <tr> - <th> </th> - <th>Member</th> - <% if cuser %> - <th>Name</th> - <% end %> - <th>Age</th> - <th>SteamID</th> - <th>Rank</th> + <th class="country"></th> + <th class="member">Member</th> + <th class="steamid">SteamID</th> + <th class="rank">Rank</th> <% if comment %> - <th>Comment</th> + <th class="note">Comment</th> <% end %> - <th>Joined</th> + <th class="joined">Joined</th> </tr> <% teamers.each do |member| %> - <% next if blacklist and blacklist.exists? :user_id => member.user_id %> + <% next if blacklist and blacklist.exists? user_id: member.user_id %> <% next if member.user.nil? %> - <tr class="<%= cycle('even', 'odd') %>"> + <tr> <td><%= flag member.user.country %></td> <td><%= namelink member.user %></td> - <% if cuser %> - <td><%= h member.user.realname %></td> - <% end %> - <td><%= h member.user.age %></td> - <td><%= h member.user.steamid %></td> + <td><%=h member.user.steamid %></td> <% if member.rank == Teamer::RANK_REMOVED %> <td>Ex-Member</td> <% else %> <td><%= member.ranks[member.rank] %></td> <% end %> <% if comment %> - <td><%= h member.comment %></td> + <td><%=h member.comment %></td> <% end %> - <td><%= shortdate member.created_at %></td> + <td class="joined"><%= shortdate member.created_at %></td> </tr> <% end %> </table> diff --git a/app/views/teams/_list.html.erb b/app/views/teams/_list.html.erb index 6394ef8..3e3dc23 100644 --- a/app/views/teams/_list.html.erb +++ b/app/views/teams/_list.html.erb @@ -1,28 +1,34 @@ -<table class="data"> +<table> <tr> - <th></th> - <th>Name</th> - <th>Irc</th> - <th>Members</th> + <th class="country"></th> + <th class="name">Name</th> + <th class="irc">IRC</th> + <th class="members">Members</th> <% if cuser and cuser.admin? %> - <th>Options</th> + <th class="actions"></th> <% end %> </tr> <% for team in teams %> <% if team.teamers_num > 0 %> - <tr class="<%= cycle('even', 'odd') %>"> + <tr> <td><%= flag team.country %></td> <td><%= namelink team %></td> - <td><%= h team.irc[0,15] if team.irc %></td> + <td><%= h team.irc if team.irc %></td> <td><%= h team.teamers_num %></td> <% if cuser and cuser.admin? %> - <td> - <%= link_to 'Edit', edit_team_path(team) %> + <td class="actions"> + <%= link_to edit_team_path(team) do %> + <%= icon 'pencil' %> Edit + <% end %> <% if team.active %> - <%= link_to 'Destroy', team, :confirm => 'Are you sure?', :method => :delete %> + <%= link_to team, confirm: 'Are you sure?', method: :delete do %> + <%= icon 'times' %> Delete + <% end %> <% else %> - <%= link_to 'Recover', :action => "recover", :id => team %> + <%= link_to action: "recover", id: team do %> + <%= icon 'save' %> + <% end %> <% end %> </td> <% end %> diff --git a/app/views/teams/index.html.erb b/app/views/teams/index.html.erb index af2f79e..3ca5627 100644 --- a/app/views/teams/index.html.erb +++ b/app/views/teams/index.html.erb @@ -1,9 +1,10 @@ -<h1>Listing teams</h1> <h4>Teams with 0 members are not displayed.</h4> +<h1>Listing teams</h1> +<p>Teams with no current members are not displayed.</p> -<div id="box"> - <%= render :partial => "list", :locals => {:teams => @teams} %> +<div id="teams"> + <%= render partial: 'list', locals: { teams: @teams } %> </div> <script type="text/javascript"> - var tabber1 = new Yetii({id: 'teamsTab'}); + new Yetii({id: 'teamsTab'}); </script> diff --git a/app/views/teams/show.html.erb b/app/views/teams/show.html.erb index d5241ec..42bd0bc 100644 --- a/app/views/teams/show.html.erb +++ b/app/views/teams/show.html.erb @@ -1,108 +1,89 @@ -<h1 class="center"> - <%= h @team.name %> -</h1> +<div id="team-profile"> + <h1 class="fancy"> + <span><%=h @team.name %></span> + </h1> -<% if @team.logo %> - <%= image_tag @team.logo.url, :class => "centered" %> -<% end %> - -<br /> - -<div id="teamTab"> - <ul id="teamTab-nav" class="tabs"> - <li><a href="#general">General</a></li> - <li><a href="#members">Members</a></li> - <li><a href="#matches">Matches</a></li> - <li><a href="#statistics">Statistics</a></li> - </ul> - - <div class="box wide tabs"> - <div class="tab" id="general"> - <table class="split"> - <tr> - <th>Irc:</th> - <td><%= h @team.irc %></td> - </tr> - - <tr> - <th>Web:</th> - <td><%= h @team.web %></td> - </tr> - - <tr> - <th>Tag:</th> - <td><%= h @team.tag %></td> - </tr> - - <tr> - <th>Country:</th> - <td><%= h @team.country %></td> - </tr> - - <tr> - <th>Founder:</th> - <td><%= namelink @team.founder %></td> - </tr> - - <tr> - <th>Comment:</th> - <td><%= h @team.comment %></td> - </tr> - - <% if @team.recruiting %> - <tr> - <th>Recruiting:</th> - <td><%= h @team.recruiting %></td> - </tr> - <% end %> - </table> - - <p class="center"> - <%= link_to "Send a message", :controller => "messages", :action => "new", :id => "Team", :id2 => @team %> - </p> + <% if @team.logo %> + <div class="logo"> + <%= image_tag @team.logo.url, class: 'logo' %> </div> + <% end %> - <div class="tab" id="members"> - <h3 class="center"> - Current Members - </h3> + <div id="team" class="tabbed"> + <ul id="team-nav" class="tabs"> + <li><a href="#general">General</a></li> + <li><a href="#members">Members</a></li> + <li><a href="#matches">Matches</a></li> + <li><a href="#statistics">Statistics</a></li> + </ul> - <%= render :partial => "teamers/list", :locals => {:teamers => @team.teamers.active.ordered.distinct, :blacklist => false, :comment => true } %> + <div class="tabbed-contents"> + <div class="tab" id="general"> + <dl> + <dt>Irc:</dt> + <dd><%= h @team.irc %></dd> + <dt>Web:</dt> + <dd><%= h @team.web %></dd> + <dt>Tag:</dt> + <dd><%= h @team.tag %></dd> + <dt>Country:</dt> + <dd><%= h @team.country %></dd> + <dt>Founder:</dt> + <dd><%= namelink @team.founder %></dd> + <dt>Comment:</dt> + <dd><%= h @team.comment %></dd> + <% if @team.recruiting %> + <dt>Recruiting:</dt> + <dd><%= h @team.recruiting %></dd> + <% end %> + </dl> - <h3 class="center"> - Past Members - </h3> + <%= link_to "Send a message", { controller: "messages", action: "new", id: "Team", id2: @team }, { class: 'button tiny' } %> + </div> - <%= render :partial => "teamers/list", :locals => {:teamers => @team.teamers.past.distinct, :blacklist => @team.teamers.active.ordered.distinct, :comment => false} %> - </div> + <div class="tab" id="members"> + <h3>Current Members</h3> + <%= render partial: "teamers/list", locals: { teamers: @team.teamers.active.ordered.distinct, blacklist: false, comment: true } %> - <div class="tab" id="matches"> - <% @team.contesters.chronological.each do |contester| %> - <% next if Match.finished.ordered.of_contester(contester).count == 0 %> - <h3> - <%= link_to contester.contest, contester.contest, :name => "contest_#{contester.contest.id}" %> - </h3> + <h3>Past Members</h3> + <%= render partial: "teamers/list", locals: { teamers: @team.teamers.past.distinct, blacklist: @team.teamers.active.ordered.distinct, comment: false } %> + </div> - <%= render :partial => "matches/list", - :locals => {:matches => Match.finished.ordered.of_contester(contester), :friendly => contester.team, :contest => false} %> - <% end %> - </div> + <div class="tab" id="matches"> + <% @team.contesters.chronological.each do |contester| %> + <% next if Match.finished.ordered.of_contester(contester).count == 0 %> + <h3> + <%= link_to contester.contest, contester.contest, :name => "contest_#{contester.contest.id}" %> + </h3> + <%= render partial: "matches/list", locals: { matches: Match.finished.ordered.of_contester(contester), friendly: contester.team, contest: false } %> + <% end %> + </div> - <div class="tab" id="matches"> - <p> - <b>Matches:</b> <%= @team.matches_finished.count %> played / <%= @team.matches.count %> total<br /> - - <b>Won:</b> <%= @team.matches_won.count %> (<%= 100.0*@team.matches_won.count/@team.matches_finished.count %> %) <br /> - - <b>Lost:</b> <%= @team.matches_lost.count %> (<%= 100.0*@team.matches_lost.count/@team.matches_finished.count %> %) <br /> - - <b>Draw:</b> <%= @team.matches_draw.count %> (<%= 100.0*@team.matches_draw.count/@team.matches_finished.count %> %) <br /> - </p> + <div class="tab" id="matches"> + <dl> + <dt>Matches:</dt> + <dd><%= @team.matches_finished.count %> dllayed / <%= @team.matches.count %> total</dd> + <dt>Won:</dt> + <dd><%= @team.matches_won.count %> (<%= 100.0*@team.matches_won.count/@team.matches_finished.count %> %)</dd> + <dt>Lost:</dt> + <dd><%= @team.matches_lost.count %> (<%= 100.0*@team.matches_lost.count/@team.matches_finished.count %> %)</dd> + <dt>Draw:</dt> + <dd><%= @team.matches_draw.count %> (<%= 100.0*@team.matches_draw.count/@team.matches_finished.count %> %)</dd> + </dl> + </div> </div> </div> + + <script type="text/javascript"> + new Yetii({ + id: 'team', + active: 2 + }); + </script> + + <% if cuser and @team.can_update? cuser %> + <div class="controls"> + <%= link_to 'Edit Team', edit_team_path(@team), class: 'button' %> + </div> + <% end %> </div> - -<script type="text/javascript"> - var tabber1 = new Yetii({id: 'teamTab', active: 2}); -</script> - -<% if cuser and @team.can_update? cuser %> - <%= link_to 'Edit', edit_team_path(@team) %> -<% end %> diff --git a/app/views/topics/show.html.erb b/app/views/topics/show.html.erb index a65041b..77a7a7a 100644 --- a/app/views/topics/show.html.erb +++ b/app/views/topics/show.html.erb @@ -22,9 +22,13 @@ <% end %> <% if @newpost.errors.count > 0 %> - <% @newpost.error_messages.each do |m| %> - <%= h m %><br> - <% end %> + <div class="flash warning"> + <ul> + <% @newpost.error_messages.each do |m| %> + <li><%= h m %></li> + <% end %> + </ul> + </div> <% end %> </div> @@ -46,7 +50,7 @@ <%= will_paginate @posts %> - <div class="right minitext"> + <div> <% if @newpost.can_create? cuser %> <%= link_to_function 'Fast Reply', "$('#reply').fadeIn('slow')", class: 'button' %> <%= link_to 'Reply', new_post_path(@newpost, id: @topic), class: 'button' %> diff --git a/app/views/users/edit.html.erb b/app/views/users/edit.html.erb index 118a43b..55bb571 100644 --- a/app/views/users/edit.html.erb +++ b/app/views/users/edit.html.erb @@ -2,8 +2,8 @@ <%= form_for @user, :html => { :multipart => true } do |f| %> <% f.fields_for :profile do |p| %> - <div id="userTab"> - <ul id="userTab-nav" class="tabs"> + <div id="user" class="tabbed"> + <ul id="user-nav" class="tabs"> <li><a href="#userTabGeneral">General</a></li> <li><a href="#userTabContact">Contact</a></li> <li><a href="#userTabCountry"><%= t('profile.locals') %></a></li> @@ -14,7 +14,7 @@ <li><a href="#notifications">Notify</a></li> </ul> - <div class="box wide tabs"> + <div class="tabbed-contents"> <div class="tab" id="userTabGeneral"> <% if @user.errors.any? %> <div id="error_explanation"> @@ -286,5 +286,7 @@ <% end %> <script type="text/javascript"> - var tabber1 = new Yetii({id: 'userTab'}); + new Yetii({ + id: 'user' + }); </script> diff --git a/app/views/users/index.html.erb b/app/views/users/index.html.erb index 5b7137c..c11bba2 100644 --- a/app/views/users/index.html.erb +++ b/app/views/users/index.html.erb @@ -1,55 +1,47 @@ -<h1>Listing users</h1> +<h1>Listing Users</h1> -<%= form_tag users_path, :method => 'get' do %> +<%= form_tag(users_path, method: 'get', class: 'square search') do %> <%= hidden_field_tag :direction, params[:direction] %> <%= hidden_field_tag :sort, params[:sort] %> - <p> + <div class="fields query"> <%= text_field_tag :search, params[:search] %> - <%= submit_tag "Search", :name => nil %> - </p> + </div> + <div class="controls"> + <%= submit_tag "Search", name: nil %> + </div> <% end %> -<table id="usersTable" class="data"> +<table id="users"> <tr> - <th> - Country - </th> - <th> - Username - </th> - <th> - Real name - </th> - <th> - Steam ID - </th> - <th> - Age - </th> + <th class="country"></th> + <th class="username">Username</th> + <th class="name">Name</th> + <th class="steamid">Steam ID</th> + <th class="age">Age</th> <% if cuser and cuser.admin? %> - <th> - Options - </th> + <th class="actions"></th> <% end %> </tr> <% @users.each do |user| %> - <tr class="<%= cycle('even', 'odd') %>"> + <tr> <td><%= flag user.country %></td> <td><%= link_to (h user.username), user %></td> <td><%= h user.firstname %> <%=h user.lastname %></td> <td><%= h user.steamid %></td> <td><%= user.age %></td> <% if cuser and cuser.admin? %> - <td> - <%= link_to 'Edit', edit_user_path(user) %> - <%= link_to 'Delete', user, :confirm => "Proceed to delete?", :method => :delete %> + <td class="actions"> + <%= link_to edit_user_path(user) do %> + <%= icon 'pencil' %> Edit + <% end %> + <%= link_to user, confirm: "Proceed to delete?", method: :delete do %> + <%= icon 'times' %> Delete + <% end %> </td> <% end %> </tr> <% end %> </table> -<p> - <%= will_paginate @users %> -</p> +<%= will_paginate @users %> diff --git a/config/application.rb b/config/application.rb index 8e08714..5fe9a48 100644 --- a/config/application.rb +++ b/config/application.rb @@ -12,12 +12,11 @@ module Ensl # Custom directories with classes and modules you want to be autoloadable. config.autoload_paths += Dir["#{config.root}/app/services/**/", "#{config.root}/app/models/concerns/"] - # Only load the plugins named here, in the order given (default is alphabetical). - # :all can be used as a placeholder for all plugins nowt explicitly named. - # config.plugins = [ :exception_notification, :ssl_requirement, :all ] + # Load secrets from .env + config.secret_token = ENV['APP_SECRET'] - # Activate observers that should always be running. - # config.active_record.observers = :cacher, :garbage_collector, :forum_observer + # Use cookies + config.session_store :cookie_store, :key => '_ENSL_session_key', :expire_after => 30.days.to_i # Set Time.zone default to the specified zone and make Active Record auto-convert to this zone. # Run "rake -D time" for a list of tasks for finding time zone names. Default is UTC. diff --git a/config/deploy/staging.rb b/config/deploy/staging.rb index 58c65d4..6f04ccb 100644 --- a/config/deploy/staging.rb +++ b/config/deploy/staging.rb @@ -1,4 +1,4 @@ -set :branch, 'develop' +set :branch, 'feature-redesign' set :deploy_to, '/var/www/virtual/ensl.org/staging/rails' set :rails_env, 'staging' diff --git a/config/environments/development.rb b/config/environments/development.rb index 42d5820..6a8fbf4 100644 --- a/config/environments/development.rb +++ b/config/environments/development.rb @@ -27,4 +27,10 @@ Ensl::Application.configure do # Expands the lines which load the assets config.assets.debug = true + + # Use a different cache store + config.cache_store = :dalli_store + + # Enable threaded mode + config.threadsafe! end diff --git a/config/environments/production.rb b/config/environments/production.rb index 980ff81..f607881 100644 --- a/config/environments/production.rb +++ b/config/environments/production.rb @@ -53,7 +53,7 @@ Ensl::Application.configure do config.action_mailer.raise_delivery_errors = true # Enable threaded mode - # config.threadsafe! + config.threadsafe! # Enable locale fallbacks for I18n (makes lookups for any locale fall back to # the I18n.default_locale when a translation can not be found) diff --git a/config/environments/staging.rb b/config/environments/staging.rb index 1bf7d89..797adaa 100644 --- a/config/environments/staging.rb +++ b/config/environments/staging.rb @@ -53,7 +53,7 @@ Ensl::Application.configure do config.action_mailer.raise_delivery_errors = true # Enable threaded mode - # config.threadsafe! + config.threadsafe! # Enable locale fallbacks for I18n (makes lookups for any locale fall back to # the I18n.default_locale when a translation can not be found) diff --git a/config/environments/test.rb b/config/environments/test.rb index 46393fe..d099083 100644 --- a/config/environments/test.rb +++ b/config/environments/test.rb @@ -11,14 +11,14 @@ Ensl::Application.configure do config.whiny_nils = true # Show full error reports and disable caching - config.consider_all_requests_local = true + config.consider_all_requests_local = true config.action_controller.perform_caching = false # Raise exceptions instead of rendering exception templates config.action_dispatch.show_exceptions = false # Disable request forgery protection in test environment - config.action_controller.allow_forgery_protection = false + config.action_controller.allow_forgery_protection = false # Tell Action Mailer not to deliver emails to the real world. # The :test delivery method accumulates sent emails in the @@ -32,4 +32,7 @@ Ensl::Application.configure do # Print deprecation notices to the stderr config.active_support.deprecation = :stderr + + # Enable threaded mode + config.threadsafe! end diff --git a/config/initializers/phpcookies.rb b/config/initializers/phpcookies.rb deleted file mode 100644 index f5c799f..0000000 --- a/config/initializers/phpcookies.rb +++ /dev/null @@ -1,11 +0,0 @@ -module ActionDispatch - class Cookies - class SignedCookieJar - def initialize(parent_jar, secret) - ensure_secret_secure(secret) - @parent_jar = parent_jar - @verifier = MessageVerifier.new(secret,:serializer=>YAML) - end - end - end -end diff --git a/config/initializers/secret_token.rb b/config/initializers/secret_token.rb deleted file mode 100644 index 7a11632..0000000 --- a/config/initializers/secret_token.rb +++ /dev/null @@ -1 +0,0 @@ -Ensl::Application.config.secret_token = ENV['APP_SECRET'] diff --git a/config/initializers/session_store.rb b/config/initializers/session_store.rb deleted file mode 100644 index 324191f..0000000 --- a/config/initializers/session_store.rb +++ /dev/null @@ -1,4 +0,0 @@ -Ensl::Application.config.session_store :active_record_store, - :key => '_ENSL_session_key', - :expire_after => 30.days.to_i - \ No newline at end of file