Commit a767a86ce8ae768242013d9dfd5d68f2bd0dd77f

Authored by gitlabhq
2 parents ae47d692 5c9cb850

Merge branch 'dev'

Showing 71 changed files with 1354 additions and 267 deletions   Show diff stats
Gemfile
... ... @@ -19,6 +19,7 @@ gem "pygments.rb", "0.2.3"
19 19 gem "thin"
20 20 gem "git"
21 21 gem "acts_as_list"
  22 +gem 'rdiscount'
22 23  
23 24 group :assets do
24 25 gem 'sass-rails', " ~> 3.1.0"
... ... @@ -26,7 +27,8 @@ group :assets do
26 27 gem 'uglifier'
27 28 end
28 29  
29   -group :development do
  30 +group :development do
  31 + gem 'letter_opener'
30 32 gem 'rails-footnotes', '>= 3.7.5.rc4'
31 33 gem 'annotate', :git => 'git://github.com/ctran/annotate_models.git'
32 34 end
... ...
Gemfile.lock
... ... @@ -119,6 +119,8 @@ GEM
119 119 rails (>= 3.0.0)
120 120 launchy (2.0.5)
121 121 addressable (~> 2.2.6)
  122 + letter_opener (0.0.2)
  123 + launchy
122 124 libv8 (3.3.10.2)
123 125 linecache19 (0.5.12)
124 126 ruby_core_source (>= 0.1.4)
... ... @@ -161,6 +163,7 @@ GEM
161 163 rdoc (~> 3.4)
162 164 thor (~> 0.14.6)
163 165 rake (0.9.2)
  166 + rdiscount (1.6.8)
164 167 rdoc (3.9.4)
165 168 rspec (2.6.0)
166 169 rspec-core (~> 2.6.0)
... ... @@ -261,9 +264,11 @@ DEPENDENCIES
261 264 jquery-rails
262 265 kaminari
263 266 launchy
  267 + letter_opener
264 268 pygments.rb (= 0.2.3)
265 269 rails (= 3.1.0)
266 270 rails-footnotes (>= 3.7.5.rc4)
  271 + rdiscount
267 272 rspec-rails
268 273 ruby-debug19
269 274 sass-rails (~> 3.1.0)
... ...
app/assets/images/.directory
1 1 [Dolphin]
2 2 ShowPreview=true
3   -Timestamp=2011,9,14,20,34,18
  3 +Timestamp=2011,10,28,13,16,25
4 4 Version=2
... ...
app/assets/images/bg-header.png 0 → 100644

212 Bytes

app/assets/images/icon-search.png 0 → 100644

422 Bytes

app/assets/images/images.png 0 → 100644

8.49 KB

app/assets/images/login-logo.png 0 → 100644

1.4 KB

app/assets/javascripts/modernizr-2.0.6.min.js 0 → 100755
... ... @@ -0,0 +1,4 @@
  1 +/* Modernizr 2.0.6 | MIT & BSD
  2 + * Contains: All core tests, html5shiv, yepnope, respond.js. Get your own custom build at www.modernizr.com/download/
  3 + */
  4 +;window.Modernizr=function(a,b,c){function I(){e.input=function(a){for(var b=0,c=a.length;b<c;b++)t[a[b]]=a[b]in l;return t}("autocomplete autofocus list placeholder max min multiple pattern required step".split(" ")),e.inputtypes=function(a){for(var d=0,e,f,h,i=a.length;d<i;d++)l.setAttribute("type",f=a[d]),e=l.type!=="text",e&&(l.value=m,l.style.cssText="position:absolute;visibility:hidden;",/^range$/.test(f)&&l.style.WebkitAppearance!==c?(g.appendChild(l),h=b.defaultView,e=h.getComputedStyle&&h.getComputedStyle(l,null).WebkitAppearance!=="textfield"&&l.offsetHeight!==0,g.removeChild(l)):/^(search|tel)$/.test(f)||(/^(url|email)$/.test(f)?e=l.checkValidity&&l.checkValidity()===!1:/^color$/.test(f)?(g.appendChild(l),g.offsetWidth,e=l.value!=m,g.removeChild(l)):e=l.value!=m)),s[a[d]]=!!e;return s}("search tel url email datetime date month week time datetime-local number range color".split(" "))}function G(a,b){var c=a.charAt(0).toUpperCase()+a.substr(1),d=(a+" "+p.join(c+" ")+c).split(" ");return F(d,b)}function F(a,b){for(var d in a)if(k[a[d]]!==c)return b=="pfx"?a[d]:!0;return!1}function E(a,b){return!!~(""+a).indexOf(b)}function D(a,b){return typeof a===b}function C(a,b){return B(o.join(a+";")+(b||""))}function B(a){k.cssText=a}var d="2.0.6",e={},f=!0,g=b.documentElement,h=b.head||b.getElementsByTagName("head")[0],i="modernizr",j=b.createElement(i),k=j.style,l=b.createElement("input"),m=":)",n=Object.prototype.toString,o=" -webkit- -moz- -o- -ms- -khtml- ".split(" "),p="Webkit Moz O ms Khtml".split(" "),q={svg:"http://www.w3.org/2000/svg"},r={},s={},t={},u=[],v=function(a,c,d,e){var f,h,j,k=b.createElement("div");if(parseInt(d,10))while(d--)j=b.createElement("div"),j.id=e?e[d]:i+(d+1),k.appendChild(j);f=["&shy;","<style>",a,"</style>"].join(""),k.id=i,k.innerHTML+=f,g.appendChild(k),h=c(k,a),k.parentNode.removeChild(k);return!!h},w=function(b){if(a.matchMedia)return matchMedia(b).matches;var c;v("@media "+b+" { #"+i+" { position: absolute; } }",function(b){c=(a.getComputedStyle?getComputedStyle(b,null):b.currentStyle).position=="absolute"});return c},x=function(){function d(d,e){e=e||b.createElement(a[d]||"div"),d="on"+d;var f=d in e;f||(e.setAttribute||(e=b.createElement("div")),e.setAttribute&&e.removeAttribute&&(e.setAttribute(d,""),f=D(e[d],"function"),D(e[d],c)||(e[d]=c),e.removeAttribute(d))),e=null;return f}var a={select:"input",change:"input",submit:"form",reset:"form",error:"img",load:"img",abort:"img"};return d}(),y,z={}.hasOwnProperty,A;!D(z,c)&&!D(z.call,c)?A=function(a,b){return z.call(a,b)}:A=function(a,b){return b in a&&D(a.constructor.prototype[b],c)};var H=function(c,d){var f=c.join(""),g=d.length;v(f,function(c,d){var f=b.styleSheets[b.styleSheets.length-1],h=f.cssRules&&f.cssRules[0]?f.cssRules[0].cssText:f.cssText||"",i=c.childNodes,j={};while(g--)j[i[g].id]=i[g];e.touch="ontouchstart"in a||j.touch.offsetTop===9,e.csstransforms3d=j.csstransforms3d.offsetLeft===9,e.generatedcontent=j.generatedcontent.offsetHeight>=1,e.fontface=/src/i.test(h)&&h.indexOf(d.split(" ")[0])===0},g,d)}(['@font-face {font-family:"font";src:url("https://")}',["@media (",o.join("touch-enabled),("),i,")","{#touch{top:9px;position:absolute}}"].join(""),["@media (",o.join("transform-3d),("),i,")","{#csstransforms3d{left:9px;position:absolute}}"].join(""),['#generatedcontent:after{content:"',m,'";visibility:hidden}'].join("")],["fontface","touch","csstransforms3d","generatedcontent"]);r.flexbox=function(){function c(a,b,c,d){a.style.cssText=o.join(b+":"+c+";")+(d||"")}function a(a,b,c,d){b+=":",a.style.cssText=(b+o.join(c+";"+b)).slice(0,-b.length)+(d||"")}var d=b.createElement("div"),e=b.createElement("div");a(d,"display","box","width:42px;padding:0;"),c(e,"box-flex","1","width:10px;"),d.appendChild(e),g.appendChild(d);var f=e.offsetWidth===42;d.removeChild(e),g.removeChild(d);return f},r.canvas=function(){var a=b.createElement("canvas");return!!a.getContext&&!!a.getContext("2d")},r.canvastext=function(){return!!e.canvas&&!!D(b.createElement("canvas").getContext("2d").fillText,"function")},r.webgl=function(){return!!a.WebGLRenderingContext},r.touch=function(){return e.touch},r.geolocation=function(){return!!navigator.geolocation},r.postmessage=function(){return!!a.postMessage},r.websqldatabase=function(){var b=!!a.openDatabase;return b},r.indexedDB=function(){for(var b=-1,c=p.length;++b<c;)if(a[p[b].toLowerCase()+"IndexedDB"])return!0;return!!a.indexedDB},r.hashchange=function(){return x("hashchange",a)&&(b.documentMode===c||b.documentMode>7)},r.history=function(){return!!a.history&&!!history.pushState},r.draganddrop=function(){return x("dragstart")&&x("drop")},r.websockets=function(){for(var b=-1,c=p.length;++b<c;)if(a[p[b]+"WebSocket"])return!0;return"WebSocket"in a},r.rgba=function(){B("background-color:rgba(150,255,150,.5)");return E(k.backgroundColor,"rgba")},r.hsla=function(){B("background-color:hsla(120,40%,100%,.5)");return E(k.backgroundColor,"rgba")||E(k.backgroundColor,"hsla")},r.multiplebgs=function(){B("background:url(https://),url(https://),red url(https://)");return/(url\s*\(.*?){3}/.test(k.background)},r.backgroundsize=function(){return G("backgroundSize")},r.borderimage=function(){return G("borderImage")},r.borderradius=function(){return G("borderRadius")},r.boxshadow=function(){return G("boxShadow")},r.textshadow=function(){return b.createElement("div").style.textShadow===""},r.opacity=function(){C("opacity:.55");return/^0.55$/.test(k.opacity)},r.cssanimations=function(){return G("animationName")},r.csscolumns=function(){return G("columnCount")},r.cssgradients=function(){var a="background-image:",b="gradient(linear,left top,right bottom,from(#9f9),to(white));",c="linear-gradient(left top,#9f9, white);";B((a+o.join(b+a)+o.join(c+a)).slice(0,-a.length));return E(k.backgroundImage,"gradient")},r.cssreflections=function(){return G("boxReflect")},r.csstransforms=function(){return!!F(["transformProperty","WebkitTransform","MozTransform","OTransform","msTransform"])},r.csstransforms3d=function(){var a=!!F(["perspectiveProperty","WebkitPerspective","MozPerspective","OPerspective","msPerspective"]);a&&"webkitPerspective"in g.style&&(a=e.csstransforms3d);return a},r.csstransitions=function(){return G("transitionProperty")},r.fontface=function(){return e.fontface},r.generatedcontent=function(){return e.generatedcontent},r.video=function(){var a=b.createElement("video"),c=!1;try{if(c=!!a.canPlayType){c=new Boolean(c),c.ogg=a.canPlayType('video/ogg; codecs="theora"');var d='video/mp4; codecs="avc1.42E01E';c.h264=a.canPlayType(d+'"')||a.canPlayType(d+', mp4a.40.2"'),c.webm=a.canPlayType('video/webm; codecs="vp8, vorbis"')}}catch(e){}return c},r.audio=function(){var a=b.createElement("audio"),c=!1;try{if(c=!!a.canPlayType)c=new Boolean(c),c.ogg=a.canPlayType('audio/ogg; codecs="vorbis"'),c.mp3=a.canPlayType("audio/mpeg;"),c.wav=a.canPlayType('audio/wav; codecs="1"'),c.m4a=a.canPlayType("audio/x-m4a;")||a.canPlayType("audio/aac;")}catch(d){}return c},r.localstorage=function(){try{return!!localStorage.getItem}catch(a){return!1}},r.sessionstorage=function(){try{return!!sessionStorage.getItem}catch(a){return!1}},r.webworkers=function(){return!!a.Worker},r.applicationcache=function(){return!!a.applicationCache},r.svg=function(){return!!b.createElementNS&&!!b.createElementNS(q.svg,"svg").createSVGRect},r.inlinesvg=function(){var a=b.createElement("div");a.innerHTML="<svg/>";return(a.firstChild&&a.firstChild.namespaceURI)==q.svg},r.smil=function(){return!!b.createElementNS&&/SVG/.test(n.call(b.createElementNS(q.svg,"animate")))},r.svgclippaths=function(){return!!b.createElementNS&&/SVG/.test(n.call(b.createElementNS(q.svg,"clipPath")))};for(var J in r)A(r,J)&&(y=J.toLowerCase(),e[y]=r[J](),u.push((e[y]?"":"no-")+y));e.input||I(),e.addTest=function(a,b){if(typeof a=="object")for(var d in a)A(a,d)&&e.addTest(d,a[d]);else{a=a.toLowerCase();if(e[a]!==c)return;b=typeof b=="boolean"?b:!!b(),g.className+=" "+(b?"":"no-")+a,e[a]=b}return e},B(""),j=l=null,a.attachEvent&&function(){var a=b.createElement("div");a.innerHTML="<elem></elem>";return a.childNodes.length!==1}()&&function(a,b){function s(a){var b=-1;while(++b<g)a.createElement(f[b])}a.iepp=a.iepp||{};var d=a.iepp,e=d.html5elements||"abbr|article|aside|audio|canvas|datalist|details|figcaption|figure|footer|header|hgroup|mark|meter|nav|output|progress|section|summary|time|video",f=e.split("|"),g=f.length,h=new RegExp("(^|\\s)("+e+")","gi"),i=new RegExp("<(/*)("+e+")","gi"),j=/^\s*[\{\}]\s*$/,k=new RegExp("(^|[^\\n]*?\\s)("+e+")([^\\n]*)({[\\n\\w\\W]*?})","gi"),l=b.createDocumentFragment(),m=b.documentElement,n=m.firstChild,o=b.createElement("body"),p=b.createElement("style"),q=/print|all/,r;d.getCSS=function(a,b){if(a+""===c)return"";var e=-1,f=a.length,g,h=[];while(++e<f){g=a[e];if(g.disabled)continue;b=g.media||b,q.test(b)&&h.push(d.getCSS(g.imports,b),g.cssText),b="all"}return h.join("")},d.parseCSS=function(a){var b=[],c;while((c=k.exec(a))!=null)b.push(((j.exec(c[1])?"\n":c[1])+c[2]+c[3]).replace(h,"$1.iepp_$2")+c[4]);return b.join("\n")},d.writeHTML=function(){var a=-1;r=r||b.body;while(++a<g){var c=b.getElementsByTagName(f[a]),d=c.length,e=-1;while(++e<d)c[e].className.indexOf("iepp_")<0&&(c[e].className+=" iepp_"+f[a])}l.appendChild(r),m.appendChild(o),o.className=r.className,o.id=r.id,o.innerHTML=r.innerHTML.replace(i,"<$1font")},d._beforePrint=function(){p.styleSheet.cssText=d.parseCSS(d.getCSS(b.styleSheets,"all")),d.writeHTML()},d.restoreHTML=function(){o.innerHTML="",m.removeChild(o),m.appendChild(r)},d._afterPrint=function(){d.restoreHTML(),p.styleSheet.cssText=""},s(b),s(l);d.disablePP||(n.insertBefore(p,n.firstChild),p.media="print",p.className="iepp-printshim",a.attachEvent("onbeforeprint",d._beforePrint),a.attachEvent("onafterprint",d._afterPrint))}(a,b),e._version=d,e._prefixes=o,e._domPrefixes=p,e.mq=w,e.hasEvent=x,e.testProp=function(a){return F([a])},e.testAllProps=G,e.testStyles=v,e.prefixed=function(a){return G(a,"pfx")},g.className=g.className.replace(/\bno-js\b/,"")+(f?" js "+u.join(" "):"");return e}(this,this.document),function(a,b){function u(){r(!0)}a.respond={},respond.update=function(){},respond.mediaQueriesSupported=b;if(!b){var c=a.document,d=c.documentElement,e=[],f=[],g=[],h={},i=30,j=c.getElementsByTagName("head")[0]||d,k=j.getElementsByTagName("link"),l=[],m=function(){var b=k,c=b.length,d=0,e,f,g,i;for(;d<c;d++)e=b[d],f=e.href,g=e.media,i=e.rel&&e.rel.toLowerCase()==="stylesheet",!!f&&i&&!h[f]&&(!/^([a-zA-Z]+?:(\/\/)?(www\.)?)/.test(f)||f.replace(RegExp.$1,"").split("/")[0]===a.location.host?l.push({href:f,media:g}):h[f]=!0);n()},n=function(){if(l.length){var a=l.shift();s(a.href,function(b){o(b,a.href,a.media),h[a.href]=!0,n()})}},o=function(a,b,c){var d=a.match(/@media[^\{]+\{([^\{\}]+\{[^\}\{]+\})+/gi),g=d&&d.length||0,b=b.substring(0,b.lastIndexOf("/")),h=function(a){return a.replace(/(url\()['"]?([^\/\)'"][^:\)'"]+)['"]?(\))/g,"$1"+b+"$2$3")},i=!g&&c,j=0,k,l,m,n,o;b.length&&(b+="/"),i&&(g=1);for(;j<g;j++){k=0,i?(l=c,f.push(h(a))):(l=d[j].match(/@media ([^\{]+)\{([\S\s]+?)$/)&&RegExp.$1,f.push(RegExp.$2&&h(RegExp.$2))),n=l.split(","),o=n.length;for(;k<o;k++)m=n[k],e.push({media:m.match(/(only\s+)?([a-zA-Z]+)(\sand)?/)&&RegExp.$2,rules:f.length-1,minw:m.match(/\(min\-width:[\s]*([\s]*[0-9]+)px[\s]*\)/)&&parseFloat(RegExp.$1),maxw:m.match(/\(max\-width:[\s]*([\s]*[0-9]+)px[\s]*\)/)&&parseFloat(RegExp.$1)})}r()},p,q,r=function(a){var b="clientWidth",h=d[b],l=c.compatMode==="CSS1Compat"&&h||c.body[b]||h,m={},n=c.createDocumentFragment(),o=k[k.length-1],s=(new Date).getTime();if(a&&p&&s-p<i)clearTimeout(q),q=setTimeout(r,i);else{p=s;for(var t in e){var u=e[t];if(!u.minw&&!u.maxw||(!u.minw||u.minw&&l>=u.minw)&&(!u.maxw||u.maxw&&l<=u.maxw))m[u.media]||(m[u.media]=[]),m[u.media].push(f[u.rules])}for(var t in g)g[t]&&g[t].parentNode===j&&j.removeChild(g[t]);for(var t in m){var v=c.createElement("style"),w=m[t].join("\n");v.type="text/css",v.media=t,v.styleSheet?v.styleSheet.cssText=w:v.appendChild(c.createTextNode(w)),n.appendChild(v),g.push(v)}j.insertBefore(n,o.nextSibling)}},s=function(a,b){var c=t();if(!!c){c.open("GET",a,!0),c.onreadystatechange=function(){c.readyState==4&&(c.status==200||c.status==304)&&b(c.responseText)};if(c.readyState==4)return;c.send()}},t=function(){var a=!1,b=[function(){return new ActiveXObject("Microsoft.XMLHTTP")},function(){return new XMLHttpRequest}],c=b.length;while(c--){try{a=b[c]()}catch(d){continue}break}return function(){return a}}();m(),respond.update=m,a.addEventListener?a.addEventListener("resize",u,!1):a.attachEvent&&a.attachEvent("onresize",u)}}(this,Modernizr.mq("only all")),function(a,b,c){function k(a){return!a||a=="loaded"||a=="complete"}function j(){var a=1,b=-1;while(p.length- ++b)if(p[b].s&&!(a=p[b].r))break;a&&g()}function i(a){var c=b.createElement("script"),d;c.src=a.s,c.onreadystatechange=c.onload=function(){!d&&k(c.readyState)&&(d=1,j(),c.onload=c.onreadystatechange=null)},m(function(){d||(d=1,j())},H.errorTimeout),a.e?c.onload():n.parentNode.insertBefore(c,n)}function h(a){var c=b.createElement("link"),d;c.href=a.s,c.rel="stylesheet",c.type="text/css";if(!a.e&&(w||r)){var e=function(a){m(function(){if(!d)try{a.sheet.cssRules.length?(d=1,j()):e(a)}catch(b){b.code==1e3||b.message=="security"||b.message=="denied"?(d=1,m(function(){j()},0)):e(a)}},0)};e(c)}else c.onload=function(){d||(d=1,m(function(){j()},0))},a.e&&c.onload();m(function(){d||(d=1,j())},H.errorTimeout),!a.e&&n.parentNode.insertBefore(c,n)}function g(){var a=p.shift();q=1,a?a.t?m(function(){a.t=="c"?h(a):i(a)},0):(a(),j()):q=0}function f(a,c,d,e,f,h){function i(){!o&&k(l.readyState)&&(r.r=o=1,!q&&j(),l.onload=l.onreadystatechange=null,m(function(){u.removeChild(l)},0))}var l=b.createElement(a),o=0,r={t:d,s:c,e:h};l.src=l.data=c,!s&&(l.style.display="none"),l.width=l.height="0",a!="object"&&(l.type=d),l.onload=l.onreadystatechange=i,a=="img"?l.onerror=i:a=="script"&&(l.onerror=function(){r.e=r.r=1,g()}),p.splice(e,0,r),u.insertBefore(l,s?null:n),m(function(){o||(u.removeChild(l),r.r=r.e=o=1,j())},H.errorTimeout)}function e(a,b,c){var d=b=="c"?z:y;q=0,b=b||"j",C(a)?f(d,a,b,this.i++,l,c):(p.splice(this.i++,0,a),p.length==1&&g());return this}function d(){var a=H;a.loader={load:e,i:0};return a}var l=b.documentElement,m=a.setTimeout,n=b.getElementsByTagName("script")[0],o={}.toString,p=[],q=0,r="MozAppearance"in l.style,s=r&&!!b.createRange().compareNode,t=r&&!s,u=s?l:n.parentNode,v=a.opera&&o.call(a.opera)=="[object Opera]",w="webkitAppearance"in l.style,x=w&&"async"in b.createElement("script"),y=r?"object":v||x?"img":"script",z=w?"img":y,A=Array.isArray||function(a){return o.call(a)=="[object Array]"},B=function(a){return Object(a)===a},C=function(a){return typeof a=="string"},D=function(a){return o.call(a)=="[object Function]"},E=[],F={},G,H;H=function(a){function f(a){var b=a.split("!"),c=E.length,d=b.pop(),e=b.length,f={url:d,origUrl:d,prefixes:b},g,h;for(h=0;h<e;h++)g=F[b[h]],g&&(f=g(f));for(h=0;h<c;h++)f=E[h](f);return f}function e(a,b,e,g,h){var i=f(a),j=i.autoCallback;if(!i.bypass){b&&(b=D(b)?b:b[a]||b[g]||b[a.split("/").pop().split("?")[0]]);if(i.instead)return i.instead(a,b,e,g,h);e.load(i.url,i.forceCSS||!i.forceJS&&/css$/.test(i.url)?"c":c,i.noexec),(D(b)||D(j))&&e.load(function(){d(),b&&b(i.origUrl,h,g),j&&j(i.origUrl,h,g)})}}function b(a,b){function c(a){if(C(a))e(a,h,b,0,d);else if(B(a))for(i in a)a.hasOwnProperty(i)&&e(a[i],h,b,i,d)}var d=!!a.test,f=d?a.yep:a.nope,g=a.load||a.both,h=a.callback,i;c(f),c(g),a.complete&&b.load(a.complete)}var g,h,i=this.yepnope.loader;if(C(a))e(a,0,i,0);else if(A(a))for(g=0;g<a.length;g++)h=a[g],C(h)?e(h,0,i,0):A(h)?H(h):B(h)&&b(h,i);else B(a)&&b(a,i)},H.addPrefix=function(a,b){F[a]=b},H.addFilter=function(a){E.push(a)},H.errorTimeout=1e4,b.readyState==null&&b.addEventListener&&(b.readyState="loading",b.addEventListener("DOMContentLoaded",G=function(){b.removeEventListener("DOMContentLoaded",G,0),b.readyState="complete"},0)),a.yepnope=d()}(this,this.document),Modernizr.load=function(){yepnope.apply(window,[].slice.call(arguments,0))};
0 5 \ No newline at end of file
... ...
app/assets/stylesheets/projects.css.scss
... ... @@ -102,54 +102,6 @@ table.round-borders {
102 102 float:left;
103 103 }
104 104  
105   -.day-commits-table {
106   - @include round-borders-all(4px);
107   - padding: 4px 0px;
108   - margin-bottom:10px;
109   - display:block;
110   - width:100%;
111   - background: #E6F1F6;
112   -
113   - .day-header {
114   - padding:10px;
115   - h3 {
116   - margin:0px;
117   - }
118   - }
119   -
120   - ul {
121   - display:block;
122   - list-style:none;
123   - margin:0px;
124   - padding:0px;
125   -
126   - li.commit {
127   - display:list-item;
128   - padding:8px;
129   - margin:0px;
130   - background: #F7FBFC;
131   - border-top: 1px solid #E2EAEE;
132   -
133   - &:first-child {
134   - border-top: 1px solid #E2EAEE;
135   - }
136   - &:nth-child(2n+1) {
137   - background: white;
138   - }
139   -
140   - a.button {
141   - width:85px;
142   - padding:10px;
143   - margin:0px;
144   - float:right;
145   - }
146   - p {
147   - margin-bottom: 3px;
148   - font-size: 13px;
149   - }
150   - }
151   - }
152   -}
153 105 @mixin panel-color {
154 106 background: #111 !important;
155 107 background: -webkit-gradient(linear,left top,left bottom,from(#333),to(#111)) !important;
... ... @@ -210,9 +162,9 @@ table.round-borders {
210 162 padding:20px;
211 163 }
212 164  
213   -body {
214   - background: #eaeaea;
215   -}
  165 +//body {
  166 + //background: #eaeaea;
  167 +//}
216 168  
217 169 a {
218 170 color: #111;
... ... @@ -383,23 +335,19 @@ input.ssh_project_url {
383 335 border-width: 1px;
384 336 }
385 337  
386   -tbody tr:nth-child(2n) td, tbody tr.even td {
387   - background: none repeat scroll 0 0 #F7FBFC;
388   - border-top: 1px solid #E2EAEE;
389   - border-bottom: 1px solid #E2EAEE;
390   -}
391 338  
392 339 .top_menu_count {
393   - background: none repeat scroll 0 0 #FFF6BF;
394   - border-color: #FFD324;
395   - color: #514721;
396   - border: 1px solid #DDDDDD;
  340 + background: none repeat scroll 0 0 white;
  341 + color: #333;
  342 + border-color: #4BB8D2;
397 343 padding: 2px;
398   - font-size:12px;
399   - position:relative;
400   - top:-14px;
401   - left:10px;
  344 + font-size:10px;
402 345 border-top:none;
  346 + text-align:center;
  347 + float:right;
  348 + width:25px;
  349 +
  350 +
403 351 }
404 352  
405 353 #logo {
... ... @@ -411,7 +359,7 @@ tbody tr:nth-child(2n) td, tbody tr.even td {
411 359 text-shadow: #555 1px 1px;
412 360 }
413 361  
414   -/** FALSH **/
  362 +/** FLASH **/
415 363  
416 364 #flash_container {
417 365 height:40px;
... ... @@ -429,6 +377,7 @@ tbody tr:nth-child(2n) td, tbody tr.even td {
429 377 color:#444;
430 378 font-size:22px;
431 379 padding-top:5px;
  380 + margin:2px;
432 381 }
433 382 }
434 383  
... ... @@ -682,9 +631,9 @@ tbody tr:nth-child(2n) td, tbody tr.even td {
682 631 }
683 632  
684 633 .top_panel_issues{
685   - #issue_search_form {
686   - margin:5px 0;
687   - input {
  634 + #issue_search_form {
  635 + margin:5px 0;
  636 + input {
688 637 border:1px solid #D3D3D3;
689 638 padding: 3px;
690 639 height: 28px;
... ... @@ -693,10 +642,67 @@ tbody tr:nth-child(2n) td, tbody tr.even td {
693 642 box-sizing: border-box;
694 643 -moz-box-sizing: border-box;
695 644  
696   - &:focus {
  645 + &:focus {
697 646 border-color:#c2e1ef;
698 647 }
699 648 }
700 649 }
701 650 }
702 651  
  652 +.left {
  653 + float:left;
  654 +}
  655 +.right {
  656 + float:right;
  657 +}
  658 +
  659 +.width-50p{
  660 + width:50%;
  661 +}
  662 +.width-49p{
  663 + width:49%;
  664 +}
  665 +.width-30p{
  666 + width:30%;
  667 +}
  668 +.width-65p{
  669 + width:65%;
  670 +}
  671 +pre.commit_message {
  672 + white-space: pre-wrap;
  673 +}
  674 +
  675 +#container {
  676 + min-height:100%;
  677 +}
  678 +.ui-selectmenu{
  679 + @include round-borders-all(4px);
  680 + margin-right:10px;
  681 + font-size:1.5em;
  682 + height:auto;
  683 + font-weight:bold;
  684 + .ui-selectmenu-status {
  685 + padding:3px 10px;
  686 + }
  687 +}
  688 +
  689 +td.code {
  690 + width: 100%;
  691 + .highlight {
  692 + margin-left: 55px;
  693 + overflow:auto;
  694 + overflow-y:hidden;
  695 + }
  696 +}
  697 +.highlight pre {
  698 + white-space: pre;
  699 + word-wrap:normal;
  700 +}
  701 +
  702 +.highlighttable tr:hover {
  703 + background:white;
  704 +}
  705 +table.highlighttable pre{
  706 + line-height:16px !important;
  707 + font-size:12px !important;
  708 +}
... ...
app/assets/stylesheets/style.scss 0 → 100755
... ... @@ -0,0 +1,660 @@
  1 +/* HTML5 ✰ Boilerplate
  2 + * ==|== normalize ==========================================================
  3 + */
  4 +
  5 +article, aside, details, figcaption, figure, footer, header, hgroup, nav, section { display: block; }
  6 +audio, canvas, video { display: inline-block; *display: inline; *zoom: 1; }
  7 +audio:not([controls]) { display: none; }
  8 +[hidden] { display: none; }
  9 +
  10 +html { font-size: 100%; overflow-y: scroll; -webkit-text-size-adjust: 100%; -ms-text-size-adjust: 100%; }
  11 +body { margin: 0; font-size: 13px; line-height: 1.231; }
  12 +body, button, input, select, textarea { font-family: sans-serif; color: #222; }
  13 +
  14 +::-moz-selection { background: #fe57a1; color: #fff; text-shadow: none; }
  15 +::selection { background: #fe57a1; color: #fff; text-shadow: none; }
  16 +
  17 +a { color: #00e; }
  18 +a:hover { color: #06e; }
  19 +a:focus { outline: thin dotted; }
  20 +a:hover, a:active { outline: 0; }
  21 +
  22 +abbr[title] { border-bottom: 1px dotted; }
  23 +b, strong { font-weight: bold; }
  24 +blockquote { margin: 1em 40px; }
  25 +dfn { font-style: italic; }
  26 +hr { display: block; height: 1px; border: 0; border-top: 1px solid #ccc; margin: 1em 0; padding: 0; }
  27 +ins { background: #ff9; color: #000; text-decoration: none; }
  28 +mark { background: #ff0; color: #000; font-style: italic; font-weight: bold; }
  29 +pre, code, kbd, samp { font-family: monospace, monospace; _font-family: 'courier new', monospace; font-size: 1em; }
  30 +pre { white-space: pre; white-space: pre-wrap; word-wrap: break-word; }
  31 +q { quotes: none; }
  32 +q:before, q:after { content: ""; content: none; }
  33 +small { font-size: 85%; }
  34 +sub, sup { font-size: 75%; line-height: 0; position: relative; vertical-align: baseline; }
  35 +sup { top: -0.5em; }
  36 +sub { bottom: -0.25em; }
  37 +ul, ol { margin: 1em 0; padding: 0 0 0 40px; }
  38 +dd { margin: 0 0 0 40px; }
  39 +nav ul, nav ol { list-style: none; list-style-image: none; margin: 0; padding: 0; }
  40 +img { border: 0; -ms-interpolation-mode: bicubic; vertical-align: middle; }
  41 +svg:not(:root) { overflow: hidden; }
  42 +figure { margin: 0; }
  43 +
  44 +form { margin: 0; }
  45 +fieldset { border: 0; margin: 0; padding: 0; }
  46 +label { cursor: pointer; }
  47 +legend { border: 0; *margin-left: -7px; padding: 0; }
  48 +button, input, select, textarea { font-size: 100%; margin: 0; vertical-align: baseline; *vertical-align: middle; }
  49 +button, input { line-height: normal; *overflow: visible; }
  50 +table button, table input { *overflow: auto; }
  51 +button, input[type="button"], input[type="reset"], input[type="submit"] { cursor: pointer; -webkit-appearance: button; }
  52 +input[type="checkbox"], input[type="radio"] { box-sizing: border-box; }
  53 +input[type="search"] { -webkit-appearance: textfield; -moz-box-sizing: content-box; -webkit-box-sizing: content-box; box-sizing: content-box; }
  54 +input[type="search"]::-webkit-search-decoration { -webkit-appearance: none; }
  55 +button::-moz-focus-inner, input::-moz-focus-inner { border: 0; padding: 0; }
  56 +textarea { overflow: auto; vertical-align: top; resize: vertical; }
  57 +input:valid, textarea:valid { }
  58 +input:invalid, textarea:invalid { background-color: #f0dddd; }
  59 +
  60 +table { border-collapse: collapse; border-spacing: 0; }
  61 +td { vertical-align: top; }
  62 +
  63 +
  64 +/* ==|== primary styles =====================================================
  65 + Author: Ricardo Rauch
  66 + ========================================================================== */
  67 +
  68 +/* 960gs */
  69 +.container_4{width:98%;margin-left:1%;margin-right:1%}.grid_1,.grid_2,.grid_3,.grid_4{display:inline;float:left;position:relative;margin-left:1%;margin-right:1%}.alpha{margin-left:0}.omega{margin-right:0}.container_4 .grid_1{width:23.0%}.container_4 .grid_2{width:48.0%}.container_4 .grid_3{width:73.0%}.container_4 .grid_4{width:98.0%}.container_4 .prefix_1{padding-left:25.0%}.container_4 .prefix_2{padding-left:50.0%}.container_4 .prefix_3{padding-left:75.0%}.container_4 .suffix_1{padding-right:25.0%}.container_4 .suffix_2{padding-right:50.0%}.container_4 .suffix_3{padding-right:75.0%}.container_4 .push_1{left:25.0%}.container_4 .push_2{left:50.0%}.container_4 .push_3{left:75.0%}.container_4 .pull_1{left:-25.0%}.container_4 .pull_2{left:-50.0%}.container_4 .pull_3{left:-75.0%}.clear{clear:both;display:block;overflow:hidden;visibility:hidden;width:0;height:0}.clearfix:after{clear:both;content:' ';display:block;font-size:0;line-height:0;visibility:hidden;width:0;height:0}.clearfix{display:inline-block}* html .clearfix{height:1%}.clearfix{display:block}
  70 +/* eo 960gs*/
  71 +
  72 +/* Vars */
  73 +$color: "#4BB8D2";
  74 +$blue_link: "#2fa0bb";
  75 +/* eo Vars */
  76 +
  77 +html{ -webkit-font-smoothing:antialiased; }
  78 +*{text-shadow: 0 1px 0 white}
  79 +body{font-size: 12px; background-color: #eee;}
  80 +a{text-decoration: none; font-weight: bold; color: #666}
  81 +a:hover{color: #333}
  82 +/* Typography */
  83 +h1,h2,h3,h4,h5{font-weight: normal; color: #666}
  84 +h2{margin: 1.5em 0}
  85 +/* eo Typography */
  86 +
  87 +/* Forms */
  88 +input[type="text"]:focus, input[type="password"]:focus { outline: none; }
  89 +input.text{border: 1px solid #ccc; border-radius: 4px; display: block; padding: 10px}
  90 +/* eo Forms */
  91 +
  92 +/* Tables */
  93 +table {width:100%; border: 1px solid #DEE2E3}
  94 +table thead{
  95 + -webkit-border-top-left-radius: 5px;
  96 + -webkit-border-top-right-radius: 5px;
  97 + -moz-border-radius-topleft: 5px;
  98 + -moz-border-radius-topright: 5px;
  99 + border-top-left-radius: 5px;
  100 + border-top-right-radius: 5px;
  101 +}
  102 +table thead th{
  103 + background-image: -webkit-gradient(linear, 0 0, 0 26, color-stop(0.076, #fefefe), to(#F6F7F8));
  104 + background-image: -webkit-linear-gradient(#fefefe 7.6%, #F6F7F8);
  105 + background-image: -moz-linear-gradient(#fefefe 7.6%, #F6F7F8);
  106 + background-image: -o-linear-gradient(#fefefe 7.6%, #F6F7F8);
  107 + margin: 0;
  108 + font-weight: normal;
  109 + font-weight: bold;
  110 + text-align: left;
  111 + color: #97A0A5;
  112 +}
  113 +td, th{ padding: .9em 1em; vertical-align: middle; }
  114 +
  115 +table thead .image{width:100px}
  116 +table tr:hover, .listed_items tr.odd:hover{background-color:#FFFFCF}
  117 +/* eo Tables */
  118 +
  119 +
  120 +/* Buttons */
  121 +.grey-button{
  122 + border-radius: 5px;
  123 + font-size: 12px;
  124 + font-weight: bold;
  125 + padding: 6px 20px;
  126 + border: 1px solid #999;
  127 + color: #666;
  128 + display: inline-block;
  129 + box-shadow: 0 1px 2px rgba(0,0,0,.3);
  130 + background-image: -webkit-gradient(linear, 0 0, 0 26, color-stop(0.076, #f7f7f7), to(#d5d5d5));
  131 + background-image: -webkit-linear-gradient(#f7f7f7 7.6%, #d5d5d5);
  132 + background-image: -moz-linear-gradient(#f7f7f7 7.6%, #d5d5d5);
  133 + background-image: -o-linear-gradient(#f7f7f7 7.6%, #d5d5d5);
  134 +}
  135 +
  136 +.button{
  137 + padding: 10px 20px;
  138 + text-align: center;
  139 + display: inline-block;
  140 + border-radius: 5px;
  141 + color: #578E91;
  142 + font-size: 12px;
  143 + text-transform: uppercase;
  144 + border: 1px solid #8CE2E6;
  145 + background-image: -webkit-gradient(linear, 0 0, 0 34, color-stop(0.794, #dbf5f6), to(#c5eef0));
  146 + background-image: -webkit-linear-gradient(#dbf5f6 79.4%, #c5eef0);
  147 + background-image: -moz-linear-gradient(#dbf5f6 79.4%, #c5eef0);
  148 + background-image: -o-linear-gradient(#dbf5f6 79.4%, #c5eef0);
  149 +}
  150 +
  151 +.button:hover {color: rgba(0,0,0,.8)}
  152 +
  153 +.button.green {margin-right: 0; }
  154 +
  155 +.button.yellow{
  156 + color: #908054;
  157 + border-color: #DDCDA1;
  158 + background-image: -webkit-gradient(linear, 0 0, 0 34, color-stop(0.794, #FFEFC3), to(#F3E3B7));
  159 + background-image: -webkit-linear-gradient(#FFEFC3 79.4%, #F3E3B7);
  160 + background-image: -moz-linear-gradient(#FFEFC3 79.4%, #F3E3B7);
  161 + background-image: -o-linear-gradient(#FFEFC3 79.4%, #F3E3B7);
  162 +}
  163 +
  164 +.button.blue{
  165 + color: #417E97;
  166 + border-color: #b2cdec;
  167 + background-image: -webkit-gradient(linear, 0 0, 0 34, color-stop(0.794, #dbe8f6), to(#c7daf1));
  168 + background-image: -webkit-linear-gradient(#dbe8f6 79.4%, #c7daf1);
  169 + background-image: -moz-linear-gradient(#dbe8f6 79.4%, #c7daf1);
  170 + background-image: -o-linear-gradient(#dbe8f6 79.4%, #c7daf1);
  171 +}
  172 +
  173 +.button-small{ text-shadow: none; padding: 4px 10px; }
  174 +.button-green{background: #A6B807; color: white}
  175 +
  176 +/* eo Buttons */
  177 +
  178 +/* UI Box */
  179 +.ui-box{border: 1px solid #DEDFE1; float: left; border-radius: 5px}
  180 +.ui-box h3{
  181 + background-image: -webkit-gradient(linear, 0 0, 0 26, color-stop(0.076, #fefefe), to(#F6F7F8));
  182 + background-image: -webkit-linear-gradient(#fefefe 7.6%, #F6F7F8);
  183 + background-image: -moz-linear-gradient(#fefefe 7.6%, #F6F7F8);
  184 + background-image: -o-linear-gradient(#fefefe 7.6%, #F6F7F8);
  185 + margin: 0;
  186 + padding: 1em;
  187 + font-size: 12px;
  188 + font-weight: normal;
  189 + font-weight: bold;
  190 + font-size: 16px;
  191 + border-bottom: 1px solid #DEDFE1;
  192 + -webkit-border-top-left-radius: 5px;
  193 + -webkit-border-top-right-radius: 5px;
  194 + -moz-border-radius-topleft: 5px;
  195 + -moz-border-radius-topright: 5px;
  196 + border-top-left-radius: 5px;
  197 + border-top-right-radius: 5px;
  198 +}
  199 +
  200 +.ui-box.ui-box-small h3{
  201 + padding: 8px 10px;
  202 + font-size: 12px;
  203 +}
  204 +
  205 +
  206 +.ui-box .data{padding: .5em 1em}
  207 +
  208 +.ui-box .buttons{background-color: #f7f8f9; padding: 1em;
  209 + -webkit-border-bottom-right-radius: 5px;
  210 + -webkit-border-bottom-left-radius: 5px;
  211 + -moz-border-radius-bottomright: 5px;
  212 + -moz-border-radius-bottomleft: 5px;
  213 + border-bottom-right-radius: 5px;
  214 + border-bottom-left-radius: 5px;
  215 +}
  216 +
  217 +.ui-box .buttons .button{padding: 8px 9px; font-size: 11px}
  218 +
  219 +.ui-box.hover:hover{box-shadow: 0 0 10px rgba(0,0,0,.1); border: 1px solid #ccc;
  220 +
  221 + -webkit-transition: all 200ms cubic-bezier(0.470, 0.000, 0.745, 0.715);
  222 + -moz-transition: all 200ms cubic-bezier(0.470, 0.000, 0.745, 0.715);
  223 + -o-transition: all 200ms cubic-bezier(0.470, 0.000, 0.745, 0.715);
  224 + transition: all 200ms cubic-bezier(0.470, 0.000, 0.745, 0.715);
  225 +}
  226 +
  227 +/* eo UI Box */
  228 +
  229 +/* Login Page */
  230 +body.login-page{background-color: #f1f1f1; padding-top: 10%}
  231 +
  232 +.login-box{
  233 + width: 304px;
  234 + position: relative;
  235 + border-radius: 5px;
  236 + margin: auto;
  237 + padding: 20px;
  238 + background: white;
  239 + box-shadow: rgba(0, 0, 0, 0.07) 0 1px 0,white 0 2px 0,rgba(0, 0, 0, 0.07) 0 3px 0,white 0 4px 0, rgba(0, 0, 0, 0.07) 0 5px 0;
  240 +}
  241 +
  242 +.login-box .login-logo{
  243 + margin: 10px 0 30px 0;
  244 + display: block;
  245 +}
  246 +
  247 +.login-box input.text{background-color: #f1f1f1; font-size: 16px; border-radius: 0; padding: 14px 10px; width: 280px}
  248 +
  249 +.login-box input.text.top{
  250 + -webkit-border-top-left-radius: 5px;
  251 + -webkit-border-top-right-radius: 5px;
  252 + -moz-border-radius-topleft: 5px;
  253 + -moz-border-radius-topright: 5px;
  254 + border-top-left-radius: 5px;
  255 + border-top-right-radius: 5px;
  256 +}
  257 +
  258 +.login-box input.text.bottom{
  259 + -webkit-border-bottom-right-radius: 5px;
  260 + -webkit-border-bottom-left-radius: 5px;
  261 + -moz-border-radius-bottomright: 5px;
  262 + -moz-border-radius-bottomleft: 5px;
  263 + border-bottom-right-radius: 5px;
  264 + border-bottom-left-radius: 5px;
  265 + border-top: 0;
  266 + margin-bottom: 20px;
  267 +}
  268 +
  269 +.login-box a.forgot{float: right; padding-top: 6px}
  270 +
  271 +
  272 +/* Icons */
  273 +.directory, .file{
  274 + display: inline-block;
  275 + margin-right: 10px;
  276 + width: 14px;
  277 +}
  278 +
  279 +.directory{
  280 + background: url('images.png') no-repeat -73px -26px;
  281 + height: 11px;
  282 + margin-bottom: -1px;
  283 +}
  284 +
  285 +.file{
  286 + background: url('images.png') no-repeat -114px -24px;
  287 + height: 16px;
  288 + margin-bottom: -3px;
  289 +}
  290 +
  291 +/* eo Icons*/
  292 +
  293 +/* General */
  294 +#container{background-color: white; overflow: hidden;}
  295 +/*#container{margin: auto; width: 980px; border: 1px solid rgba(0,0,0,.22); border-top: 0; box-shadow: 0 0 0px 4px rgba(0,0,0,.04)}*/
  296 +
  297 +
  298 +
  299 +/* Header */
  300 +header{background: #474D57 url('bg-header.png') repeat-x bottom; z-index: 10000; height: 44px; padding: 10px 2% 6px 2%}
  301 +header a{color: white; text-shadow: 0 -1px 0 black}
  302 +header a:hover{color: #f1f1f1}
  303 +header h1{
  304 + width: 65px;
  305 +}
  306 +header h1.logo{margin: 0; padding: 0}
  307 +header h1.logo a{
  308 + background: url('images.png') no-repeat -3px -7px;
  309 + width: 65px;
  310 + height: 26px;
  311 + margin: 5px 0;
  312 + padding: 0;
  313 + display: block;
  314 + float: left;
  315 + text-indent: -1000em;
  316 +}
  317 +
  318 +
  319 +
  320 +header nav{border-radius: 4px; box-shadow: 0 1px 2px black; width: 294px; margin: auto;
  321 + background-image: -webkit-gradient(linear, 0 0, 0 30, color-stop(0.066, #595d63), to(#31363e));
  322 + background-image: -webkit-linear-gradient(#595d63 6.6%, #31363e);
  323 + background-image: -moz-linear-gradient(#595d63 6.6%, #31363e);
  324 + background-image: -o-linear-gradient(#595d63 6.6%, #31363e);
  325 + margin-top: 2px;
  326 +}
  327 +header nav a{padding: 8px 12px 8px 34px; display: inline-block; color: #D6DADF; border-right: 1px solid #31363E; position: relative; box-shadow: 1px 0 0 rgba(255,255,255,.1); margin: 0}
  328 +header nav a span{width: 20px; height: 20px; display: inline-block; background: red; position: absolute; left: 8px; top: 6px;}
  329 +header nav a:last-child {border: 0; box-shadow: none}
  330 +header nav a:hover, header nav a.current{
  331 + background-image: -webkit-gradient(linear, 0 0, 0 30, color-stop(0.066, #595d63), to(#2c2f35));
  332 + background-image: -webkit-linear-gradient(#595d63 6.6%, #2c2f35);
  333 + background-image: -moz-linear-gradient(#595d63 6.6%, #202227);
  334 + background-image: -o-linear-gradient(#595d63 6.6%, #202227);
  335 +}
  336 +
  337 +header nav a:active{
  338 + box-shadow: 0 1px 4px rgba(0,0,0,.8) inset;
  339 +}
  340 +
  341 +
  342 +header nav a.dashboard {
  343 + -webkit-border-top-left-radius: 4px;
  344 + -webkit-border-bottom-left-radius: 4px;
  345 + -moz-border-radius-topleft: 4px;
  346 + -moz-border-radius-bottomleft: 4px;
  347 + border-top-left-radius: 4px;
  348 + border-bottom-left-radius: 4px;
  349 +}
  350 +
  351 +header nav a.admin{
  352 + -webkit-border-top-right-radius: 4px;
  353 + -webkit-border-bottom-right-radius: 4px;
  354 + -moz-border-radius-topright: 4px;
  355 + -moz-border-radius-bottomright: 4px;
  356 + border-top-right-radius: 4px;
  357 + border-bottom-right-radius: 4px;
  358 +}
  359 +
  360 +
  361 +header .search{ display: inline-block; float: right; margin-right: 10px}
  362 +
  363 +header nav a span{width: 20px; height: 20px; display: inline-block; background: red; position: absolute; left: 8px; top: 6px;}
  364 +
  365 +header nav a.dashboard span{background: url('images.png') no-repeat -161px 0;}
  366 +header nav a.admin span{background: url('images.png') no-repeat -184px 0;}
  367 +header nav a.project span{background: url('images.png') no-repeat -209px -1px; top: 7px}
  368 +/*
  369 +
  370 +header nav a span{width: 20px; height: 20px; display: inline-block; background: red; position: absolute; left: 8px; top: 14px;}
  371 +
  372 +header nav a.dashboard.current span{ background-position: -163px -22px; }
  373 +header nav a.admin.current span{ background-position: -186px -22px;}
  374 +header nav a.project.current span{ background-position: -211px -23px;}
  375 +
  376 +header nav a.project span{background: url('images.png') no-repeat -209px -1px; top: 15px}
  377 +
  378 +
  379 +header nav a span.current{top: 18px}
  380 +
  381 +
  382 +header nav {margin-left: 180px; display: inline-block; float: left;}
  383 +header nav a{float: left; background: #31363e; padding: 16px 20px 20px 34px; margin-right: 10px;
  384 + -webkit-border-top-left-radius: 5px;
  385 + -webkit-border-top-right-radius: 5px;
  386 + -moz-border-radius-topleft: 5px;
  387 + -moz-border-radius-topright: 5px;
  388 + border-top-left-radius: 5px;
  389 + border-top-right-radius: 5px;
  390 + position: relative;
  391 +}
  392 +
  393 +header nav a.current{background: white; color: #333; text-shadow: none;}
  394 +*/
  395 +
  396 +header .login-top{float: right; width: 180px;
  397 + background-image: -webkit-gradient(linear, 0 0, 0 62, color-stop(0.032, #464c56), to(#363c45));
  398 + background-image: -webkit-linear-gradient(#464c56 3.2%, #363c45);
  399 + background-image: -moz-linear-gradient(#464c56 3.2%, #363c45);
  400 + background-image: -o-linear-gradient(#464c56 3.2%, #363c45);
  401 + padding: 0 10px;
  402 + height: 44px;
  403 +}
  404 +header .login-top a{display: block;}
  405 +header .login-top a.pic{float: left; margin-right: 10px;
  406 + img{ height: 36px; width: 36px; border: 1px solid black}
  407 +}
  408 +header .login-top a.username{margin-bottom: 5px}
  409 +header .login-top a.logout{color: #ccc}
  410 +header{margin-bottom: 0; clear: both; }
  411 +
  412 +.page-title{background-color: #f1f1f1;display: block; float: left; clear: both; width: 98%; padding: 1% 1%; border-bottom: 1px solid #ccc; box-shadow: 0 -1px 0 white inset; margin-bottom: 1.5em}
  413 +.page-title h1{font-size: 20px; width: 400px; margin: 0; padding-top: 8px }
  414 +.page-title a.grey-button{float: right;}
  415 +.right{float: right;}
  416 +
  417 +/* Account box */
  418 +header .account-box{position: relative;z-index: 10000; top: -3px; width: 38px; height: 38px; font-size: 11px; float: right; display: block; cursor: pointer; }
  419 +header .account-box img{ border-radius: 4px; width: 38px; height: 38px; display: block; box-shadow: 0 1px 2px black}
  420 +header .account-box:after{
  421 + content: " ";
  422 + display: block;
  423 + position: absolute;
  424 + top: 0;
  425 + right: 0;
  426 +left: 0;
  427 + bottom: 0;
  428 +float: right;
  429 + border-radius: 5px;
  430 + border: 1px solid rgba(255, 255, 255, .1);
  431 + border-bottom: 0;
  432 + background: -webkit-gradient(linear, 0% 0%, 0% 100%, from(rgba(255, 255, 255, .15)), to(rgba(0, 0, 0, .25))), -webkit-gradient(linear, left top, right bottom, color-stop(0, rgba(255, 255, 255, 0)), color-stop(0.5, rgba(255, 255, 255, .1)), color-stop(0.501, rgba(255, 255, 255, 0)), color-stop(1, rgba(255, 255, 255, 0)));
  433 + background: -moz-linear-gradient(top, rgba(255, 255, 255, .15), rgba(0, 0, 0, .25)), -moz-linear-gradient(left top, rgba(255, 255, 255, 0), rgba(255, 255, 255, .1) 50%, rgba(255, 255, 255, 0) 50%, rgba(255, 255, 255, 0));
  434 + background: linear-gradient(top, rgba(255, 255, 255, .15), rgba(0, 0, 0, .25)), linear-gradient(left top, rgba(255, 255, 255, 0), rgba(255, 255, 255, .1) 50%, rgba(255, 255, 255, 0) 50%, rgba(255, 255, 255, 0));
  435 + -webkit-background-origin: border-box;
  436 + -moz-background-origin: border;
  437 + background-origin: border-box;
  438 +}
  439 +
  440 +.account-box:hover > .account-links, .account-box:hover > .arrow-up{display: block;}
  441 +header .account-links{background: white; display: none; border-radius: 5px; width: 100px; margin-top: 0; float: right; box-shadow: 0 1px 1px rgba(0,0,0,.2); }
  442 +header .account-links a{color: #666; padding: 6px 10px; display: block; text-shadow: none; border-bottom: 1px solid #eee}
  443 +header .account-links a:hover{background-color: #f1f1f1; text-shadow: none; color: #333}
  444 +
  445 +header .account-links a:first-child{
  446 + -webkit-border-top-left-radius: 5px;
  447 + -webkit-border-top-right-radius: 5px;
  448 + -moz-border-radius-topleft: 5px;
  449 + -moz-border-radius-topright: 5px;
  450 + border-top-left-radius: 5px;
  451 + border-top-right-radius: 5px;
  452 +}
  453 +
  454 +header .account-links a:last-child{
  455 + -webkit-border-bottom-right-radius: 5px;
  456 + -webkit-border-bottom-left-radius: 5px;
  457 + -moz-border-radius-bottomright: 5px;
  458 + -moz-border-radius-bottomleft: 5px;
  459 + border-bottom-right-radius: 5px;
  460 + border-bottom-left-radius: 5px;
  461 + border-bottom: 0;
  462 +}
  463 +
  464 +header a.arrow-up{
  465 + display: none;
  466 + width: 0;
  467 + height: 0;
  468 + float: right;
  469 + margin-right: 26px;
  470 + margin-bottom: 0;
  471 + border-left: 5px solid transparent;
  472 + border-right: 5px solid transparent;
  473 +
  474 + border-bottom: 5px solid white;
  475 +}
  476 +/* eo Account Box */
  477 +input.search-input{float: left; text-shadow: none; width: 116px; background-image: url('icon-search.png') ; background-repeat: no-repeat; background-position: 10px; border-radius: 100px; border: 1px solid rgba(0,0,0,.7); box-shadow: 0 1px 0 rgba(255,255,255,.2), 0 2px 2px rgba(0,0,0,.4) inset ; background-color: #D2D5DA; background-color: rgba(255,255,255,.5); padding: 5px; padding-left: 26px; margin-top: 4px; margin-right: 10px }
  478 +input.search-input:focus{ background-color: white; width: 216px;}
  479 +input.search-input::-webkit-input-placeholder {color: #666}
  480 +/* eo Header */
  481 +
  482 +
  483 +h2.icon{position: relative; padding-left: 40px; float: left; }
  484 +/*h2 a{font-weight: normal;}*/
  485 +h2.icon span{background: #E3E5EA url('images.png'); height: 32px; width: 32px; left: 0; top: -5px; border-radius: 4px; display: inline-block; position: absolute}
  486 +
  487 +
  488 +
  489 +/* Dashboard Page */
  490 +html, body { height: 100%; }
  491 +
  492 +body.dashboard-page h2.icon span{ background-position: 9px -69px; }
  493 +body.dashboard-page header{margin-bottom: 0}
  494 +body.dashboard-page .news-feed{padding-left: 1em; margin-right: 450px; margin-left: 1%}
  495 +body.dashboard-page .dashboard-content{ position: relative; float: left; width: 100%; height: 100%; }
  496 +body.dashboard-page .news-feed h2{float: left;}
  497 +body.dashboard-page aside{ width: 420px; float: right; right: 0; height: 100%; bottom: 0; position: absolute; background-color: #f7f7f7; border-left: 1px solid #ccc }
  498 +body.dashboard-page aside h4{margin: 0; border-bottom: 1px solid #ccc; padding: 10px 10px; font-size: 11px; font-weight: bold; text-transform: uppercase;}
  499 +body.dashboard-page aside h4 a.button-small{float: right; text-transform: none; border-radius: 4px; margin-right: 4%; margin-top: -4px; display: block;}
  500 +body.dashboard-page aside .project-list {list-style: none; margin: 0; padding: 0;}
  501 +body.dashboard-page aside .project-list li a {background: white; color: #{$blue_link}; display: block; border-bottom: 1px solid #eee; padding: 14px 6% 14px 14px;}
  502 +body.dashboard-page aside .project-list li a:hover {background: #f1f1f1}
  503 +body.dashboard-page aside .project-list li a:hover span.arrow{background-color: #E3E5EA;}
  504 +body.dashboard-page aside .project-list li a span.project-name{font-size: 14px; display: block; margin-bottom: 8px}
  505 +body.dashboard-page aside .project-list li a span.time{color: #666; font-weight: normal; font-size: 11px}
  506 +body.dashboard-page aside .project-list li a span.arrow{float: right; background: #E3E5EA; padding: 10px; border-radius: 5px; margin-top: 2px; text-shadow: none; color: #999}
  507 +body.dashboard-page .news-feed .project-updates {margin-bottom: 20px; display: block; width: 100%;}
  508 +body.dashboard-page .news-feed .project-updates .data{ padding: 0}
  509 +body.dashboard-page .news-feed .project-updates a.project-update {padding: 10px; border-bottom: 1px solid #eee; overflow: hidden; display: block;}
  510 +body.dashboard-page .news-feed .project-updates a.project-update:last-child{border-bottom: 0}
  511 +body.dashboard-page .news-feed .project-updates a.project-update img{float: left; margin-right: 10px;}
  512 +body.dashboard-page .news-feed .project-updates a.project-update span.update-title, .dashboard-page .news-feed .project-updates li a span.update-author{display: block;}
  513 +body.dashboard-page .news-feed .project-updates a.project-update span.update-title{margin-bottom: 10px}
  514 +body.dashboard-page .news-feed .project-updates a.project-update span.update-author{color: #999; font-weight: normal; font-style: italic;}
  515 +body.dashboard-page .news-feed .project-updates a.project-update span.update-author strong{font-weight: bold; font-style: normal;}
  516 +/* eo Dashboard Page */
  517 +
  518 +
  519 +.grey-button.right{margin-top: 20px}
  520 +
  521 +/* Project Page */
  522 +
  523 +body.project-page h2.icon .project-name, body.project-page h2.icon d{border: 1px solid #eee; padding: 5px 30px 5px 10px; border-radius: 5px; position: relative;}
  524 +body.project-page h2.icon .project-name i.arrow{float: right;
  525 + position: absolute;
  526 + right: 10px;
  527 + top: 13px;
  528 + display: block;
  529 + background: url('images.png') no-repeat -97px -29px;
  530 + width: 4px;
  531 + height: 5px;
  532 +}
  533 +
  534 +
  535 +
  536 +body.project-page h2.icon span{ background-position: -78px -68px; }
  537 +body.project-page .project-container{ position: relative; float: left; width: 100%; height: 100%; }
  538 +body.project-page .page-title{margin-bottom: 0}
  539 +body.project-page .project-sidebar {width: 220px; left: 0; top: 0; height: 100%; bottom: 0; position: absolute; background-color: #f7f7f7; border-left: 1px solid #ccc; float: left; display: inline-block; background: #f7f7f7; padding: 20px 0 20px 2%; margin: 0; }
  540 +body.project-page .project-sidebar input.text.git-url{ font-size: 12px; border-radius: 5px; color: #666; box-shadow: 0 1px 2px rgba(0,0,0,.2) inset; padding: 8px 14px 8px 30px; margin-bottom: 20px; background: white url('images.png') no-repeat 8px -40px;}
  541 +body.project-page .project-sidebar aside{width: 219px}
  542 +body.project-page .project-sidebar aside a{display: block; position: relative; background: white; padding: 15px 10px; border-bottom: 1px solid #eee}
  543 +body.project-page .project-sidebar aside a:first-child{
  544 + -webkit-border-top-left-radius: 5px;
  545 + -moz-border-radius-topleft: 5px;
  546 + border-top-left-radius: 5px;
  547 +}
  548 +.project-page .project-sidebar aside a:last-child{
  549 + -webkit-border-bottom-left-radius: 5px;
  550 + -moz-border-radius-bottomleft: 5px;
  551 + border-bottom-left-radius: 5px;
  552 +}
  553 +body.project-page .project-sidebar aside a:hover{background-color: #eee;}
  554 +body.project-page .project-sidebar aside a span.number{float: right; border-radius: 5px; text-shadow: none; background: rgba(0,0,0,.12); text-align: center; padding: 5px 8px; position: absolute; top: 10px; right: 10px}
  555 +body.project-page .project-sidebar aside a.current{background-color: #79c3e0; color: white; text-shadow: none; border-color: transparent}
  556 +body.project-page .project-content{ padding: 20px; display: block; margin-left: 250px }
  557 +body.project-page .project-content h2{ margin-top: 6px}
  558 +body.project-page .project-content .button.right{margin-left: 20px}
  559 +body.project-page table .commit a{color: #{$blue_link}}
  560 +body.project-page table th, body.project-page table td{ border-bottom: 1px solid #DEE2E3;}
  561 +body.project-page .fixed{position: fixed; }
  562 +
  563 +/* Commit Page */
  564 +body.project-page.commits-page .commit-info{float: right;}
  565 +body.project-page.commits-page .commit-info data{
  566 + padding: 4px 10px;
  567 + font-size: 11px;
  568 +}
  569 +body.project-page.commits-page .commit-info data.commit-button{
  570 + background-image: -webkit-gradient(linear, 0 0, 0 26, color-stop(0.192, #fff), to(#f4f4f4));
  571 + background-image: -webkit-linear-gradient(#fff 19.2%, #f4f4f4);
  572 + background-image: -moz-linear-gradient(#fff 19.2%, #f4f4f4);
  573 + background-image: -o-linear-gradient(#fff 19.2%, #f4f4f4);
  574 + box-shadow: 0 -1px 0 white inset;
  575 + display: block;
  576 + border: 1px solid #eee;
  577 + border-radius: 5px;
  578 + margin-bottom: 2px;
  579 + position: relative;
  580 + padding-right: 20px;
  581 +}
  582 +
  583 +
  584 +body.project-page.commits-page .commit-button i{
  585 + background: url('images.png') no-repeat -138px -27px;
  586 + width: 6px;
  587 + height: 9px;
  588 + float: right;
  589 + position: absolute;
  590 + top: 6px;
  591 + right: 5px;
  592 +}
  593 +body.project-page.commits-page .commits-date {display: block; width: 100%; margin-bottom: 20px}
  594 +body.project-page.commits-page .commits-date .data {padding: 0}
  595 +body.project-page.commits-page a.commit{padding: 10px; border-bottom: 1px solid #eee; overflow: hidden; display: block;}
  596 +body.project-page.commits-page .commits-date a.commit {padding: 10px; border-bottom: 1px solid #eee; overflow: hidden; display: block;}
  597 +body.project-page.commits-page .commits-date a.commit:last-child{border-bottom: 0}
  598 +body.project-page.commits-page .commits-date a.commit img{float: left; margin-right: 10px;}
  599 +body.project-page.commits-page .commits-date a.commit span.commit-title{display: block;}
  600 +body.project-page.commits-page .commits-date a.commit span.commit-title{margin-bottom: 10px}
  601 +body.project-page.commits-page .commits-date a.commit span.commit-author{color: #999; font-weight: normal; font-style: italic;}
  602 +body.project-page.commits-page .commits-date a.commit span.commit-author strong{font-weight: bold; font-style: normal;}
  603 +
  604 +/* eo Commit Page */
  605 +
  606 +/* eo Project Page */
  607 +
  608 +
  609 +
  610 +
  611 +/* Projects Page */
  612 +body.projects-page h2.icon span{background-position: -31px -70px;}
  613 +body.projects-page .project-box.ui-box .data .repository {margin-bottom: 20px}
  614 +body.projects-page .project-box.ui-box .data .title span{ font-weight: bold;}
  615 +body.projects-page .project-box{width: 100%; margin-bottom: 3em}
  616 +body.projects-page .browse-code{margin-right: 10px}
  617 +/* eo Projects Page */
  618 +
  619 +
  620 +/* ==|== non-semantic helper classes ======================================== */
  621 +.ir { display: block; border: 0; text-indent: -999em; overflow: hidden; background-color: transparent; background-repeat: no-repeat; text-align: left; direction: ltr; }
  622 +.ir br { display: none; }
  623 +.hidden { display: none !important; visibility: hidden; }
  624 +.visuallyhidden { border: 0; clip: rect(0 0 0 0); height: 1px; margin: -1px; overflow: hidden; padding: 0; position: absolute; width: 1px; }
  625 +.visuallyhidden.focusable:active, .visuallyhidden.focusable:focus { clip: auto; height: auto; margin: 0; overflow: visible; position: static; width: auto; }
  626 +.invisible { visibility: hidden; }
  627 +.clearfix:before, .clearfix:after { content: ""; display: table; }
  628 +.clearfix:after { clear: both; }
  629 +.clearfix { zoom: 1; }
  630 +
  631 +
  632 +/* ==|== media queries ====================================================== */
  633 +
  634 +@media only screen and (min-width: 480px) {
  635 +
  636 +
  637 +}
  638 +
  639 +@media only screen and (min-width: 768px) {
  640 +
  641 +}
  642 +
  643 +
  644 +
  645 +/* ==|== print styles ======================================================= */
  646 +
  647 +@media print {
  648 + * { background: transparent !important; color: black !important; text-shadow: none !important; filter:none !important; -ms-filter: none !important; }
  649 + a, a:visited { text-decoration: underline; }
  650 + a[href]:after { content: " (" attr(href) ")"; }
  651 + abbr[title]:after { content: " (" attr(title) ")"; }
  652 + .ir a:after, a[href^="javascript:"]:after, a[href^="#"]:after { content: ""; }
  653 + pre, blockquote { border: 1px solid #999; page-break-inside: avoid; }
  654 + thead { display: table-header-group; }
  655 + tr, img { page-break-inside: avoid; }
  656 + img { max-width: 100% !important; }
  657 + @page { margin: 0.5cm; }
  658 + p, h2, h3 { orphans: 3; widows: 3; }
  659 + h2, h3 { page-break-after: avoid; }
  660 +}
... ...
app/controllers/admin/mailer_controller.rb
1 1 class Admin::MailerController < ApplicationController
  2 + layout "admin"
2 3 before_filter :authenticate_user!
3 4 before_filter :authenticate_admin!
4 5  
... ...
app/controllers/admin/projects_controller.rb
1 1 class Admin::ProjectsController < ApplicationController
  2 + layout "admin"
2 3 before_filter :authenticate_user!
3 4 before_filter :authenticate_admin!
4 5  
... ...
app/controllers/admin/team_members_controller.rb
1 1 class Admin::TeamMembersController < ApplicationController
  2 + layout "admin"
2 3 before_filter :authenticate_user!
3 4 before_filter :authenticate_admin!
4 5  
... ...
app/controllers/admin/users_controller.rb
1 1 class Admin::UsersController < ApplicationController
  2 + layout "admin"
2 3 before_filter :authenticate_user!
3 4 before_filter :authenticate_admin!
4 5  
... ...
app/controllers/application_controller.rb
... ... @@ -8,8 +8,18 @@ class ApplicationController &lt; ActionController::Base
8 8 render :file => File.join(Rails.root, "public", "gitosis_error"), :layout => false
9 9 end
10 10  
  11 + layout :layout_by_resource
  12 +
11 13 protected
12 14  
  15 + def layout_by_resource
  16 + if devise_controller?
  17 + "devise"
  18 + else
  19 + "application"
  20 + end
  21 + end
  22 +
13 23 def abilities
14 24 @abilities ||= Six.new
15 25 end
... ...
app/controllers/commits_controller.rb
... ... @@ -2,6 +2,7 @@ require &quot;base64&quot;
2 2  
3 3 class CommitsController < ApplicationController
4 4 before_filter :project
  5 + layout "project"
5 6  
6 7 # Authorize
7 8 before_filter :add_project_abilities
... ...
app/controllers/dashboard_controller.rb
1 1 class DashboardController < ApplicationController
2 2 def index
3 3 @projects = current_user.projects.all
  4 + @active_projects = @projects.select(&:last_activity_date).sort_by(&:last_activity_date).reverse
4 5 end
5 6 end
... ...
app/controllers/issues_controller.rb
... ... @@ -2,6 +2,7 @@ class IssuesController &lt; ApplicationController
2 2 before_filter :authenticate_user!
3 3 before_filter :project
4 4 before_filter :issue, :only => [:edit, :update, :destroy, :show]
  5 + layout "project"
5 6  
6 7 # Authorize
7 8 before_filter :add_project_abilities
... ... @@ -41,7 +42,7 @@ class IssuesController &lt; ApplicationController
41 42 def create
42 43 @issue = @project.issues.new(params[:issue])
43 44 @issue.author = current_user
44   - if @issue.save
  45 + if @issue.save && @issue.assignee != current_user
45 46 Notify.new_issue_email(@issue).deliver
46 47 end
47 48  
... ...
app/controllers/keys_controller.rb
1 1 class KeysController < ApplicationController
  2 + layout "profile"
2 3 respond_to :js
3 4  
4 5 def index
... ...
app/controllers/profile_controller.rb
1 1 class ProfileController < ApplicationController
  2 + layout "profile"
2 3 def show
3 4 @user = current_user
4 5 end
... ...
app/controllers/projects_controller.rb
1 1 class ProjectsController < ApplicationController
2 2 before_filter :project, :except => [:index, :new, :create]
  3 + layout :determine_layout
3 4  
4 5 # Authorize
5 6 before_filter :add_project_abilities
... ... @@ -152,4 +153,12 @@ class ProjectsController &lt; ApplicationController
152 153 def project
153 154 @project ||= Project.find_by_code(params[:id])
154 155 end
  156 +
  157 + def determine_layout
  158 + if @project && !@project.new_record?
  159 + "project"
  160 + else
  161 + "application"
  162 + end
  163 + end
155 164 end
... ...
app/controllers/snippets_controller.rb
1 1 class SnippetsController < ApplicationController
2 2 before_filter :authenticate_user!
3 3 before_filter :project
  4 + layout "project"
4 5  
5 6 # Authorize
6 7 before_filter :add_project_abilities
... ...
app/controllers/team_members_controller.rb
1 1 class TeamMembersController < ApplicationController
2 2 before_filter :project
  3 + layout "project"
3 4  
4 5 # Authorize
5 6 before_filter :add_project_abilities
... ...
app/helpers/application_helper.rb
... ... @@ -28,6 +28,12 @@ module ApplicationHelper
28 28 else
29 29 "Never"
30 30 end
  31 + rescue
  32 + "Never"
  33 + end
  34 +
  35 + def markdown(text)
  36 + RDiscount.new(text, :autolink, :no_pseudo_protocols, :safelink, :smart, :filter_html).to_html.html_safe
31 37 end
32 38  
33 39 def search_autocomplete_source
... ...
app/helpers/dashboard_helper.rb
1 1 module DashboardHelper
  2 + def dashboard_feed_path(project, object)
  3 + case object.class.name.to_s
  4 + when "Issue" then project_issues_path(project, project.issues.find(object.id))
  5 + when "Grit::Commit" then project_commit_path(project, project.repo.commits(object.id).first)
  6 + when "Note"
  7 + then
  8 + note = object
  9 + case note.noteable_type
  10 + when "Issue" then project_issue_path(project, note.noteable_id)
  11 + when "Snippet" then project_snippet_path(project, note.noteable_id)
  12 + when "Commit" then project_commit_path(project, :id => note.noteable_id)
  13 + else wall_project_path(project)
  14 + end
  15 + else "#"
  16 + end
  17 + rescue
  18 + "#"
  19 + end
  20 +
  21 + def dashboard_feed_title(object)
  22 + title = case object.class.name.to_s
  23 + when "Note" then markdown(object.note)
  24 + when "Issue" then object.title
  25 + when "Grit::Commit" then object.safe_message
  26 + else ""
  27 + end
  28 + "[#{object.class.name}] #{truncate(sanitize(title, :tags => []), :length => 60)} "
  29 + end
2 30 end
... ...
app/models/issue.rb
... ... @@ -10,6 +10,11 @@ class Issue &lt; ActiveRecord::Base
10 10 validates_presence_of :assignee_id
11 11 validates_presence_of :author_id
12 12  
  13 + delegate :name,
  14 + :email,
  15 + :to => :author,
  16 + :prefix => true
  17 +
13 18 validates :title,
14 19 :presence => true,
15 20 :length => { :within => 0..255 }
... ...
app/models/note.rb
... ... @@ -7,6 +7,11 @@ class Note &lt; ActiveRecord::Base
7 7 belongs_to :author,
8 8 :class_name => "User"
9 9  
  10 + delegate :name,
  11 + :email,
  12 + :to => :author,
  13 + :prefix => true
  14 +
10 15 attr_protected :author, :author_id
11 16  
12 17 validates_presence_of :project
... ...
app/models/project.rb
... ... @@ -119,6 +119,26 @@ class Project &lt; ActiveRecord::Base
119 119 repo rescue false
120 120 end
121 121  
  122 + def last_activity
  123 + updates(1).first
  124 + rescue
  125 + nil
  126 + end
  127 +
  128 + def last_activity_date
  129 + last_activity.try(:created_at)
  130 + end
  131 +
  132 + def updates(n = 3)
  133 + [
  134 + fresh_commits(n),
  135 + issues.last(n),
  136 + notes.fresh.limit(n)
  137 + ].compact.flatten.sort do |x, y|
  138 + y.created_at <=> x.created_at
  139 + end[0...n]
  140 + end
  141 +
122 142 def commit(commit_id = nil)
123 143 if commit_id
124 144 repo.commits(commit_id).first
... ... @@ -131,16 +151,16 @@ class Project &lt; ActiveRecord::Base
131 151 @heads ||= repo.heads
132 152 end
133 153  
134   - def fresh_commits
  154 + def fresh_commits(n = 10)
135 155 commits = heads.map do |h|
136   - repo.commits(h.name, 10)
  156 + repo.commits(h.name, n)
137 157 end.flatten.uniq { |c| c.id }
138 158  
139 159 commits.sort! do |x, y|
140 160 y.committed_date <=> x.committed_date
141 161 end
142 162  
143   - commits[0..10]
  163 + commits[0...n]
144 164 end
145 165  
146 166 def commits_since(date)
... ...
app/views/admin/_top_menu.html.haml
... ... @@ -1,6 +0,0 @@
1   -%div.top_project_menu
2   - %span= link_to "Users", admin_users_path, :style => "width:50px;", :class => controller.controller_name == "users" ? "current" : nil
3   - %span= link_to "Projects", admin_projects_path, :style => "width:50px;", :class => controller.controller_name == "projects" ? "current" : nil
4   - %span= link_to "Teams", admin_team_members_path, :style => "width:50px;", :class => controller.controller_name == "team_members" ? "current" : nil
5   - %span= link_to "Emails", admin_emails_path, :style => "width:50px;", :class => controller.controller_name == "mailer" ? "current" : nil
6   -
app/views/admin/projects/index.html.haml
1 1 %table
2   - %tr
  2 + %thead
3 3 %th Name
4 4 %th Code
5 5 %th Path
... ...
app/views/admin/team_members/index.html.haml
1 1 - @admin_team_members.group_by(&:project).sort.each do |project, members|
2 2 %h3= link_to project.name, [:admin, project]
3 3 %table
4   - %tr
  4 + %thead
5 5 %th Name
6 6 %th Email
7 7 %th Read
... ...
app/views/admin/users/index.html.haml
1 1 %table
2   - %tr
  2 + %thead
3 3 %th Admin
4 4 %th Name
5 5 %th Email
... ...
app/views/commits/_commits.html.haml
1 1 - @commits.group_by { |c| c.committed_date.to_date }.each do |day, commits|
2   - .day-commits-table
3   - .day-header
  2 + %div{ :class => "commits-date ui-box ui-box-small ui-box-big" }
  3 + .day-commits-table
4 4 %h3= day.stamp("28 Aug, 2010")
5   - %ul
6   - - commits.each do |commit|
7   - %li{ :class => "commit", :url => project_commit_path(@project, :id => commit.id) }
8   - - if commit.author.email
9   - = image_tag gravatar_icon(commit.author.email), :class => "left", :width => 40, :style => "padding-right:5px;"
10   - - else
11   - = image_tag "no_avatar.png", :class => "left", :width => 40, :style => "padding-right:5px;"
12   - %p
13   - %strong
14   - = truncate(commit.safe_message, :length => 60)
15   - = link_to "Browse Code", tree_project_path(@project, :commit_id => commit.id), :class => "lite_button", :style => "float:right"
16   - = link_to truncate(commit.id.to_s, :length => 16), project_commit_path(@project, :id => commit.id), :class => "lite_button", :style => "width:120px;float:right"
17   - %span
18   - %span.author
19   - = commit.author
20   - = time_ago_in_words(commit.committed_date)
21   - ago
  5 + .data
  6 + - commits.each do |commit|
  7 + %a{ :class => "commit", :href => project_commit_path(@project, :id => commit.id) }
  8 + %span.commit-info
  9 + %data.commit-button
  10 + = truncate(commit.id.to_s, :length => 16)
  11 + %i
  12 + %data.commit-browse{ :onclick => "location.href='#{tree_project_path(@project, :commit_id => commit.id)}';return false;"}
  13 + Browse Code
  14 + - if commit.author_email
  15 + = image_tag gravatar_icon(commit.author_email), :class => "left", :width => 40, :style => "padding-right:5px;"
  16 + - else
  17 + = image_tag "no_avatar.png", :class => "left", :width => 40, :style => "padding-right:5px;"
  18 + %span.commit-title
  19 + %strong
  20 + = truncate(commit.safe_message, :length => 60)
  21 + %span.commit-author
  22 + %strong= commit.author_name
  23 + = time_ago_in_words(commit.committed_date)
  24 + ago
22 25 = more_commits_link if @commits.size > 99
... ...
app/views/commits/index.html.haml
1   -%div
2   - %h3
3   - .left
4   - = form_tag project_commits_path(@project), :method => :get do
5   - = select_tag "branch", options_for_select(@repo.heads.map(&:name), @branch), :onchange => "this.form.submit();", :class => "", :prompt => "Branches"
6   - &nbsp;
7   - .left.prepend-1
8   - = form_tag project_commits_path(@project), :method => :get do
9   - = select_tag "tag", options_for_select(@project.tags, @tag), :onchange => "this.form.submit();", :class => "", :prompt => "Tags"
10   - = text_field_tag "ssh", @project.url_to_repo, :class => ["ssh_project_url", "one_click_select"]
11   - .clear
  1 +- content_for(:body_class, "project-page commits-page")
  2 +
  3 +.left
  4 + = form_tag project_commits_path(@project), :method => :get do
  5 + = select_tag "branch", options_for_select(@repo.heads.map(&:name), @branch), :onchange => "this.form.submit();", :class => "", :prompt => "Branches"
  6 +.left
  7 + = form_tag project_commits_path(@project), :method => :get do
  8 + = select_tag "tag", options_for_select(@project.tags, @tag), :onchange => "this.form.submit();", :class => "", :prompt => "Tags"
  9 +.clear
  10 +
  11 +%br
  12 +
  13 +
  14 +-#%a.right.button{:href => "#"} Download
  15 +-#-if can? current_user, :admin_project, @project
  16 + %a.right.button.blue{:href => "#"} EDIT
  17 +%h2.icon
  18 + %span
  19 + %a.project-name{:href => "#"}
  20 + %i.arrow>
  21 + Project
  22 + &nbsp;
  23 + %d
  24 + %a{:href => "#"}
  25 + = @ref
12 26 - if params[:path]
13   - %h3{:style => "color:#555"} /#{params[:path]}
14   - %div{:id => dom_id(@project)}
15   - = render "commits"
  27 + &nbsp;
  28 + %d
  29 + %a{:href => "#"}= params[:path].split("/").join(" / ")
  30 +
  31 +
  32 +%div{:id => dom_id(@project)}
  33 + = render "commits"
... ...
app/views/commits/show.html.haml
... ... @@ -7,7 +7,7 @@
7 7 %td= @commit.id
8 8 %tr
9 9 %td Author
10   - %td= @commit.author
  10 + %td= @commit.author_name
11 11 %tr
12 12 %td Commiter
13 13 %td= @commit.committer
... ... @@ -16,7 +16,9 @@
16 16 %td= @commit.committed_date
17 17 %tr
18 18 %td Message
19   - %td= @commit.safe_message
  19 + %td
  20 + %pre.commit_message
  21 + = preserve @commit.safe_message
20 22 %tr
21 23 %td Tree
22 24 %td= link_to 'Browse Code', tree_project_path(@project, :commit_id => @commit.id)
... ...
app/views/dashboard/index.html.haml
1   -timeline
  1 +- content_for(:body_class, "dashboard-page")
  2 +
  3 +#dashboard-content.dashboard-content.content
  4 + %aside
  5 + %h4
  6 + - if current_user.can_create_project?
  7 + %a.button-small.button-green{:href => new_project_path} New Repository
  8 + Your Repositories
  9 + %ol.project-list
  10 + - @projects.each do |project|
  11 + %li
  12 + %a{:href => project_path(project)}
  13 + %span.arrow →
  14 + %span.project-name= project.name
  15 + %span.time
  16 + %strong Last activity:
  17 + = project.last_activity_date ? time_ago_in_words(project.last_activity_date) + " ago" : "Never"
  18 + #news-feed.news-feed
  19 + %h2.icon
  20 + %span>
  21 + Dashboard
  22 + - @active_projects.first(3).each do |project|
  23 + .project-box.project-updates.ui-box.ui-box-small.ui-box-big
  24 + %h3= project.name
  25 + .data
  26 + - project.updates.each do |update|
  27 + %a.project-update{:href => dashboard_feed_path(project, update)}
  28 + = image_tag gravatar_icon(update.author_email), :class => "left", :width => 40
  29 + %span.update-title
  30 + = dashboard_feed_title(update)
  31 + %span.update-author
  32 + %strong= update.author_name
  33 + authored
  34 + = time_ago_in_words(update.created_at)
  35 + ago
  36 + %br
  37 + / .project-update
  38 + / .project-updates
  39 + / #news-feed
  40 +/ #dashboard-content
... ...
app/views/devise/passwords/new.html.erb
1   -<h2>Forgot your password?</h2>
2   -
3   -<div class="span-12 colborder">
4   - <%= form_for(resource, :as => resource_name, :url => password_path(resource_name), :html => { :method => :post }) do |f| %>
5   - <%= devise_error_messages! %>
6   -
7   - <div><%= f.label :email %><br />
8   - <%= f.email_field :email %></div>
9   -
10   - <div><%= f.submit "Send me reset password instructions", :class => "lbutton vm" %></div>
11   - <% end %>
12   -</div>
13   -<div>
14   - <%= render :partial => "devise/shared/links" %>
15   -</div>
  1 +<%= form_for(resource, :as => resource_name, :url => password_path(resource_name), :html => { :class => "login-box", :method => :post }) do |f| %>
  2 + <%= image_tag "login-logo.png", :width => "304", :height => "66", :class => "login-logo", :alt => "Login Logo" %>
  3 + <%= devise_error_messages! %>
  4 + <%= f.email_field :email, :placeholder => "Email", :class => "text top" %>
  5 + <br/>
  6 + <%= f.submit "Reset password", :class => "grey-button" %>
  7 + <div class="right"> <%= render :partial => "devise/shared/links" %></div>
  8 +<% end %>
... ...
app/views/devise/sessions/new.html.erb
1   -<h2>Sign in</h2>
  1 +<%= form_for(resource, :as => resource_name, :url => session_path(resource_name), :html => { :class => "login-box" }) do |f| %>
  2 + <%= image_tag "login-logo.png", :width => "304", :height => "66", :class => "login-logo", :alt => "Login Logo" %>
  3 + <%= f.text_field :email, :class => "text top", :placeholder => "Email" %>
  4 + <%= f.password_field :password, :class => "text bottom", :placeholder => "Password" %>
2 5  
3   -<div class="span-12 colborder">
4   - <%= form_for(resource, :as => resource_name, :url => session_path(resource_name)) do |f| %>
5   - <div><%= f.label :email %><br />
6   - <%= f.text_field :email %></div>
7   -
8   - <div><%= f.label :password %><br />
9   - <%= f.password_field :password %></div>
10   -
11   - <% if devise_mapping.rememberable? -%>
12   - <div><%= f.check_box :remember_me %> <%= f.label :remember_me %></div>
13   - <% end -%>
14   - <br/>
15   - <div><%= f.submit "Sign in", :class => "lbutton vm" %></div>
16   - <% end %>
17   -</div>
18   -<div>
19   - <%= render :partial => "devise/shared/links" %>
20   -</div>
  6 + <% if devise_mapping.rememberable? -%>
  7 + <div><%= f.check_box :remember_me %> <%= f.label :remember_me %></div>
  8 + <% end -%>
  9 + <br/>
  10 + <%= f.submit "Sign in", :class => "grey-button" %>
  11 + <div class="right"> <%= render :partial => "devise/shared/links" %></div>
  12 +<% end %>
... ...
app/views/issues/_issues.html.haml
1 1 %table.round-borders#issues-table
2   - %tr
  2 + %thead
3 3 - if can?(current_user, :admin_issue, @project) && !params[:f] || params[:f] == "0"
4 4 %th
5 5 %th Assignee
... ...
app/views/issues/show.html.haml
1 1 %h2
2 2 = "Issue ##{@issue.id} - #{html_escape(@issue.title)}"
3   -.span-15
  3 +.left.width-65p
4 4 -#= simple_format html_escape(@issue.content)
5 5 .issue_notes= render "notes/notes"
6   -.span-8.right
  6 +.right.width-30p
7 7 .span-8
8 8 - if @issue.closed
9 9 %center.success Closed
... ...
app/views/layouts/_head_panel.html.erb
1   -<div id="header-panel">
  1 +<!-- Page Header -->
  2 +<header>
  3 +<h1 class="logo">
  4 + <a href="/">GITLAB</a></h1>
  5 + <div class="login-top">
  6 + <%= link_to profile_path, :class => "pic" do %>
  7 + <%= image_tag gravatar_icon(current_user.email) %>
  8 + <% end %>
  9 + <%= link_to profile_path, :class => "username" do %>
  10 + <%= current_user.name %>
  11 + <% end %>
  12 + <%= link_to 'Logout', destroy_user_session_path, :class => "logout", :method => :delete %>
  13 + </div>
  14 + <div class="search">
  15 + <%= text_field_tag "search", nil, :placeholder => "Search", :class => "search-input" %>
  16 + </div>
  17 + <!-- .login-top -->
  18 + <nav>
  19 + <%= link_to dashboard_path, :class => current_page?(root_path) ? "current dashboard" : "dashboard" do %>
  20 + <span></span>Dashboard
  21 + <% end %>
  22 + <%= link_to projects_path, :class => current_page?(projects_path) ? "current project" : "project" do %>
  23 + <span></span>Projects
  24 + <% end %>
  25 + <%= link_to((current_user.is_admin? ? admin_root_path : "#"), :class => (admin_namespace? ? "current admin" : "admin")) do %>
  26 + <span></span>Admin
  27 + <% end %>
  28 + </nav>
  29 +</header>
  30 +<!-- eo Page Header -->
  31 +
  32 +<div id="header-panel" style="display:none">
2 33 <div class="container">
3 34 <div class="span-24">
4 35 <div class="span-10">
5   - <%#= image_tag "git.png", :height => 40, :class => "left" %>
6   - <%#= link_to "gitlab", root_path, :id => "logo" %>
7 36 <span class="search-holder">
8   - <%= text_field_tag "search", nil, :placeholder => "Search" %>
9 37 </span>
10 38 </div>
11 39 <div class="right">
12 40 <%= link_to truncate(@project.name, :length => 20), project_path(@project), :class => "current button" if @project && !@project.new_record? %>
13   - <%= link_to 'Projects', projects_path, :class => current_page?(projects_path) ? "current button" : "button" %>
14   - <%= link_to('Admin', admin_root_path, :class => admin_namespace? ? "current button" : "button" ) if current_user.is_admin? %>
15   - <%= link_to profile_path, :class => ((controller.controller_name == "keys" || controller.controller_name == "profile") ? "current button" : "button") do %>
16   - <%= image_tag gravatar_icon(current_user.email) %>
17   - <%= current_user.name.split(" ").first %>
18   - <% end %>
19   - <%= link_to 'Logout', destroy_user_session_path, :style => "border-left: 1px solid #666;", :class => "button", :method => :delete %>
20 41 </div>
21 42 </div>
22 43 </div>
... ...
app/views/layouts/_page_title.html.haml 0 → 100644
... ... @@ -0,0 +1,2 @@
  1 +- if content_for?(:page_title)
  2 + = yield :page_title
... ...
app/views/layouts/admin.html.haml 0 → 100644
... ... @@ -0,0 +1,27 @@
  1 +!!!
  2 +%html
  3 + %head
  4 + %title
  5 + GitLab #{" - #{@project.name}" if @project && !@project.new_record?}
  6 + = stylesheet_link_tag "application"
  7 + = javascript_include_tag "application"
  8 + = csrf_meta_tags
  9 + %link{:href => "/assets/favicon.png", :rel => "icon", :type => "image/png"}/
  10 + = javascript_tag do
  11 + REQ_URI = "#{request.env["REQUEST_URI"]}";
  12 + REQ_REFFER = "#{request.env["HTTP_REFERER"]}";
  13 + %body{ :class => content_for?(:body_class) ? yield(:body_class) : 'project-page', :id => yield(:boyd_id)}
  14 + #container
  15 + = render :partial => "layouts/flash"
  16 + = render :partial => "layouts/head_panel"
  17 + .project-container
  18 + .project-sidebar
  19 + .fixed
  20 + %aside
  21 + = link_to "Users", admin_users_path, :class => controller.controller_name == "users" ? "current" : nil
  22 + = link_to "Projects", admin_projects_path, :class => controller.controller_name == "projects" ? "current" : nil
  23 + = link_to "Teams", admin_team_members_path, :class => controller.controller_name == "team_members" ? "current" : nil
  24 + = link_to "Emails", admin_emails_path, :class => controller.controller_name == "mailer" ? "current" : nil
  25 +
  26 + .project-content
  27 + = yield
... ...
app/views/layouts/application.html.haml
... ... @@ -3,10 +3,10 @@
3 3 %head
4 4 %title
5 5 GitLab #{" - #{@project.name}" if @project && !@project.new_record?}
6   - = stylesheet_link_tag 'blueprint/screen', :media => "screen, projection"
7   - = stylesheet_link_tag 'blueprint/print', :media => "print"
8   - = stylesheet_link_tag 'blueprint/plugins/buttons/screen', :media => "screen, projection"
9   - = stylesheet_link_tag 'blueprint/plugins/link-icons/screen', :media => "screen, projection"
  6 + -#= stylesheet_link_tag 'blueprint/screen', :media => "screen, projection"
  7 + -#= stylesheet_link_tag 'blueprint/print', :media => "print"
  8 + -#= stylesheet_link_tag 'blueprint/plugins/buttons/screen', :media => "screen, projection"
  9 + -#= stylesheet_link_tag 'blueprint/plugins/link-icons/screen', :media => "screen, projection"
10 10 = stylesheet_link_tag "application"
11 11 = javascript_include_tag "application"
12 12 = csrf_meta_tags
... ... @@ -14,15 +14,10 @@
14 14 = javascript_tag do
15 15 REQ_URI = "#{request.env["REQUEST_URI"]}";
16 16 REQ_REFFER = "#{request.env["HTTP_REFERER"]}";
17   - %body#thebody
18   - = render :partial => "layouts/flash"
19   - - if user_signed_in?
  17 + %body{ :class => yield(:body_class), :id => yield(:boyd_id)}
  18 + #container
  19 + = render :partial => "layouts/flash"
20 20 = render :partial => "layouts/head_panel"
21   - .top_bar.container
22   - = render :partial => "projects/top_menu" if @project && !@project.new_record?
23   - = render :partial => "projects/projects_top_menu" if (controller.controller_name == "projects" && ["index", "new", "create"].include?(controller.action_name)) && !admin_namespace?
24   - = render :partial => "profile/top_menu" if ["keys", "profile"].include?(controller.controller_name)
25   - = render :partial => "admin/top_menu" if admin_namespace?
26   - #content-container.container
27   - .span-24
  21 + %div{ :id => "main", :role => "main", :class => "container_4" }
  22 + = render :partial => "layouts/page_title"
28 23 = yield
... ...
app/views/layouts/devise.html.haml 0 → 100644
... ... @@ -0,0 +1,15 @@
  1 +!!!
  2 +%html
  3 + %head
  4 + %title
  5 + GitLab #{" - #{@project.name}" if @project && !@project.new_record?}
  6 + = stylesheet_link_tag "application"
  7 + = javascript_include_tag "application"
  8 + = csrf_meta_tags
  9 + %link{:href => "/assets/favicon.png", :rel => "icon", :type => "image/png"}/
  10 + = javascript_tag do
  11 + REQ_URI = "#{request.env["REQUEST_URI"]}";
  12 + REQ_REFFER = "#{request.env["HTTP_REFERER"]}";
  13 + %body.login-page
  14 + = render :partial => "layouts/flash"
  15 + = yield
... ...
app/views/layouts/profile.html.haml 0 → 100644
... ... @@ -0,0 +1,29 @@
  1 +!!!
  2 +%html
  3 + %head
  4 + %title
  5 + GitLab #{" - #{@project.name}" if @project && !@project.new_record?}
  6 + = stylesheet_link_tag "application"
  7 + = javascript_include_tag "application"
  8 + = csrf_meta_tags
  9 + %link{:href => "/assets/favicon.png", :rel => "icon", :type => "image/png"}/
  10 + = javascript_tag do
  11 + REQ_URI = "#{request.env["REQUEST_URI"]}";
  12 + REQ_REFFER = "#{request.env["HTTP_REFERER"]}";
  13 + %body{ :class => content_for?(:body_class) ? yield(:body_class) : 'project-page', :id => yield(:boyd_id)}
  14 + #container
  15 + = render :partial => "layouts/flash"
  16 + = render :partial => "layouts/head_panel"
  17 + .project-container
  18 + .project-sidebar
  19 + .fixed
  20 + %aside
  21 + = link_to "Profile", profile_path, :class => current_page?(:controller => "profile", :action => :show) ? "current" : nil
  22 + = link_to "Password", profile_password_path, :class => current_page?(:controller => "profile", :action => :password) ? "current" : nil
  23 + = link_to keys_path, :class => controller.controller_name == "keys" ? "current" : nil do
  24 + Keys
  25 + - unless current_user.keys.empty?
  26 + %span{ :class => "number" }= current_user.keys.count
  27 +
  28 + .project-content
  29 + = yield
... ...
app/views/layouts/project.html.haml 0 → 100644
... ... @@ -0,0 +1,45 @@
  1 +!!!
  2 +%html
  3 + %head
  4 + %title
  5 + GitLab #{" - #{@project.name}" if @project && !@project.new_record?}
  6 + = stylesheet_link_tag "application"
  7 + = javascript_include_tag "application"
  8 + = csrf_meta_tags
  9 + %link{:href => "/assets/favicon.png", :rel => "icon", :type => "image/png"}/
  10 + = javascript_tag do
  11 + REQ_URI = "#{request.env["REQUEST_URI"]}";
  12 + REQ_REFFER = "#{request.env["HTTP_REFERER"]}";
  13 + %body{ :class => content_for?(:body_class) ? yield(:body_class) : 'project-page', :id => yield(:boyd_id)}
  14 + #container
  15 + = render :partial => "layouts/flash"
  16 + = render :partial => "layouts/head_panel"
  17 + .project-container
  18 + .project-sidebar
  19 + .fixed
  20 + %input.git-url.text{:id => "", :name => "", :readonly => "", :type => "text", :value => @project.url_to_repo}
  21 + %aside
  22 + = link_to "History", project_path(@project), :class => current_page?(:controller => "projects", :action => "show", :id => @project) ? "current" : nil
  23 + = link_to "Tree", tree_project_path(@project), :class => current_page?(:controller => "projects", :action => "tree", :id => @project) ? "current" : nil
  24 + = link_to "Commits", project_commits_path(@project), :class => current_page?(:controller => "commits", :action => "index", :project_id => @project) ? "current" : nil
  25 + = link_to team_project_path(@project), :class => (current_page?(:controller => "projects", :action => "team", :id => @project) || controller.controller_name == "team_members") ? "current" : nil do
  26 + Team
  27 + - if @project.users_projects.count > 0
  28 + %span{ :class => "number" }= @project.users_projects.count
  29 + = link_to project_issues_path(@project), :class => (controller.controller_name == "issues") ? "current" : nil do
  30 + Issues
  31 + - if @project.issues.opened.count > 0
  32 + %span{ :class => "number" }= @project.issues.opened.count
  33 + = link_to wall_project_path(@project), :class => current_page?(:controller => "projects", :action => "wall", :id => @project) ? "current" : nil do
  34 + Wall
  35 + - if @project.common_notes.count > 0
  36 + %span{ :class => "number" }= @project.common_notes.count
  37 + = link_to project_snippets_path(@project), :class => (controller.controller_name == "snippets") ? "current" : nil do
  38 + Snippets
  39 + - if @project.snippets.count > 0
  40 + %span{ :class => "number" }= @project.snippets.non_expired.count
  41 + - if @commit
  42 + = link_to truncate(commit_name(@project,@commit), :length => 15), project_commit_path(@project, :id => @commit.id), :class => current_page?(:controller => "commits", :action => "show", :project_id => @project, :id => @commit.id) ? "current" : nil
  43 +
  44 + .project-content
  45 + = yield
... ...
app/views/notes/_show.html.haml
... ... @@ -2,7 +2,7 @@
2 2 %div.note_author
3 3 = image_tag gravatar_icon(note.author.email), :class => "left", :width => 40, :style => "padding-right:5px;"
4 4 %div.note_content.left
5   - = simple_format(html_escape(note.note))
  5 + = markdown(note.note)
6 6 - if note.attachment.url
7 7 Attachment:
8 8 = link_to note.attachment_identifier, note.attachment.url, :target => "_blank"
... ...
app/views/profile/_top_menu.html.haml
... ... @@ -1,5 +0,0 @@
1   -%div.top_project_menu
2   - %span= link_to "Profile", profile_path, :class => current_page?(:controller => "profile", :action => :show) ? "current" : nil
3   - %span= link_to "Password", profile_password_path, :style => "width:70px;", :class => current_page?(:controller => "profile", :action => :password) ? "current" : nil
4   - %span= link_to "Keys", keys_path, :class => controller.controller_name == "keys" ? "current" : nil
5   -
app/views/projects/_recent_messages.html.haml
... ... @@ -40,7 +40,7 @@
40 40 %p{:style => "margin-bottom: 3px;"}
41 41 %span.author
42 42 = note.author.name
43   - = link_to truncate(note.note, :length => 200), link_to_item + "#note_#{note.id}"
  43 + = link_to markdown(truncate(note.note, :length => 200)), link_to_item + "#note_#{note.id}"
44 44 - if note.attachment.url
45 45 %br
46 46 Attachment:
... ...
app/views/projects/_team.html.haml
... ... @@ -2,7 +2,7 @@
2 2 %div#new-member-holder
3 3 = link_to "Add new", new_project_team_member_path(@project), :remote => true, :class => "lbutton vm"
4 4 %table.round-borders#team-table
5   - %tr
  5 + %thead
6 6 %th Name
7 7 %th Email
8 8 %th Web
... ...
app/views/projects/_tile.html.haml
1 1 - @projects.in_groups_of(3, false) do |projects|
2 2 - projects.each_with_index do |project, i|
3   - %div{ :class => "project_thumb round-borders", :style => i == 2 ? "" : "margin-right:30px;" }
4   - %div{ :class => "project", :url => project_path(project) }
5   - %h2
6   - = image_tag gravatar_icon(project.name), :class => "left", :width => 40, :style => "padding-right:5px;"
7   - = link_to ("/" + project.code), project_path(project), :style => "text-decoration:none"
8   - %p= project.name
9   - %p= project.url_to_repo
10   - -#%p
11   - Commit &ndash;
12   - = last_commit(project)
13   - %hr
14   - = link_to "Browse Code", tree_project_path(project), :class => "lbutton"
15   - = link_to "Commits", project_commits_path(project), :class => "lbutton", :style => "float:right;width:80px;"
16   - .clear
  3 + %div.grid_1
  4 + %div{ :class => "project-box ui-box ui-box-big" }
  5 + = link_to project_path(project) do
  6 + %h3= project.name
  7 + .data
  8 + %p.title.repository
  9 + %span Repository:
  10 + = project.url_to_repo
  11 + %p.title.activity
  12 + %span Last Activity:
  13 + - last_note = project.notes.last
  14 + = last_note ? last_note.created_at.stamp("24 Aug, 2011") : "Never"
  15 + .buttons
  16 + %a.browse-code.button.yellow{:href => tree_project_path(project)} Browse code
  17 + %a.commits.button.green{:href => project_commits_path(project)} Commits
... ...
app/views/projects/_top_menu.html.haml
1 1 %div.top_project_menu
2   - -#%span= link_to @project.code.capitalize, @project, :class => current_page?(:controller => "projects", :action => "show", :id => @project) ? "current" : nil
3 2 - if @project.repo_exists?
4 3 %span= link_to image_tag("home.png", :width => 20), project_path(@project), :class => current_page?(:controller => "projects", :action => "show", :id => @project) ? "current" : nil
5 4 %span= link_to "Tree", tree_project_path(@project), :class => current_page?(:controller => "projects", :action => "tree", :id => @project) ? "current" : nil
... ...
app/views/projects/_tree.html.haml
1   -%h3
2   - .left
3   - = form_tag tree_project_path(@project), :method => :get do
4   - = select_tag "branch", options_for_select(@repo.heads.map(&:name), @branch), :onchange => "this.form.submit();", :class => "", :prompt => "Branches"
5   - &nbsp;
6   - .left.prepend-1
7   - = form_tag tree_project_path(@project), :method => :get do
8   - = select_tag "tag", options_for_select(@project.tags, @tag), :onchange => "this.form.submit();", :class => "", :prompt => "Tags"
9   - = text_field_tag "ssh", @project.url_to_repo, :class => ["ssh_project_url","one_click_select"]
10   - .clear
11   -
12   -%h3#tree-breadcrumbs
13   - = link_to @project.name, tree_project_path(@project, :path => nil, :commit_id => @commit.try(:id)), :remote => true
14   - - if params[:path]
15   - - part_path = ""
16   - - params[:path].split("\/").each do |part|
17   - - part_path = File.join(part_path, part) unless part_path.empty?
18   - - if part_path.empty?
19   - - part_path = part
20   - \/
21   - = link_to truncate(part, :length => 40), tree_file_project_path(@project, :path => part_path, :commit_id => @commit.try(:id), :branch => @branch, :tag => @tag), :remote => :true
  1 +.left
  2 + = form_tag tree_project_path(@project), :method => :get do
  3 + = select_tag "branch", options_for_select(@repo.heads.map(&:name), @branch), :onchange => "this.form.submit();", :class => "", :prompt => "Branches"
  4 +.left
  5 + = form_tag tree_project_path(@project), :method => :get do
  6 + = select_tag "tag", options_for_select(@project.tags, @tag), :onchange => "this.form.submit();", :class => "", :prompt => "Tags"
  7 +.clear
  8 +
  9 +%br
  10 +
  11 +-#%a.right.button{:href => "#"} Download
  12 +-#-if can? current_user, :admin_project, @project
  13 + %a.right.button.blue{:href => "#"} EDIT
  14 +#tree-breadcrumbs
  15 + %h2.icon
  16 + %span
  17 + = link_to tree_project_path(@project, :path => nil, :commit_id => @commit.try(:id)), :remote => true, :class => 'project-name' do
  18 + %i.arrow>
  19 + = @project.name
  20 + &nbsp;
  21 + %d
  22 + %a{:href => "#"}
  23 + = @ref
  24 +
  25 + - if params[:path]
  26 + - part_path = ""
  27 + - params[:path].split("\/").each do |part|
  28 + - part_path = File.join(part_path, part) unless part_path.empty?
  29 + - if part_path.empty?
  30 + - part_path = part
  31 + \/
  32 + = link_to truncate(part, :length => 40), tree_file_project_path(@project, :path => part_path, :commit_id => @commit.try(:id), :branch => @branch, :tag => @tag), :remote => :true
  33 +
  34 +.clear
  35 +
22 36 #tree-content-holder
23 37 - if tree.is_a?(Grit::Blob)
24 38 = render :partial => "projects/tree_file", :locals => { :name => tree.name, :content => tree.data, :file => tree }
25 39 - else
26 40 - contents = tree.contents
27 41 %table#tree-slider.round-borders
28   - %tr
  42 + %thead
29 43 %th Name
30 44 %th Last Update
31 45 %th
... ...
app/views/projects/index.html.haml
  1 +- content_for(:body_class, "projects-page")
  2 +- content_for(:page_title) do
  3 + .grid_4
  4 + - if current_user.can_create_project?
  5 + %a.grey-button.right{:href => new_project_path} Create new project
  6 + %h2.icon
  7 + %span
  8 + Projects
  9 +
1 10 - unless @projects.empty?
2 11 %div{:class => "tile", :style => view_mode_style("tile")}
3 12 = render "tile"
... ...
app/views/projects/show.html.haml
... ... @@ -13,11 +13,11 @@
13 13 = label_tag "week_view","Week"
14 14 .clear
15 15 %hr
16   -.span-11
  16 +.left.width-49p
17 17 %h3 Commits
18 18 =render "projects/recent_commits"
19 19  
20   -.span-11.right
  20 +.right.width-49p
21 21 %h3 Talk
22 22 =render "projects/recent_messages"
23 23  
... ...
config/environments/development.rb
... ... @@ -29,4 +29,5 @@ Gitlab::Application.configure do
29 29 config.assets.debug = true
30 30  
31 31 config.action_mailer.default_url_options = { :host => 'localhost:3000' }
  32 + config.action_mailer.delivery_method = :letter_opener
32 33 end
... ...
config/routes.rb
... ... @@ -15,6 +15,7 @@ Gitlab::Application.routes.draw do
15 15 put "profile/password", :to => "profile#password_update"
16 16 put "profile/edit", :to => "profile#social_update"
17 17 get "profile", :to => "profile#show"
  18 + get "dashboard", :to => "dashboard#index"
18 19 #get "profile/:id", :to => "profile#show"
19 20  
20 21 resources :projects, :only => [:new, :create, :index]
... ... @@ -53,5 +54,5 @@ Gitlab::Application.routes.draw do
53 54 end
54 55 resources :notes, :only => [:create, :destroy]
55 56 end
56   - root :to => "projects#index"
  57 + root :to => "dashboard#index"
57 58 end
... ...
lib/commit_ext.rb
... ... @@ -8,4 +8,16 @@ module CommitExt
8 8 rescue
9 9 "-- invalid encoding for commit message"
10 10 end
  11 +
  12 + def created_at
  13 + committed_date
  14 + end
  15 +
  16 + def author_email
  17 + author.email.force_encoding(Encoding::UTF_8)
  18 + end
  19 +
  20 + def author_name
  21 + author.name.force_encoding(Encoding::UTF_8)
  22 + end
11 23 end
... ...
public/apple-touch-icon-114x114-precomposed.png 0 → 100755

1.01 KB

public/apple-touch-icon-57x57-precomposed.png 0 → 100755

640 Bytes

public/apple-touch-icon-72x72-precomposed.png 0 → 100755

747 Bytes

public/apple-touch-icon-precomposed.png 0 → 100755

640 Bytes

public/apple-touch-icon.png 0 → 100755

640 Bytes

public/favicon.ico 100644 → 100755
No preview for this file type
spec/models/project_spec.rb
... ... @@ -62,6 +62,51 @@ describe Project do
62 62 end
63 63 end
64 64  
  65 + describe "updates" do
  66 + let(:project) { Factory :project }
  67 +
  68 + before do
  69 + @issue = Factory :issue,
  70 + :project => project,
  71 + :author => Factory(:user),
  72 + :assignee => Factory(:user)
  73 +
  74 + @note = Factory :note,
  75 + :project => project,
  76 + :author => Factory(:user)
  77 +
  78 + @commit = project.fresh_commits(1).first
  79 + end
  80 +
  81 + describe "return commit, note & issue" do
  82 + it { project.updates(3).count.should == 3 }
  83 + it { project.updates(3).last.id.should == @commit.id }
  84 + it { project.updates(3).include?(@issue).should be_true }
  85 + it { project.updates(3).include?(@note).should be_true }
  86 + end
  87 + end
  88 +
  89 + describe "last_activity" do
  90 + let(:project) { Factory :project }
  91 +
  92 + before do
  93 + @note = Factory :note,
  94 + :project => project,
  95 + :author => Factory(:user)
  96 + end
  97 +
  98 + it { project.last_activity.should == @note }
  99 + it { project.last_activity_date.to_s.should == @note.created_at.to_s }
  100 + end
  101 +
  102 + describe "fresh commits" do
  103 + let(:project) { Factory :project }
  104 +
  105 + it { project.fresh_commits(3).count.should == 3 }
  106 + it { project.fresh_commits.first.id.should == "2fb376f61875b58bceee0492e270e9c805294b1a" }
  107 + it { project.fresh_commits.last.id.should == "0dac878dbfe0b9c6104a87d65fe999149a8d862c" }
  108 + end
  109 +
65 110 describe "Git methods" do
66 111 let(:project) { Factory :project }
67 112  
... ...
spec/requests/dashboard_spec.rb 0 → 100644
... ... @@ -0,0 +1,30 @@
  1 +require 'spec_helper'
  2 +
  3 +describe "Dashboard" do
  4 + before { login_as :user }
  5 +
  6 + describe "GET /dashboard" do
  7 + before do
  8 + @project = Factory :project
  9 + @project.add_access(@user, :read, :write)
  10 + visit dashboard_path
  11 + end
  12 +
  13 + it "should be on dashboard page" do
  14 + current_path.should == dashboard_path
  15 + end
  16 +
  17 + it "should have projects panel" do
  18 + within ".project-list" do
  19 + page.should have_content(@project.name)
  20 + end
  21 + end
  22 +
  23 + it "should have news feed" do
  24 + within "#news-feed" do
  25 + page.should have_content(@project.commit.author.name)
  26 + page.should have_content(@project.commit.safe_message)
  27 + end
  28 + end
  29 + end
  30 +end
... ...
spec/requests/issues_spec.rb
... ... @@ -5,7 +5,10 @@ describe &quot;Issues&quot; do
5 5  
6 6 before do
7 7 login_as :user
  8 + @user2 = Factory :user
  9 +
8 10 project.add_access(@user, :read, :write)
  11 + project.add_access(@user2, :read, :write)
9 12 end
10 13  
11 14 describe "GET /issues" do
... ... @@ -49,20 +52,20 @@ describe &quot;Issues&quot; do
49 52 end
50 53  
51 54 it "should show only open" do
52   - should have_content(@issue.title)
  55 + should have_content(@issue.title[0..25])
53 56 should have_no_content(@closed_issue.title)
54 57 end
55 58  
56 59 it "should show only closed" do
57 60 choose "closed_issues"
58 61 should have_no_content(@issue.title)
59   - should have_content(@closed_issue.title)
  62 + should have_content(@closed_issue.title[0..25])
60 63 end
61 64  
62 65 it "should show all" do
63 66 choose "all_issues"
64   - should have_content(@issue.title)
65   - should have_content(@closed_issue.title)
  67 + should have_content(@issue.title[0..25])
  68 + should have_content(@closed_issue.title[0..25])
66 69 end
67 70 end
68 71 end
... ... @@ -78,35 +81,66 @@ describe &quot;Issues&quot; do
78 81 end
79 82  
80 83 describe "fill in" do
81   - before do
82   - fill_in "issue_title", :with => "bug 345"
83   - click_link "Select user"
84   - click_link @user.name
85   - end
86   -
87   - it { expect { click_button "Save" }.to change {Issue.count}.by(1) }
88   -
89   - it "should add new issue to table" do
90   - click_button "Save"
91   -
92   - page.should_not have_content("Add new issue")
93   - page.should have_content @user.name
94   - page.should have_content "bug 345"
95   - page.should have_content project.name
  84 + describe 'assign to me' do
  85 + before do
  86 + fill_in "issue_title", :with => "bug 345"
  87 + click_link "Select user"
  88 + within "#issue_assignee_id-menu" do
  89 + click_link @user.name
  90 + end
  91 + end
  92 +
  93 + it { expect { click_button "Save" }.to change {Issue.count}.by(1) }
  94 +
  95 + it "should add new issue to table" do
  96 + click_button "Save"
  97 +
  98 + page.should_not have_content("Add new issue")
  99 + page.should have_content @user.name
  100 + page.should have_content "bug 345"
  101 + page.should have_content project.name
  102 + end
  103 +
  104 + it "should call send mail" do
  105 + Notify.should_not_receive(:new_issue_email)
  106 + click_button "Save"
  107 + end
96 108 end
97 109  
98   - it "should call send mail" do
99   - Notify.should_receive(:new_issue_email).and_return(stub(:deliver => true))
100   - click_button "Save"
101   - end
  110 + describe 'assign to other' do
  111 + before do
  112 + fill_in "issue_title", :with => "bug 345"
  113 + click_link "Select user"
  114 + within "#issue_assignee_id-menu" do
  115 + click_link @user2.name
  116 + end
  117 + end
  118 +
  119 + it { expect { click_button "Save" }.to change {Issue.count}.by(1) }
  120 +
  121 + it "should add new issue to table" do
  122 + click_button "Save"
  123 +
  124 + page.should_not have_content("Add new issue")
  125 + page.should have_content @user2.name
  126 + page.should have_content "bug 345"
  127 + page.should have_content project.name
  128 + end
  129 +
  130 + it "should call send mail" do
  131 + Notify.should_receive(:new_issue_email).and_return(stub(:deliver => true))
  132 + click_button "Save"
  133 + end
  134 +
  135 + it "should send valid email to user with email & password" do
  136 + click_button "Save"
  137 + issue = Issue.last
  138 + email = ActionMailer::Base.deliveries.last
  139 + email.subject.should have_content("New Issue was created")
  140 + email.body.should have_content(issue.title)
  141 + email.body.should have_content(issue.assignee.name)
  142 + end
102 143  
103   - it "should send valid email to user with email & password" do
104   - click_button "Save"
105   - issue = Issue.last
106   - email = ActionMailer::Base.deliveries.last
107   - email.subject.should have_content("New Issue was created")
108   - email.body.should have_content(issue.title)
109   - email.body.should have_content(issue.assignee.name)
110 144 end
111 145 end
112 146 end
... ...
spec/requests/projects_spec.rb
... ... @@ -13,14 +13,14 @@ describe &quot;Projects&quot; do
13 13 end
14 14  
15 15 it "should have link to new project" do
16   - page.should have_content("New Project")
  16 + page.should have_content("Create new project")
17 17 end
18 18 end
19 19  
20 20 describe "GET /projects/new" do
21 21 before do
22 22 visit projects_path
23   - click_link "New Project"
  23 + click_link "Create new project"
24 24 end
25 25  
26 26 it "should be correct path" do
... ...
spec/support/login.rb
... ... @@ -12,15 +12,15 @@ module LoginMacros
12 12 end
13 13  
14 14 visit new_user_session_path
15   - fill_in "Email", :with => @user.email
16   - fill_in "Password", :with => "123456"
  15 + fill_in "user_email", :with => @user.email
  16 + fill_in "user_password", :with => "123456"
17 17 click_button "Sign in"
18 18 end
19 19  
20 20 def login_with(user)
21 21 visit new_user_session_path
22   - fill_in "Email", :with => user.email
23   - fill_in "Password", :with => "123456"
  22 + fill_in "user_email", :with => user.email
  23 + fill_in "user_password", :with => "123456"
24 24 click_button "Sign in"
25 25 end
26 26  
... ...
vendor/assets/stylesheets/jquery-ui/jquery-ui.css
... ... @@ -445,7 +445,7 @@ button.ui-button::-moz-focus-inner { border: 0; padding: 0; } /* reset extra pad
445 445 * http://docs.jquery.com/UI/Dialog#theming
446 446 */
447 447 .ui-dialog { position: absolute; padding: 0; width: 300px; overflow: hidden; }
448   -.ui-dialog .ui-dialog-titlebar { padding: .4em 1em; position: relative; background: #333; color:#eaeaea }
  448 +.ui-dialog .ui-dialog-titlebar { padding: .4em 1em; position: relative; background: #F7F7F7; color:#555; }
449 449 .ui-dialog .ui-dialog-title { float: left; margin: .1em 16px .1em 0;}
450 450 .ui-dialog .ui-dialog-titlebar-close { position: absolute; right: .3em; top: 50%; width: 19px; margin: -10px 0 0 0; padding: 1px; height: 18px; background:#eaeaea}
451 451 .ui-dialog .ui-dialog-titlebar-close span { display: block; margin: 1px; }
... ...